--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2010 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.databoard.units.internal.library;
+
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+import gnu.trove.procedure.TObjectIntProcedure;\r
+import gnu.trove.procedure.TObjectObjectProcedure;\r
+\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.InputStreamReader;\r
+import java.io.Reader;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.simantics.databoard.Units;\r
+import org.simantics.databoard.file.RuntimeIOException;\r
+import org.simantics.databoard.units.internal.UnitParseException;\r
+import org.simantics.databoard.units.internal.parser.UnitParser;\r
+
+public class UnitLibrary {
+
+ final THashMap<String, UnitConversion> conversions =
+ new THashMap<String, UnitConversion>();
+\r
+ public Set<String> getUnits() {\r
+ return conversions.keySet();\r
+ }\r
+
+ public UnitConversion getConversion(String unit) {
+ return conversions.get(unit);
+ }
+
+ private static final String[] PREFIXES = new String[] {
+ "y", "z", "a", "f", "p", "n", "ยต", "m", "c", "d", "da", "h", "k", "M", "G", "T", "P", "E", "Z", "Y"
+ };
+
+ private static final int[] PREFIX_MAGNITUDES = new int[] {
+ -24, -21, -18, -15, -12, -9, -6, -3, -2, -1, 1, 2, 3, 6, 9, 12, 15, 18, 21, 24
+ };
+
+
+ public static List<String> readTokens(InputStream stream) throws IOException {
+ Reader reader = new InputStreamReader(stream);
+ StringBuilder b = new StringBuilder();
+ ArrayList<String> strings = new ArrayList<String>();
+ while(true) {
+ int c = reader.read();
+ if(c == -1) {
+ if(b.length() > 0)
+ strings.add(b.toString());
+ break;
+ }
+ if(c == ' ' || c == '\t' || c == '\n' || c == '\r') {
+ if(b.length() > 0) {
+ strings.add(b.toString());
+ b.setLength(0);
+ }
+ }
+ else
+ b.append((char)c);
+ }
+ reader.close();
+ return strings;
+ }
+
+ private UnitConversion parseUnit(String unit) throws UnitParseException {
+ final TObjectIntHashMap<String> exponents = new TObjectIntHashMap<String>(4);
+ final double[] scale = new double[] { 1.0 };
+ final int[] magnitude = new int[] { 0 };
+ new UnitParser() {
+ public void visit(String baseUnit, int exponent) {
+ UnitConversion conversion = conversions.get(baseUnit);
+ if(conversion == null) {
+ if(exponents.adjustOrPutValue(baseUnit, exponent, exponent) == 0)
+ exponents.remove(baseUnit);
+ }
+ else {
+ scale[0] *= Math.pow(conversion.scale, exponent);
+ magnitude[0] += conversion.magnitude * exponent;
+ for(int i=0;i<conversion.baseUnits.length;++i) {
+ String u = conversion.baseUnits[i];
+ int exp = conversion.exponents[i];
+ if(exponents.adjustOrPutValue(u, exp, exp) == 0)
+ exponents.remove(u);
+ }
+ }
+ }
+ }.unit(unit, 1);
+ final String[] unitArray = new String[exponents.size()];
+ final int[] exponentArray = new int[exponents.size()];
+ exponents.forEachEntry(new TObjectIntProcedure<String>() {
+ int i = 0;
+
+ @Override
+ public boolean execute(String arg0, int arg1) {
+ unitArray[i] = arg0;
+ exponentArray[i] = arg1;
+ ++i;
+ return true;
+ }
+ });
+ return new UnitConversion(
+ scale[0],
+ magnitude[0],
+ unitArray,
+ exponentArray
+ );
+ }
+
+ public static UnitLibrary createDefault() {
+ UnitLibrary result = new UnitLibrary();
+
+ try {
+ for(String unit : readTokens( Units.class.getResourceAsStream("baseUnits.txt") ))
+ for(int i=0;i<PREFIXES.length;++i)
+ result.conversions.put(PREFIXES[i] + unit,
+ new UnitConversion(1.0, PREFIX_MAGNITUDES[i], unit));
+
+ {
+ List<String> units = readTokens( Units.class.getResourceAsStream("scalableDerivedUnits.txt") );
+ for(int i=0;i<units.size();i+=3) {
+ UnitConversion conversion = result.parseUnit(units.get(i+2));
+ conversion.scale *= Double.parseDouble(units.get(i+1));
+ String unit = units.get(i);
+ result.conversions.put(unit, conversion);
+
+ for(int j=0;j<PREFIXES.length;++j) {
+ UnitConversion scaledConversion =
+ new UnitConversion(conversion.scale,
+ conversion.magnitude + PREFIX_MAGNITUDES[j],
+ conversion.baseUnits, conversion.exponents);
+ result.conversions.put(PREFIXES[j] + unit, scaledConversion);
+ }
+ }
+ }
+
+ {
+ List<String> units = readTokens( Units.class.getResourceAsStream("nonscalableDerivedUnits.txt") );
+ for(int i=0;i<units.size();i+=3) {
+ UnitConversion conversion = result.parseUnit(units.get(i+2));
+ conversion.scale *= Double.parseDouble(units.get(i+1));
+ result.conversions.put(units.get(i), conversion);
+ }
+ }
+ return result;
+
+ } catch (UnitParseException e) {
+ throw new RuntimeException( e );
+ } catch (IOException e) {
+ throw new RuntimeIOException( e );
+ }
+
+ }
+
+ public static void main(String[] args) {
+ UnitLibrary lib = UnitLibrary.createDefault();
+ lib.conversions.forEachEntry(new TObjectObjectProcedure<String, UnitConversion>() {
+
+ @Override
+ public boolean execute(String unit, UnitConversion conversion) {
+ System.out.println(unit + " = " + conversion.scale +
+ " * 10^" + conversion.magnitude + ", base=" + Arrays.toString(conversion.baseUnits));
+ return true;
+ }
+
+ });
+ }
+
+}