1 | /* |
2 | * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences. |
3 | * Copyright (C) 2007 - JScience (http://jscience.org/) |
4 | * All rights reserved. |
5 | * |
6 | * Permission to use, copy, modify, and distribute this software is |
7 | * freely granted, provided that this notice is preserved. |
8 | */ |
9 | package javax.measure; |
10 | |
11 | import java.io.Serializable; |
12 | import java.math.BigDecimal; |
13 | import java.math.MathContext; |
14 | |
15 | import javax.measure.quantity.Quantity; |
16 | import javax.measure.unit.CompoundUnit; |
17 | import javax.measure.unit.Unit; |
18 | |
19 | /** |
20 | * <p> This class represents the result of a measurement stated in a |
21 | * known unit.</p> |
22 | * |
23 | * <p> There is no constraint upon the measurement value itself: scalars, |
24 | * vectors, or even data sets are valid values as long as |
25 | * an aggregate magnitude can be determined (see {@link Measurable}).</p> |
26 | * |
27 | * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> |
28 | * @version 4.2, August 26, 2007 |
29 | */ |
30 | public abstract class Measure<V, Q extends Quantity> implements Measurable<Q>, |
31 | Serializable { |
32 | |
33 | /** |
34 | * Default constructor. |
35 | */ |
36 | protected Measure() { |
37 | } |
38 | |
39 | /** |
40 | * Returns the scalar measure for the specified <code>double</code> |
41 | * stated in the specified unit. |
42 | * |
43 | * @param doubleValue the measurement value. |
44 | * @param unit the measurement unit. |
45 | */ |
46 | public static <Q extends Quantity> Measure<java.lang.Double, Q> valueOf( |
47 | double doubleValue, Unit<Q> unit) { |
48 | return new Double<Q>(doubleValue, unit); |
49 | } |
50 | |
51 | /** |
52 | * Returns the scalar measure for the specified <code>double</code> |
53 | * stated in the specified unit. |
54 | * |
55 | * @param longValue the measurement value. |
56 | * @param unit the measurement unit. |
57 | */ |
58 | public static <Q extends Quantity> Measure<java.lang.Long, Q> valueOf( |
59 | long longValue, Unit<Q> unit) { |
60 | return new Long<Q>(longValue, unit); |
61 | } |
62 | |
63 | /** |
64 | * Returns the scalar measure for the specified <code>float</code> |
65 | * stated in the specified unit. |
66 | * |
67 | * @param floatValue the measurement value. |
68 | * @param unit the measurement unit. |
69 | */ |
70 | public static <Q extends Quantity> Measure<java.lang.Float, Q> valueOf( |
71 | float floatValue, Unit<Q> unit) { |
72 | return new Float<Q>(floatValue, unit); |
73 | } |
74 | |
75 | /** |
76 | * Returns the scalar measure for the specified <code>int</code> |
77 | * stated in the specified unit. |
78 | * |
79 | * @param intValue the measurement value. |
80 | * @param unit the measurement unit. |
81 | */ |
82 | public static <Q extends Quantity> Measure<java.lang.Integer, Q> valueOf( |
83 | int intValue, Unit<Q> unit) { |
84 | return new Integer<Q>(intValue, unit); |
85 | } |
86 | |
87 | /** |
88 | * Returns the measurement value of this measure. |
89 | * |
90 | * @return the measurement value. |
91 | */ |
92 | public abstract V getValue(); |
93 | |
94 | /** |
95 | * Returns the measurement unit of this measure. |
96 | * |
97 | * @return the measurement unit. |
98 | */ |
99 | public abstract Unit<Q> getUnit(); |
100 | |
101 | /** |
102 | * Returns the measure equivalent to this measure but stated in the |
103 | * specified unit. This method may result in lost of precision |
104 | * (e.g. measure of integral value). |
105 | * |
106 | * @param unit the new measurement unit. |
107 | * @return the measure stated in the specified unit. |
108 | */ |
109 | public abstract Measure<V, Q> to(Unit<Q> unit); |
110 | |
111 | /** |
112 | * Returns the value of this measure stated in the specified unit as |
113 | * a <code>double</code>. If the measure has too great a magnitude to |
114 | * be represented as a <code>double</code>, it will be converted to |
115 | * <code>Double.NEGATIVE_INFINITY</code> or |
116 | * <code>Double.POSITIVE_INFINITY</code> as appropriate. |
117 | * |
118 | * @param unit the unit in which this measure is stated. |
119 | * @return the numeric value after conversion to type <code>double</code>. |
120 | */ |
121 | public abstract double doubleValue(Unit<Q> unit); |
122 | |
123 | /** |
124 | * Returns the estimated integral value of this measure stated in |
125 | * the specified unit as a <code>long</code>. |
126 | * |
127 | * <p> Note: This method differs from the <code>Number.longValue()</code> |
128 | * in the sense that the closest integer value is returned |
129 | * and an ArithmeticException is raised instead |
130 | * of a bit truncation in case of overflow (safety critical).</p> |
131 | * |
132 | * @param unit the unit in which the measurable value is stated. |
133 | * @return the numeric value after conversion to type <code>long</code>. |
134 | * @throws ArithmeticException if this quantity cannot be represented |
135 | * as a <code>long</code> number in the specified unit. |
136 | */ |
137 | public long longValue(Unit<Q> unit) throws ArithmeticException { |
138 | double doubleValue = doubleValue(unit); |
139 | if (java.lang.Double.isNaN(doubleValue) |
140 | || (doubleValue < java.lang.Long.MIN_VALUE) |
141 | || (doubleValue > java.lang.Long.MAX_VALUE)) |
142 | throw new ArithmeticException(doubleValue + " " + unit |
143 | + " cannot be represented as long"); |
144 | return Math.round(doubleValue); |
145 | } |
146 | |
147 | /** |
148 | * Returns the value of this measure stated in the specified unit as a |
149 | * <code>float</code>. If the measure has too great a magnitude to be |
150 | * represented as a <code>float</code>, it will be converted to |
151 | * <code>Float.NEGATIVE_INFINITY</code> or |
152 | * <code>Float.POSITIVE_INFINITY</code> as appropriate. |
153 | * |
154 | * @param unit the unit in which the measure is stated. |
155 | * @return the numeric value after conversion to type <code>float</code>. |
156 | */ |
157 | public float floatValue(Unit<Q> unit) { |
158 | return (float) doubleValue(unit); |
159 | } |
160 | |
161 | /** |
162 | * Returns the estimated integral value of this measure stated in |
163 | * the specified unit as a <code>int</code>. |
164 | * |
165 | * <p> Note: This method differs from the <code>Number.intValue()</code> |
166 | * in the sense that the closest integer value is returned |
167 | * and an ArithmeticException is raised instead |
168 | * of a bit truncation in case of overflow (safety critical).</p> |
169 | * |
170 | * @param unit the unit in which the measurable value is stated. |
171 | * @return the numeric value after conversion to type <code>int</code>. |
172 | * @throws ArithmeticException if this quantity cannot be represented |
173 | * as a <code>int</code> number in the specified unit. |
174 | */ |
175 | public int intValue(Unit<Q> unit) { |
176 | long longValue = longValue(unit); |
177 | if ((longValue > java.lang.Integer.MAX_VALUE) |
178 | || (longValue < java.lang.Integer.MIN_VALUE)) |
179 | throw new ArithmeticException("Overflow"); |
180 | return (int) longValue; |
181 | } |
182 | |
183 | /** |
184 | * Compares this measure against the specified object for |
185 | * strict equality (same unit and amount). |
186 | * To compare measures stated using different units the |
187 | * {@link #compareTo} method should be used. |
188 | * |
189 | * @param obj the object to compare with. |
190 | * @return <code>true</code> if both objects are identical (same |
191 | * unit and same amount); <code>false</code> otherwise. |
192 | */ |
193 | @SuppressWarnings("unchecked") |
194 | public boolean equals(Object obj) { |
195 | if (!(obj instanceof Measure)) |
196 | return false; |
197 | Measure that = (Measure) obj; |
198 | return this.getUnit().equals(that.getUnit()) |
199 | && this.getValue().equals(that.getValue()); |
200 | } |
201 | |
202 | /** |
203 | * Returns the hash code for this scalar. |
204 | * |
205 | * @return the hash code value. |
206 | */ |
207 | public int hashCode() { |
208 | return getUnit().hashCode() + getValue().hashCode(); |
209 | } |
210 | |
211 | /** |
212 | * Returns the <code>String</code> representation of this measure |
213 | * The string produced for a given measure is always the same; |
214 | * it is not affected by locale. This means that it can be used |
215 | * as a canonical string representation for exchanging data, |
216 | * or as a key for a Hashtable, etc. Locale-sensitive |
217 | * measure formatting and parsing is handled by the {@link |
218 | * MeasureFormat} class and its subclasses. |
219 | * |
220 | * @return the string representation of this measure. |
221 | */ |
222 | public String toString() { |
223 | if (getUnit() instanceof CompoundUnit) |
224 | return MeasureFormat.DEFAULT.formatCompound(doubleValue(getUnit()), |
225 | getUnit(), new StringBuffer(), null).toString(); |
226 | return getValue() + " " + getUnit(); |
227 | } |
228 | |
229 | /** |
230 | * Compares this measure to the specified measurable quantity. |
231 | * This method compares the {@link Measurable#doubleValue(Unit)} of |
232 | * both this measure and the specified measurable stated in the |
233 | * same unit (this measure's {@link #getUnit() unit}). |
234 | * |
235 | * @return a negative integer, zero, or a positive integer as this measure |
236 | * is less than, equal to, or greater than the specified measurable |
237 | * quantity. |
238 | * @return <code>Double.compare(this.doubleValue(getUnit()), |
239 | * that.doubleValue(getUnit()))</code> |
240 | */ |
241 | public int compareTo(Measurable<Q> that) { |
242 | return java.lang.Double.compare(doubleValue(getUnit()), that |
243 | .doubleValue(getUnit())); |
244 | } |
245 | |
246 | /** |
247 | * Holds scalar implementation for <code>double</code> values. |
248 | */ |
249 | private static final class Double<Q extends Quantity> extends |
250 | Measure<java.lang.Double, Q> { |
251 | |
252 | private final double _value; |
253 | |
254 | private final Unit<Q> _unit; |
255 | |
256 | public Double(double value, Unit<Q> unit) { |
257 | _value = value; |
258 | _unit = unit; |
259 | } |
260 | |
261 | @Override |
262 | public Unit<Q> getUnit() { |
263 | return _unit; |
264 | } |
265 | |
266 | @Override |
267 | public java.lang.Double getValue() { |
268 | return _value; |
269 | } |
270 | |
271 | @Override |
272 | public Measure<java.lang.Double, Q> to(Unit<Q> unit) { |
273 | if ((unit == _unit) || (unit.equals(_unit))) |
274 | return this; |
275 | return new Double<Q>(doubleValue(unit), unit); |
276 | } |
277 | |
278 | public double doubleValue(Unit<Q> unit) { |
279 | if ((unit == _unit) || (unit.equals(_unit))) |
280 | return _value; |
281 | return _unit.getConverterTo(unit).convert(_value); |
282 | } |
283 | |
284 | private static final long serialVersionUID = 1L; |
285 | } |
286 | |
287 | /** |
288 | * Holds scalar implementation for <code>long</code> values. |
289 | */ |
290 | private static final class Long<Q extends Quantity> extends |
291 | Measure<java.lang.Long, Q> { |
292 | |
293 | private final long _value; |
294 | |
295 | private final Unit<Q> _unit; |
296 | |
297 | public Long(long value, Unit<Q> unit) { |
298 | _value = value; |
299 | _unit = unit; |
300 | } |
301 | |
302 | @Override |
303 | public Unit<Q> getUnit() { |
304 | return _unit; |
305 | } |
306 | |
307 | @Override |
308 | public java.lang.Long getValue() { |
309 | return _value; |
310 | } |
311 | |
312 | @Override |
313 | public Measure<java.lang.Long, Q> to(Unit<Q> unit) { |
314 | if ((unit == _unit) || (unit.equals(_unit))) |
315 | return this; |
316 | return new Long<Q>(longValue(unit), unit); |
317 | } |
318 | |
319 | public double doubleValue(Unit<Q> unit) { |
320 | if ((unit == _unit) || (unit.equals(_unit))) |
321 | return _value; |
322 | return _unit.getConverterTo(unit).convert(_value); |
323 | } |
324 | |
325 | public long longValue(Unit<Q> unit) throws ArithmeticException { |
326 | if ((unit == _unit) || (unit.equals(_unit))) |
327 | return _value; // No conversion, returns value directly. |
328 | return super.longValue(unit); |
329 | } |
330 | |
331 | private static final long serialVersionUID = 1L; |
332 | |
333 | } |
334 | |
335 | /** |
336 | * Holds scalar implementation for <code>float</code> values. |
337 | */ |
338 | private static final class Float<Q extends Quantity> extends |
339 | Measure<java.lang.Float, Q> { |
340 | |
341 | private final float _value; |
342 | |
343 | private final Unit<Q> _unit; |
344 | |
345 | public Float(float value, Unit<Q> unit) { |
346 | _value = value; |
347 | _unit = unit; |
348 | } |
349 | |
350 | @Override |
351 | public Unit<Q> getUnit() { |
352 | return _unit; |
353 | } |
354 | |
355 | @Override |
356 | public java.lang.Float getValue() { |
357 | return _value; |
358 | } |
359 | |
360 | @Override |
361 | public Measure<java.lang.Float, Q> to(Unit<Q> unit) { |
362 | if ((unit == _unit) || (unit.equals(_unit))) |
363 | return this; |
364 | return new Float<Q>(floatValue(unit), unit); |
365 | } |
366 | |
367 | public double doubleValue(Unit<Q> unit) { |
368 | if ((unit == _unit) || (unit.equals(_unit))) |
369 | return _value; |
370 | return _unit.getConverterTo(unit).convert(_value); |
371 | } |
372 | |
373 | private static final long serialVersionUID = 1L; |
374 | } |
375 | |
376 | /** |
377 | * Holds scalar implementation for <code>long</code> values. |
378 | */ |
379 | private static final class Integer<Q extends Quantity> extends |
380 | Measure<java.lang.Integer, Q> { |
381 | |
382 | private final int _value; |
383 | |
384 | private final Unit<Q> _unit; |
385 | |
386 | public Integer(int value, Unit<Q> unit) { |
387 | _value = value; |
388 | _unit = unit; |
389 | } |
390 | |
391 | @Override |
392 | public Unit<Q> getUnit() { |
393 | return _unit; |
394 | } |
395 | |
396 | @Override |
397 | public java.lang.Integer getValue() { |
398 | return _value; |
399 | } |
400 | |
401 | @Override |
402 | public Measure<java.lang.Integer, Q> to(Unit<Q> unit) { |
403 | if ((unit == _unit) || (unit.equals(_unit))) |
404 | return this; |
405 | return new Integer<Q>(intValue(unit), unit); |
406 | } |
407 | |
408 | public double doubleValue(Unit<Q> unit) { |
409 | if ((unit == _unit) || (unit.equals(_unit))) |
410 | return _value; |
411 | return _unit.getConverterTo(unit).convert(_value); |
412 | } |
413 | |
414 | public long longValue(Unit<Q> unit) throws ArithmeticException { |
415 | if ((unit == _unit) || (unit.equals(_unit))) |
416 | return _value; // No conversion, returns value directly. |
417 | return super.longValue(unit); |
418 | } |
419 | |
420 | private static final long serialVersionUID = 1L; |
421 | |
422 | } |
423 | |
424 | /** |
425 | * @deprecated {@link DecimalMeasure} should be used directly. |
426 | */ |
427 | public static <Q extends Quantity> Measure<BigDecimal, Q> valueOf( |
428 | BigDecimal decimal, Unit<Q> unit) { |
429 | return DecimalMeasure.valueOf(decimal, unit); |
430 | } |
431 | |
432 | /** |
433 | * @deprecated {@link DecimalMeasure} should be used directly and |
434 | * <code>MathContext</code> specified explicitly when |
435 | * {@link DecimalMeasure#to(Unit, MathContext) converting}. |
436 | */ |
437 | public static <Q extends Quantity> Measure<BigDecimal, Q> valueOf( |
438 | BigDecimal decimal, Unit<Q> unit, MathContext mathContext) { |
439 | return DecimalMeasure.valueOf(decimal, unit); |
440 | } |
441 | |
442 | /** |
443 | * @deprecated {@link VectorMeasure} should be used directly. |
444 | */ |
445 | public static <Q extends Quantity> Measure<double[], Q> valueOf( |
446 | double[] components, Unit<Q> unit) { |
447 | return VectorMeasure.valueOf(components, unit); |
448 | } |
449 | } |