001/*
002 * Units of Measurement API
003 * Copyright (c) 2014-2016, 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 length, time, heat, or value) adopted as a standard of measurement.
041 *
042 * <p>
043 * It is helpful to think of instances of this class as recording the history by which they are created. Thus, for example, the string {@code "g/kg"}
044 * (which is a dimensionless unit) would result from invoking the method {@link #toString()} on a unit that was created by dividing a gram unit by a
045 * kilogram unit.
046 * </p>
047 *
048 * <p>
049 * This interface supports the multiplication of offsets units. The result is usually a unit not convertible to its {@linkplain #getSystemUnit()
050 * system unit}. Such units may appear in derivative quantities. For example Celsius per meter is an unit of gradient, which is common in atmospheric
051 * and oceanographic research.
052 * </p>
053 *
054 * <p>
055 * Units raised at non-integral powers are not supported. For example, {@code LITRE.root(2)} raises an {@code ArithmeticException}, but
056 * {@code HECTARE.root(2)} returns {@code HECTOMETRE} (100 metres).
057 * </p>
058 *
059 * <p>
060 * Unit instances shall be immutable.
061 * </p>
062 *
063 * @param <Q>
064 *          The type of the quantity measured by this unit.
065 *
066 * @author <a href="mailto:[email protected]">Jean-Marie Dautelle</a>
067 * @author <a href="mailto:[email protected]">Steve Emmerson</a>
068 * @author <a href="mailto:[email protected]">Martin Desruisseaux</a>
069 * @author <a href="mailto:[email protected]">Werner Keil</a>
070 * @version 0.22, June 28, 2016
071 *
072 * @see <a href="http://en.wikipedia.org/wiki/Units_of_measurement">Wikipedia: Units of measurement</a>
073 */
074public interface Unit<Q extends Quantity<Q>> {
075
076  /*******************/
077  /** Units Queries **/
078  /*******************/
079
080  /**
081   * Returns the symbol (if any) of this unit. This method returns {@code null} if this unit has no specific symbol associated with.
082   *
083   * @return this unit symbol, or {@code null} if this unit has not specific symbol associated with (e.g. product of units).
084   *
085   * @see #toString()
086   * @see javax.measure.format.UnitFormat
087   */
088  String getSymbol();
089
090  /**
091   * Returns the name (if any) of this unit. This method returns {@code null} if this unit has no specific name associated with.
092   *
093   * @return this unit name, or {@code null} if this unit has not specific name associated with (e.g. product of units).
094   *
095   * @see #toString()
096   * @see javax.measure.format.UnitFormat
097   */
098  String getName();
099
100  /**
101   * Returns the dimension of this unit. Two units {@code u1} and {@code u2} 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. System units are either base units, {@linkplain #alternate(String) alternate}
112   * units or product of rational powers of system units.
113   *
114   * <p>
115   * Because the system unit is unique by quantity type, it can be be used to identify the quantity given the unit. For example:
116   * </p>
117   * <code>
118   *     static boolean isAngularSpeed(Unit<?> unit) {<br>
119   *     &nbsp;&nbsp;    return unit.getSystemUnit().equals(RADIAN.divide(SECOND));<br>
120   *     }<br>
121   *     assert isAngularSpeed(REVOLUTION.divide(MINUTE)); // Returns true.<br><br>
122   * </code>
123   *
124   * @return the system unit this unit is derived from, or {@code this} if this unit is a system unit.
125   */
126  Unit<Q> getSystemUnit();
127
128  /**
129   * Returns the base units and their exponent whose product is this unit, or {@code null} if this unit is a base unit (not a product of existing
130   * units).
131   *
132   * @return the base units and their exponent making up this unit.
133   */
134  Map<? extends Unit<?>, Integer> getBaseUnits();
135
136  /**
137   * Indicates if this unit is compatible with the unit specified. Units don't need to be equals to be compatible. For example (assuming {@code ONE}
138   * is a dimensionless unit):
139   *
140   * <code>
141   *     RADIAN.equals(ONE) == false<br>
142   *     RADIAN.isCompatible(ONE) == true<br>
143   * </code>
144   *
145   * @param that
146   *          the other unit to compare for compatibility.
147   * @return {@code this.getDimension().equals(that.getDimension())}
148   *
149   * @see #getDimension()
150   */
151  boolean isCompatible(Unit<?> that);
152
153  /**
154   * Casts this unit to a parameterized unit of specified nature or throw a {@code ClassCastException} if the dimension of the specified quantity and
155   * this unit's dimension do not match. For example:
156   *
157   * <code>
158   *      {@literal Unit<Speed>} C = METRE.multiply(299792458).divide(SECOND).asType(Speed.class);
159   * </code>
160   *
161   * @param <T>
162   *          The type of the quantity measured by the unit.
163   * @param type
164   *          the quantity class identifying the nature of the unit.
165   * @return this unit parameterized with the specified type.
166   * @throws ClassCastException
167   *           if the dimension of this unit is different from the specified quantity dimension.
168   */
169  <T extends Quantity<T>> Unit<T> asType(Class<T> type) throws ClassCastException;
170
171  /**
172   * Returns a converter of numeric values from this unit to another unit of same type. This method performs the same work than
173   * {@link #getConverterToAny(Unit)} without raising checked exception.
174   *
175   * @param that
176   *          the unit of same type to which to convert the numeric values.
177   * @return the converter from this unit to {@code that} unit.
178   * @throws UnconvertibleException
179   *           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. This method can be used when the quantity type of the specified unit is
187   * unknown at compile-time or when dimensional analysis allows for conversion between units of different type.
188   *
189   * <p>
190   * To convert to a unit having the same parameterized type, {@link #getConverterTo(Unit)} is preferred (no checked exception raised).
191   * </p>
192   *
193   * @param that
194   *          the unit to which to convert the numeric values.
195   * @return the converter from this unit to {@code that} unit.
196   * @throws IncommensurableException
197   *           if this unit is not {@linkplain #isCompatible(Unit) compatible} with {@code that}�unit.
198   * @throws UnconvertibleException
199   *           if a converter cannot be constructed.
200   *
201   * @see #getConverterTo(Unit)
202   * @see #isCompatible(Unit)
203   */
204  UnitConverter getConverterToAny(Unit<?> that) throws IncommensurableException, UnconvertibleException;
205
206  /**********************/
207  /** Units Operations **/
208  /**********************/
209
210  /**
211   * Returns a system unit equivalent to this unscaled standard unit but used in expressions to distinguish between quantities of a different nature
212   * but of the same dimensions.
213   *
214   * <p>
215   * Examples of alternate units:
216   * </p>
217   *
218   * <code>
219   *     {@literal Unit<Angle>} RADIAN = ONE.alternate("rad").asType(Angle.class);<br>
220   *     {@literal Unit<Force>} NEWTON = METRE.multiply(KILOGRAM).divide(SECOND.pow(2)).alternate("N").asType(Force.class);<br>
221   *     {@literal Unit<Pressure>} PASCAL = NEWTON.divide(METRE.pow(2)).alternate("Pa").asType(Pressure.class);<br>
222   * </code>
223   *
224   * @param symbol
225   *          the new symbol for the alternate unit.
226   * @return the alternate unit.
227   * @throws UnsupportedOperationException
228   *           if this unit is not an unscaled standard unit.
229   * @throws IllegalArgumentException
230   *           if the specified symbol is already associated to a different unit.
231   */
232  Unit<Q> alternate(String symbol);
233
234  /**
235   * Returns the result of setting the origin of the scale of measurement to the given value. The returned unit is convertible with all units that are
236   * convertible with this unit. For example the following code:
237   *
238   * <code>
239   *    CELSIUS = KELVIN.shift(273.15);
240   * </code>
241   *
242   * creates a new unit where 0�C (the origin of the new unit) is equals to 273.15 K. Converting from the old unit to the new one is equivalent to
243   * <em>subtracting</em> the offset to the value in the old unit.
244   *
245   * @param offset
246   *          the offset added (expressed in this unit).
247   * @return this unit offset by the specified value.
248   */
249  Unit<Q> shift(double offset);
250
251  /**
252   * Returns the result of multiplying this unit by the specified factor. If the factor is an integer value, the multiplication is exact
253   * (recommended). For example:
254   *
255   * <code>
256   *    FOOT = METRE.multiply(3048).divide(10000); // Exact definition.
257   *    ELECTRON_MASS = KILOGRAM.multiply(9.10938188e-31); // Approximation.
258   * </code>
259   *
260   * @param multiplier
261   *          the multiplier
262   * @return this unit scaled by the specified multiplier.
263   */
264  Unit<Q> multiply(double multiplier);
265
266  /**
267   * Returns the product of this unit with the one specified.
268   *
269   * @param multiplier
270   *          the unit multiplier.
271   * @return {@code this * multiplier}
272   */
273  Unit<?> multiply(Unit<?> multiplier);
274
275  /**
276   * Returns the inverse of this unit.
277   *
278   * @return {@code 1 / this}
279   */
280  Unit<?> inverse();
281
282  /**
283   * Returns the result of dividing this unit by an approximate divisor. If the factor is an integer value, the division is exact. For example:
284   *
285   * <code>
286   *    GRAM = KILOGRAM.divide(1000); // Exact definition.
287   * </code>
288   *
289   * @param divisor
290   *          the divisor value.
291   * @return this unit divided by the specified divisor.
292   */
293  Unit<Q> divide(double divisor);
294
295  /**
296   * Returns the quotient of this unit with the one specified.
297   *
298   * @param divisor
299   *          the unit divisor.
300   * @return {@code this / divisor}
301   */
302  Unit<?> divide(Unit<?> divisor);
303
304  /**
305   * Returns a unit equals to the given root of this unit.
306   *
307   * @param n
308   *          the root's order.
309   * @return the result of taking the given root of this unit.
310   * @throws ArithmeticException
311   *           if {@code n == 0} or if this operation would result in an unit with a fractional exponent.
312   */
313  Unit<?> root(int n);
314
315  /**
316   * Returns a unit equals to this unit raised to an exponent.
317   *
318   * @param n
319   *          the exponent.
320   * @return the result of raising this unit to the exponent.
321   */
322  Unit<?> pow(int n);
323
324  /**
325   * Returns the unit derived from this unit using the specified converter. The converter does not need to be linear. For example:<br>
326   * <code>
327   *     {@literal Unit<Dimensionless>} DECIBEL = Unit.ONE.transform(
328   *         new LogConverter(10).inverse().concatenate(
329   *             new RationalConverter(1, 10)));
330   * </code>
331   *
332   * @param operation
333   *          the converter from the transformed unit to this unit.
334   * @return the unit after the specified transformation.
335   */
336  Unit<Q> transform(UnitConverter operation);
337
338  /**
339   * <p>
340   * Returns a string representation of this unit. The string representation may be the unit {@linkplain #getSymbol() symbol}, or may be some
341   * representation of {@linkplain #getBaseUnits() product units}, multiplication factor and offset if any.
342   * </p>
343   * The string may be localized at implementation choice by the means of a particular device and platform. <br>
344   *
345   * @return the string representation of this unit.
346   *
347   * @see #getSymbol()
348   */
349  @Override
350  String toString();
351}