001/*
002 * Units of Measurement Reference Implementation
003 * Copyright (c) 2005-2021, 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, Indriya nor the names of their 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 tech.units.indriya.quantity;
031
032import static javax.measure.Quantity.Scale.ABSOLUTE;
033import static org.apiguardian.api.API.Status.MAINTAINED;
034
035import javax.measure.Quantity;
036import javax.measure.Unit;
037
038import org.apiguardian.api.API;
039
040import tech.units.indriya.AbstractQuantity;
041import tech.units.indriya.ComparableQuantity;
042import tech.units.indriya.internal.function.Calculator;
043import tech.units.indriya.internal.function.ScaleHelper;
044
045/**
046 * Implementation of {@link ComparableQuantity} that holds a Java {@link Number}, 
047 * which represented this quantity's amount.
048 * <p> 
049 * This object is immutable.
050 * <p>
051 *
052 * @see AbstractQuantity
053 * @see Quantity
054 * @see ComparableQuantity
055 * @param <Q>
056 *          The type of the quantity.
057 * @author Andi Huber
058 * @author Werner Keil
059 * @version 2.3, May 14, 2021
060 * @since 1.0
061 * 
062 */
063@API(status=MAINTAINED)
064public final class NumberQuantity<Q extends Quantity<Q>> extends AbstractQuantity<Q> {
065
066    private static final long serialVersionUID = -6494337491031528402L;
067    
068    private final Number value;
069
070    /**
071     * @since 2.0
072     */
073    protected NumberQuantity(Number number, Unit<Q> unit, Scale sc) {
074      super(unit, sc);
075      value = Calculator.of(number).peek(); // takes care of invalid number values (infinity, ...)
076    }
077    
078    protected NumberQuantity(Number number, Unit<Q> unit) {
079        this(number, unit, ABSOLUTE); 
080    }
081
082    @Override
083    public ComparableQuantity<Q> add(Quantity<Q> that) {
084        return ScaleHelper.addition(this, that, 
085                (thisValue, thatValue) -> Calculator.of(thisValue).add(thatValue).peek());
086    }
087
088    @Override
089    public ComparableQuantity<Q> subtract(Quantity<Q> that) {
090        return ScaleHelper.addition(this, that, 
091                (thisValue, thatValue) -> Calculator.of(thisValue).subtract(thatValue).peek());
092    }
093
094    @Override
095    public ComparableQuantity<?> divide(Quantity<?> that) {
096        return ScaleHelper.multiplication(this, that, 
097                (thisValue, thatValue) -> Calculator.of(thisValue).divide(thatValue).peek(),
098                (thisUnit, thatUnit) -> thisUnit.divide(thatUnit));
099    }
100
101    @Override
102    public ComparableQuantity<Q> divide(Number divisor) {
103        return ScaleHelper.scalarMultiplication(this, thisValue -> 
104                Calculator.of(thisValue).divide(divisor).peek());
105    }
106
107    @Override
108    public ComparableQuantity<?> multiply(Quantity<?> that) {
109        return ScaleHelper.multiplication(this, that, 
110                (thisValue, thatValue) -> Calculator.of(thisValue).multiply(thatValue).peek(),
111                (thisUnit, thatUnit) -> thisUnit.multiply(thatUnit));
112    }
113
114    @Override
115    public ComparableQuantity<Q> multiply(Number factor) {
116        return ScaleHelper.scalarMultiplication(this, thisValue -> 
117                Calculator.of(thisValue).multiply(factor).peek());
118    }
119
120    @Override
121    public ComparableQuantity<?> inverse() {
122        final Number resultValueInThisUnit = Calculator
123                .of(getValue())
124                .reciprocal()
125                .peek();
126        return Quantities.getQuantity(resultValueInThisUnit, getUnit().inverse(), getScale());
127    }
128
129    @Override
130    public Quantity<Q> negate() {
131        final Number resultValueInThisUnit = Calculator
132                .of(getValue())
133                .negate()
134                .peek();
135        return Quantities.getQuantity(resultValueInThisUnit, getUnit(), getScale());
136    }
137
138    @Override
139    public Number getValue() {
140        return value;
141    }
142}