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 units derived from other units using
016 *     {@link UnitConverter converters}.</p>
017 *     
018 * <p> Examples of transformed units:[code]
019 *         CELSIUS = KELVIN.add(273.15);
020 *         FOOT = METER.multiply(0.3048);
021 *         MILLISECOND = MILLI(SECOND); 
022 *     [/code]</p>
023 *     
024 * <p> Transformed units have no label. But like any other units,
025 *     they may have labels attached to them:[code]
026 *         UnitFormat.getStandardInstance().label(FOOT, "ft");
027 *     [/code]
028 *     or aliases: [code]
029 *         UnitFormat.getStandardInstance().alias(CENTI(METER)), "centimeter");
030 *         UnitFormat.getStandardInstance().alias(CENTI(METER)), "centimetre");
031 *     [/code]</p>
032 *
033 * @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
034 * @version 3.1, April 22, 2006
035 * @see     Unit#plus(double)
036 * @see     Unit#times(double)
037 * @see     Unit#transform(UnitConverter)
038 * @see     UnitFormat
039 */
040public final class TransformedUnit<Q extends Quantity> extends DerivedUnit<Q> {
041
042    /**
043     * Holds the parent unit (not a transformed unit).
044     */
045    private final Unit<Q> _parentUnit;
046
047    /**
048     * Holds the converter to the parent unit.
049     */
050    private final UnitConverter _toParentUnit;
051
052    /**
053     * Creates a transformed unit from the specified parent unit.
054     *
055     * @param parentUnit the untransformed unit from which this unit is 
056     *        derived.
057     * @param  toParentUnit the converter to the parent units.
058     * @throws IllegalArgumentException if <code>toParentUnit == 
059     *         {@link UnitConverter#IDENTITY UnitConverter.IDENTITY}</code>
060     */
061    TransformedUnit(Unit<Q> parentUnit, UnitConverter toParentUnit) {
062        if (toParentUnit == UnitConverter.IDENTITY)
063            throw new IllegalArgumentException("Identity not allowed");
064        _parentUnit = parentUnit;
065        _toParentUnit = toParentUnit;
066    }
067        
068    /**
069     * Returns the parent unit for this unit. The parent unit is the 
070     * untransformed unit from which this unit is derived.
071     *
072     * @return the untransformed unit from which this unit is derived.
073     */
074    public Unit<Q> getParentUnit() {
075        return _parentUnit;
076    }
077        
078    /**
079     * Returns the converter to the parent unit.
080     *
081     * @return the converter to the parent unit.
082     */
083    public UnitConverter toParentUnit() {
084        return _toParentUnit;
085    }
086        
087    /**
088     * Indicates if this transformed unit is considered equals to the specified 
089     * object (both are transformed units with equal parent unit and equal
090     * converter to parent unit).
091     *
092     * @param  that the object to compare for equality.
093     * @return <code>true</code> if <code>this</code> and <code>that</code>
094     *         are considered equals; <code>false</code>otherwise. 
095     */
096    public boolean equals(Object that) {
097        if (this == that) return true;
098        if (!(that instanceof TransformedUnit)) return false;
099        TransformedUnit<?> thatUnit = (TransformedUnit<?>) that; 
100        return this._parentUnit.equals(thatUnit._parentUnit) &&
101                 this._toParentUnit.equals(thatUnit._toParentUnit);
102    }
103
104    // Implements abstract method.
105    public int hashCode() {
106        return _parentUnit.hashCode() + _toParentUnit.hashCode();
107    }
108
109    // Implements abstract method.
110    public Unit<? super Q> getStandardUnit() {
111        return _parentUnit.getStandardUnit();
112    }
113
114    // Implements abstract method.
115    public UnitConverter toStandardUnit() {
116        return _parentUnit.toStandardUnit().concatenate(_toParentUnit);
117    }
118
119    private static final long serialVersionUID = 1L;
120
121}