X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.utils%2Fsrc%2Forg%2Fsimantics%2Futils%2Fstrings%2Fformat%2FMetricsFormat.java;fp=bundles%2Forg.simantics.utils%2Fsrc%2Forg%2Fsimantics%2Futils%2Fstrings%2Fformat%2FMetricsFormat.java;h=f6184a77999a95a8d5ac85c6aa28881633e36b99;hp=c675f6d9c37f0c287a3ff8942bd87995739c5a78;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.utils/src/org/simantics/utils/strings/format/MetricsFormat.java b/bundles/org.simantics.utils/src/org/simantics/utils/strings/format/MetricsFormat.java index c675f6d9c..f6184a779 100644 --- a/bundles/org.simantics.utils/src/org/simantics/utils/strings/format/MetricsFormat.java +++ b/bundles/org.simantics.utils/src/org/simantics/utils/strings/format/MetricsFormat.java @@ -1,349 +1,349 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.utils.strings.format; - -import java.io.Serializable; -import java.text.DecimalFormat; -import java.util.IllegalFormatConversionException; -import java.util.IllegalFormatException; - -/** - * Value metrics data - * - * Use 'S' Prefix to use String formatting rules http://java.sun.com/javase/6/docs/api/java/util/Formatter.html#syntax - * Use 'D' Prefix to use DecimalFormat rules http://java.sun.com/javase/6/docs/api/java/text/DecimalFormat.html - * - * If no prefix is detected, String rules are used. - * - * @author Toni Kalajainen - * @Author Marko Luukkainen - */ -public class MetricsFormat implements Serializable { - - /** - * Define serial version of this class - */ - private static final long serialVersionUID = 8036591251300342995L; - - - /** Presentation format */ - private String pattern; - - /** Presentation format */ - private String internalPattern; - - /** Presentation format */ - private String[] internalPatternDivided; - - /** flag if format can adjust decimals */ - private boolean canUseDecimals = false; - - /** scale */ - private double scale; - - /** name */ - private String name; - - /** hash */ - private int hash; - - /** Is double or long */ - private boolean isDouble = true; - - private boolean useDecimalFormat = false; - - /** Array reserved for formatter use */ - private Object args[] = new Object[1]; - - - public String getName() { - return name; - } - - public MetricsFormat(String pattern, double scale, String name) - throws IllegalArgumentException - { - this.scale = scale; - pattern = setPattern(pattern); - this.internalPattern = formatPattern( pattern ); - this.internalPatternDivided = formatPatternDivided( pattern ); - this.name = name; - this.hash = makeHash(); - } - - public MetricsFormat(String pattern, double scale) - throws IllegalArgumentException - { - this.scale = scale; - pattern = setPattern(pattern); - this.internalPattern = formatPattern( pattern ); - this.internalPatternDivided = formatPatternDivided( pattern ); - this.name = ""; - this.hash = makeHash(); - } - - public MetricsFormat(String pattern) - throws IllegalArgumentException - { - this.scale = 1.0f; - pattern = setPattern(pattern); - this.internalPattern = formatPattern( pattern ); - this.internalPatternDivided = formatPatternDivided( pattern ); - this.name = ""; - this.hash = makeHash(); - - } - - private String setPattern(String pattern) { - this.pattern = pattern; - if (pattern.startsWith("D")) { - pattern = pattern.substring(1); - useDecimalFormat = true; - } else { - if (pattern.startsWith("S")) - pattern = pattern.substring(1); - useDecimalFormat = false; - } - return pattern; - } - - /** - * Replacs all % with %1$ unless % precedes with \ - * - * @param pattern - * @return - */ - private String formatPattern(String pattern) { - int pos = 0; - if (!useDecimalFormat) { - while ( (pos = pattern.indexOf('%', pos)) >= 0 ) { - if (pos==0 || pattern.indexOf(pos-1)!='\\') { - pattern = pattern.substring(0, pos+1) + "1$" + pattern.substring(pos+1, pattern.length()); - pos += 3; - continue; - } - pos++; - } - } - - double value = 0; - if (useDecimalFormat) { - isDouble = true; - useDecimalFormat = true; - canUseDecimals = false; - DecimalFormat format = new DecimalFormat(pattern); - format.format(value); - - } else { - try { - isDouble = true; - useDecimalFormat = false; - args[0] = value; - String.format(pattern, args); - } catch(IllegalFormatConversionException e1) { - try { - isDouble = false; - useDecimalFormat = false; - args[0] = (long)value; - String.format(pattern, args); - } catch (Exception e2) { - throw e1; - } - } - } - - return pattern; - } - - /** - * Replacs all % with %1$ unless % precedes with \ - * - * Divides formatString into half so that - * formats precision can be adjusted with .(n)
- * Currently only format which supports adjustable - * decimals is f/F (floating point as decimal number) - * - * - * @param pattern - * @return - */ - private String[] formatPatternDivided(String pattern) { - String divPattern[] = new String[]{"",""}; - if (useDecimalFormat) - return divPattern; - int pos = 0; - while ( (pos = pattern.indexOf('%', pos)) >= 0 ) { - if (pos==0 || pattern.indexOf(pos-1)!='\\') { - divPattern[0] = pattern.substring(0, pos+1) + "1$"; - divPattern[1] = pattern.substring(pos+1, pattern.length()); - // parse flags - int pos2 = 0; - while(true) { - char c = divPattern[1].charAt(pos2); - if (c == '-' || - c == '#' || - c == '+' || - c == ' ' || - c == '0' || - c == ',' || - c == '(' || - Character.isDigit(c)) - pos2++; - else - break; - } - // get rid of possible precisision setting - // TODO : maybe we should let the user to set the precision - // and then use user given precision instead of dynamic precision - int pos3 = pos2; - while(true) { - char c = divPattern[1].charAt(pos3); - if (c == '.' || Character.isDigit(c)) { - pos3++; - } else if (c == 'f'|| c == 'F') { - this.canUseDecimals = true; - break; - } else { - this.canUseDecimals = false; - break; - } - } - if (pos2 > 0 || pos3 > 0) { - divPattern[0] += divPattern[1].substring(0,pos2); - divPattern[1] = divPattern[1].substring(pos3, divPattern[1].length()); - } - pos += 3; - // divided patterns can have only one % - break; - } - pos++; - } - - double value = 0; - try { - // checking if format can be used - args[0] = value; - String.format(divPattern[0] + ".2" + divPattern[1] , args); - } catch (IllegalFormatException e1) { - try { - pattern = formatPattern(pattern); - isDouble = false; - args[0] = (long)value; - String.format(pattern, args); - // if we get this far by not using decimals something strange has happened... - divPattern[0] = null; - divPattern[1] = null; - canUseDecimals = false; - } catch(Exception e2) { - throw e1; - } - } - - return divPattern; - } - - /** - * Formats value - * @param value - * @return - */ - public String formatValue(double value) { - return _formatValue(internalPattern, value); - } - - /** - * Format value - * Note: cannot DecimalFormatter syntax does not work with this method - * @param value - * @param numDecimals - * @return - */ - public String formatValue(double value, int numDecimals) { - if (canUseDecimals) { - if (numDecimals < 0) - numDecimals = 0; - return _formatValue(value, numDecimals); - } else { - return _formatValue(internalPattern, value); - } - - } - - - private String _formatValue(String pattern, double value) { - //value *= scale; - if (!useDecimalFormat) { - if (isDouble) { - args[0] = value; - return String.format(pattern, args); - } else { - args[0] = new Long((long)value); - return String.format(pattern, args); - } - } else { - DecimalFormat format = new DecimalFormat(pattern); - return format.format(value); - } - } - - private String _formatValue(double value, int decimals) { - //value *= scale; - args[0] = value; - return String.format(internalPatternDivided[0] + "." + decimals + internalPatternDivided[1], args); - - } - - public String getPattern() { - return pattern; - } - - public double getScale() { - return scale; - } - - public String toString() { - return name; - } - - - - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof MetricsFormat)) return false; - MetricsFormat other = (MetricsFormat) obj; - if (other.hash!=hash) return false; - return other.pattern.equals(pattern) && other.scale==scale && other.name.equals(name); - } - - private int makeHash() { - long longBits = Double.doubleToLongBits(scale); - int scaleHash = ((int)longBits)^(int)(longBits<<16); - return pattern.hashCode() ^ scaleHash ^ name.hashCode(); - } - - public int hashCode() { - return hash; - } - - /* - private void changeContent(MetricsFormat newContent) { - this.name = newContent.name; - this.pattern = newContent.pattern; - this.scale = newContent.scale; - this.internalPattern = newContent.internalPattern; - this.hash = newContent.hash; - }*/ - - - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.utils.strings.format; + +import java.io.Serializable; +import java.text.DecimalFormat; +import java.util.IllegalFormatConversionException; +import java.util.IllegalFormatException; + +/** + * Value metrics data + * + * Use 'S' Prefix to use String formatting rules http://java.sun.com/javase/6/docs/api/java/util/Formatter.html#syntax + * Use 'D' Prefix to use DecimalFormat rules http://java.sun.com/javase/6/docs/api/java/text/DecimalFormat.html + * + * If no prefix is detected, String rules are used. + * + * @author Toni Kalajainen + * @Author Marko Luukkainen + */ +public class MetricsFormat implements Serializable { + + /** + * Define serial version of this class + */ + private static final long serialVersionUID = 8036591251300342995L; + + + /** Presentation format */ + private String pattern; + + /** Presentation format */ + private String internalPattern; + + /** Presentation format */ + private String[] internalPatternDivided; + + /** flag if format can adjust decimals */ + private boolean canUseDecimals = false; + + /** scale */ + private double scale; + + /** name */ + private String name; + + /** hash */ + private int hash; + + /** Is double or long */ + private boolean isDouble = true; + + private boolean useDecimalFormat = false; + + /** Array reserved for formatter use */ + private Object args[] = new Object[1]; + + + public String getName() { + return name; + } + + public MetricsFormat(String pattern, double scale, String name) + throws IllegalArgumentException + { + this.scale = scale; + pattern = setPattern(pattern); + this.internalPattern = formatPattern( pattern ); + this.internalPatternDivided = formatPatternDivided( pattern ); + this.name = name; + this.hash = makeHash(); + } + + public MetricsFormat(String pattern, double scale) + throws IllegalArgumentException + { + this.scale = scale; + pattern = setPattern(pattern); + this.internalPattern = formatPattern( pattern ); + this.internalPatternDivided = formatPatternDivided( pattern ); + this.name = ""; + this.hash = makeHash(); + } + + public MetricsFormat(String pattern) + throws IllegalArgumentException + { + this.scale = 1.0f; + pattern = setPattern(pattern); + this.internalPattern = formatPattern( pattern ); + this.internalPatternDivided = formatPatternDivided( pattern ); + this.name = ""; + this.hash = makeHash(); + + } + + private String setPattern(String pattern) { + this.pattern = pattern; + if (pattern.startsWith("D")) { + pattern = pattern.substring(1); + useDecimalFormat = true; + } else { + if (pattern.startsWith("S")) + pattern = pattern.substring(1); + useDecimalFormat = false; + } + return pattern; + } + + /** + * Replacs all % with %1$ unless % precedes with \ + * + * @param pattern + * @return + */ + private String formatPattern(String pattern) { + int pos = 0; + if (!useDecimalFormat) { + while ( (pos = pattern.indexOf('%', pos)) >= 0 ) { + if (pos==0 || pattern.indexOf(pos-1)!='\\') { + pattern = pattern.substring(0, pos+1) + "1$" + pattern.substring(pos+1, pattern.length()); + pos += 3; + continue; + } + pos++; + } + } + + double value = 0; + if (useDecimalFormat) { + isDouble = true; + useDecimalFormat = true; + canUseDecimals = false; + DecimalFormat format = new DecimalFormat(pattern); + format.format(value); + + } else { + try { + isDouble = true; + useDecimalFormat = false; + args[0] = value; + String.format(pattern, args); + } catch(IllegalFormatConversionException e1) { + try { + isDouble = false; + useDecimalFormat = false; + args[0] = (long)value; + String.format(pattern, args); + } catch (Exception e2) { + throw e1; + } + } + } + + return pattern; + } + + /** + * Replacs all % with %1$ unless % precedes with \ + * + * Divides formatString into half so that + * formats precision can be adjusted with .(n)
+ * Currently only format which supports adjustable + * decimals is f/F (floating point as decimal number) + * + * + * @param pattern + * @return + */ + private String[] formatPatternDivided(String pattern) { + String divPattern[] = new String[]{"",""}; + if (useDecimalFormat) + return divPattern; + int pos = 0; + while ( (pos = pattern.indexOf('%', pos)) >= 0 ) { + if (pos==0 || pattern.indexOf(pos-1)!='\\') { + divPattern[0] = pattern.substring(0, pos+1) + "1$"; + divPattern[1] = pattern.substring(pos+1, pattern.length()); + // parse flags + int pos2 = 0; + while(true) { + char c = divPattern[1].charAt(pos2); + if (c == '-' || + c == '#' || + c == '+' || + c == ' ' || + c == '0' || + c == ',' || + c == '(' || + Character.isDigit(c)) + pos2++; + else + break; + } + // get rid of possible precisision setting + // TODO : maybe we should let the user to set the precision + // and then use user given precision instead of dynamic precision + int pos3 = pos2; + while(true) { + char c = divPattern[1].charAt(pos3); + if (c == '.' || Character.isDigit(c)) { + pos3++; + } else if (c == 'f'|| c == 'F') { + this.canUseDecimals = true; + break; + } else { + this.canUseDecimals = false; + break; + } + } + if (pos2 > 0 || pos3 > 0) { + divPattern[0] += divPattern[1].substring(0,pos2); + divPattern[1] = divPattern[1].substring(pos3, divPattern[1].length()); + } + pos += 3; + // divided patterns can have only one % + break; + } + pos++; + } + + double value = 0; + try { + // checking if format can be used + args[0] = value; + String.format(divPattern[0] + ".2" + divPattern[1] , args); + } catch (IllegalFormatException e1) { + try { + pattern = formatPattern(pattern); + isDouble = false; + args[0] = (long)value; + String.format(pattern, args); + // if we get this far by not using decimals something strange has happened... + divPattern[0] = null; + divPattern[1] = null; + canUseDecimals = false; + } catch(Exception e2) { + throw e1; + } + } + + return divPattern; + } + + /** + * Formats value + * @param value + * @return + */ + public String formatValue(double value) { + return _formatValue(internalPattern, value); + } + + /** + * Format value + * Note: cannot DecimalFormatter syntax does not work with this method + * @param value + * @param numDecimals + * @return + */ + public String formatValue(double value, int numDecimals) { + if (canUseDecimals) { + if (numDecimals < 0) + numDecimals = 0; + return _formatValue(value, numDecimals); + } else { + return _formatValue(internalPattern, value); + } + + } + + + private String _formatValue(String pattern, double value) { + //value *= scale; + if (!useDecimalFormat) { + if (isDouble) { + args[0] = value; + return String.format(pattern, args); + } else { + args[0] = new Long((long)value); + return String.format(pattern, args); + } + } else { + DecimalFormat format = new DecimalFormat(pattern); + return format.format(value); + } + } + + private String _formatValue(double value, int decimals) { + //value *= scale; + args[0] = value; + return String.format(internalPatternDivided[0] + "." + decimals + internalPatternDivided[1], args); + + } + + public String getPattern() { + return pattern; + } + + public double getScale() { + return scale; + } + + public String toString() { + return name; + } + + + + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (!(obj instanceof MetricsFormat)) return false; + MetricsFormat other = (MetricsFormat) obj; + if (other.hash!=hash) return false; + return other.pattern.equals(pattern) && other.scale==scale && other.name.equals(name); + } + + private int makeHash() { + long longBits = Double.doubleToLongBits(scale); + int scaleHash = ((int)longBits)^(int)(longBits<<16); + return pattern.hashCode() ^ scaleHash ^ name.hashCode(); + } + + public int hashCode() { + return hash; + } + + /* + private void changeContent(MetricsFormat newContent) { + this.name = newContent.name; + this.pattern = newContent.pattern; + this.scale = newContent.scale; + this.internalPattern = newContent.internalPattern; + this.hash = newContent.hash; + }*/ + + + +}