1 package org.djunits.unit;
2
3 import java.util.Objects;
4
5 import org.djunits.quantity.def.Quantity;
6 import org.djunits.unit.scale.Scale;
7 import org.djunits.unit.si.SIPrefix;
8 import org.djunits.unit.si.SIPrefixes;
9 import org.djunits.unit.system.UnitSystem;
10 import org.djutils.exceptions.Throw;
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 public abstract class AbstractUnit<U extends Unit<U, Q>, Q extends Quantity<Q>> implements Unit<U, Q>
29 {
30
31 private final String textualAbbreviation;
32
33
34 private final String displayAbbreviation;
35
36
37 private final String name;
38
39
40 private final Scale scale;
41
42
43 private final UnitSystem unitSystem;
44
45
46 private SIPrefix siPrefix = null;
47
48
49
50
51
52
53
54
55 public AbstractUnit(final String textualAbbreviation, final String name, final Scale scale, final UnitSystem unitSystem)
56 {
57 this(textualAbbreviation, textualAbbreviation, name, scale, unitSystem);
58 }
59
60
61
62
63
64
65
66
67
68 public AbstractUnit(final String textualAbbreviation, final String displayAbbreviation, final String name,
69 final Scale scale, final UnitSystem unitSystem)
70 {
71
72 String cName = Units.unitClassName(getClass());
73 Throw.whenNull(textualAbbreviation, "Constructing unit %s: textualAbbreviation cannot be null", cName);
74 Throw.whenNull(displayAbbreviation, "Constructing unit %s: displayAbbreviation cannot be null", cName);
75 Throw.when(textualAbbreviation.length() == 0, UnitRuntimeException.class,
76 "Constructing unit %s: textualAbbreviation string cannot be empty", cName);
77 Throw.whenNull(name, "Constructing unit %s.%s: name cannot be null", cName, textualAbbreviation);
78 Throw.when(name.length() == 0, UnitRuntimeException.class, "Constructing unit %s.%s: name.length cannot be 0", cName,
79 textualAbbreviation);
80 Throw.whenNull(scale, "Constructing unit %s.%s: scale cannot be null", cName, textualAbbreviation);
81 Throw.whenNull(unitSystem, "Constructing unit %s.%s: unitSystem cannot be null", cName, textualAbbreviation);
82
83
84 this.displayAbbreviation = displayAbbreviation;
85 this.textualAbbreviation = textualAbbreviation;
86 this.name = name;
87 this.scale = scale;
88 this.unitSystem = unitSystem;
89
90
91 Units.register(this);
92 }
93
94
95
96
97
98
99
100 @SuppressWarnings("unchecked")
101 public U generateSiPrefixes(final boolean kilo, final boolean perUnit)
102 {
103 String cName = getClass().getSimpleName();
104 Throw.when(!getScale().isIdentityScale(), UnitRuntimeException.class,
105 "SI prefixes generation for unit %s only applicable to unit with base scale", cName);
106 Throw.when(kilo && !perUnit && !getId().startsWith("k"), UnitRuntimeException.class,
107 "SI prefixes generated for kilo class for unit %s, but abbreviation %s does not start with a 'k'", cName,
108 getId());
109 Throw.when(kilo && perUnit && !getId().startsWith("/k"), UnitRuntimeException.class,
110 "SI prefixes generated for per-kilo class for unit %s, but abbreviation %s does not start with '/k'", cName,
111 getId());
112 Throw.when(kilo && !perUnit && !getStoredName().startsWith("kilo"), UnitRuntimeException.class,
113 "SI prefixes generated for kilo class for unit %s, but name %s does not start with 'kilo'", cName,
114 getStoredName());
115 Throw.when(kilo && perUnit && !getStoredName().startsWith("per kilo"), UnitRuntimeException.class,
116 "SI prefixes generated for kilo class for unit %s, but name %s does not start with 'per kilo'", cName,
117 getStoredName());
118 Throw.when(perUnit && !getId().startsWith("/"), UnitRuntimeException.class,
119 "SI prefixes generated for 'per' class for unit %s, but abbreviation %s does not start with '/'", cName,
120 getId());
121 Throw.when(perUnit && !getStoredName().startsWith("per "), UnitRuntimeException.class,
122 "SI prefixes generated for 'per' class for unit %s, but name %s does not start with 'per '", cName,
123 getStoredName());
124
125 if (!kilo)
126 {
127 if (!perUnit)
128 {
129 this.siPrefix = SIPrefixes.UNIT_PREFIXES.get("");
130 for (SIPrefix sip : SIPrefixes.UNIT_PREFIXES.values())
131 {
132 if (sip.getFactor() != 1.0)
133 {
134 U unit = deriveUnit(sip.getDefaultTextualPrefix() + getStoredTextualAbbreviation(),
135 sip.getDefaultDisplayPrefix() + getStoredDisplayAbbreviation(),
136 sip.getPrefixName() + getStoredName(), sip.getFactor(), getUnitSystem());
137 unit.setSiPrefix(sip);
138 }
139 }
140 }
141 else
142 {
143 this.siPrefix = SIPrefixes.PER_UNIT_PREFIXES.get("/");
144 for (SIPrefix sip : SIPrefixes.PER_UNIT_PREFIXES.values())
145 {
146 if (sip.getFactor() != 1.0)
147 {
148 U unit = deriveUnit(sip.getDefaultTextualPrefix() + getStoredTextualAbbreviation().substring(1),
149 sip.getDefaultDisplayPrefix() + getStoredDisplayAbbreviation().substring(1),
150 sip.getPrefixName() + getStoredName().substring(4), sip.getFactor(), getUnitSystem());
151 unit.setSiPrefix(sip);
152 }
153 }
154 }
155 }
156 else
157 {
158 if (!perUnit)
159 {
160 this.siPrefix = SIPrefixes.KILO_PREFIXES.get("k");
161 for (SIPrefix sip : SIPrefixes.KILO_PREFIXES.values())
162 {
163 if (sip.getFactor() != 1.0)
164 {
165 U unit = deriveUnit(sip.getDefaultTextualPrefix() + getStoredTextualAbbreviation().substring(1),
166 sip.getDefaultDisplayPrefix() + getStoredDisplayAbbreviation().substring(1),
167 sip.getPrefixName() + getStoredName().substring(4), sip.getFactor(), getUnitSystem());
168 unit.setSiPrefix(sip);
169 }
170 }
171 }
172 else
173 {
174 this.siPrefix = SIPrefixes.PER_KILO_PREFIXES.get("/k");
175 for (SIPrefix sip : SIPrefixes.PER_KILO_PREFIXES.values())
176 {
177 if (sip.getFactor() != 1.0)
178 {
179
180 U unit = deriveUnit(sip.getDefaultTextualPrefix() + getStoredTextualAbbreviation().substring(2),
181 sip.getDefaultDisplayPrefix() + getStoredDisplayAbbreviation().substring(2),
182 sip.getPrefixName() + getStoredName().substring(8), sip.getFactor(), getUnitSystem());
183 unit.setSiPrefix(sip);
184 }
185 }
186 }
187 }
188 return (U) this;
189 }
190
191
192
193
194
195
196
197
198
199
200 @SuppressWarnings("checkstyle:hiddenfield")
201 public U deriveUnit(final String textualAbbreviation, final String name, final double scaleFactor,
202 final UnitSystem unitSystem)
203 {
204 return deriveUnit(textualAbbreviation, textualAbbreviation, name, scaleFactor, unitSystem);
205 }
206
207
208
209
210
211
212
213
214
215
216 @SuppressWarnings("checkstyle:hiddenfield")
217 public abstract U deriveUnit(String textualAbbreviation, String displayAbbreviation, String name, double scaleFactor,
218 UnitSystem unitSystem);
219
220 @Override
221 public String getId()
222 {
223 return this.textualAbbreviation;
224 }
225
226 @Override
227 public String getStoredTextualAbbreviation()
228 {
229 return this.textualAbbreviation;
230 }
231
232 @Override
233 public String getTextualAbbreviation()
234 {
235 return Units.localizedUnitTextualAbbr(getClass(), getId());
236 }
237
238 @Override
239 public String getStoredDisplayAbbreviation()
240 {
241 return this.displayAbbreviation;
242 }
243
244 @Override
245 public String getDisplayAbbreviation()
246 {
247 return Units.localizedUnitDisplayAbbr(getClass(), getId());
248 }
249
250 @Override
251 public String getStoredName()
252 {
253 return this.name;
254 }
255
256 @Override
257 public String getName()
258 {
259 return Units.localizedUnitName(getClass(), getId());
260 }
261
262 @Override
263 public Scale getScale()
264 {
265 return this.scale;
266 }
267
268 @Override
269 public UnitSystem getUnitSystem()
270 {
271 return this.unitSystem;
272 }
273
274 @SuppressWarnings({"unchecked", "hiddenfield"})
275 @Override
276 public U setSiPrefix(final SIPrefix siPrefix)
277 {
278 this.siPrefix = siPrefix;
279 return (U) this;
280 }
281
282 @Override
283 public U setSiPrefix(final String prefix)
284 {
285 SIPrefix sip = SIPrefixes.getSiPrefix(prefix);
286 return setSiPrefix(sip);
287 }
288
289 @Override
290 public U setSiPrefixKilo(final String prefix)
291 {
292 SIPrefix sip = SIPrefixes.getSiPrefixKilo(prefix);
293 return setSiPrefix(sip);
294 }
295
296 @Override
297 public U setSiPrefixPer(final String prefix)
298 {
299 SIPrefix sip = SIPrefixes.getSiPrefixPer(prefix);
300 return setSiPrefix(sip);
301 }
302
303 @Override
304 public SIPrefix getSiPrefix()
305 {
306 return this.siPrefix;
307 }
308
309 @Override
310 public int hashCode()
311 {
312 return Objects.hash(this.displayAbbreviation, this.name, this.scale, this.textualAbbreviation, this.unitSystem);
313 }
314
315 @Override
316 @SuppressWarnings("checkstyle:needbraces")
317 public boolean equals(final Object obj)
318 {
319 if (this == obj)
320 return true;
321 if (obj == null)
322 return false;
323 if (getClass() != obj.getClass())
324 return false;
325 AbstractUnit<?, ?> other = (AbstractUnit<?, ?>) obj;
326 return Objects.equals(this.displayAbbreviation, other.displayAbbreviation) && Objects.equals(this.name, other.name)
327 && Objects.equals(this.scale, other.scale)
328 && Objects.equals(this.textualAbbreviation, other.textualAbbreviation)
329 && Objects.equals(this.unitSystem, other.unitSystem);
330 }
331
332 @Override
333 public String toString()
334 {
335 return this.displayAbbreviation;
336 }
337 }