001/* 002 * Units of Measurement Reference Implementation 003 * Copyright (c) 2005-2018, 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 java.io.Serializable; 033import java.math.BigDecimal; 034import java.math.BigInteger; 035import java.util.Objects; 036 037import javax.measure.Quantity; 038import javax.measure.UnconvertibleException; 039import javax.measure.Unit; 040import javax.measure.UnitConverter; 041 042import tech.units.indriya.AbstractQuantity; 043import tech.units.indriya.ComparableQuantity; 044import tech.units.indriya.function.Calculus; 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) throws ArithmeticException { 138 return Calculus.toBigDecimal(value); 139 } 140 141 @Override 142 public ComparableQuantity<Q> subtract(Quantity<Q> that) { 143 return toDecimalQuantity().subtract(that); 144 } 145 146 private DecimalQuantity<Q> toDecimalQuantity() { 147 return new DecimalQuantity<>(BigDecimal.valueOf(value.doubleValue()), getUnit()); 148 } 149 150 /** 151 * Returns the scalar quantity for the specified <code>long</code> stated in the specified unit. 152 * 153 * @param longValue 154 * the quantity value. 155 * @param unit 156 * the measurement unit. 157 * @return the corresponding <code>int</code> quantity. 158 */ 159 public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(long longValue, Unit<Q> unit) { 160 return new LongQuantity<Q>(longValue, unit); 161 } 162 163 /** 164 * Returns the scalar quantity for the specified <code>int</code> stated in the specified unit. 165 * 166 * @param intValue 167 * the quantity value. 168 * @param unit 169 * the measurement unit. 170 * @return the corresponding <code>int</code> quantity. 171 */ 172 public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(int intValue, Unit<Q> unit) { 173 return new IntegerQuantity<Q>(intValue, unit); 174 } 175 176 /** 177 * Returns the scalar quantity for the specified <code>short</code> stated in the specified unit. 178 * 179 * @param value 180 * the quantity value. 181 * @param unit 182 * the measurement unit. 183 * @return the corresponding <code>short</code> quantity. 184 */ 185 public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(short value, Unit<Q> unit) { 186 return new ShortQuantity<Q>(value, unit); 187 } 188 189 /** 190 * Returns the scalar quantity for the specified <code>byte</code> stated in the specified unit. 191 * 192 * @param value 193 * the quantity value. 194 * @param unit 195 * the measurement unit. 196 * @return the corresponding <code>byte</code> quantity. 197 */ 198 public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(byte value, Unit<Q> unit) { 199 return new ByteQuantity<Q>(value, unit); 200 } 201 202 /** 203 * Returns the scalar quantity for the specified <code>float</code> stated in the specified unit. 204 * 205 * @param floatValue 206 * the measurement value. 207 * @param unit 208 * the measurement unit. 209 * @return the corresponding <code>float</code> quantity. 210 */ 211 public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(float floatValue, Unit<Q> unit) { 212 return new FloatQuantity<Q>(floatValue, unit); 213 } 214 215 /** 216 * Returns the scalar quantity for the specified <code>double</code> stated in the specified unit. 217 * 218 * @param doubleValue 219 * the measurement value. 220 * @param unit 221 * the measurement unit. 222 * @return the corresponding <code>double</code> quantity. 223 */ 224 public static <Q extends Quantity<Q>> AbstractQuantity<Q> of(double doubleValue, Unit<Q> unit) { 225 return new DoubleQuantity<Q>(doubleValue, unit); 226 } 227 228 @Override 229 public boolean equals(Object obj) { 230 if (this == obj) { 231 return true; 232 } 233 if (obj instanceof Quantity<?>) { 234 Quantity<?> that = (Quantity<?>) obj; 235 return Objects.equals(getUnit(), that.getUnit()) && Equalizer.hasEquality(value, that.getValue()); 236 } 237 return false; 238 } 239 240}