001/*
002 * Units of Measurement Implementation for Java SE
003 * Copyright (c) 2005-2017, 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 */
030package tec.uom.se.quantity;
031
032import java.io.Serializable;
033import java.math.BigDecimal;
034import java.math.BigInteger;
035import java.math.MathContext;
036import java.util.Objects;
037
038import javax.measure.Quantity;
039import javax.measure.UnconvertibleException;
040import javax.measure.Unit;
041import javax.measure.UnitConverter;
042
043import tec.uom.se.AbstractQuantity;
044import tec.uom.se.ComparableQuantity;
045
046/**
047 * An amount of quantity, implementation of {@link ComparableQuantity} that keep {@link Number} as possible otherwise converts to
048 * {@link DecimalQuantity}, this object is immutable.
049 *
050 * @see AbstractQuantity
051 * @see Quantity
052 * @see ComparableQuantity
053 * @param <Q>
054 *          The type of the quantity.
055 * @author otaviojava
056 * @author <a href="mailto:units@catmedia.us">Werner Keil</a>
057 * @version 1.0.1, $Date: 2017-05-28 $
058 * @since 1.0
059 */
060@SuppressWarnings({ "rawtypes", "unchecked" })
061public class NumberQuantity<Q extends Quantity<Q>> extends AbstractQuantity<Q> implements Serializable {
062
063  private static final long serialVersionUID = 7312161895652321241L;
064
065  private final Number value;
066
067  /**
068   * Indicates if this quantity is big.
069   */
070  private final boolean isBig;
071
072  protected NumberQuantity(Number number, Unit<Q> unit) {
073    super(unit);
074    value = number;
075    isBig = number instanceof BigDecimal || number instanceof BigInteger;
076  }
077
078  @Override
079  public double doubleValue(Unit<Q> unit) {
080    Unit<Q> myUnit = getUnit();
081    try {
082      UnitConverter converter = myUnit.getConverterTo(unit);
083      return converter.convert(getValue().doubleValue());
084    } catch (UnconvertibleException e) {
085      throw e;
086    }
087  }
088
089  @Override
090  public Number getValue() {
091    return value;
092  }
093
094  /**
095   * Indicates if this measured amount is a big number, i.E. BigDecimal or BigInteger. In all other cases this would be false.
096   *
097   * @return <code>true</code> if this quantity is big; <code>false</code> otherwise.
098   */
099  @Override
100  public boolean isBig() {
101    return isBig;
102  }
103
104  @Override
105  public ComparableQuantity<Q> add(Quantity<Q> that) {
106    return toDecimalQuantity().add(that);
107  }
108
109  @Override
110  public ComparableQuantity<?> multiply(Quantity<?> that) {
111    return toDecimalQuantity().multiply(that);
112  }
113
114  @Override
115  public ComparableQuantity<Q> multiply(Number that) {
116    return toDecimalQuantity().multiply(that);
117  }
118
119  @Override
120  public ComparableQuantity<?> divide(Quantity<?> that) {
121    return toDecimalQuantity().divide(that);
122  }
123
124  @Override
125  public ComparableQuantity<Q> divide(Number that) {
126    return toDecimalQuantity().divide(that);
127  }
128
129  @Override
130  public ComparableQuantity<Q> inverse() {
131
132    return new NumberQuantity((getValue() instanceof BigDecimal ? BigDecimal.ONE.divide((BigDecimal) getValue()) : 1d / getValue().doubleValue()),
133        getUnit().inverse());
134  }
135
136  @Override
137  public BigDecimal decimalValue(Unit<Q> unit, MathContext ctx) throws ArithmeticException {
138    if (value instanceof BigDecimal) {
139      return (BigDecimal) value;
140    }
141    if (value instanceof BigInteger) {
142      return new BigDecimal((BigInteger) value);
143    }
144    return BigDecimal.valueOf(value.doubleValue());
145  }
146
147  @Override
148  public ComparableQuantity<Q> subtract(Quantity<Q> that) {
149    return toDecimalQuantity().subtract(that);
150  }
151
152  private DecimalQuantity<Q> toDecimalQuantity() {
153    return new DecimalQuantity<>(BigDecimal.valueOf(value.doubleValue()), getUnit());
154  }
155
156  /**
157   * Returns the scalar quantity for the specified <code>long</code> stated in the specified unit.
158   *
159   * @param longValue
160   *          the quantity value.
161   * @param unit
162   *          the measurement unit.
163   * @return the corresponding <code>int</code> quantity.
164   */
165  public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(long longValue, Unit<Q> unit) {
166    return new LongQuantity<Q>(longValue, unit);
167  }
168
169  /**
170   * Returns the scalar quantity for the specified <code>int</code> stated in the specified unit.
171   *
172   * @param intValue
173   *          the quantity value.
174   * @param unit
175   *          the measurement unit.
176   * @return the corresponding <code>int</code> quantity.
177   */
178  public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(int intValue, Unit<Q> unit) {
179    return new IntegerQuantity<Q>(intValue, unit);
180  }
181
182  /**
183   * Returns the scalar quantity for the specified <code>short</code> stated in the specified unit.
184   *
185   * @param value
186   *          the quantity value.
187   * @param unit
188   *          the measurement unit.
189   * @return the corresponding <code>short</code> quantity.
190   */
191  public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(short value, Unit<Q> unit) {
192    return new ShortQuantity<Q>(value, unit);
193  }
194
195  /**
196   * Returns the scalar quantity for the specified <code>byte</code> stated in the specified unit.
197   *
198   * @param value
199   *          the quantity value.
200   * @param unit
201   *          the measurement unit.
202   * @return the corresponding <code>byte</code> quantity.
203   */
204  public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(byte value, Unit<Q> unit) {
205    return new ByteQuantity<Q>(value, unit);
206  }
207
208  /**
209   * Returns the scalar quantity for the specified <code>float</code> stated in the specified unit.
210   *
211   * @param floatValue
212   *          the measurement value.
213   * @param unit
214   *          the measurement unit.
215   * @return the corresponding <code>float</code> quantity.
216   */
217  public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(float floatValue, Unit<Q> unit) {
218    return new FloatQuantity<Q>(floatValue, unit);
219  }
220
221  /**
222   * Returns the scalar quantity for the specified <code>double</code> stated in the specified unit.
223   *
224   * @param doubleValue
225   *          the measurement value.
226   * @param unit
227   *          the measurement unit.
228   * @return the corresponding <code>double</code> quantity.
229   */
230  public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(double doubleValue, Unit<Q> unit) {
231    return new DoubleQuantity<Q>(doubleValue, unit);
232  }
233
234  @Override
235  public boolean equals(Object obj) {
236    if (this == obj) {
237      return true;
238    }
239    if (obj instanceof Quantity<?>) {
240      Quantity<?> that = (Quantity<?>) obj;
241      return Objects.equals(getUnit(), that.getUnit()) && Equalizer.hasEquality(value, that.getValue());
242    }
243    return false;
244  }
245
246}