1 /*******************************************************************************
2 * Copyright (c) 2010 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.databoard.units.internal.library;
14 import gnu.trove.map.hash.THashMap;
15 import gnu.trove.map.hash.TObjectIntHashMap;
16 import gnu.trove.procedure.TObjectIntProcedure;
17 import gnu.trove.procedure.TObjectObjectProcedure;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.InputStreamReader;
22 import java.io.Reader;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.List;
28 import org.simantics.databoard.Units;
29 import org.simantics.databoard.file.RuntimeIOException;
30 import org.simantics.databoard.units.internal.UnitParseException;
31 import org.simantics.databoard.units.internal.parser.UnitParser;
33 public class UnitLibrary {
35 final THashMap<String, UnitConversion> conversions =
36 new THashMap<String, UnitConversion>();
38 public Set<String> getUnits() {
39 return conversions.keySet();
42 public UnitConversion getConversion(String unit) {
43 return conversions.get(unit);
46 private static final String[] PREFIXES = new String[] {
47 "y", "z", "a", "f", "p", "n", "ยต", "m", "c", "d", "da", "h", "k", "M", "G", "T", "P", "E", "Z", "Y"
50 private static final int[] PREFIX_MAGNITUDES = new int[] {
51 -24, -21, -18, -15, -12, -9, -6, -3, -2, -1, 1, 2, 3, 6, 9, 12, 15, 18, 21, 24
55 public static List<String> readTokens(InputStream stream) throws IOException {
56 Reader reader = new InputStreamReader(stream);
57 StringBuilder b = new StringBuilder();
58 ArrayList<String> strings = new ArrayList<String>();
60 int c = reader.read();
63 strings.add(b.toString());
66 if(c == ' ' || c == '\t' || c == '\n' || c == '\r') {
68 strings.add(b.toString());
79 private UnitConversion parseUnit(String unit) throws UnitParseException {
80 final TObjectIntHashMap<String> exponents = new TObjectIntHashMap<String>(4);
81 final double[] scale = new double[] { 1.0 };
82 final int[] magnitude = new int[] { 0 };
84 public void visit(String baseUnit, int exponent) {
85 UnitConversion conversion = conversions.get(baseUnit);
86 if(conversion == null) {
87 if(exponents.adjustOrPutValue(baseUnit, exponent, exponent) == 0)
88 exponents.remove(baseUnit);
91 scale[0] *= Math.pow(conversion.scale, exponent);
92 magnitude[0] += conversion.magnitude * exponent;
93 for(int i=0;i<conversion.baseUnits.length;++i) {
94 String u = conversion.baseUnits[i];
95 int exp = conversion.exponents[i];
96 if(exponents.adjustOrPutValue(u, exp, exp) == 0)
102 final String[] unitArray = new String[exponents.size()];
103 final int[] exponentArray = new int[exponents.size()];
104 exponents.forEachEntry(new TObjectIntProcedure<String>() {
108 public boolean execute(String arg0, int arg1) {
110 exponentArray[i] = arg1;
115 return new UnitConversion(
123 public static UnitLibrary createDefault() {
124 UnitLibrary result = new UnitLibrary();
127 for(String unit : readTokens( Units.class.getResourceAsStream("baseUnits.txt") ))
128 for(int i=0;i<PREFIXES.length;++i)
129 result.conversions.put(PREFIXES[i] + unit,
130 new UnitConversion(1.0, PREFIX_MAGNITUDES[i], unit));
133 List<String> units = readTokens( Units.class.getResourceAsStream("scalableDerivedUnits.txt") );
134 for(int i=0;i<units.size();i+=3) {
135 UnitConversion conversion = result.parseUnit(units.get(i+2));
136 conversion.scale *= Double.parseDouble(units.get(i+1));
137 String unit = units.get(i);
138 result.conversions.put(unit, conversion);
140 for(int j=0;j<PREFIXES.length;++j) {
141 UnitConversion scaledConversion =
142 new UnitConversion(conversion.scale,
143 conversion.magnitude + PREFIX_MAGNITUDES[j],
144 conversion.baseUnits, conversion.exponents);
145 result.conversions.put(PREFIXES[j] + unit, scaledConversion);
151 List<String> units = readTokens( Units.class.getResourceAsStream("nonscalableDerivedUnits.txt") );
152 for(int i=0;i<units.size();i+=3) {
153 UnitConversion conversion = result.parseUnit(units.get(i+2));
154 conversion.scale *= Double.parseDouble(units.get(i+1));
155 result.conversions.put(units.get(i), conversion);
160 } catch (UnitParseException e) {
161 throw new RuntimeException( e );
162 } catch (IOException e) {
163 throw new RuntimeIOException( e );
168 public static void main(String[] args) {
169 UnitLibrary lib = UnitLibrary.createDefault();
170 lib.conversions.forEachEntry(new TObjectObjectProcedure<String, UnitConversion>() {
173 public boolean execute(String unit, UnitConversion conversion) {
174 System.out.println(unit + " = " + conversion.scale +
175 " * 10^" + conversion.magnitude + ", base=" + Arrays.toString(conversion.baseUnits));