001/** 002 * Unit-API - Units of Measurement API for Java 003 * Copyright (c) 2014 Jean-Marie Dautelle, Werner Keil, V2COM 004 * All rights reserved. 005 * 006 * See LICENSE.txt for details. 007 */ 008package javax.measure; 009 010import java.util.Map; 011 012/** 013 * Represents a determinate {@linkplain Quantity quantity} (as of 014 * length, time, heat, or value) adopted as a standard of measurement. 015 * 016 * <p>It is helpful to think of instances of this class as recording the history 017 * by which they are created. Thus, for example, the string {@code "g/kg"} (which 018 * is a dimensionless unit) would result from invoking the method {@link #toString()} 019 * on a unit that was created by dividing a gram unit by a kilogram unit.</p> 020 * 021 * <p>This interface supports the multiplication of offsets units. The result is 022 * usually a unit not convertible to its {@linkplain #getSystemUnit() system unit}. 023 * Such units may appear in derivative quantities. For example Celsius per meter is 024 * an unit of gradient, which is common in atmospheric and oceanographic research.</p> 025 * 026 * <p>Units raised at non-integral powers are not supported. For example, 027 * {@code LITRE.root(2)} raises an {@code ArithmeticException}, but 028 * {@code HECTARE.root(2)} returns {@code HECTOMETRE} (100 metres).</p> 029 * 030 * <p>Unit instances shall be immutable.</p> 031 * 032 * @param <Q> The type of the quantity measured by this unit. 033 * 034 * @author <a href="mailto:[email protected]">Jean-Marie Dautelle</a> 035 * @author <a href="mailto:[email protected]">Steve Emmerson</a> 036 * @author <a href="mailto:[email protected]">Martin Desruisseaux</a> 037 * @author <a href="mailto:[email protected]">Werner Keil</a> 038 * @version 0.17, December 15, 2014 039 * 040 * @see <a href="http://en.wikipedia.org/wiki/Units_of_measurement">Wikipedia: Units of measurement</a> 041 */ 042public interface Unit<Q extends Quantity<Q>> { 043 044 /*******************/ 045 /** Units Queries **/ 046 /*******************/ 047 048 /** 049 * Returns the symbol (if any) of this unit. 050 * This method returns {@code null} if this unit has no specific symbol associated with. 051 * 052 * @return this unit symbol, or {@code null} if this unit has not 053 * specific symbol associated with (e.g. product of units). 054 * 055 * @see #toString() 056 * @see UnitFormat 057 */ 058 String getSymbol(); 059 060 /** 061 * Returns the name (if any) of this unit. 062 * This method returns {@code null} if this unit has no specific name associated with. 063 * 064 * @return this unit name, or {@code null} if this unit has not 065 * specific name associated with (e.g. product of units). 066 * 067 * @see #toString() 068 * @see UnitFormat 069 */ 070 String getName(); 071 072 /** 073 * Returns the dimension of this unit. Two units {@code u1} and {@code u2} 074 * are {@linkplain #isCompatible(Unit) compatible} if and only if 075 * {@code u1.getDimension().equals(u2.getDimension())}. 076 * 077 * @return the dimension of this unit. 078 * 079 * @see #isCompatible(Unit) 080 */ 081 Dimension getDimension(); 082 083 /** 084 * Returns the unscaled system unit from which this unit is derived. 085 * System units are either base units, {@linkplain #alternate(String) 086 * alternate} units or product of rational powers of system units. 087 * 088 * <p>Because the system unit is unique by quantity type, it can be 089 * be used to identify the quantity given the unit. For example:</p> 090 * 091 * [code] 092 * static boolean isAngularSpeed(Unit<?> unit) { 093 * return unit.getSystemUnit().equals(RADIAN.divide(SECOND)); 094 * } 095 * assert isAngularSpeed(REVOLUTION.divide(MINUTE)); // Returns true. 096 * [/code] 097 * 098 * @return the system unit this unit is derived from, 099 * or {@code this} if this unit is a system unit. 100 */ 101 Unit<Q> getSystemUnit(); 102 103 /** 104 * Returns the base units and their exponent whose product is this unit, 105 * or {@code null} if this unit is a base unit (not a product of existing units). 106 * 107 * @return the base units and their exponent making up this unit. 108 */ 109 Map<? extends Unit<?>, Integer> getProductUnits(); 110 111 /** 112 * Indicates if this unit is compatible with the unit specified. 113 * Units don't need to be equals to be compatible. For example 114 * (assuming {@code ONE} is a dimensionless unit): 115 * 116 * [code] 117 * RADIAN.equals(ONE) == false 118 * RADIAN.isCompatible(ONE) == true 119 * [/code] 120 * 121 * @param that the other unit to compare for compatibility. 122 * @return {@code this.getDimension().equals(that.getDimension())} 123 * 124 * @see #getDimension() 125 */ 126 boolean isCompatible(Unit<?> that); 127 128 /** 129 * Casts this unit to a parameterized unit of specified nature or throw a 130 * {@code ClassCastException} if the dimension of the specified quantity 131 * and this unit's dimension do not match. For example: 132 * 133 * [code] 134 * Unit<Speed> C = METRE.times(299792458).divide(SECOND).asType(Speed.class); 135 * [/code] 136 * 137 * @param <T> The type of the quantity measured by the unit. 138 * @param type the quantity class identifying the nature of the unit. 139 * @return this unit parameterized with the specified type. 140 * @throws ClassCastException if the dimension of this unit is different 141 * from the specified quantity dimension. 142 */ 143 <T extends Quantity<T>> Unit<T> asType(Class<T> type) throws ClassCastException; 144 145 /** 146 * Returns a converter of numeric values from this unit to another unit of same type. 147 * This method performs the same work than {@link #getConverterToAny(Unit)} without 148 * raising checked exception. 149 * 150 * @param that the unit of same type to which to convert the numeric values. 151 * @return the converter from this unit to {@code that} unit. 152 * @throws UnconvertibleException if a converter cannot be constructed. 153 * 154 * @see #getConverterToAny(Unit) 155 */ 156 UnitConverter getConverterTo(Unit<Q> that) throws UnconvertibleException; 157 158 /** 159 * Returns a converter from this unit to the specified unit of type unknown. 160 * This method can be used when the quantity type of the specified unit 161 * is unknown at compile-time or when dimensional analysis allows for 162 * conversion between units of different type. 163 * 164 * <p>To convert to a unit having the same parameterized type, 165 * {@link #getConverterTo(Unit)} is preferred (no checked exception raised).</p> 166 * 167 * @param that the unit to which to convert the numeric values. 168 * @return the converter from this unit to {@code that} unit. 169 * @throws IncommensurableException if this unit is not 170 * {@linkplain #isCompatible(Unit) compatible} with {@code that}�unit. 171 * @throws UnconvertibleException if a converter cannot be constructed. 172 * 173 * @see #getConverterTo(Unit) 174 * @see #isCompatible(Unit) 175 */ 176 UnitConverter getConverterToAny(Unit<?> that) throws IncommensurableException, 177 UnconvertibleException; 178 179 /**********************/ 180 /** Units Operations **/ 181 /**********************/ 182 183 /** 184 * Returns a system unit equivalent to this unscaled standard unit but used 185 * in expressions to distinguish between quantities of a different nature 186 * but of the same dimensions. 187 * 188 * <p>Examples of alternate units:</p> 189 * 190 * [code] 191 * Unit<Angle> RADIAN = ONE.alternate("rad").asType(Angle.class); 192 * Unit<Force> NEWTON = METRE.times(KILOGRAM).divide(SECOND.pow(2)).alternate("N").asType(Force.class); 193 * Unit<Pressure> PASCAL = NEWTON.divide(METRE.pow(2)).alternate("Pa").asType(Pressure.class); 194 * [/code] 195 * 196 * @param symbol the new symbol for the alternate unit. 197 * @return the alternate unit. 198 * @throws UnsupportedOperationException if this unit is not an unscaled standard unit. 199 * @throws IllegalArgumentException if the specified symbol is already 200 * associated to a different unit. 201 */ 202 Unit<Q> alternate(String symbol); 203 204 /** 205 * Returns the result of setting the origin of the scale of measurement to the given value. 206 * The returned unit is convertible with all units that are convertible with this unit. 207 * For example the following code: 208 * 209 * [code] 210 * CELSIUS = KELVIN.shift(273.15); 211 * [/code] 212 * 213 * creates a new unit where 0�C (the origin of the new unit) is equals to 273.15 K. 214 * Converting from the old unit to the new one is equivalent to <em>subtracting</em> 215 * the offset to the value in the old unit. 216 * 217 * @param offset the offset added (expressed in this unit). 218 * @return this unit offset by the specified value. 219 */ 220 Unit<Q> shift(double offset); 221 222 /** 223 * Returns the result of multiplying this unit by the specified factor. 224 * If the factor is an integer value, the multiplication is exact 225 * (recommended). For example: 226 * 227 * [code] 228 * FOOT = METRE.multiply(3048).divide(10000); // Exact definition. 229 * ELECTRON_MASS = KILOGRAM.multiply(9.10938188e-31); // Approximation. 230 * [/code] 231 * 232 * @param multiplier the multiplier 233 * @return this unit scaled by the specified multiplier. 234 */ 235 Unit<Q> multiply(double multiplier); 236 237 /** 238 * Returns the product of this unit with the one specified. 239 * 240 * @param multiplier the unit multiplier. 241 * @return {@code this * multiplier} 242 */ 243 Unit<?> multiply(Unit<?> multiplier); 244 245 /** 246 * Returns the inverse of this unit. 247 * 248 * @return {@code 1 / this} 249 */ 250 Unit<?> inverse(); 251 252 /** 253 * Returns the result of dividing this unit by an approximate divisor. 254 * If the factor is an integer value, the division is exact. 255 * For example: 256 * 257 * [code] 258 * QUART = GALLON_LIQUID_US.divide(4); // Exact definition. 259 * [/code] 260 * 261 * @param divisor the divisor value. 262 * @return this unit divided by the specified divisor. 263 */ 264 Unit<Q> divide(double divisor); 265 266 /** 267 * Returns the quotient of this unit with the one specified. 268 * 269 * @param divisor the unit divisor. 270 * @return {@code this / divisor} 271 */ 272 Unit<?> divide(Unit<?> divisor); 273 274 /** 275 * Returns a unit equals to the given root of this unit. 276 * 277 * @param n the root's order. 278 * @return the result of taking the given root of this unit. 279 * @throws ArithmeticException if {@code n == 0} or if this operation 280 * would result in an unit with a fractional exponent. 281 */ 282 Unit<?> root(int n); 283 284 /** 285 * Returns a unit equals to this unit raised to an exponent. 286 * 287 * @param n the exponent. 288 * @return the result of raising this unit to the exponent. 289 */ 290 Unit<?> pow(int n); 291 292 /** 293 * <p>Returns a string representation of this unit. The string representation may 294 * be the unit {@linkplain #getSymbol() symbol}, or may be some representation 295 * of {@linkplain #getProductUnits() product units}, multiplication factor and 296 * offset if any.</p> 297 * The string may be localized at implementation choice by the means of a particular device and platform. 298 * <br> 299 * @return the string representation of this unit. 300 * 301 * @see #getSymbol() 302 */ 303 @Override 304 String toString(); 305 306 /** 307 * Returns the unit derived from this unit using the specified converter. 308 * The converter does not need to be linear. For example:<br> 309 * <code> 310 * Unit<Dimensionless> DECIBEL = Unit.ONE.transform( 311 * new LogConverter(10).inverse().concatenate( 312 * new RationalConverter(1, 10))); 313 * </code> 314 * 315 * @param operation the converter from the transformed unit to this unit. 316 * @return the unit after the specified transformation. 317 */ 318 Unit<Q> transform(UnitConverter converter); 319}