1 package org.djunits.unit.quantity;
2
3 import java.io.Serializable;
4 import java.util.LinkedHashMap;
5 import java.util.Map;
6
7 import org.djunits.Throw;
8 import org.djunits.unit.Unit;
9 import org.djunits.unit.si.SIDimensions;
10 import org.djunits.unit.si.SIPrefix;
11 import org.djunits.unit.si.SIPrefixes;
12 import org.djunits.unit.util.UnitException;
13 import org.djunits.unit.util.UnitRuntimeException;
14
15
16
17
18
19
20
21
22
23
24
25 public class Quantity<U extends Unit<U>> implements Serializable
26 {
27
28 private static final long serialVersionUID = 20190818L;
29
30
31
32
33
34 private final SIDimensions siDimensions;
35
36
37 private final String name;
38
39
40 private final Map<String, U> unitsById = new LinkedHashMap<String, U>();
41
42
43 private final Map<String, U> unitsByAbbreviation = new LinkedHashMap<String, U>();
44
45
46 private U standardUnit = null;
47
48
49
50
51
52
53
54 public Quantity(final String name, final SIDimensions siDimensions)
55 {
56 Throw.whenNull(name, "name cannot be null");
57 Throw.when(name.length() == 0, UnitRuntimeException.class, "name of unit cannot be empty");
58 Throw.whenNull(siDimensions, "siDimensions cannot be null");
59 this.name = name;
60 this.siDimensions = siDimensions;
61 }
62
63
64
65
66
67
68
69
70 public Quantity(final String name, final String siString) throws UnitRuntimeException
71 {
72 Throw.whenNull(name, "name cannot be null");
73 Throw.when(name.length() == 1, UnitRuntimeException.class, "name of unit cannot be empty");
74 Throw.whenNull(siString, "siString cannot be null");
75 this.name = name;
76 try
77 {
78 this.siDimensions = SIDimensions.of(siString);
79 }
80 catch (UnitException exception)
81 {
82 throw new UnitRuntimeException(exception);
83 }
84 }
85
86
87
88
89
90
91
92 public Quantity(final String name, final byte[] siSignature)
93 {
94 this(name, new SIDimensions(siSignature));
95 }
96
97
98
99
100
101
102
103
104
105
106
107
108 public void registerUnit(final U unit, final SIPrefixes siPrefixes, final double siPrefixPower)
109 {
110 Throw.whenNull(unit, "unit cannot be null");
111 if (this.standardUnit == null)
112 {
113 this.standardUnit = unit;
114 Quantities.INSTANCE.register(this);
115 }
116 if (siPrefixes.equals(SIPrefixes.UNIT))
117 {
118 for (SIPrefix siPrefix : SIPrefixes.UNIT_PREFIXES.values())
119 {
120 unit.deriveSI(siPrefix, siPrefixPower, true);
121
122 }
123 }
124 else if (siPrefixes.equals(SIPrefixes.UNIT_POS))
125 {
126 for (SIPrefix siPrefix : SIPrefixes.UNIT_POS_PREFIXES.values())
127 {
128 unit.deriveSI(siPrefix, siPrefixPower, true);
129 }
130 }
131 else if (siPrefixes.equals(SIPrefixes.KILO))
132 {
133 for (SIPrefix siPrefix : SIPrefixes.KILO_PREFIXES.values())
134 {
135 unit.deriveSIKilo(siPrefix, siPrefixPower, true);
136 }
137 }
138 else if (siPrefixes.equals(SIPrefixes.PER_UNIT))
139 {
140 for (SIPrefix siPrefix : SIPrefixes.PER_UNIT_PREFIXES.values())
141 {
142 unit.derivePerSI(siPrefix, siPrefixPower, true);
143 }
144 }
145
146
147 if (this.unitsById.containsKey(unit.getId()))
148 {
149
150 if (this.unitsById.get(unit.getId()).isGenerated() == unit.isGenerated())
151 {
152 throw new UnitRuntimeException("A unit with id " + unit.getId() + " has already been registered for unit type "
153 + unit.getClass().getSimpleName());
154 }
155 else
156 {
157 if (!unit.isGenerated())
158 {
159
160 this.unitsById.put(unit.getId(), unit);
161 }
162
163 }
164 }
165 else
166 {
167
168 this.unitsById.put(unit.getId(), unit);
169 }
170
171
172 for (String abbreviation : unit.getAbbreviations())
173 {
174 if (this.unitsByAbbreviation.containsKey(abbreviation))
175 {
176
177 if (getUnitByAbbreviation(abbreviation).isGenerated() == unit.isGenerated())
178 {
179 throw new UnitRuntimeException("A unit with abbreviation " + abbreviation
180 + " has already been registered for unit type " + unit.getClass().getSimpleName());
181 }
182 else
183 {
184 if (!unit.isGenerated())
185 {
186
187 this.unitsByAbbreviation.put(abbreviation, unit);
188 }
189
190 }
191 }
192 else
193 {
194
195 this.unitsByAbbreviation.put(abbreviation, unit);
196 }
197 }
198 }
199
200
201
202
203
204 public void unregister(final U unit)
205 {
206 Throw.whenNull(unit, "null unit cannot be removed from the unit registry");
207 if (this.unitsById.containsValue(unit))
208 {
209 this.unitsById.remove(unit.getId(), unit);
210 }
211 for (String abbreviation : unit.getAbbreviations())
212 {
213 if (this.unitsByAbbreviation.containsKey(abbreviation))
214 {
215 if (unit.equals(this.unitsByAbbreviation.get(abbreviation)))
216 {
217 this.unitsByAbbreviation.remove(abbreviation, unit);
218 }
219 }
220 }
221 }
222
223
224
225
226
227 public final String getName()
228 {
229 return this.name;
230 }
231
232
233
234
235 public final SIDimensions getSiDimensions()
236 {
237 return this.siDimensions;
238 }
239
240
241
242
243
244
245 public U getUnitById(final String id)
246 {
247 return this.unitsById.get(id);
248 }
249
250
251
252
253
254
255
256
257 public U getUnitByAbbreviation(final String abbreviation)
258 {
259 U unit = this.unitsByAbbreviation.get(abbreviation);
260 if (unit == null)
261 {
262 unit = this.unitsByAbbreviation.get(abbreviation.replaceAll("[ .^]", ""));
263 }
264 if (unit == null)
265 {
266 try
267 {
268 SIDimensions dim = SIDimensions.of(abbreviation);
269 if (dim != null && dim.equals(this.siDimensions))
270 {
271 unit = this.standardUnit;
272 }
273 }
274 catch (UnitException exception)
275 {
276 unit = null;
277 }
278 }
279 return unit;
280 }
281
282
283
284
285
286
287
288
289 public U of(final String abbreviation)
290 {
291 return this.getUnitByAbbreviation(abbreviation);
292 }
293
294
295
296
297
298 public Map<String, U> getUnitsById()
299 {
300 return new LinkedHashMap<>(this.unitsById);
301 }
302
303
304
305
306
307 public Map<String, U> getUnitsByAbbreviation()
308 {
309 return new LinkedHashMap<>(this.unitsByAbbreviation);
310 }
311
312
313
314
315
316 public U getStandardUnit()
317 {
318 return this.standardUnit;
319 }
320
321
322 @Override
323 public int hashCode()
324 {
325
326
327
328 final int prime = 31;
329 int result = 1;
330 result = prime * result + ((this.siDimensions == null) ? 0 : this.siDimensions.hashCode());
331 result = prime * result + ((this.standardUnit == null) ? 0 : this.standardUnit.getId().hashCode());
332 result = prime * result + ((this.unitsByAbbreviation == null) ? 0 : this.unitsByAbbreviation.keySet().hashCode());
333 result = prime * result + ((this.unitsById == null) ? 0 : this.unitsById.keySet().hashCode());
334 return result;
335 }
336
337
338 @Override
339 @SuppressWarnings("checkstyle:needbraces")
340 public boolean equals(final Object obj)
341 {
342 if (this == obj)
343 return true;
344 if (obj == null)
345 return false;
346 if (getClass() != obj.getClass())
347 return false;
348 Quantity<?> other = (Quantity<?>) obj;
349 if (this.siDimensions == null)
350 {
351 if (other.siDimensions != null)
352 return false;
353 }
354 else if (!this.siDimensions.equals(other.siDimensions))
355 return false;
356 if (this.standardUnit == null)
357 {
358 if (other.standardUnit != null)
359 return false;
360 }
361
362 else if (!this.standardUnit.getId().equals(other.standardUnit.getId()))
363 return false;
364 if (this.unitsByAbbreviation == null)
365 {
366 if (other.unitsByAbbreviation != null)
367 return false;
368 }
369
370 else if (!this.unitsByAbbreviation.keySet().equals(other.unitsByAbbreviation.keySet()))
371 return false;
372 if (this.unitsById == null)
373 {
374 if (other.unitsById != null)
375 return false;
376 }
377
378 else if (!this.unitsById.keySet().equals(other.unitsById.keySet()))
379 return false;
380 return true;
381 }
382
383
384 @Override
385 public String toString()
386 {
387 return "Quantity [standardUnit=" + this.standardUnit + ", name=" + this.name + ", siDimensions=" + this.siDimensions
388 + "]";
389 }
390
391 }