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<Dimensionless> 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}