1 9 package javax.measure.units; 10 11 import java.io.Serializable ; 12 import java.text.ParsePosition ; 13 import java.util.HashMap ; 14 15 import javax.measure.converters.AddConverter; 16 import javax.measure.converters.ConversionException; 17 import javax.measure.converters.MultiplyConverter; 18 import javax.measure.converters.RationalConverter; 19 import javax.measure.converters.UnitConverter; 20 import javax.measure.quantities.Dimensionless; 21 import javax.measure.quantities.Quantity; 22 23 53 public abstract class Unit<Q extends Quantity> implements Serializable { 54 55 58 public static final Unit<Dimensionless> ONE = new ProductUnit<Dimensionless>(); 59 60 63 static final HashMap <String , Unit> SYMBOL_TO_UNIT = new HashMap <String , Unit>(); 64 65 69 Unit() { 70 } 71 72 76 93 public abstract Unit<? super Q> getSystemUnit(); 94 95 100 public abstract UnitConverter toSystemUnit(); 101 102 107 public abstract int hashCode(); 108 109 117 public abstract boolean equals(Object that); 118 119 129 public final boolean isCompatible(Unit that) { 130 return (this == that) 131 || this.getSystemUnit().equals(that.getSystemUnit()) 132 || this.getDimension().equals(that.getDimension()); 133 } 134 135 147 @SuppressWarnings ("unchecked") 148 public final <T extends Quantity> Unit<T> sameTypeAs(Unit<T> that) { 149 if (!isCompatible(that)) throw new ConversionException(this + " and " + 150 that + " are not compatible units"); 151 return (Unit<T>)this; 152 } 153 154 160 public final Dimension getDimension() { 161 Unit systemUnit = this.getSystemUnit(); 162 if (systemUnit instanceof BaseUnit) 163 return Dimension.getModel().getDimension((BaseUnit) systemUnit); 164 if (systemUnit instanceof AlternateUnit) 165 return ((AlternateUnit) systemUnit).getParent().getDimension(); 166 ProductUnit productUnit = (ProductUnit) systemUnit; 168 Dimension dimension = Dimension.NONE; 169 for (int i = 0; i < productUnit.getUnitCount(); i++) { 170 Unit unit = productUnit.getUnit(i); 171 Dimension d = unit.getDimension().pow(productUnit.getUnitPow(i)) 172 .root(productUnit.getUnitRoot(i)); 173 dimension = dimension.times(d); 174 } 175 return dimension; 176 } 177 178 186 public final UnitConverter getConverterTo(Unit that) 187 throws ConversionException { 188 if (this.equals(that)) 189 return UnitConverter.IDENTITY; 190 Unit thisSystemUnit = this.getSystemUnit(); 191 Unit thatSystemUnit = that.getSystemUnit(); 192 if (thisSystemUnit.equals(thatSystemUnit)) 193 return that.toSystemUnit().inverse().concatenate( 194 this.toSystemUnit()); 195 if (!thisSystemUnit.getDimension() 197 .equals(thatSystemUnit.getDimension())) 198 throw new ConversionException(this + " is not compatible with " 199 + that); 200 UnitConverter thisTransform = this.toSystemUnit().concatenate( 202 transformOf(this.getBaseUnits())); 203 UnitConverter thatTransform = that.toSystemUnit().concatenate( 204 transformOf(that.getBaseUnits())); 205 return thatTransform.inverse().concatenate(thisTransform); 206 } 207 208 private Unit getBaseUnits() { 209 Unit systemUnit = this.getSystemUnit(); 210 if (systemUnit instanceof BaseUnit) return systemUnit; 211 if (systemUnit instanceof AlternateUnit) 212 return ((AlternateUnit)systemUnit).getParent().getBaseUnits(); 213 if (systemUnit instanceof ProductUnit) { 214 ProductUnit productUnit = (ProductUnit)systemUnit; 215 Unit baseUnits = ONE; 216 for (int i = 0; i < productUnit.getUnitCount(); i++) { 217 Unit unit = productUnit.getUnit(i).getBaseUnits(); 218 unit = unit.pow(productUnit.getUnitPow(i)); 219 unit = unit.root(productUnit.getUnitRoot(i)); 220 baseUnits = baseUnits.times(unit); 221 } 222 return baseUnits; 223 } else { 224 throw new InternalError ( 225 "System Unit cannot be an instance of " + this.getClass()); 226 } 227 } 228 private static UnitConverter transformOf(Unit baseUnits) { 229 if (baseUnits instanceof BaseUnit) 230 return Dimension.getModel().getTransform((BaseUnit) baseUnits); 231 ProductUnit productUnit = (ProductUnit) baseUnits; 233 UnitConverter converter = UnitConverter.IDENTITY; 234 for (int i = 0; i < productUnit.getUnitCount(); i++) { 235 Unit unit = productUnit.getUnit(i); 236 UnitConverter cvtr = transformOf(unit); 237 if (!cvtr.isLinear()) 238 throw new ConversionException(baseUnits 239 + " is non-linear, cannot convert"); 240 if (productUnit.getUnitRoot(i) != 1) 241 throw new ConversionException(productUnit 242 + " holds a base unit with fractional exponent"); 243 int pow = productUnit.getUnitPow(i); 244 if (pow < 0) { pow = -pow; 246 cvtr = cvtr.inverse(); 247 } 248 for (int j = 0; j < pow; j++) { 249 converter = converter.concatenate(cvtr); 250 } 251 } 252 return converter; 253 } 254 255 267 public final CompoundUnit<Q> compound(Unit<Q> subunit) { 268 return new CompoundUnit<Q>(this, subunit); 269 } 270 271 281 public final Unit<Q> transform(UnitConverter operation) { 282 if (this instanceof TransformedUnit) { 283 TransformedUnit<Q> tf = (TransformedUnit<Q>) this; 284 Unit<Q> parent = tf.getParentUnit(); 285 UnitConverter toParent = tf.toParentUnit().concatenate(operation); 286 if (toParent == UnitConverter.IDENTITY) 287 return parent; 288 return new TransformedUnit<Q>(parent, toParent); 289 } 290 if (operation == UnitConverter.IDENTITY) 291 return this; 292 return new TransformedUnit<Q>(this, operation); 293 } 294 295 303 public final Unit<Q> plus(double offset) { 304 return transform(new AddConverter(offset)); 305 } 306 307 314 public final Unit<Q> times(long factor) { 315 return transform(new RationalConverter(factor, 1)); 316 } 317 318 325 public final Unit<Q> times(double factor) { 326 return transform(new MultiplyConverter(factor)); 327 } 328 329 335 public final Unit<? extends Quantity> times(Unit that) { 336 return ProductUnit.getProductInstance(this, that); 337 } 338 339 344 public final Unit<? extends Quantity> inverse() { 345 return ProductUnit.getQuotientInstance(ONE, this); 346 } 347 348 355 public final Unit<Q> divide(long divisor) { 356 return transform(new RationalConverter(1, divisor)); 357 } 358 359 365 public final Unit<Q> divide(double divisor) { 366 return transform(new MultiplyConverter(1.0 / divisor)); 367 } 368 369 375 public final Unit<? extends Quantity> divide(Unit that) { 376 return this.times(that.inverse()); 377 } 378 379 386 public final Unit<? extends Quantity> root(int n) { 387 if (n > 0) { 388 return ProductUnit.getRootInstance(this, n); 389 } else if (n == 0) { 390 throw new ArithmeticException ("Root's order of zero"); 391 } else { return ONE.divide(this.root(-n)); 393 } 394 } 395 396 402 public final Unit<? extends Quantity> pow(int n) { 403 if (n > 0) { 404 return this.times(this.pow(n - 1)); 405 } else if (n == 0) { 406 return ONE; 407 } else { return ONE.divide(this.pow(-n)); 409 } 410 } 411 412 430 public static Unit<? extends Quantity> valueOf(CharSequence csq) { 431 return UnitFormat.getStandardInstance() 432 .parse(csq, new ParsePosition (0)); 433 } 434 435 439 444 public final String toString() { 445 return UnitFormat.getStandardInstance().format(this); 446 } 447 } | Popular Tags |