001/* 002 * SI Units 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, are permitted provided that the following conditions are met: 008 * 009 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 010 * 011 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 012 * 013 * 3. Neither the name of JSR-363 nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 014 * 015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 016 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 017 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 018 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 019 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 020 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 021 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 022 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 023 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 024 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 025 */ 026package si.uom; 027 028import javax.measure.Quantity; 029import javax.measure.Unit; 030import javax.measure.quantity.Acceleration; 031import javax.measure.quantity.Angle; 032import javax.measure.quantity.Area; 033import javax.measure.quantity.Energy; 034import javax.measure.quantity.Length; 035import javax.measure.quantity.Mass; 036 037import si.uom.quantity.*; 038import tec.units.ri.AbstractSystemOfUnits; 039import tec.units.ri.AbstractUnit; 040import tec.units.ri.format.SimpleUnitFormat; 041import tec.units.ri.function.MultiplyConverter; 042import tec.units.ri.function.PiMultiplierConverter; 043import tec.units.ri.function.RationalConverter; 044import tec.units.ri.unit.AlternateUnit; 045import tec.units.ri.unit.ProductUnit; 046import tec.units.ri.unit.TransformedUnit; 047import tec.units.ri.unit.Units; 048 049/** 050 * <p> 051 * This class defines all SI (Système International d'Unités) base units and 052 * derived units as well as units that are accepted for use with the SI units. 053 * </p> 054 * 055 * @see <a href= 056 * "http://en.wikipedia.org/wiki/International_System_of_Units">Wikipedia: 057 * International System of Units</a> 058 * @see <a href="http://physics.nist.gov/cuu/Units/outside.html">Units outside 059 * the SI that are accepted for use with the SI</a> 060 * @see <a href="http://www.bipm.org/utils/common/pdf/si_brochure_8.pdf">SI 2006 061 * - Official Specification</a> 062 * @see MetricPrefix 063 * 064 * @noextend This class is not intended to be extended by clients. 065 * 066 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> 067 * @author <a href="mailto:werner@uom.si">Werner Keil</a> 068 * @version 1.0.1, October 23, 2016 069 */ 070public final class SI extends Units { 071 072 /** 073 * The singleton instance. 074 */ 075 private static final SI INSTANCE = new SI(); 076 077 /** 078 * Default constructor (prevents this class from being instantiated). 079 */ 080 private SI() { 081 } 082 083 /** 084 * Returns the singleton instance of this class. 085 * 086 * @return the metric system instance. 087 */ 088 public static SI getInstance() { 089 return INSTANCE; 090 } 091 092 //////////////////////////////// 093 // SI DERIVED ALTERNATE UNITS // 094 //////////////////////////////// 095 096 /** 097 * The SI unit for magnetomotive force (standard name <code>At</code>). 098 */ 099 public static final AlternateUnit<MagnetomotiveForce> AMPERE_TURN = addUnit( 100 new AlternateUnit<MagnetomotiveForce>(SI.AMPERE, "At"), MagnetomotiveForce.class); 101 102 ////////////////////////////// 103 // SI DERIVED PRODUCT UNITS // 104 ////////////////////////////// 105 106 /** 107 * The SI unit for acceleration quantities (standard name 108 * <code>m/s2</code>). 109 */ 110 public static final Unit<Acceleration> METRE_PER_SQUARE_SECOND = addUnit( 111 new ProductUnit<Acceleration>(METRE_PER_SECOND.divide(SECOND)), Acceleration.class); 112 /** 113 * Alias for METRE_PER_SQUARE_SECOND. 114 * 115 * @deprecated use METRE_PER_SQUARE_SECOND instead. 116 */ 117 public static final Unit<Acceleration> METRES_PER_SQUARE_SECOND = METRE_PER_SQUARE_SECOND; 118 119 /** 120 * The SI unit for action quantities (standard name <code>j.s</code>). 121 */ 122 public static final Unit<Action> JOULE_SECOND = addUnit(new ProductUnit<Action>(JOULE.multiply(SECOND)), 123 Action.class); 124 125 /** 126 * The SI unit for electric permittivity (standard name <code>ε</code>, 127 * <code>F/m </code> or <code>F·m−1</code>). In electromagnetism, absolute 128 * permittivity is the measure of resistance that is encountered when 129 * forming an electric field in a medium. 130 */ 131 public static final Unit<ElectricPermittivity> FARAD_PER_METRE = addUnit( 132 new AlternateUnit<ElectricPermittivity>(FARAD.divide(METRE), "ε"), ElectricPermittivity.class); 133 134 /** 135 * The SI unit for magnetic permeability quantities (standard name 136 * <code>N/A2</code>). 137 */ 138 public static final Unit<MagneticPermeability> NEWTON_PER_SQUARE_AMPERE = addUnit( 139 new ProductUnit<MagneticPermeability>(NEWTON.divide(AMPERE.pow(2))), MagneticPermeability.class); 140 141 /** 142 * Alias for NEWTON_PER_SQUARE_AMPERE. 143 * 144 * @deprecated use NEWTON_PER_SQUARE_AMPERE. 145 */ 146 public static final Unit<MagneticPermeability> NEWTONS_PER_SQUARE_AMPERE = NEWTON_PER_SQUARE_AMPERE; 147 148 /** 149 * The SI unit for wave number quantities (standard name <code>1/m</code>). 150 */ 151 public static final Unit<WaveNumber> RECIPROCAL_METRE = addUnit(new ProductUnit<WaveNumber>(METRE.pow(-1)), 152 WaveNumber.class); 153 154 /** 155 * The SI unit for dynamic viscosity quantities (standard name 156 * <code>Pa.s</code>). 157 */ 158 public static final Unit<DynamicViscosity> PASCAL_SECOND = addUnit( 159 new ProductUnit<DynamicViscosity>(PASCAL.multiply(SECOND)), DynamicViscosity.class); 160 161 /** 162 * Luminance is a photometric measure of the luminous intensity per unit 163 * area of light travelling in a given direction. It describes the amount of 164 * light that passes through, is emitted or reflected from a particular 165 * area, and falls within a given solid angle. The SI unit for luminance is 166 * candela per square metre (<code>cd/m2</code>). 167 * 168 * @see <a href="https://en.wikipedia.org/wiki/Luminance"> Wikipedia: 169 * Luminance</a> 170 */ 171 public static final Unit<Luminance> CANDELA_PER_SQUARE_METRE = addUnit( 172 new ProductUnit<Luminance>(CANDELA.divide(SQUARE_METRE)), Luminance.class); 173 174 /** 175 * The SI unit for kinematic viscosity quantities (standard name 176 * <code>m2/s"</code>). 177 */ 178 public static final Unit<KinematicViscosity> SQUARE_METRE_PER_SECOND = addUnit( 179 new ProductUnit<KinematicViscosity>(SQUARE_METRE.divide(SECOND)), KinematicViscosity.class); 180 181 /** 182 * Alias for SQUARE_METRE_PER_SECOND. 183 * 184 * @deprecated use SQUARE_METRE_PER_SECOND. 185 */ 186 public static final Unit<KinematicViscosity> SQUARE_METRES_PER_SECOND = SQUARE_METRE_PER_SECOND; 187 188 /** 189 * The SI unit for magnetic field strength quantities (standard name 190 * <code>A/m"</code>). 191 */ 192 public static final Unit<MagneticFieldStrength> AMPERE_PER_METRE = addUnit( 193 new ProductUnit<MagneticFieldStrength>(AMPERE.divide(METRE)), MagneticFieldStrength.class); 194 195 /** 196 * Alias for AMPERE_PER_METRE. 197 * 198 * @deprecated use AMPERE_PER_METRE. 199 */ 200 public static final Unit<MagneticFieldStrength> AMPERES_PER_METRE = AMPERE_PER_METRE; 201 202 /** 203 * The SI unit for ionizing radiation quantities (standard name 204 * <code>C/kg"</code>). 205 */ 206 public static final Unit<IonizingRadiation> COULOMB_PER_KILOGRAM = addUnit( 207 new ProductUnit<IonizingRadiation>(COULOMB.divide(KILOGRAM)), IonizingRadiation.class); 208 /** 209 * Alias for COULOMB_PER_KILOGRAM. 210 * 211 * @deprecated use COULOMB_PER_KILOGRAM. 212 */ 213 public static final Unit<IonizingRadiation> COULOMBS_PER_KILOGRAM = COULOMB_PER_KILOGRAM; 214 215 /** 216 * The SI unit for radiant intensity (standard name <code>W/sr</code>). 217 */ 218 public static final Unit<RadiantIntensity> WATT_PER_STERADIAN = addUnit( 219 WATT.divide(STERADIAN).asType(RadiantIntensity.class)); 220 221 /** 222 * The SI unit for radiance (standard name <code>W⋅sr−1⋅m−2</code>). 223 */ 224 public static final Unit<Radiance> WATT_PER_STERADIAN_PER_SQUARE_METRE = addUnit( 225 WATT_PER_STERADIAN.divide(SQUARE_METRE).asType(Radiance.class)); 226 227 ///////////////////////////////////////////////////////////////// 228 // Units outside the SI that are accepted for use with the SI. // 229 ///////////////////////////////////////////////////////////////// 230 231 /** 232 * An angle unit accepted for use with SI units (standard name 233 * <code>deg</code>). 234 * 235 * @deprecated use NonSI 236 */ 237 public static final Unit<Angle> DEGREE_ANGLE = addUnit( 238 new TransformedUnit<Angle>(RADIAN, new PiMultiplierConverter().concatenate(new RationalConverter(1, 180)))); 239 240 /** 241 * An angle unit accepted for use with SI units (standard name 242 * <code>'</code>). 243 * 244 * @deprecated use NonSI 245 */ 246 public static final Unit<Angle> MINUTE_ANGLE = addUnit(new TransformedUnit<Angle>(RADIAN, 247 new PiMultiplierConverter().concatenate(new RationalConverter(1, 180 * 60)))); 248 249 /** 250 * An angle unit accepted for use with SI units (standard name 251 * <code>''</code>). 252 * 253 * @deprecated use NonSI 254 */ 255 public static final Unit<Angle> SECOND_ANGLE = new TransformedUnit<Angle>(RADIAN, 256 new PiMultiplierConverter().concatenate(new RationalConverter(1, 180 * 60 * 60))); 257 258 /** 259 * A mass unit accepted for use with SI units (standard name 260 * <code>t</code>). 261 * 262 * @deprecated use NonSI 263 */ 264 public static final Unit<Mass> TONNE = AbstractSystemOfUnits.Helper.addUnit(INSTANCE.units, 265 new TransformedUnit<Mass>(KILOGRAM, new RationalConverter(1000, 1)), "Tonne", "t"); 266 267 /** 268 * An energy unit accepted for use with SI units (standard name 269 * <code>eV</code>). The electronvolt is the kinetic energy acquired by an 270 * electron passing through a potential difference of 1 V in vacuum. The 271 * value must be obtained by experiment, and is therefore not known exactly. 272 */ 273 public static final Unit<Energy> ELECTRON_VOLT = addUnit( 274 new TransformedUnit<Energy>(JOULE, new MultiplyConverter(1.602176487E-19))); 275 // CODATA 2006 - http://physics.nist.gov/cuu/Constants/codata.pdf 276 277 /** 278 * A mass unit accepted for use with SI units (standard name 279 * <code>u</code>). The unified atomic mass unit is equal to 1/12 of the 280 * mass of an unbound atom of the nuclide 12C, at rest and in its ground 281 * state. The value must be obtained by experiment, and is therefore not 282 * known exactly. 283 */ 284 public static final Unit<Mass> UNIFIED_ATOMIC_MASS = addUnit( 285 new TransformedUnit<Mass>(KILOGRAM, new MultiplyConverter(1.660538782E-27)), "Unified atomic mass", "u", 286 true); 287 // CODATA 2006 - http://physics.nist.gov/cuu/Constants/codata.pdf 288 289 /** 290 * A length unit accepted for use with SI units (standard name 291 * <code>UA</code>). The astronomical unit is a unit of length. Its value is 292 * such that, when used to describe the motion of bodies in the solar 293 * system, the heliocentric gravitation constant is (0.017 202 098 95)2 294 * ua3·d-2. The value must be obtained by experiment, and is therefore not 295 * known exactly. 296 */ 297 public static final Unit<Length> ASTRONOMICAL_UNIT = addUnit( 298 new TransformedUnit<Length>(METRE, new MultiplyConverter(149597871000.0))); 299 // Best estimate source: http://maia.usno.navy.mil/NSFA/CBE.html 300 301 /** 302 * An angle unit accepted for use with SI units (standard name 303 * <code>rev</code>). 304 */ 305 public static final Unit<Angle> REVOLUTION = addUnit( 306 new TransformedUnit<Angle>(RADIAN, new PiMultiplierConverter().concatenate(new RationalConverter(2, 1)))); 307 308 /** 309 * An angle unit accepted for use with SI units (standard name 310 * <code>ha</code>). 311 */ 312 public static final Unit<Area> HECTARE = addUnit( 313 new TransformedUnit<Area>(SQUARE_METRE, new RationalConverter(10000, 1))); 314 315 ///////////////////// 316 // Collection View // 317 ///////////////////// 318 319 @Override 320 public String getName() { 321 return "SI"; 322 } 323 324 /** 325 * Adds a new unit not mapped to any specified quantity type. 326 * 327 * @param unit 328 * the unit being added. 329 * @return <code>unit</code>. 330 */ 331 private static <U extends Unit<?>> U addUnit(U unit) { 332 INSTANCE.units.add(unit); 333 return unit; 334 } 335 336 /** 337 * Adds a new unit not mapped to any specified quantity type and puts a text 338 * as symbol or label. 339 * 340 * @param unit 341 * the unit being added. 342 * @param name 343 * the string to use as name 344 * @param text 345 * the string to use as label or symbol 346 * @param isLabel 347 * if the string should be used as a label or not 348 * @return <code>unit</code>. 349 */ 350 private static <U extends Unit<?>> U addUnit(U unit, String name, String text, boolean isLabel) { 351 if (isLabel) { 352 SimpleUnitFormat.getInstance().label(unit, text); 353 } 354 if (name != null && unit instanceof AbstractUnit) { 355 return Helper.addUnit(INSTANCE.units, unit, name); 356 } else { 357 INSTANCE.units.add(unit); 358 } 359 return unit; 360 } 361 362 /** 363 * Adds a new unit not mapped to any specified quantity type and puts a text 364 * as symbol or label. 365 * 366 * @param unit 367 * the unit being added. 368 * @param text 369 * the string to use as label or symbol 370 * @param isLabel 371 * if the string should be used as a label or not 372 * @return <code>unit</code>. 373 */ 374 @SuppressWarnings("unused") 375 private static <U extends Unit<?>> U addUnit(U unit, String text, boolean isLabel) { 376 return addUnit(unit, null, text, isLabel); 377 } 378 379 /** 380 * Adds a new unit not mapped to any specified quantity type and puts a text 381 * as symbol or label. 382 * 383 * @param unit 384 * the unit being added. 385 * @param name 386 * the string to use as name 387 * @param label 388 * the string to use as label 389 * @return <code>unit</code>. 390 */ 391 private static <U extends Unit<?>> U addUnit(U unit, String name, String label) { 392 return addUnit(unit, name, label, true); 393 } 394 395 /** 396 * Adds a new unit and maps it to the specified quantity type. 397 * 398 * @param unit 399 * the unit being added. 400 * @param type 401 * the quantity type. 402 * @return <code>unit</code>. 403 */ 404 private static <U extends AbstractUnit<?>> U addUnit(U unit, Class<? extends Quantity<?>> type) { 405 INSTANCE.units.add(unit); 406 INSTANCE.quantityToUnit.put(type, unit); 407 return unit; 408 } 409}