001/*
002 * Units of Measurement API
003 * Copyright (c) 2014-2015, Jean-Marie Dautelle, Werner Keil, V2COM.
004 *
005 * All rights reserved.
006 *
007 * Redistribution and use in source and binary forms, with or without modification,
008 * are permitted provided that the following conditions are met:
009 *
010 * 1. Redistributions of source code must retain the above copyright notice,
011 *    this list of conditions and the following disclaimer.
012 *
013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
014 *    and the following disclaimer in the documentation and/or other materials provided with the distribution.
015 *
016 * 3. Neither the name of JSR-363 nor the names of its contributors may be used to endorse or promote products
017 *    derived from this software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030//
031// This source code implements specifications defined by the Java
032// Community Process. In order to remain compliant with the specification
033// DO NOT add / change / or delete method signatures!
034//
035package javax.measure;
036
037import java.util.Map;
038
039/**
040 * Represents a determinate {@linkplain Quantity quantity} (as of
041 * length, time, heat, or value) adopted as a standard of measurement.
042 *
043 * <p>It is helpful to think of instances of this class as recording the history
044 * by which they are created. Thus, for example, the string {@code "g/kg"} (which
045 * is a dimensionless unit) would result from invoking the method {@link #toString()}
046 * on a unit that was created by dividing a gram unit by a kilogram unit.</p>
047 *
048 * <p>This interface supports the multiplication of offsets units. The result is
049 * usually a unit not convertible to its {@linkplain #getSystemUnit() system unit}.
050 * Such units may appear in derivative quantities. For example Celsius per meter is
051 * an unit of gradient, which is common in atmospheric and oceanographic research.</p>
052 *
053 * <p>Units raised at non-integral powers are not supported. For example,
054 * {@code LITRE.root(2)} raises an {@code ArithmeticException}, but
055 * {@code HECTARE.root(2)} returns {@code HECTOMETRE} (100 metres).</p>
056 *
057 * <p>Unit instances shall be immutable.</p>
058 *
059 * @param <Q> The type of the quantity measured by this unit.
060 *
061 * @author <a href="mailto:[email protected]">Jean-Marie Dautelle</a>
062 * @author <a href="mailto:[email protected]">Steve Emmerson</a>
063 * @author <a href="mailto:[email protected]">Martin Desruisseaux</a>
064 * @author <a href="mailto:[email protected]">Werner Keil</a>
065 * @version 0.19, October 13, 2015
066 *
067 * @see <a href="http://en.wikipedia.org/wiki/Units_of_measurement">Wikipedia: Units of measurement</a>
068 */
069public interface Unit<Q extends Quantity<Q>> {
070
071    /*******************/
072    /** Units Queries **/
073    /*******************/
074
075    /**
076     * Returns the symbol (if any) of this unit.
077     * This method returns {@code null} if this unit has no specific symbol associated with.
078     *
079     * @return this unit symbol, or {@code null} if this unit has not
080     *         specific symbol associated with (e.g. product of units).
081     *
082     * @see #toString()
083     * @see UnitFormat
084     */
085    String getSymbol();
086    
087    /**
088     * Returns the name (if any) of this unit.
089     * This method returns {@code null} if this unit has no specific name associated with.
090     *
091     * @return this unit name, or {@code null} if this unit has not
092     *         specific name associated with (e.g. product of units).
093     *
094     * @see #toString()
095     * @see UnitFormat
096     */
097    String getName();
098
099    /**
100     * Returns the dimension of this unit. Two units {@code u1} and {@code u2}
101     * are {@linkplain #isCompatible(Unit) compatible} if and only if
102     * {@code u1.getDimension().equals(u2.getDimension())}.
103     *
104     * @return the dimension of this unit.
105     *
106     * @see #isCompatible(Unit)
107     */
108    Dimension getDimension();
109
110    /**
111     * Returns the unscaled system unit from which this unit is derived.
112     * System units are either base units, {@linkplain #alternate(String)
113     * alternate} units or product of rational powers of system units.
114     *
115     * <p>Because the system unit is unique by quantity type, it can be
116     * be used to identify the quantity given the unit. For example:</p>
117     *
118     * [code]
119     *     static boolean isAngularSpeed(Unit<?> unit) {
120     *         return unit.getSystemUnit().equals(RADIAN.divide(SECOND));
121     *     }
122     *     assert isAngularSpeed(REVOLUTION.divide(MINUTE)); // Returns true.
123     * [/code]
124     *
125     * @return the system unit this unit is derived from,
126     *         or {@code this} if this unit is a system unit.
127     */
128    Unit<Q> getSystemUnit();
129
130    /**
131     * Returns the base units and their exponent whose product is this unit,
132     * or {@code null} if this unit is a base unit (not a product of existing units).
133     *
134     * @return the base units and their exponent making up this unit.
135     */
136    Map<? extends Unit<?>, Integer> getProductUnits();
137
138    /**
139     * Indicates if this unit is compatible with the unit specified.
140     * Units don't need to be equals to be compatible. For example
141     * (assuming {@code ONE} is a dimensionless unit):
142     *
143     * [code]
144     *     RADIAN.equals(ONE) == false
145     *     RADIAN.isCompatible(ONE) == true
146     * [/code]
147     *
148     * @param  that the other unit to compare for compatibility.
149     * @return {@code this.getDimension().equals(that.getDimension())}
150     *
151     * @see #getDimension()
152     */
153    boolean isCompatible(Unit<?> that);
154
155    /**
156     * Casts this unit to a parameterized unit of specified nature or throw a
157     * {@code ClassCastException} if the dimension of the specified quantity
158     * and this unit's dimension do not match. For example:
159     *
160     * [code]
161     *      Unit<Speed> C = METRE.times(299792458).divide(SECOND).asType(Speed.class);
162     * [/code]
163     *
164     * @param  <T> The type of the quantity measured by the unit.
165     * @param  type the quantity class identifying the nature of the unit.
166     * @return this unit parameterized with the specified type.
167     * @throws ClassCastException if the dimension of this unit is different
168     *         from the specified quantity dimension.
169     */
170    <T extends Quantity<T>> Unit<T> asType(Class<T> type) throws ClassCastException;
171
172    /**
173     * Returns a converter of numeric values from this unit to another unit of same type.
174     * This method performs the same work than {@link #getConverterToAny(Unit)} without
175     * raising checked exception.
176     *
177     * @param  that the unit of same type to which to convert the numeric values.
178     * @return the converter from this unit to {@code that} unit.
179     * @throws UnconvertibleException if a converter cannot be constructed.
180     *
181     * @see #getConverterToAny(Unit)
182     */
183    UnitConverter getConverterTo(Unit<Q> that) throws UnconvertibleException;
184
185    /**
186     * Returns a converter from this unit to the specified unit of type unknown.
187     * This method can be used when the quantity type of the specified unit
188     * is unknown at compile-time or when dimensional analysis allows for
189     * conversion between units of different type.
190     *
191     * <p>To convert to a unit having the same parameterized type,
192     * {@link #getConverterTo(Unit)} is preferred (no checked exception raised).</p>
193     *
194     * @param  that the unit to which to convert the numeric values.
195     * @return the converter from this unit to {@code that} unit.
196     * @throws IncommensurableException if this unit is not
197     *         {@linkplain #isCompatible(Unit) compatible} with {@code that}�unit.
198     * @throws UnconvertibleException if a converter cannot be constructed.
199     *
200     * @see #getConverterTo(Unit)
201     * @see #isCompatible(Unit)
202     */
203    UnitConverter getConverterToAny(Unit<?> that) throws IncommensurableException,
204            UnconvertibleException;
205
206    /**********************/
207    /** Units Operations **/
208    /**********************/
209
210    /**
211     * Returns a system unit equivalent to this unscaled standard unit but used
212     * in expressions to distinguish between quantities of a different nature
213     * but of the same dimensions.
214     *
215     * <p>Examples of alternate units:</p>
216     *
217     * [code]
218     *     Unit<Angle> RADIAN = ONE.alternate("rad").asType(Angle.class);
219     *     Unit<Force> NEWTON = METRE.times(KILOGRAM).divide(SECOND.pow(2)).alternate("N").asType(Force.class);
220     *     Unit<Pressure> PASCAL = NEWTON.divide(METRE.pow(2)).alternate("Pa").asType(Pressure.class);
221     * [/code]
222     *
223     * @param  symbol the new symbol for the alternate unit.
224     * @return the alternate unit.
225     * @throws UnsupportedOperationException if this unit is not an unscaled standard unit.
226     * @throws IllegalArgumentException if the specified symbol is already
227     *         associated to a different unit.
228     */
229    Unit<Q> alternate(String symbol);
230
231    /**
232     * Returns the result of setting the origin of the scale of measurement to the given value.
233     * The returned unit is convertible with all units that are convertible with this unit.
234     * For example the following code:
235     *
236     * <code>
237     *    CELSIUS = KELVIN.shift(273.15);
238     * </code>
239     *
240     * creates a new unit where 0�C (the origin of the new unit) is equals to 273.15 K.
241     * Converting from the old unit to the new one is equivalent to <em>subtracting</em>
242     * the offset to the value in the old unit.
243     *
244     * @param  offset the offset added (expressed in this unit).
245     * @return this unit offset by the specified value.
246     */
247    Unit<Q> shift(double offset);
248
249    /**
250     * Returns the result of multiplying this unit by the specified factor.
251     * If the factor is an integer value, the multiplication is exact
252     * (recommended). For example:
253     *
254     * <code>
255     *    FOOT = METRE.multiply(3048).divide(10000); // Exact definition.
256     *    ELECTRON_MASS = KILOGRAM.multiply(9.10938188e-31); // Approximation.
257     * </code>
258     *
259     * @param  multiplier the multiplier
260     * @return this unit scaled by the specified multiplier.
261     */
262    Unit<Q> multiply(double multiplier);
263
264    /**
265     * Returns the product of this unit with the one specified.
266     *
267     * @param  multiplier the unit multiplier.
268     * @return {@code this * multiplier}
269     */
270    Unit<?> multiply(Unit<?> multiplier);
271
272    /**
273     * Returns the inverse of this unit.
274     *
275     * @return {@code 1 / this}
276     */
277    Unit<?> inverse();
278
279    /**
280     * Returns the result of dividing this unit by an approximate divisor.
281     * If the factor is an integer value, the division is exact.
282     * For example:
283     *
284     * <code>
285     *    GRAM = KILOGRAM.divide(1000); // Exact definition.
286     * </code>
287     *
288     * @param  divisor the divisor value.
289     * @return this unit divided by the specified divisor.
290     */
291    Unit<Q> divide(double divisor);
292
293    /**
294     * Returns the quotient of this unit with the one specified.
295     *
296     * @param  divisor the unit divisor.
297     * @return {@code this / divisor}
298     */
299    Unit<?> divide(Unit<?> divisor);
300
301    /**
302     * Returns a unit equals to the given root of this unit.
303     *
304     * @param  n the root's order.
305     * @return the result of taking the given root of this unit.
306     * @throws ArithmeticException if {@code n == 0} or if this operation
307     *         would result in an unit with a fractional exponent.
308     */
309    Unit<?> root(int n);
310
311    /**
312     * Returns a unit equals to this unit raised to an exponent.
313     *
314     * @param  n the exponent.
315     * @return the result of raising this unit to the exponent.
316     */
317    Unit<?> pow(int n);
318
319    /**
320     * Returns the unit derived from this unit using the specified converter.
321     * The converter does not need to be linear. For example:<br>
322     * <code>
323     *     Unit<Dimensionless> DECIBEL = Unit.ONE.transform(
324     *         new LogConverter(10).inverse().concatenate(
325     *             new RationalConverter(1, 10)));
326     * </code>
327     *
328     * @param  operation the converter from the transformed unit to this unit.
329     * @return the unit after the specified transformation.
330     */
331    Unit<Q> transform(UnitConverter converter);
332        
333    /**
334     * <p>Returns a string representation of this unit. The string representation may
335     * be the unit {@linkplain #getSymbol() symbol}, or may be some representation
336     * of {@linkplain #getProductUnits() product units}, multiplication factor and
337     * offset if any.</p>
338     * The string may be localized at implementation choice by the means of a particular device and platform.
339     * <br>
340     * @return the string representation of this unit.
341     *
342     * @see #getSymbol()
343     */
344    @Override
345    String toString();
346}