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}