1 package org.opentrafficsim.core.unit;
2
3 import java.io.Serializable;
4 import java.util.HashMap;
5 import java.util.HashSet;
6 import java.util.Map;
7 import java.util.Set;
8
9 import org.opentrafficsim.core.locale.Localization;
10 import org.opentrafficsim.core.unit.unitsystem.UnitSystem;
11 import org.reflections.Reflections;
12
13
14
15
16
17
18
19
20
21
22
23
24
25 public abstract class Unit<U extends Unit<U>> implements Serializable
26 {
27
28 private static final long serialVersionUID = 20140607;
29
30
31 private final String nameKey;
32
33
34 private final String abbreviationKey;
35
36
37 private final UnitSystem unitSystem;
38
39
40 private final double conversionFactorToStandardUnit;
41
42
43 private SICoefficients siCoefficients;
44
45
46 private static final Map<String, SICoefficients> SI_COEFFICIENTS = new HashMap<String, SICoefficients>();
47
48
49 private static final Map<String, Map<Class<Unit<?>>, Unit<?>>> SI_UNITS =
50 new HashMap<String, Map<Class<Unit<?>>, Unit<?>>>();
51
52
53 private static final Map<String, Set<Unit<?>>> UNITS = new HashMap<String, Set<Unit<?>>>();
54
55
56 private static Localization localization = new Localization("localeunit");
57
58
59 private static boolean initialized = false;
60
61
62 private static void initialize()
63 {
64 Reflections reflections = new Reflections("org.opentrafficsim.core.unit");
65 @SuppressWarnings("rawtypes")
66 Set<Class<? extends Unit>> classes = reflections.getSubTypesOf(Unit.class);
67
68 for (@SuppressWarnings("rawtypes")
69 Class<? extends Unit> clazz : classes)
70 {
71 try
72 {
73 Class.forName(clazz.getCanonicalName());
74 }
75 catch (Exception exception)
76 {
77
78
79 System.err.println("Could not load class " + clazz.getCanonicalName());
80 }
81 }
82 initialized = true;
83 }
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141 public Unit(final String nameKey, final String abbreviationKey, final UnitSystem unitSystem, final boolean safe)
142 {
143 this.conversionFactorToStandardUnit = 1.0;
144 this.nameKey = nameKey;
145 this.abbreviationKey = abbreviationKey;
146 this.unitSystem = unitSystem;
147 try
148 {
149 addUnit(this);
150 }
151 catch (UnitException ue)
152 {
153 if (!safe)
154 {
155 throw new Error(ue);
156 }
157
158 }
159 }
160
161
162
163
164
165
166
167
168
169
170 public Unit(final String nameKey, final String abbreviationKey, final UnitSystem unitSystem, final U referenceUnit,
171 final double conversionFactorToReferenceUnit, final boolean safe)
172 {
173
174
175 if (referenceUnit == null)
176 {
177 this.conversionFactorToStandardUnit = 1.0;
178 }
179 else
180 {
181 this.conversionFactorToStandardUnit =
182 referenceUnit.getConversionFactorToStandardUnit() * conversionFactorToReferenceUnit;
183 }
184 this.nameKey = nameKey;
185 this.abbreviationKey = abbreviationKey;
186 this.unitSystem = unitSystem;
187 try
188 {
189 addUnit(this);
190 }
191 catch (UnitException ue)
192 {
193 if (!safe)
194 {
195 throw new Error(ue);
196 }
197
198 }
199 }
200
201
202
203
204
205
206 private void addUnit(final Unit<U> unit) throws UnitException
207 {
208 if (!UNITS.containsKey(unit.getClass().getSimpleName()))
209 {
210 UNITS.put(unit.getClass().getSimpleName(), new HashSet<Unit<?>>());
211 }
212 UNITS.get(unit.getClass().getSimpleName()).add(unit);
213
214
215 String siCoefficientsString = SICoefficients.normalize(getSICoefficientsString()).toString();
216 if (SI_COEFFICIENTS.containsKey(siCoefficientsString))
217 {
218 this.siCoefficients = SI_COEFFICIENTS.get(siCoefficientsString);
219 }
220 else
221 {
222 this.siCoefficients = new SICoefficients(SICoefficients.parse(siCoefficientsString));
223 SI_COEFFICIENTS.put(siCoefficientsString, this.siCoefficients);
224 }
225
226
227 Map<Class<Unit<?>>, Unit<?>> unitMap = SI_UNITS.get(siCoefficientsString);
228 if (unitMap == null)
229 {
230 unitMap = new HashMap<Class<Unit<?>>, Unit<?>>();
231 SI_UNITS.put(siCoefficientsString, unitMap);
232 }
233 if (!unitMap.containsKey(unit.getClass()))
234 {
235 @SuppressWarnings("unchecked")
236 Class<Unit<?>> clazz = (Class<Unit<?>>) unit.getClass();
237 if (this.getStandardUnit() == null)
238 {
239 unitMap.put(clazz, this);
240 }
241 else
242 {
243 unitMap.put(clazz, this.getStandardUnit());
244 }
245 }
246 }
247
248
249
250
251
252
253
254
255 @SuppressWarnings("unchecked")
256 public static <V extends Unit<V>> Set<V> getUnits(final Class<V> unitClass)
257 {
258 if (!initialized)
259 {
260 initialize();
261 }
262 Set<V> returnSet = new HashSet<V>();
263 if (UNITS.containsKey(unitClass.getSimpleName()))
264 {
265 for (Unit<?> unit : UNITS.get(unitClass.getSimpleName()))
266 {
267 returnSet.add((V) unit);
268 }
269 }
270 return returnSet;
271 }
272
273
274
275
276
277
278
279 @SuppressWarnings("unchecked")
280 public final Set<Unit<U>> getAllUnitsOfThisType()
281 {
282 if (!initialized)
283 {
284 initialize();
285 }
286 Set<Unit<U>> returnSet = new HashSet<Unit<U>>();
287 if (UNITS.containsKey(this.getClass().getSimpleName()))
288 {
289 for (Unit<?> unit : UNITS.get(this.getClass().getSimpleName()))
290 {
291 returnSet.add((Unit<U>) unit);
292 }
293 }
294 return returnSet;
295 }
296
297
298
299
300 public final String getName()
301 {
302 return localization.getString(this.nameKey);
303 }
304
305
306
307
308 public final String getNameKey()
309 {
310 return this.nameKey;
311 }
312
313
314
315
316 public final String getAbbreviation()
317 {
318 return localization.getString(this.abbreviationKey);
319 }
320
321
322
323
324 public final String getAbbreviationKey()
325 {
326 return this.abbreviationKey;
327 }
328
329
330
331
332 public final double getConversionFactorToStandardUnit()
333 {
334 return this.conversionFactorToStandardUnit;
335 }
336
337
338
339
340 public final UnitSystem getUnitSystem()
341 {
342 return this.unitSystem;
343 }
344
345
346
347
348 public abstract U getStandardUnit();
349
350
351
352
353
354 public abstract String getSICoefficientsString();
355
356
357
358
359 public final SICoefficients getSICoefficients()
360 {
361 return this.siCoefficients;
362 }
363
364
365
366
367
368 public static Set<Unit<?>> lookupUnitWithSICoefficients(final String normalizedSICoefficientsString)
369 {
370 if (!initialized)
371 {
372 initialize();
373 }
374 if (SI_UNITS.containsKey(normalizedSICoefficientsString))
375 {
376 return new HashSet<Unit<?>>(SI_UNITS.get(normalizedSICoefficientsString).values());
377 }
378 return new HashSet<Unit<?>>();
379 }
380
381
382
383
384
385
386 public static Set<Unit<?>> lookupOrCreateUnitWithSICoefficients(final String normalizedSICoefficientsString)
387 {
388 if (!initialized)
389 {
390 initialize();
391 }
392 if (SI_UNITS.containsKey(normalizedSICoefficientsString))
393 {
394 return new HashSet<Unit<?>>(SI_UNITS.get(normalizedSICoefficientsString).values());
395 }
396 SIUnit unit = new SIUnit("SIUnit." + normalizedSICoefficientsString);
397 Set<Unit<?>> unitSet = new HashSet<Unit<?>>();
398 unitSet.add(unit);
399 return unitSet;
400 }
401
402
403
404
405
406 public static SIUnit lookupOrCreateSIUnitWithSICoefficients(final String normalizedSICoefficientsString)
407 {
408 if (!initialized)
409 {
410 initialize();
411 }
412 if (SI_UNITS.containsKey(normalizedSICoefficientsString)
413 && SI_UNITS.get(normalizedSICoefficientsString).containsKey(SIUnit.class))
414 {
415 return (SIUnit) SI_UNITS.get(normalizedSICoefficientsString).get(SIUnit.class);
416 }
417 SIUnit unit = new SIUnit("SIUnit." + normalizedSICoefficientsString);
418 return unit;
419 }
420
421
422 @Override
423 public final String toString()
424 {
425 return getAbbreviation();
426 }
427
428 }