1 package org.djunits.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.djunits.locale.Localization;
10 import org.djunits.unit.scale.Scale;
11 import org.djunits.unit.scale.StandardScale;
12 import org.djunits.unit.unitsystem.UnitSystem;
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 public abstract class Unit<U extends Unit<U>> implements Serializable
28 {
29
30 private static final long serialVersionUID = 20140607;
31
32
33 private final String nameKey;
34
35
36 private final String abbreviationKey;
37
38
39
40
41
42 private final String name;
43
44
45
46
47
48 private final String abbreviation;
49
50
51 private final UnitSystem unitSystem;
52
53
54 @SuppressWarnings("checkstyle:visibilitymodifier")
55 protected Scale scale;
56
57
58 private SICoefficients siCoefficients;
59
60
61 private static final Map<String, SICoefficients> SI_COEFFICIENTS = new HashMap<String, SICoefficients>();
62
63
64 private static final Map<String, Map<Class<Unit<?>>, Unit<?>>> SI_UNITS =
65 new HashMap<String, Map<Class<Unit<?>>, Unit<?>>>();
66
67
68 private static final Map<String, Set<Unit<?>>> UNITS = new HashMap<String, Set<Unit<?>>>();
69
70
71 private static Localization localization = new Localization("localeunit");
72
73
74 private static boolean initialized = false;
75
76
77 private boolean baseSIUnit;
78
79
80 public static final String[] STANDARD_UNITS = new String[] { "AbsoluteTemperatureUnit", "AccelerationUnit",
81 "AngleSolidUnit", "AngleUnit", "AreaUnit", "DensityUnit", "DimensionlessUnit", "DirectionUnit", "DurationUnit",
82 "ElectricalChargeUnit", "ElectricalCurrentUnit", "ElectricalPotentialUnit", "ElectricalResistanceUnit",
83 "EnergyUnit", "FlowMassUnit", "FlowVolumeUnit", "ForceUnit", "FrequencyUnit", "LengthUnit", "LinearDensityUnit",
84 "MassUnit", "MoneyUnit", "MoneyPerAreaUnit", "MoneyPerEnergyUnit", "MoneyPerLengthUnit", "MoneyPerMassUnit",
85 "MoneyPerDurationUnit", "MoneyPerVolumeUnit", "PositionUnit", "PowerUnit", "PressureUnit", "SpeedUnit",
86 "TemperatureUnit", "TimeUnit", "TorqueUnit", "VolumeUnit" };
87
88
89 private final int cachedHashCode;
90
91
92 private static void initialize()
93 {
94 for (String className : STANDARD_UNITS)
95 {
96 try
97 {
98 Class.forName("org.djunits.unit." + className);
99 }
100 catch (Exception exception)
101 {
102
103 System.err.println("Could not load class org.djunits.unit." + className);
104 }
105 }
106 initialized = true;
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120 protected Unit(final String nameOrNameKey, final String abbreviationOrAbbreviationKey, final UnitSystem unitSystem,
121 final boolean standardUnit)
122 {
123 this.scale = StandardScale.SCALE;
124 this.baseSIUnit = true;
125 if (standardUnit)
126 {
127 this.nameKey = nameOrNameKey;
128 this.abbreviationKey = abbreviationOrAbbreviationKey;
129 this.name = null;
130 this.abbreviation = null;
131 }
132 else
133 {
134 this.nameKey = null;
135 this.abbreviationKey = null;
136 this.name = nameOrNameKey;
137 this.abbreviation = abbreviationOrAbbreviationKey;
138 }
139 this.unitSystem = unitSystem;
140 this.cachedHashCode = generateHashCode();
141 try
142 {
143 addUnit(this);
144 }
145 catch (UnitException ue)
146 {
147 if (!standardUnit)
148 {
149 throw new RuntimeException(ue);
150 }
151 }
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165
166 protected Unit(final String nameOrNameKey, final String abbreviationOrAbbreviationKey, final UnitSystem unitSystem,
167 final Scale scale, final boolean standardUnit)
168 {
169 this(nameOrNameKey, abbreviationOrAbbreviationKey, unitSystem, standardUnit);
170 this.scale = scale;
171 this.baseSIUnit = scale.isBaseSIScale();
172 }
173
174
175
176
177
178 public final boolean isLocalizable()
179 {
180 return this.nameKey != null;
181 }
182
183
184
185
186
187
188 private void addUnit(final Unit<U> unit) throws UnitException
189 {
190 if (!UNITS.containsKey(unit.getClass().getSimpleName()))
191 {
192 UNITS.put(unit.getClass().getSimpleName(), new HashSet<Unit<?>>());
193 }
194 UNITS.get(unit.getClass().getSimpleName()).add(unit);
195
196
197 String siCoefficientsString = SICoefficients.normalize(getSICoefficientsString()).toString();
198 if (SI_COEFFICIENTS.containsKey(siCoefficientsString))
199 {
200 this.siCoefficients = SI_COEFFICIENTS.get(siCoefficientsString);
201 }
202 else
203 {
204 this.siCoefficients = new SICoefficients(SICoefficients.parse(siCoefficientsString));
205 SI_COEFFICIENTS.put(siCoefficientsString, this.siCoefficients);
206 }
207
208
209 Map<Class<Unit<?>>, Unit<?>> unitMap = SI_UNITS.get(siCoefficientsString);
210 if (unitMap == null)
211 {
212 unitMap = new HashMap<Class<Unit<?>>, Unit<?>>();
213 SI_UNITS.put(siCoefficientsString, unitMap);
214 }
215 if (!unitMap.containsKey(unit.getClass()))
216 {
217 @SuppressWarnings("unchecked")
218 Class<Unit<?>> clazz = (Class<Unit<?>>) unit.getClass();
219 if (this.getStandardUnit() == null)
220 {
221 unitMap.put(clazz, this);
222 }
223 else
224 {
225 unitMap.put(clazz, this.getStandardUnit());
226 }
227 }
228 }
229
230
231
232
233
234
235
236
237 @SuppressWarnings("unchecked")
238 public static <V extends Unit<V>> Set<V> getUnits(final Class<V> unitClass)
239 {
240 if (!initialized)
241 {
242 initialize();
243 }
244 Set<V> returnSet = new HashSet<V>();
245 if (UNITS.containsKey(unitClass.getSimpleName()))
246 {
247 for (Unit<?> unit : UNITS.get(unitClass.getSimpleName()))
248 {
249 returnSet.add((V) unit);
250 }
251 }
252 return returnSet;
253 }
254
255
256
257
258
259
260
261 @SuppressWarnings("unchecked")
262 public final Set<Unit<U>> getAllUnitsOfThisType()
263 {
264 if (!initialized)
265 {
266 initialize();
267 }
268 Set<Unit<U>> returnSet = new HashSet<Unit<U>>();
269 if (UNITS.containsKey(this.getClass().getSimpleName()))
270 {
271 for (Unit<?> unit : UNITS.get(this.getClass().getSimpleName()))
272 {
273 returnSet.add((Unit<U>) unit);
274 }
275 }
276 return returnSet;
277 }
278
279
280
281
282 public final String getName()
283 {
284 if (this.name != null)
285 {
286 return this.name;
287 }
288 return localization.getString(this.nameKey);
289 }
290
291
292
293
294
295 public final String getNameKey()
296 {
297 return this.nameKey;
298 }
299
300
301
302
303 public final String getAbbreviation()
304 {
305 if (this.abbreviation != null)
306 {
307 return this.abbreviation;
308 }
309 return localization.getString(this.abbreviationKey);
310 }
311
312
313
314
315
316 public final String getAbbreviationKey()
317 {
318 return this.abbreviationKey;
319 }
320
321
322
323
324 @SuppressWarnings("checkstyle:designforextension")
325 public Scale getScale()
326 {
327 return this.scale;
328 }
329
330
331
332
333 public final UnitSystem getUnitSystem()
334 {
335 return this.unitSystem;
336 }
337
338
339
340
341 public abstract U getStandardUnit();
342
343
344
345
346
347 public abstract String getSICoefficientsString();
348
349
350
351
352 public final SICoefficients getSICoefficients()
353 {
354 return this.siCoefficients;
355 }
356
357
358
359
360
361 public final boolean isBaseSIUnit()
362 {
363 return this.baseSIUnit;
364 }
365
366
367
368
369
370 public static Set<Unit<?>> lookupUnitWithSICoefficients(final String normalizedSICoefficientsString)
371 {
372 if (!initialized)
373 {
374 initialize();
375 }
376 if (SI_UNITS.containsKey(normalizedSICoefficientsString))
377 {
378 return new HashSet<Unit<?>>(SI_UNITS.get(normalizedSICoefficientsString).values());
379 }
380 return new HashSet<Unit<?>>();
381 }
382
383
384
385
386
387
388 public static Set<Unit<?>> lookupOrCreateUnitWithSICoefficients(final String normalizedSICoefficientsString)
389 {
390 if (!initialized)
391 {
392 initialize();
393 }
394 if (SI_UNITS.containsKey(normalizedSICoefficientsString))
395 {
396 return new HashSet<Unit<?>>(SI_UNITS.get(normalizedSICoefficientsString).values());
397 }
398 SIUnit unit = new SIUnit("SIUnit." + normalizedSICoefficientsString);
399 Set<Unit<?>> unitSet = new HashSet<Unit<?>>();
400 unitSet.add(unit);
401 return unitSet;
402 }
403
404
405
406
407
408 public static SIUnit lookupOrCreateSIUnitWithSICoefficients(final String normalizedSICoefficientsString)
409 {
410 if (!initialized)
411 {
412 initialize();
413 }
414 if (SI_UNITS.containsKey(normalizedSICoefficientsString)
415 && SI_UNITS.get(normalizedSICoefficientsString).containsKey(SIUnit.class))
416 {
417 return (SIUnit) SI_UNITS.get(normalizedSICoefficientsString).get(SIUnit.class);
418 }
419 SIUnit unit = new SIUnit("SIUnit." + normalizedSICoefficientsString, false);
420 return unit;
421 }
422
423
424 @Override
425 public final String toString()
426 {
427 return getAbbreviation();
428 }
429
430
431
432
433
434 public final int generateHashCode()
435 {
436 final int prime = 31;
437 int result = 1;
438 result = prime * result + ((this.abbreviation == null) ? 0 : this.abbreviation.hashCode());
439 result = prime * result + ((this.abbreviationKey == null) ? 0 : this.abbreviationKey.hashCode());
440 result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
441 result = prime * result + ((this.nameKey == null) ? 0 : this.nameKey.hashCode());
442 return result;
443 }
444
445
446 @SuppressWarnings("checkstyle:designforextension")
447 @Override
448 public int hashCode()
449 {
450 return this.cachedHashCode;
451 }
452
453
454 @SuppressWarnings({ "checkstyle:designforextension", "checkstyle:needbraces" })
455 @Override
456 public boolean equals(final Object obj)
457 {
458 if (this == obj)
459 return true;
460 if (obj == null)
461 return false;
462 if (getClass() != obj.getClass())
463 return false;
464 Unit<?> other = (Unit<?>) obj;
465 if (this.abbreviation == null)
466 {
467 if (other.abbreviation != null)
468 return false;
469 }
470 else if (!this.abbreviation.equals(other.abbreviation))
471 return false;
472 if (this.abbreviationKey == null)
473 {
474 if (other.abbreviationKey != null)
475 return false;
476 }
477 else if (!this.abbreviationKey.equals(other.abbreviationKey))
478 return false;
479 if (this.name == null)
480 {
481 if (other.name != null)
482 return false;
483 }
484 else if (!this.name.equals(other.name))
485 return false;
486 if (this.nameKey == null)
487 {
488 if (other.nameKey != null)
489 return false;
490 }
491 else if (!this.nameKey.equals(other.nameKey))
492 return false;
493 return true;
494 }
495
496 }