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