001/*
002 * Units of Measurement Reference Implementation
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.units.ri.quantity;
031
032import java.util.Objects;
033
034import javax.measure.Quantity;
035import javax.measure.Unit;
036import javax.measure.UnconvertibleException;
037import javax.measure.UnitConverter;
038
039import tec.units.ri.AbstractQuantity;
040import tec.units.ri.format.QuantityFormat;
041
042/**
043 * An amount of quantity, consisting of a Number and a Unit. NumberQuantity objects are immutable.
044 * 
045 * @see AbstractQuantity
046 * @see Quantity
047 * @author <a href="mailto:werner@uom.technology">Werner Keil</a>
048 * @param <Q>
049 *          The type of the quantity.
050 * @version 1.0.2, $Date: 2017-05-28 $
051 * @since 1.0
052 */
053public class NumberQuantity<Q extends Quantity<Q>> extends AbstractQuantity<Q> {
054
055  /**
056     * 
057     */
058  // private static final long serialVersionUID = 7312161895652321241L;
059
060  private final Number value;
061
062  /**
063   * Indicates if this quantity is exact.
064   */
065  private final boolean isExact;
066
067  /**
068   * Holds the exact value (when exact) stated in this quantity's unit.
069   */
070  // private long exactValue;
071
072  /**
073   * Holds the minimum value stated in this quantity's unit. For inexact measures: minimum < maximum
074   */
075  // private double minimum;
076
077  /**
078   * Holds the maximum value stated in this quantity's unit. For inexact measures: maximum > minimum
079   */
080  // private double maximum;
081
082  protected NumberQuantity(Number number, Unit<Q> unit) {
083    super(unit);
084    value = number;
085    isExact = false;
086  }
087
088  /*
089   * (non-Javadoc)
090   * 
091   * @see AbstractQuantity#equals(java.lang.Object)
092   */
093  @Override
094  public boolean equals(Object obj) {
095    if (obj == null)
096      return false;
097    if (obj == this)
098      return true;
099    if (obj instanceof Quantity<?>) {
100      Quantity<?> that = (Quantity<?>) obj;
101      return Objects.equals(getUnit(), that.getUnit()) && Equalizer.hasEquality(value, that.getValue());
102    }
103    return false;
104  }
105
106  /*
107   * (non-Javadoc)
108   * 
109   * @see AbstractQuantity#doubleValue(javax.measure.Unit)
110   */
111  @Override
112  public double doubleValue(Unit<Q> unit) {
113    Unit<Q> myUnit = getUnit();
114    try {
115      UnitConverter converter = myUnit.getConverterTo(unit);
116      return converter.convert(getValue().doubleValue());
117    } catch (UnconvertibleException e) {
118      throw e;
119    }
120  }
121
122  protected final int intValue(Unit<Q> unit) throws ArithmeticException {
123    long longValue = longValue(unit);
124    if ((longValue < Integer.MIN_VALUE) || (longValue > Integer.MAX_VALUE)) {
125      throw new ArithmeticException("Cannot convert " + longValue + " to int (overflow)");
126    }
127    return (int) longValue;
128  }
129
130  /*
131   * (non-Javadoc)
132   * 
133   * @see javax.measure.Quantity#getValue()
134   */
135  public Number getValue() {
136    return value;
137  }
138
139  /**
140   * Indicates if this measured quantity is exact. An exact quantity is guaranteed exact only when stated in this quantity's unit (e.g.
141   * <code>this.longValue()</code>); stating the quantity in any other unit may introduce conversion errors.
142   * 
143   * @return <code>true</code> if this quantity is exact; <code>false</code> otherwise.
144   */
145  public boolean isExact() {
146    return isExact;
147  }
148
149  @SuppressWarnings({ "rawtypes", "unchecked" })
150  protected Quantity<Q> add(AbstractQuantity<Q> that) {
151    final Quantity<Q> thatToUnit = that.to(getUnit());
152    return new NumberQuantity(this.getValue().doubleValue() + thatToUnit.getValue().doubleValue(), getUnit());
153  }
154
155  public String toString() {
156    return String.valueOf(getValue()) + " " + String.valueOf(getUnit());
157  }
158
159  @SuppressWarnings({ "rawtypes", "unchecked" })
160  public Quantity<?> multiply(Quantity<?> that) {
161    final Unit<?> unit = getUnit().multiply(that.getUnit());
162    return new NumberQuantity((getValue().doubleValue() * that.getValue().doubleValue()), unit);
163  }
164
165  public Quantity<Q> multiply(Number that) {
166    return (AbstractQuantity<Q>) NumberQuantity.of((getValue().doubleValue() * that.doubleValue()), getUnit());
167  }
168
169  @SuppressWarnings({ "rawtypes", "unchecked" })
170  public Quantity<Q> divide(Quantity<?> that) {
171    final Unit<?> unit = getUnit().divide(that.getUnit());
172    return new NumberQuantity((getValue().doubleValue() / that.getValue().doubleValue()), unit);
173  }
174
175  public Quantity<Q> divide(Number that) {
176    return NumberQuantity.of(getValue().doubleValue() / that.doubleValue(), getUnit());
177  }
178
179  @SuppressWarnings("unchecked")
180  public Quantity<Q> inverse() {
181    return (AbstractQuantity<Q>) NumberQuantity.of(1d / value.doubleValue(), getUnit().inverse());
182  }
183
184  // public Quantity<Q> inverse() {
185  // @SuppressWarnings({ "rawtypes", "unchecked" })
186  // final Quantity<Q> m = new NumberQuantity(1d / getValue().doubleValue(),
187  // getUnit().inverse());
188  // return m;
189  // }
190
191  @SuppressWarnings({ "rawtypes", "unchecked" })
192  public Quantity<Q> subtract(Quantity<Q> that) {
193    final Quantity<Q> thatToUnit = (Quantity<Q>) that.to(getUnit());
194    return new NumberQuantity(this.getValue().doubleValue() - thatToUnit.getValue().doubleValue(), getUnit());
195  }
196
197  @SuppressWarnings({ "rawtypes", "unchecked" })
198  public Quantity<Q> add(Quantity<Q> that) {
199    final Quantity<Q> thatToUnit = (Quantity<Q>) that.to(getUnit());
200    return new NumberQuantity(this.getValue().doubleValue() + thatToUnit.getValue().doubleValue(), getUnit());
201  }
202
203  /**
204   * Returns the scalar quantity for the specified <code>long</code> stated in the specified unit.
205   *
206   * @param longValue
207   *          the quantity value.
208   * @param unit
209   *          the measurement unit.
210   * @return the corresponding <code>int</code> quantity.
211   */
212  public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(long longValue, Unit<Q> unit) {
213    return new LongQuantity<Q>(longValue, unit);
214  }
215
216  /**
217   * Returns the scalar quantity for the specified <code>int</code> stated in the specified unit.
218   *
219   * @param intValue
220   *          the quantity value.
221   * @param unit
222   *          the measurement unit.
223   * @return the corresponding <code>int</code> quantity.
224   */
225  public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(int intValue, Unit<Q> unit) {
226    return new IntegerQuantity<Q>(intValue, unit);
227  }
228
229  /**
230   * Returns the scalar quantity for the specified <code>short</code> stated in the specified unit.
231   *
232   * @param value
233   *          the quantity value.
234   * @param unit
235   *          the measurement unit.
236   * @return the corresponding <code>short</code> quantity.
237   */
238  public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(short value, Unit<Q> unit) {
239    return new ShortQuantity<Q>(value, unit);
240  }
241
242  /**
243   * Returns the scalar quantity for the specified <code>float</code> stated in the specified unit.
244   *
245   * @param floatValue
246   *          the measurement value.
247   * @param unit
248   *          the measurement unit.
249   * @return the corresponding <code>float</code> quantity.
250   */
251  public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(float floatValue, Unit<Q> unit) {
252    return new FloatQuantity<Q>(floatValue, unit);
253  }
254
255  /**
256   * Returns the scalar quantity for the specified <code>double</code> stated in the specified unit.
257   *
258   * @param doubleValue
259   *          the measurement value.
260   * @param unit
261   *          the measurement unit.
262   * @return the corresponding <code>double</code> quantity.
263   */
264  public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(double doubleValue, Unit<Q> unit) {
265    return new DoubleQuantity<Q>(doubleValue, unit);
266  }
267
268  /**
269   * Returns the decimal quantity of unknown type corresponding to the specified representation. This method can be used to parse dimensionless
270   * quantities.<br>
271   * <code>
272   *     Quantity&lt;Dimensionless&gt; proportion = NumberQuantity.parse("0.234").asType(Dimensionless.class);
273   * </code>
274   *
275   * <p>
276   * Note: This method handles only {@link tec.units.ri.SimpleUnitFormat.UnitFormat#getStandard standard} unit format.
277   * </p>
278   *
279   * @param csq
280   *          the decimal value and its unit (if any) separated by space(s).
281   * @return <code>QuantityFormat.getInstance().parse(csq)</code>
282   */
283  public static Quantity<?> parse(CharSequence csq) {
284    return QuantityFormat.getInstance().parse(csq);
285  }
286}