001/* 002 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences. 003 * Copyright (C) 2007 - JScience (http://jscience.org/) 004 * All rights reserved. 005 * 006 * Permission to use, copy, modify, and distribute this software is 007 * freely granted, provided that this notice is preserved. 008 */ 009package javax.measure; 010 011import java.io.Serializable; 012import java.math.BigDecimal; 013import java.math.MathContext; 014 015import javax.measure.quantity.Quantity; 016import javax.measure.unit.CompoundUnit; 017import javax.measure.unit.Unit; 018 019/** 020 * <p> This class represents the result of a measurement stated in a 021 * known unit.</p> 022 * 023 * <p> There is no constraint upon the measurement value itself: scalars, 024 * vectors, or even data sets are valid values as long as 025 * an aggregate magnitude can be determined (see {@link Measurable}).</p> 026 * 027 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> 028 * @version 4.2, August 26, 2007 029 */ 030public abstract class Measure<V, Q extends Quantity> implements Measurable<Q>, 031 Serializable { 032 033 /** 034 * Default constructor. 035 */ 036 protected Measure() { 037 } 038 039 /** 040 * Returns the scalar measure for the specified <code>double</code> 041 * stated in the specified unit. 042 * 043 * @param doubleValue the measurement value. 044 * @param unit the measurement unit. 045 */ 046 public static <Q extends Quantity> Measure<java.lang.Double, Q> valueOf( 047 double doubleValue, Unit<Q> unit) { 048 return new Double<Q>(doubleValue, unit); 049 } 050 051 /** 052 * Returns the scalar measure for the specified <code>double</code> 053 * stated in the specified unit. 054 * 055 * @param longValue the measurement value. 056 * @param unit the measurement unit. 057 */ 058 public static <Q extends Quantity> Measure<java.lang.Long, Q> valueOf( 059 long longValue, Unit<Q> unit) { 060 return new Long<Q>(longValue, unit); 061 } 062 063 /** 064 * Returns the scalar measure for the specified <code>float</code> 065 * stated in the specified unit. 066 * 067 * @param floatValue the measurement value. 068 * @param unit the measurement unit. 069 */ 070 public static <Q extends Quantity> Measure<java.lang.Float, Q> valueOf( 071 float floatValue, Unit<Q> unit) { 072 return new Float<Q>(floatValue, unit); 073 } 074 075 /** 076 * Returns the scalar measure for the specified <code>int</code> 077 * stated in the specified unit. 078 * 079 * @param intValue the measurement value. 080 * @param unit the measurement unit. 081 */ 082 public static <Q extends Quantity> Measure<java.lang.Integer, Q> valueOf( 083 int intValue, Unit<Q> unit) { 084 return new Integer<Q>(intValue, unit); 085 } 086 087 /** 088 * Returns the measurement value of this measure. 089 * 090 * @return the measurement value. 091 */ 092 public abstract V getValue(); 093 094 /** 095 * Returns the measurement unit of this measure. 096 * 097 * @return the measurement unit. 098 */ 099 public abstract Unit<Q> getUnit(); 100 101 /** 102 * Returns the measure equivalent to this measure but stated in the 103 * specified unit. This method may result in lost of precision 104 * (e.g. measure of integral value). 105 * 106 * @param unit the new measurement unit. 107 * @return the measure stated in the specified unit. 108 */ 109 public abstract Measure<V, Q> to(Unit<Q> unit); 110 111 /** 112 * Returns the value of this measure stated in the specified unit as 113 * a <code>double</code>. If the measure has too great a magnitude to 114 * be represented as a <code>double</code>, it will be converted to 115 * <code>Double.NEGATIVE_INFINITY</code> or 116 * <code>Double.POSITIVE_INFINITY</code> as appropriate. 117 * 118 * @param unit the unit in which this measure is stated. 119 * @return the numeric value after conversion to type <code>double</code>. 120 */ 121 public abstract double doubleValue(Unit<Q> unit); 122 123 /** 124 * Returns the estimated integral value of this measure stated in 125 * the specified unit as a <code>long</code>. 126 * 127 * <p> Note: This method differs from the <code>Number.longValue()</code> 128 * in the sense that the closest integer value is returned 129 * and an ArithmeticException is raised instead 130 * of a bit truncation in case of overflow (safety critical).</p> 131 * 132 * @param unit the unit in which the measurable value is stated. 133 * @return the numeric value after conversion to type <code>long</code>. 134 * @throws ArithmeticException if this quantity cannot be represented 135 * as a <code>long</code> number in the specified unit. 136 */ 137 public long longValue(Unit<Q> unit) throws ArithmeticException { 138 double doubleValue = doubleValue(unit); 139 if (java.lang.Double.isNaN(doubleValue) 140 || (doubleValue < java.lang.Long.MIN_VALUE) 141 || (doubleValue > java.lang.Long.MAX_VALUE)) 142 throw new ArithmeticException(doubleValue + " " + unit 143 + " cannot be represented as long"); 144 return Math.round(doubleValue); 145 } 146 147 /** 148 * Returns the value of this measure stated in the specified unit as a 149 * <code>float</code>. If the measure has too great a magnitude to be 150 * represented as a <code>float</code>, it will be converted to 151 * <code>Float.NEGATIVE_INFINITY</code> or 152 * <code>Float.POSITIVE_INFINITY</code> as appropriate. 153 * 154 * @param unit the unit in which the measure is stated. 155 * @return the numeric value after conversion to type <code>float</code>. 156 */ 157 public float floatValue(Unit<Q> unit) { 158 return (float) doubleValue(unit); 159 } 160 161 /** 162 * Returns the estimated integral value of this measure stated in 163 * the specified unit as a <code>int</code>. 164 * 165 * <p> Note: This method differs from the <code>Number.intValue()</code> 166 * in the sense that the closest integer value is returned 167 * and an ArithmeticException is raised instead 168 * of a bit truncation in case of overflow (safety critical).</p> 169 * 170 * @param unit the unit in which the measurable value is stated. 171 * @return the numeric value after conversion to type <code>int</code>. 172 * @throws ArithmeticException if this quantity cannot be represented 173 * as a <code>int</code> number in the specified unit. 174 */ 175 public int intValue(Unit<Q> unit) { 176 long longValue = longValue(unit); 177 if ((longValue > java.lang.Integer.MAX_VALUE) 178 || (longValue < java.lang.Integer.MIN_VALUE)) 179 throw new ArithmeticException("Overflow"); 180 return (int) longValue; 181 } 182 183 /** 184 * Compares this measure against the specified object for 185 * strict equality (same unit and amount). 186 * To compare measures stated using different units the 187 * {@link #compareTo} method should be used. 188 * 189 * @param obj the object to compare with. 190 * @return <code>true</code> if both objects are identical (same 191 * unit and same amount); <code>false</code> otherwise. 192 */ 193 @SuppressWarnings("unchecked") 194 public boolean equals(Object obj) { 195 if (!(obj instanceof Measure)) 196 return false; 197 Measure that = (Measure) obj; 198 return this.getUnit().equals(that.getUnit()) 199 && this.getValue().equals(that.getValue()); 200 } 201 202 /** 203 * Returns the hash code for this scalar. 204 * 205 * @return the hash code value. 206 */ 207 public int hashCode() { 208 return getUnit().hashCode() + getValue().hashCode(); 209 } 210 211 /** 212 * Returns the <code>String</code> representation of this measure 213 * The string produced for a given measure is always the same; 214 * it is not affected by locale. This means that it can be used 215 * as a canonical string representation for exchanging data, 216 * or as a key for a Hashtable, etc. Locale-sensitive 217 * measure formatting and parsing is handled by the {@link 218 * MeasureFormat} class and its subclasses. 219 * 220 * @return the string representation of this measure. 221 */ 222 public String toString() { 223 if (getUnit() instanceof CompoundUnit) 224 return MeasureFormat.DEFAULT.formatCompound(doubleValue(getUnit()), 225 getUnit(), new StringBuffer(), null).toString(); 226 return getValue() + " " + getUnit(); 227 } 228 229 /** 230 * Compares this measure to the specified measurable quantity. 231 * This method compares the {@link Measurable#doubleValue(Unit)} of 232 * both this measure and the specified measurable stated in the 233 * same unit (this measure's {@link #getUnit() unit}). 234 * 235 * @return a negative integer, zero, or a positive integer as this measure 236 * is less than, equal to, or greater than the specified measurable 237 * quantity. 238 * @return <code>Double.compare(this.doubleValue(getUnit()), 239 * that.doubleValue(getUnit()))</code> 240 */ 241 public int compareTo(Measurable<Q> that) { 242 return java.lang.Double.compare(doubleValue(getUnit()), that 243 .doubleValue(getUnit())); 244 } 245 246 /** 247 * Holds scalar implementation for <code>double</code> values. 248 */ 249 private static final class Double<Q extends Quantity> extends 250 Measure<java.lang.Double, Q> { 251 252 private final double _value; 253 254 private final Unit<Q> _unit; 255 256 public Double(double value, Unit<Q> unit) { 257 _value = value; 258 _unit = unit; 259 } 260 261 @Override 262 public Unit<Q> getUnit() { 263 return _unit; 264 } 265 266 @Override 267 public java.lang.Double getValue() { 268 return _value; 269 } 270 271 @Override 272 public Measure<java.lang.Double, Q> to(Unit<Q> unit) { 273 if ((unit == _unit) || (unit.equals(_unit))) 274 return this; 275 return new Double<Q>(doubleValue(unit), unit); 276 } 277 278 public double doubleValue(Unit<Q> unit) { 279 if ((unit == _unit) || (unit.equals(_unit))) 280 return _value; 281 return _unit.getConverterTo(unit).convert(_value); 282 } 283 284 private static final long serialVersionUID = 1L; 285 } 286 287 /** 288 * Holds scalar implementation for <code>long</code> values. 289 */ 290 private static final class Long<Q extends Quantity> extends 291 Measure<java.lang.Long, Q> { 292 293 private final long _value; 294 295 private final Unit<Q> _unit; 296 297 public Long(long value, Unit<Q> unit) { 298 _value = value; 299 _unit = unit; 300 } 301 302 @Override 303 public Unit<Q> getUnit() { 304 return _unit; 305 } 306 307 @Override 308 public java.lang.Long getValue() { 309 return _value; 310 } 311 312 @Override 313 public Measure<java.lang.Long, Q> to(Unit<Q> unit) { 314 if ((unit == _unit) || (unit.equals(_unit))) 315 return this; 316 return new Long<Q>(longValue(unit), unit); 317 } 318 319 public double doubleValue(Unit<Q> unit) { 320 if ((unit == _unit) || (unit.equals(_unit))) 321 return _value; 322 return _unit.getConverterTo(unit).convert(_value); 323 } 324 325 public long longValue(Unit<Q> unit) throws ArithmeticException { 326 if ((unit == _unit) || (unit.equals(_unit))) 327 return _value; // No conversion, returns value directly. 328 return super.longValue(unit); 329 } 330 331 private static final long serialVersionUID = 1L; 332 333 } 334 335 /** 336 * Holds scalar implementation for <code>float</code> values. 337 */ 338 private static final class Float<Q extends Quantity> extends 339 Measure<java.lang.Float, Q> { 340 341 private final float _value; 342 343 private final Unit<Q> _unit; 344 345 public Float(float value, Unit<Q> unit) { 346 _value = value; 347 _unit = unit; 348 } 349 350 @Override 351 public Unit<Q> getUnit() { 352 return _unit; 353 } 354 355 @Override 356 public java.lang.Float getValue() { 357 return _value; 358 } 359 360 @Override 361 public Measure<java.lang.Float, Q> to(Unit<Q> unit) { 362 if ((unit == _unit) || (unit.equals(_unit))) 363 return this; 364 return new Float<Q>(floatValue(unit), unit); 365 } 366 367 public double doubleValue(Unit<Q> unit) { 368 if ((unit == _unit) || (unit.equals(_unit))) 369 return _value; 370 return _unit.getConverterTo(unit).convert(_value); 371 } 372 373 private static final long serialVersionUID = 1L; 374 } 375 376 /** 377 * Holds scalar implementation for <code>long</code> values. 378 */ 379 private static final class Integer<Q extends Quantity> extends 380 Measure<java.lang.Integer, Q> { 381 382 private final int _value; 383 384 private final Unit<Q> _unit; 385 386 public Integer(int value, Unit<Q> unit) { 387 _value = value; 388 _unit = unit; 389 } 390 391 @Override 392 public Unit<Q> getUnit() { 393 return _unit; 394 } 395 396 @Override 397 public java.lang.Integer getValue() { 398 return _value; 399 } 400 401 @Override 402 public Measure<java.lang.Integer, Q> to(Unit<Q> unit) { 403 if ((unit == _unit) || (unit.equals(_unit))) 404 return this; 405 return new Integer<Q>(intValue(unit), unit); 406 } 407 408 public double doubleValue(Unit<Q> unit) { 409 if ((unit == _unit) || (unit.equals(_unit))) 410 return _value; 411 return _unit.getConverterTo(unit).convert(_value); 412 } 413 414 public long longValue(Unit<Q> unit) throws ArithmeticException { 415 if ((unit == _unit) || (unit.equals(_unit))) 416 return _value; // No conversion, returns value directly. 417 return super.longValue(unit); 418 } 419 420 private static final long serialVersionUID = 1L; 421 422 } 423 424 /** 425 * @deprecated {@link DecimalMeasure} should be used directly. 426 */ 427 public static <Q extends Quantity> Measure<BigDecimal, Q> valueOf( 428 BigDecimal decimal, Unit<Q> unit) { 429 return DecimalMeasure.valueOf(decimal, unit); 430 } 431 432 /** 433 * @deprecated {@link DecimalMeasure} should be used directly and 434 * <code>MathContext</code> specified explicitly when 435 * {@link DecimalMeasure#to(Unit, MathContext) converting}. 436 */ 437 public static <Q extends Quantity> Measure<BigDecimal, Q> valueOf( 438 BigDecimal decimal, Unit<Q> unit, MathContext mathContext) { 439 return DecimalMeasure.valueOf(decimal, unit); 440 } 441 442 /** 443 * @deprecated {@link VectorMeasure} should be used directly. 444 */ 445 public static <Q extends Quantity> Measure<double[], Q> valueOf( 446 double[] components, Unit<Q> unit) { 447 return VectorMeasure.valueOf(components, unit); 448 } 449}