17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert**********************************************************************
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* Copyright (c) 2004-2013, International Business Machines
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* Corporation and others.  All Rights Reserved.
57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert**********************************************************************
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* Author: Alan Liu
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* Created: April 20, 2004
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert* Since: ICU 3.0
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert**********************************************************************
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.util;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/**
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * An amount of a specified unit, consisting of a Number and a Unit.
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * For example, a length measure consists of a Number and a length
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * unit, such as feet or meters.
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Measure objects are parsed and formatted by subclasses of
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * MeasureFormat.
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * <p>Measure objects are immutable. All subclasses must guarantee that.
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * (However, subclassing is discouraged.)
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see java.lang.Number
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see com.ibm.icu.util.MeasureUnit
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see com.ibm.icu.text.MeasureFormat
287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @author Alan Liu
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @stable ICU 3.0
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpublic class Measure {
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final Number number;
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final MeasureUnit unit;
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Constructs a new object given a number and a unit.
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param number the number
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param unit the unit
407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.0
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Measure(Number number, MeasureUnit unit) {
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (number == null || unit == null) {
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            throw new NullPointerException();
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        this.number = number;
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        this.unit = unit;
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns true if the given object is equal to this object.
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return true if this object is equal to the given object
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.0
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public boolean equals(Object obj) {
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (obj == this) {
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return true;
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!(obj instanceof Measure)) {
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return false;
617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        Measure m = (Measure) obj;
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return unit.equals(m.unit) && numbersEqual(number, m.number);
647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * See if two numbers are identical or have the same double value.
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param a A number
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param b Another number to be compared with
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return Returns true if two numbers are identical or have the same double value.
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // TODO improve this to catch more cases (two different longs that have same double values, BigDecimals, etc)
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static boolean numbersEqual(Number a, Number b) {
747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (a.equals(b)) {
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return true;
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (a.doubleValue() == b.doubleValue()) {
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return true;
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return false;
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns a hashcode for this object.
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return a 32-bit hash
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.0
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public int hashCode() {
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return 31 * Double.valueOf(number.doubleValue()).hashCode() + unit.hashCode();
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns a string representation of this object.
947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return a string representation consisting of the ISO currency
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * code together with the numeric amount
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.0
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public String toString() {
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return number.toString() + ' ' + unit.toString();
1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the numeric value of this object.
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return this object's Number
1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.0
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public Number getNumber() {
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return number;
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /**
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Returns the unit of this object.
1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return this object's Unit
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @stable ICU 3.0
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public MeasureUnit getUnit() {
1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return unit;
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
120