001/*
002 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
003 * Copyright (C) 2006 - 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.unit;
010
011import javax.measure.converter.UnitConverter;
012import javax.measure.quantity.Quantity;
013
014/**
015 * <p> This class represents the multi-radix units (such as "hour:min:sec"). 
016 *     Instances of this class are created using the {@link Unit#compound
017 *     Unit.compound} method.</p>
018 *      
019 * <p> Examples of compound units:[code]
020 *     Unit<Duration> HOUR_MINUTE_SECOND = HOUR.compound(MINUTE).compound(SECOND);
021 *     Unit<Angle> DEGREE_MINUTE_ANGLE = DEGREE_ANGLE.compound(MINUTE_ANGLE);
022 *     [/code]</p>
023 *
024 * @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
025 * @version 3.1, April 22, 2006
026 */
027public final class CompoundUnit<Q extends Quantity> extends DerivedUnit<Q> {
028
029    /**
030     * Holds the higher unit.
031     */
032    private final Unit<Q> _high;
033
034    /**
035     * Holds the lower unit.
036     */
037    private final Unit<Q> _low;
038
039    /**
040     * Creates a compound unit from the specified units. 
041     *
042     * @param  high the high unit.
043     * @param  low the lower unit(s)
044     * @throws IllegalArgumentException if both units do not the same system
045     *         unit.
046     */
047    CompoundUnit(Unit<Q> high, Unit<Q> low) {
048        if (!high.getStandardUnit().equals(low.getStandardUnit()))
049            throw new IllegalArgumentException(
050                    "Both units do not have the same system unit");
051        _high = high;
052        _low = low;
053        
054    }
055
056    /**
057     * Returns the lower unit of this compound unit.
058     *
059     * @return the lower unit.
060     */
061    public Unit<Q> getLower() {
062        return _low;
063    }
064
065    /**
066     * Returns the higher unit of this compound unit.
067     *
068     * @return the higher unit.
069     */
070    public Unit<Q> getHigher() {
071        return _high;
072    }
073
074    /**
075     * Indicates if this compound unit is considered equals to the specified 
076     * object (both are compound units with same composing units in the 
077     * same order).
078     *
079     * @param  that the object to compare for equality.
080     * @return <code>true</code> if <code>this</code> and <code>that</code>
081     *         are considered equals; <code>false</code>otherwise. 
082     */
083    public boolean equals(Object that) {
084        if (this == that)
085            return true;
086        if (!(that instanceof CompoundUnit))
087            return false;
088        CompoundUnit<?> thatUnit = (CompoundUnit<?>) that;
089        return this._high.equals(thatUnit._high)
090                && this._low.equals(thatUnit._low);
091    }
092
093    @Override
094    public int hashCode() {
095        return _high.hashCode() ^ _low.hashCode();
096    }
097
098    @Override
099    public Unit<? super Q> getStandardUnit() {
100        return _low.getStandardUnit(); 
101    }
102
103    @Override
104    public UnitConverter toStandardUnit() {
105        return _low.toStandardUnit();
106    }
107
108    private static final long serialVersionUID = 1L;
109}