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 */
030package javax.measure;
031
032/**
033 * Represents a quantitative property of a phenomenon, body, or substance, that
034 * can be quantified by measurement. {@link javax.measure.quantity.Mass Mass},
035 * time, distance, heat, and angular separation are among the familiar examples
036 * of quantitative properties.
037 * <p>
038 * <code> {@literal Unit<Mass>} pound = ... {@literal Quantity<Length>} size = ... {@literal Sensor<Temperature>}<br>
039 * thermometer = ... {@literal Vector3D<Speed>} aircraftSpeed = ... </code>
040 * </p>
041 *
042 * <dl>
043 * <dt><span class="strong">Arithmetic operations</span></dt>
044 * </dl> 
045 * This interface defines some arithmetic operations between {@code Quantity}
046 * instances. All implementations shall produce <em>equivalent</em> results for
047 * the same operation applied on equivalent quantities. Two quantities are
048 * equivalent if, after conversion to the same unit of measurement, they have
049 * the same numerical value (ignoring rounding errors). For example 2000 metres
050 * is equivalent to 2 km, but 2°C is not equivalent to 2 K; it is equivalent to
051 * 275.15 K instead. Above requirement applied to addition means that 2°C + 2 K
052 * shall be equivalent to 275.15 K + 2 K.
053 *
054 * <p>All operations shall preserve the
055 * <a href="https://en.wikiversity.org/wiki/Basic_Laws_of_Algebra">basic laws
056 * of algebra</a>, in particular <b>commutativity</b> of addition and
057 * multiplication (<var>A</var> + <var>B</var> = <var>B</var> + <var>A</var>)
058 * and <b>associativity</b> of addition and multiplication (<var>A</var> +
059 * <var>B</var>) + <var>C</var> = <var>A</var> + (<var>B</var> + <var>C</var>).
060 * In order to preserve those algebra laws, this specification requires all
061 * arithmetic operations to execute <em>as is</em> all operands were converted
062 * to {@linkplain Unit#getSystemUnit() system unit} before the operation is
063 * carried out, and the result converted back to any compatible unit at
064 * implementation choice. For example 4 cm + 1 inch shall produce any result
065 * <em>equivalent</em> to 0.04 m + 0.0254 m.</p>
066 *
067 * <p>Implementations are allowed to avoid conversion to system unit if the
068 * result is guaranteed to be equivalent. This is often the case when the
069 * conversion between quantity unit and system unit is only a
070 * {@linkplain UnitConverter#isLinear() scale factor}. However this is not
071 * the case for conversions applying an offset or more complex formula.
072 * For example 2°C + 1°C = 274.15°C, not 3°C. This counter-intuitive result
073 * is essential for preserving algebra laws like associativity, and is also
074 * the expected result from a thermodynamic point of view.</p>
075 *
076 * <dl>
077 * <dt><span class="strong">API Note:</span></dt><dd>This interface places no restrictions on the mutability of
078 *          implementations, however immutability is strongly recommended. All
079 *          implementations must be {@link Comparable}.</dd>
080 * </dl>
081 *
082 * @param <Q>
083 *            The type of the quantity.
084 *
085 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
086 * @author <a href="mailto:martin.desruisseaux@geomatys.com">Martin
087 *         Desruisseaux</a>
088 * @author <a href="mailto:werner@uom.technology">Werner Keil</a>
089 * @author <a href="mailto:otaviopolianasantana@gmail.com">Otavio Santana</a>
090 * @see Unit
091 * @see <a href="http://en.wikipedia.org/wiki/Quantity">Wikipedia: Quantity</a>
092 * @see <a href="http://martinfowler.com/eaaDev/quantity.html">Martin Fowler -
093 *      Quantity</a>
094 * @version 2.5, May 20, 2023
095 * @since 1.0
096 */
097public interface Quantity<Q extends Quantity<Q>> {
098    
099   /**
100    * The scale of a {@link Quantity}, either {@code ABSOLUTE} or {@code RELATIVE}.
101    *
102    * @since 2.0
103    * @see <a href="https://en.wikipedia.org/wiki/Absolute_scale">Wikipedia: Absolute scale</a>
104    */
105    public static enum Scale {
106        /** 
107         * Absolute scale
108         * @see <a href="https://en.wikipedia.org/wiki/Absolute_scale">Wikipedia: Absolute scale</a> 
109         */
110        ABSOLUTE, 
111        /** 
112         * Relative scale 
113         */
114        RELATIVE
115    }
116       
117    /**
118     * Returns the sum of this {@code Quantity} with the one specified.
119     * The result shall be as if this quantity and the given addend were
120     * converted to {@linkplain Unit#getSystemUnit() system unit} before
121     * to be added, and the result converted back to the unit of this
122     * quantity or any other compatible unit at implementation choice.
123     *
124     * @param addend
125     *            the {@code Quantity} to be added.
126     * @return {@code this + addend}.
127     */
128    Quantity<Q> add(Quantity<Q> addend);
129
130    /**
131     * Returns the difference between this {@code Quantity} and the one specified.
132     * The result shall be as if this quantity and the given subtrahend were
133     * converted to {@linkplain Unit#getSystemUnit() system unit} before
134     * to be subtracted, and the result converted back to the unit of this
135     * quantity or any other compatible unit at implementation choice.
136     *
137     * @param subtrahend
138     *            the {@code Quantity} to be subtracted.
139     * @return <code>this - subtrahend</code>.
140     */
141    Quantity<Q> subtract(Quantity<Q> subtrahend);
142
143    /**
144     * Returns the quotient of this {@code Quantity} divided by the {@code Quantity}
145     * specified.
146     * The result shall be as if this quantity and the given divisor were
147     * converted to {@linkplain Unit#getSystemUnit() system unit} before
148     * to be divided, and the result converted back to the unit of this
149     * quantity or any other compatible unit at implementation choice.
150     *
151     * @throws ClassCastException
152     *             if the type of an element in the specified operation is
153     *             incompatible with this quantity
154     *
155     * @param divisor
156     *            the {@code Quantity} divisor.
157     * @return <code>this / divisor</code>.
158     */
159    Quantity<?> divide(Quantity<?> divisor);
160
161    /**
162     * Returns the quotient of this {@code Quantity} divided by the {@code Number}
163     * specified.
164     * The result shall be as if this quantity was converted to
165     * {@linkplain Unit#getSystemUnit() system unit} before to be divided,
166     * and the result converted back to the unit of this quantity or any
167     * other compatible unit at implementation choice.
168     *
169     * @param divisor
170     *            the {@code Number} divisor.
171     * @return <code>this / divisor</code>.
172     */
173    Quantity<Q> divide(Number divisor);
174
175    /**
176     * Returns the product of this {@code Quantity} with the one specified.
177     * The result shall be as if this quantity and the given multiplicand were
178     * converted to {@linkplain Unit#getSystemUnit() system unit} before
179     * to be multiplied, and the result converted back to the unit of this
180     * quantity or any other compatible unit at implementation choice.
181     *
182     * @throws ClassCastException
183     *             if the type of an element in the specified operation is
184     *             incompatible with this quantity
185     *
186     * @param multiplicand
187     *            the {@code Quantity} multiplicand.
188     * @return <code>this * multiplicand</code>.
189     */
190    Quantity<?> multiply(Quantity<?> multiplicand);
191
192    /**
193     * Returns the product of this {@code Quantity} with the {@code Number} value
194     * specified.
195     * The result shall be as if this quantity was converted to
196     * {@linkplain Unit#getSystemUnit() system unit} before to be multiplied,
197     * and the result converted back to the unit of this quantity or any
198     * other compatible unit at implementation choice.
199     *
200     * @param multiplicand
201     *            the {@code Number} multiplicand.
202     * @return <code>this * multiplicand</code>.
203     */
204    Quantity<Q> multiply(Number multiplicand);
205
206    /**
207     * Returns this {@code Quantity} converted into another (compatible)
208     * {@code Unit}.
209     *
210     * @param unit
211     *            the {@code Unit unit} in which the returned quantity is stated.
212     * @return this quantity or a new quantity equivalent to this quantity stated in the specified unit.
213     * @throws ArithmeticException
214     *             if the result is inexact and the quotient has a non-terminating decimal expansion.
215     */
216    Quantity<Q> to(Unit<Q> unit);
217
218    /**
219     * Returns a {@code Quantity} that is the multiplicative inverse of this
220     * {@code Quantity}, having reciprocal value and reciprocal unit as given by
221     * {@code this.getUnit().inverse()}.
222     *
223     * @return reciprocal {@code Quantity}
224     * @see <a href=
225     *      "https://en.wikipedia.org/wiki/Multiplicative_inverse">Wikipedia:
226     *      Multiplicative inverse</a>
227     */
228    Quantity<?> inverse();
229
230    /**
231     * Returns a {@code Quantity} whose value is {@code (-this.getValue())}.
232     *
233     * @return {@code -this}.
234     */
235    Quantity<Q> negate();
236
237    /**
238     * Casts this quantity to a parameterized unit of specified nature or throw a
239     * <code>ClassCastException</code> if the dimension of the specified quantity
240     * and this measure unit's dimension do not match. For example:
241     * <p>
242     * <code>
243     *     {@literal Quantity<Length>} length = Quantities.getQuantity("2 km").asType(Length.class);
244     * </code> or <code>
245     *     {@literal Quantity<Speed>} C = length.multiply(299792458).divide(second).asType(Speed.class);
246     * </code>
247     * </p>
248     *
249     * @param <T>
250     *            The type of the quantity.
251     * @param type
252     *            the quantity class identifying the nature of the quantity.
253     * @return this quantity parameterized with the specified type.
254     * @throws ClassCastException
255     *             if the dimension of this unit is different from the specified
256     *             quantity dimension.
257     * @throws UnsupportedOperationException
258     *             if the specified quantity class does not have a SI unit for the
259     *             quantity.
260     * @see Unit#asType(Class)
261     */
262    <T extends Quantity<T>> Quantity<T> asType(Class<T> type) throws ClassCastException;
263
264    /**
265     * Returns the value of this {@code Quantity}.
266     *
267     * @return a value.
268     */
269    Number getValue();
270
271    /**
272     * Returns the unit of this {@code Quantity}.
273     *
274     * @return the unit (shall not be {@code null}).
275     */
276    Unit<Q> getUnit();
277    
278    /**
279     * Convenient method equivalent to {@link #to(javax.measure.Unit)
280     * to(getUnit().toSystemUnit())}.
281     *
282     * @return this quantity or a new quantity equivalent to this quantity stated in
283     *         SI units.
284     * @throws ArithmeticException
285     *             if the result is inexact and the quotient has a non-terminating
286     *             decimal expansion.
287     */
288    default Quantity<Q> toSystemUnit() {
289        return to(getUnit().getSystemUnit());
290    }
291      
292    /**
293     * Returns the {@code Scale} of this {@code Quantity}, if it's absolute or relative.
294     *
295     * @return the scale, if it's an absolute or relative quantity.
296     * @since 2.0
297     
298     * @see <a href="https://en.wikipedia.org/wiki/Absolute_scale">Wikipedia: Absolute scale</a>
299     */
300    Scale getScale();
301    
302    /**
303     * Compares two instances of {@code Quantity <Q>}, performing the conversion of units if necessary.
304     *
305     * @param that
306     *          the {@code quantity<Q>} to be compared with this instance.
307     * @return {@code true} if {@code that \u2261 this}.
308     * @throws NullPointerException
309     *           if the quantity is null
310     *           
311     * @see <a href= "https://dictionary.cambridge.org/dictionary/english/equivalent">Cambridge Dictionary: equivalent</a>
312     * @see <a href= "https://www.lexico.com/en/definition/equivalent">LEXICO: equivalent</a>
313     * @since 2.1       
314     */
315    boolean isEquivalentTo(Quantity<Q> that);
316}