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