001/*
002 * Units of Measurement API
003 * Copyright (c) 2014-2023, Jean-Marie Dautelle, Werner Keil, Otavio Santana.
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-385 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:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
067 * @author <a href="mailto:steve@unidata.ucar.edu">Steve Emmerson</a>
068 * @author <a href="mailto:martin.desruisseaux@geomatys.com">Martin Desruisseaux</a>
069 * @author <a href="mailto:werner@units.tech">Werner Keil</a>
070 * @version 2.4, November 11, 2020
071 * @since 1.0
072 *
073 * @see <a href="http://en.wikipedia.org/wiki/Units_of_measurement">Wikipedia: Units of measurement</a>
074 */
075public interface Unit<Q extends Quantity<Q>> {
076
077    /*******************/
078    /** Units Queries **/
079    /*******************/
080
081    /**
082     * Returns the symbol (if any) of this unit. This method returns {@code null} if this unit has no specific symbol associated with.
083     *
084     * @return this unit symbol, or {@code null} if this unit has not specific symbol associated with (e.g. product of units).
085     *
086     * @see #toString()
087     * @see javax.measure.format.UnitFormat
088     */
089    String getSymbol();
090
091    /**
092     * Returns the name (if any) of this unit. This method returns {@code null} if this unit has no specific name associated with.
093     *
094     * @return this unit name, or {@code null} if this unit has not specific name associated with (e.g. product of units).
095     *
096     * @see #toString()
097     * @see javax.measure.format.UnitFormat
098     */
099    String getName();
100
101    /**
102     * Returns the dimension of this unit. Two units {@code u1} and {@code u2} are {@linkplain #isCompatible(Unit) compatible} if and only if
103     * {@code u1.getDimension().equals(u2.getDimension())}.
104     *
105     * @return the dimension of this unit.
106     *
107     * @see #isCompatible(Unit)
108     */
109    Dimension getDimension();
110
111    /**
112     * Returns the unscaled system unit from which this unit is derived. System units are either base units, {@linkplain #alternate(String) alternate}
113     * units or product of rational powers of system units.
114     *
115     * <p>
116     * Because the system unit is unique by quantity type, it can be be used to identify the quantity given the unit. For example:
117     * </p>
118     * <code>
119     *     static boolean isAngularSpeed(Unit&lt;?&gt; unit) {<br>
120     *     &nbsp;&nbsp;    return unit.getSystemUnit().equals(RADIAN.divide(SECOND));<br>
121     *     }<br>
122     *     assert isAngularSpeed(REVOLUTION.divide(MINUTE)); // Returns true.<br><br>
123     * </code>
124     *
125     * @return the system unit this unit is derived from, or {@code this} if this unit is a system unit.
126     */
127    Unit<Q> getSystemUnit();
128
129    /**
130     * 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
131     * units).
132     *
133     * @return the base units and their exponent making up this unit.
134     */
135    Map<? extends Unit<?>, Integer> getBaseUnits();
136
137    /**
138     * Indicates if this unit is compatible with the unit specified. Units don't need to be equal to be compatible. For example (assuming {@code ONE}
139     * is a dimensionless unit):<br>
140     *
141     * <code>
142     *     RADIAN.equals(ONE) == false<br>
143     *     RADIAN.isCompatible(ONE) == true<br>
144     *     RADIAN.isEquivalentTo(ONE) <b>doesn't compile</b><br>
145     * </code>
146     *
147     * @param that
148     *          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     * Indicates if this unit represents the same quantity than the given unit, ignoring name and symbols.
157     * Two units are equivalent if the {@linkplain #getConverterTo(Unit) conversion} between them is identity.
158     *
159     * <p>
160     * Unlike {@link #isCompatible(Unit)} an equivalence check requires both units to be strictly type-compatible,
161     * because it makes no sense to compare e.g. {@code gram} and {@code mm} for equivalence.
162     * By contrast, the compatibility check can works across different quantity types.
163     * </p>
164     *
165     * @param that the {@code Unit<Q>} to be compared with this instance.
166     * @return {@code true} if {@code that \u2261 this}.
167     * @throws NullPointerException if the unit is null
168     *
169     * @see <a href= "https://dictionary.cambridge.org/dictionary/english/equivalent">Cambridge Dictionary: equivalent</a>
170     * @see <a href= "https://www.lexico.com/en/definition/equivalent">LEXICO: equivalent</a>
171     * @since 2.1
172     */
173    boolean isEquivalentTo(Unit<Q> that);
174
175    /**
176     * Casts this unit to a parameterized unit of specified nature or throw a {@code ClassCastException} if the dimension of the specified quantity and
177     * this unit's dimension do not match. For example:<br>
178     *
179     * <code>
180     *      {@literal Unit<Speed>} C = METRE.multiply(299792458).divide(SECOND).asType(Speed.class);
181     * </code>
182     *
183     * @param <T>
184     *          The type of the quantity measured by the unit.
185     * @param type
186     *          the quantity class identifying the nature of the unit.
187     * @return this unit parameterized with the specified type.
188     * @throws ClassCastException
189     *           if the dimension of this unit is different from the specified quantity dimension.
190     */
191    <T extends Quantity<T>> Unit<T> asType(Class<T> type) throws ClassCastException;
192
193    /**
194     * Returns a converter of numeric values from this unit to another unit of same type. This method performs the same work as
195     * {@link #getConverterToAny(Unit)} without raising checked exception.
196     *
197     * @param that
198     *          the unit of same type to which to convert the numeric values.
199     * @return the converter from this unit to {@code that} unit.
200     * @throws UnconvertibleException
201     *           if a converter cannot be constructed.
202     *
203     * @see #getConverterToAny(Unit)
204     */
205    UnitConverter getConverterTo(Unit<Q> that) throws UnconvertibleException;
206
207    /**
208     * 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
209     * unknown at compile-time or when dimensional analysis allows for conversion between units of different type.
210     *
211     * <p>
212     * To convert to a unit having the same parameterized type, {@link #getConverterTo(Unit)} is preferred (no checked exception raised).
213     * </p>
214     *
215     * @param that
216     *          the unit to which to convert the numeric values.
217     * @return the converter from this unit to {@code that} unit.
218     * @throws IncommensurableException
219     *           if this unit is not {@linkplain #isCompatible(Unit) compatible} with {@code that} unit.
220     * @throws UnconvertibleException
221     *           if a converter cannot be constructed.
222     *
223     * @see #getConverterTo(Unit)
224     * @see #isCompatible(Unit)
225     */
226    UnitConverter getConverterToAny(Unit<?> that) throws IncommensurableException, UnconvertibleException;
227
228    /**********************/
229    /** Units Operations **/
230    /**********************/
231
232    /**
233     * Returns a system unit equivalent to this unscaled standard unit but used in expressions to distinguish between quantities of a different nature
234     * but of the same dimensions.
235     *
236     * <p>
237     * Examples of alternate units:
238     * </p>
239     *
240     * <code>
241     *     {@literal Unit<Angle>} RADIAN = ONE.alternate("rad").asType(Angle.class);<br>
242     *     {@literal Unit<Force>} NEWTON = METRE.multiply(KILOGRAM).divide(SECOND.pow(2)).alternate("N").asType(Force.class);<br>
243     *     {@literal Unit<Pressure>} PASCAL = NEWTON.divide(METRE.pow(2)).alternate("Pa").asType(Pressure.class);<br>
244     * </code>
245     *
246     * @param symbol
247     *          the new symbol for the alternate unit.
248     * @return the alternate unit.
249     * @throws IllegalArgumentException
250     *           if this unit is not an unscaled standard unit.
251     * @throws MeasurementException
252     *           if the specified symbol is not valid or is already associated to a different unit.
253     */
254    Unit<Q> alternate(String symbol);
255
256    /**
257     * 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
258     * convertible with this unit. For example the following code:<br>
259     *
260     * <code>
261     *    CELSIUS = KELVIN.shift(273.15);
262     * </code>
263     *
264     * 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
265     * <em>subtracting</em> the offset to the value in the old unit.
266     *
267     * @param offset
268     *          the offset added (expressed in this unit).
269     * @return this unit offset by the specified value.
270     * @since 2.0
271     */
272    Unit<Q> shift(Number offset);
273
274    /**
275     * 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
276     * convertible with this unit. For example the following code:<br>
277     *
278     * <code>
279     *    CELSIUS = KELVIN.shift(273.15);
280     * </code>
281     *
282     * 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
283     * <em>subtracting</em> the offset to the value in the old unit.
284     *
285     * @param offset
286     *          the offset added (expressed in this unit).
287     * @return this unit offset by the specified value.
288     */
289    Unit<Q> shift(double offset);
290
291    /**
292     * Returns the result of multiplying this unit by the specified factor. If the factor is an integer value, the multiplication is exact
293     * (recommended). For example:<br>
294     *
295     * <code>
296     *    FOOT = METRE.multiply(3048).divide(10000); // Exact definition.<br>
297     *    ELECTRON_MASS = KILOGRAM.multiply(9.10938188e-31); // Approximation.
298     * </code>
299     *
300     * @param multiplier
301     *          the multiplier
302     * @return this unit scaled by the specified multiplier.
303     * @since 2.0
304     */
305    Unit<Q> multiply(Number multiplier);
306
307    /**
308     * Returns the result of multiplying this unit by the specified factor. For example:<br>
309     *
310     * <code>
311     *    FOOT = METRE.multiply(3048).divide(10000); // Exact definition.<br>
312     *    ELECTRON_MASS = KILOGRAM.multiply(9.10938188e-31); // Approximation.
313     * </code>
314     *
315     * @param multiplier
316     *          the multiplier
317     * @return this unit scaled by the specified multiplier.
318     */
319    Unit<Q> multiply(double multiplier);
320
321    /**
322     * Returns the product of this unit with the one specified.
323     *
324     * @param multiplier
325     *          the unit multiplier.
326     * @return {@code this * multiplier}
327     */
328    Unit<?> multiply(Unit<?> multiplier);
329
330    /**
331     * Returns the reciprocal (multiplicative inverse) of this unit.
332     *
333     * @return {@code 1 / this}
334     * @see <a href="https://en.wikipedia.org/wiki/Multiplicative_inverse">Wikipedia: Multiplicative inverse</a>
335     */
336    Unit<?> inverse();
337
338    /**
339     * Returns the result of dividing this unit by a divisor. If the factor is an integer value, the division is exact. For example:<br>
340     *
341     * <code>
342     *    GRAM = KILOGRAM.divide(1000); // Exact definition.
343     * </code>
344     *
345     * @param divisor
346     *          the divisor value.
347     * @return this unit divided by the specified divisor.
348     * @since 2.0
349     */
350    Unit<Q> divide(Number divisor);
351
352    /**
353     * Returns the result of dividing this unit by an approximate divisor. For example:<br>
354     *
355     * <code>
356     *    GRAM = KILOGRAM.divide(1000d);
357     * </code>
358     *
359     * @param divisor
360     *          the divisor value.
361     * @return this unit divided by the specified divisor.
362     */
363    Unit<Q> divide(double divisor);
364
365    /**
366     * Returns the quotient of this unit with the one specified.
367     *
368     * @param divisor
369     *          the unit divisor.
370     * @return {@code this / divisor}
371     */
372    Unit<?> divide(Unit<?> divisor);
373
374    /**
375     * Returns an unit that is the n-th (integer) root of this unit. Equivalent to the mathematical expression {@code unit^(1/n)}.
376     *
377     * @param n
378     *          an integer giving the root's order as in 'n-th root'
379     * @return the n-th root of this unit.
380     * @throws ArithmeticException
381     *           if {@code n == 0} or if this operation would result in an unit with a fractional exponent.
382     */
383    Unit<?> root(int n);
384
385    /**
386     * Returns an unit raised to the n-th (integer) power of this unit. Equivalent to the mathematical expression {@code unit^n}.
387     *
388     * @param n
389     *          the exponent.
390     * @return the result of raising this unit to the exponent.
391     */
392    Unit<?> pow(int n);
393
394    /**
395     * Returns the unit derived from this unit using the specified converter. The converter does not need to be linear. For example:<br>
396     *
397     * <pre>
398     *     {@literal Unit<Dimensionless>} DECIBEL = Unit.ONE.transform(
399     *         new LogConverter(10).inverse().concatenate(
400     *             new RationalConverter(1, 10)));
401     * </pre>
402     *
403     * @param operation
404     *          the converter from the transformed unit to this unit.
405     * @return the unit after the specified transformation.
406     */
407    Unit<Q> transform(UnitConverter operation);
408
409    /**
410     * Returns a string representation of this unit. The string representation may be the unit {@linkplain #getSymbol() symbol}, or may be some
411     * representation of {@linkplain #getBaseUnits() product units}, multiplication factor and offset if any.
412     *
413     * <p>
414     * The string may be localized at implementation choice by the means of a particular device and platform.
415     * </p>
416     *
417     * @return the string representation of this unit.
418     *
419     * @see #getSymbol()
420     * @see javax.measure.format.UnitFormat
421     */
422    @Override
423    String toString();
424
425    /**
426     * Returns a new unit equal to this unit prefixed by the specified {@code prefix}.
427     *
428     * @param prefix
429     *          the prefix to apply on this unit.
430     * @return the unit with the given prefix applied.
431     * @since 2.0
432     */
433    Unit<Q> prefix(Prefix prefix);
434}