001: /*
002: * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
003: * Copyright (C) 2007 - JScience (http://jscience.org/)
004: * All rights reserved.
005: *
006: * Permission to use, copy, modify, and distribute this software is
007: * freely granted, provided that this notice is preserved.
008: */
009: package javax.measure;
010:
011: import java.io.Serializable;
012: import java.math.BigDecimal;
013: import java.math.MathContext;
014:
015: import javax.measure.quantity.Quantity;
016: import javax.measure.unit.CompoundUnit;
017: import javax.measure.unit.Unit;
018:
019: /**
020: * <p> This class represents the result of a measurement stated in a
021: * known unit.</p>
022: *
023: * <p> There is no constraint upon the measurement value itself: scalars,
024: * vectors, or even data sets are valid values as long as
025: * an aggregate magnitude can be determined (see {@link Measurable}).</p>
026: *
027: * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
028: * @version 4.2, August 26, 2007
029: */
030: public abstract class Measure<V, Q extends Quantity> implements
031: Measurable<Q>, Serializable {
032:
033: /**
034: * Default constructor.
035: */
036: protected Measure() {
037: }
038:
039: /**
040: * Returns the scalar measure for the specified <code>double</code>
041: * stated in the specified unit.
042: *
043: * @param doubleValue the measurement value.
044: * @param unit the measurement unit.
045: */
046: public static <Q extends Quantity> Measure<java.lang.Double, Q> valueOf(
047: double doubleValue, Unit<Q> unit) {
048: return new Double<Q>(doubleValue, unit);
049: }
050:
051: /**
052: * Returns the scalar measure for the specified <code>double</code>
053: * stated in the specified unit.
054: *
055: * @param longValue the measurement value.
056: * @param unit the measurement unit.
057: */
058: public static <Q extends Quantity> Measure<java.lang.Long, Q> valueOf(
059: long longValue, Unit<Q> unit) {
060: return new Long<Q>(longValue, unit);
061: }
062:
063: /**
064: * Returns the scalar measure for the specified <code>float</code>
065: * stated in the specified unit.
066: *
067: * @param floatValue the measurement value.
068: * @param unit the measurement unit.
069: */
070: public static <Q extends Quantity> Measure<java.lang.Float, Q> valueOf(
071: float floatValue, Unit<Q> unit) {
072: return new Float<Q>(floatValue, unit);
073: }
074:
075: /**
076: * Returns the scalar measure for the specified <code>int</code>
077: * stated in the specified unit.
078: *
079: * @param intValue the measurement value.
080: * @param unit the measurement unit.
081: */
082: public static <Q extends Quantity> Measure<java.lang.Integer, Q> valueOf(
083: int intValue, Unit<Q> unit) {
084: return new Integer<Q>(intValue, unit);
085: }
086:
087: /**
088: * Returns the measurement value of this measure.
089: *
090: * @return the measurement value.
091: */
092: public abstract V getValue();
093:
094: /**
095: * Returns the measurement unit of this measure.
096: *
097: * @return the measurement unit.
098: */
099: 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(
225: doubleValue(getUnit()), getUnit(),
226: new StringBuffer(), null).toString();
227: return getValue() + " " + getUnit();
228: }
229:
230: /**
231: * Compares this measure to the specified measurable quantity.
232: * This method compares the {@link Measurable#doubleValue(Unit)} of
233: * both this measure and the specified measurable stated in the
234: * same unit (this measure's {@link #getUnit() unit}).
235: *
236: * @return a negative integer, zero, or a positive integer as this measure
237: * is less than, equal to, or greater than the specified measurable
238: * quantity.
239: * @return <code>Double.compare(this.doubleValue(getUnit()),
240: * that.doubleValue(getUnit()))</code>
241: */
242: public int compareTo(Measurable<Q> that) {
243: return java.lang.Double.compare(doubleValue(getUnit()), that
244: .doubleValue(getUnit()));
245: }
246:
247: /**
248: * Holds scalar implementation for <code>double</code> values.
249: */
250: private static final class Double<Q extends Quantity> extends
251: Measure<java.lang.Double, Q> {
252:
253: private final double _value;
254:
255: private final Unit<Q> _unit;
256:
257: public Double(double value, Unit<Q> unit) {
258: _value = value;
259: _unit = unit;
260: }
261:
262: @Override
263: public Unit<Q> getUnit() {
264: return _unit;
265: }
266:
267: @Override
268: public java.lang.Double getValue() {
269: return _value;
270: }
271:
272: @Override
273: public Measure<java.lang.Double, Q> to(Unit<Q> unit) {
274: if ((unit == _unit) || (unit.equals(_unit)))
275: return this ;
276: return new Double<Q>(doubleValue(unit), unit);
277: }
278:
279: public double doubleValue(Unit<Q> unit) {
280: if ((unit == _unit) || (unit.equals(_unit)))
281: return _value;
282: return _unit.getConverterTo(unit).convert(_value);
283: }
284:
285: private static final long serialVersionUID = 1L;
286: }
287:
288: /**
289: * Holds scalar implementation for <code>long</code> values.
290: */
291: private static final class Long<Q extends Quantity> extends
292: Measure<java.lang.Long, Q> {
293:
294: private final long _value;
295:
296: private final Unit<Q> _unit;
297:
298: public Long(long value, Unit<Q> unit) {
299: _value = value;
300: _unit = unit;
301: }
302:
303: @Override
304: public Unit<Q> getUnit() {
305: return _unit;
306: }
307:
308: @Override
309: public java.lang.Long getValue() {
310: return _value;
311: }
312:
313: @Override
314: public Measure<java.lang.Long, Q> to(Unit<Q> unit) {
315: if ((unit == _unit) || (unit.equals(_unit)))
316: return this ;
317: return new Long<Q>(longValue(unit), unit);
318: }
319:
320: public double doubleValue(Unit<Q> unit) {
321: if ((unit == _unit) || (unit.equals(_unit)))
322: return _value;
323: return _unit.getConverterTo(unit).convert(_value);
324: }
325:
326: public long longValue(Unit<Q> unit) throws ArithmeticException {
327: if ((unit == _unit) || (unit.equals(_unit)))
328: return _value; // No conversion, returns value directly.
329: return super .longValue(unit);
330: }
331:
332: private static final long serialVersionUID = 1L;
333:
334: }
335:
336: /**
337: * Holds scalar implementation for <code>float</code> values.
338: */
339: private static final class Float<Q extends Quantity> extends
340: Measure<java.lang.Float, Q> {
341:
342: private final float _value;
343:
344: private final Unit<Q> _unit;
345:
346: public Float(float value, Unit<Q> unit) {
347: _value = value;
348: _unit = unit;
349: }
350:
351: @Override
352: public Unit<Q> getUnit() {
353: return _unit;
354: }
355:
356: @Override
357: public java.lang.Float getValue() {
358: return _value;
359: }
360:
361: @Override
362: public Measure<java.lang.Float, Q> to(Unit<Q> unit) {
363: if ((unit == _unit) || (unit.equals(_unit)))
364: return this ;
365: return new Float<Q>(floatValue(unit), unit);
366: }
367:
368: public double doubleValue(Unit<Q> unit) {
369: if ((unit == _unit) || (unit.equals(_unit)))
370: return _value;
371: return _unit.getConverterTo(unit).convert(_value);
372: }
373:
374: private static final long serialVersionUID = 1L;
375: }
376:
377: /**
378: * Holds scalar implementation for <code>long</code> values.
379: */
380: private static final class Integer<Q extends Quantity> extends
381: Measure<java.lang.Integer, Q> {
382:
383: private final int _value;
384:
385: private final Unit<Q> _unit;
386:
387: public Integer(int value, Unit<Q> unit) {
388: _value = value;
389: _unit = unit;
390: }
391:
392: @Override
393: public Unit<Q> getUnit() {
394: return _unit;
395: }
396:
397: @Override
398: public java.lang.Integer getValue() {
399: return _value;
400: }
401:
402: @Override
403: public Measure<java.lang.Integer, Q> to(Unit<Q> unit) {
404: if ((unit == _unit) || (unit.equals(_unit)))
405: return this ;
406: return new Integer<Q>(intValue(unit), unit);
407: }
408:
409: public double doubleValue(Unit<Q> unit) {
410: if ((unit == _unit) || (unit.equals(_unit)))
411: return _value;
412: return _unit.getConverterTo(unit).convert(_value);
413: }
414:
415: public long longValue(Unit<Q> unit) throws ArithmeticException {
416: if ((unit == _unit) || (unit.equals(_unit)))
417: return _value; // No conversion, returns value directly.
418: return super .longValue(unit);
419: }
420:
421: private static final long serialVersionUID = 1L;
422:
423: }
424:
425: /**
426: * @deprecated {@link DecimalMeasure} should be used directly.
427: */
428: public static <Q extends Quantity> Measure<BigDecimal, Q> valueOf(
429: BigDecimal decimal, Unit<Q> unit) {
430: return DecimalMeasure.valueOf(decimal, unit);
431: }
432:
433: /**
434: * @deprecated {@link DecimalMeasure} should be used directly and
435: * <code>MathContext</code> specified explicitly when
436: * {@link DecimalMeasure#to(Unit, MathContext) converting}.
437: */
438: public static <Q extends Quantity> Measure<BigDecimal, Q> valueOf(
439: BigDecimal decimal, Unit<Q> unit, MathContext mathContext) {
440: return DecimalMeasure.valueOf(decimal, unit);
441: }
442:
443: /**
444: * @deprecated {@link VectorMeasure} should be used directly.
445: */
446: public static <Q extends Quantity> Measure<double[], Q> valueOf(
447: double[] components, Unit<Q> unit) {
448: return VectorMeasure.valueOf(components, unit);
449: }
450: }
|