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 */
009package javax.measure;
010
011import java.io.Serializable;
012import java.math.BigDecimal;
013import java.math.MathContext;
014
015import javax.measure.quantity.Quantity;
016import javax.measure.unit.CompoundUnit;
017import 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 */
030public abstract class Measure<V, Q extends Quantity> implements Measurable<Q>,
031        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(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}