[jsr-275] 01/06: Imported Upstream version 1.0.0-vbeta3-0.9.1
Johan Van de Wauw
johanvdw-guest at moszumanska.debian.org
Thu Aug 20 21:52:09 UTC 2015
This is an automated email from the git hooks/post-receive script.
johanvdw-guest pushed a commit to branch master
in repository jsr-275.
commit 2402ec7b34d0cadfef6d61fa5cb094d7824dd340
Author: Johan Van de Wauw <johan.vandewauw at gmail.com>
Date: Thu Aug 20 22:58:41 2015 +0200
Imported Upstream version 1.0.0-vbeta3-0.9.1
---
pom.xml | 242 +++++
src/main/java/javax/measure/Measurable.java | 148 +++
src/main/java/javax/measure/Measure.java | 598 +++++++++++
src/main/java/javax/measure/MeasureFormat.java | 316 ++++++
.../java/javax/measure/converter/AddConverter.java | 117 +++
.../measure/converter/ConversionException.java | 57 ++
.../java/javax/measure/converter/ExpConverter.java | 110 ++
.../javax/measure/converter/LinearConverter.java | 126 +++
.../java/javax/measure/converter/LogConverter.java | 112 ++
.../javax/measure/converter/MultiplyConverter.java | 116 +++
.../javax/measure/converter/RationalConverter.java | 148 +++
.../javax/measure/converter/UnitConverter.java | 230 +++++
.../java/javax/measure/quantity/Acceleration.java | 46 +
src/main/java/javax/measure/quantity/Action.java | 50 +
.../javax/measure/quantity/AmountOfSubstance.java | 46 +
src/main/java/javax/measure/quantity/Angle.java | 47 +
.../measure/quantity/AngularAcceleration.java | 49 +
.../javax/measure/quantity/AngularVelocity.java | 49 +
src/main/java/javax/measure/quantity/Area.java | 47 +
.../javax/measure/quantity/CatalyticActivity.java | 46 +
.../java/javax/measure/quantity/DataAmount.java | 46 +
src/main/java/javax/measure/quantity/DataRate.java | 47 +
.../java/javax/measure/quantity/Dimensionless.java | 44 +
src/main/java/javax/measure/quantity/Duration.java | 46 +
.../javax/measure/quantity/DynamicViscosity.java | 51 +
.../measure/quantity/ElectricCapacitance.java | 46 +
.../javax/measure/quantity/ElectricCharge.java | 46 +
.../measure/quantity/ElectricConductance.java | 46 +
.../javax/measure/quantity/ElectricCurrent.java | 47 +
.../javax/measure/quantity/ElectricInductance.java | 46 +
.../measure/quantity/ElectricPermittivity.java | 50 +
.../javax/measure/quantity/ElectricPotential.java | 46 +
.../javax/measure/quantity/ElectricResistance.java | 46 +
src/main/java/javax/measure/quantity/Energy.java | 46 +
src/main/java/javax/measure/quantity/Force.java | 47 +
.../java/javax/measure/quantity/Frequency.java | 47 +
.../java/javax/measure/quantity/Illuminance.java | 46 +
.../javax/measure/quantity/IonizingRadiation.java | 50 +
.../javax/measure/quantity/KinematicViscosity.java | 50 +
src/main/java/javax/measure/quantity/Length.java | 47 +
.../java/javax/measure/quantity/Luminance.java | 48 +
.../java/javax/measure/quantity/LuminousFlux.java | 46 +
.../javax/measure/quantity/LuminousIntensity.java | 47 +
.../measure/quantity/MagneticFieldStrength.java | 47 +
.../java/javax/measure/quantity/MagneticFlux.java | 46 +
.../measure/quantity/MagneticFluxDensity.java | 46 +
.../measure/quantity/MagneticPermeability.java | 50 +
.../javax/measure/quantity/MagnetomotiveForce.java | 49 +
src/main/java/javax/measure/quantity/Mass.java | 48 +
.../java/javax/measure/quantity/MassFlowRate.java | 50 +
src/main/java/javax/measure/quantity/Power.java | 46 +
src/main/java/javax/measure/quantity/Pressure.java | 46 +
src/main/java/javax/measure/quantity/Quantity.java | 50 +
.../measure/quantity/RadiationDoseAbsorbed.java | 46 +
.../measure/quantity/RadiationDoseEffective.java | 47 +
.../measure/quantity/RadioactiveActivity.java | 46 +
.../java/javax/measure/quantity/SolidAngle.java | 47 +
.../java/javax/measure/quantity/Temperature.java | 46 +
src/main/java/javax/measure/quantity/Torque.java | 53 +
src/main/java/javax/measure/quantity/Velocity.java | 46 +
src/main/java/javax/measure/quantity/Volume.java | 47 +
.../javax/measure/quantity/VolumetricDensity.java | 49 +
.../javax/measure/quantity/VolumetricFlowRate.java | 51 +
.../java/javax/measure/quantity/Wavenumber.java | 49 +
.../javax/measure/quantity/icons/Acceleration.png | Bin 0 -> 2770 bytes
.../java/javax/measure/quantity/icons/Angle.png | Bin 0 -> 3121 bytes
.../java/javax/measure/quantity/icons/Area.png | Bin 0 -> 732 bytes
.../java/javax/measure/quantity/icons/Clothing.png | Bin 0 -> 2903 bytes
.../java/javax/measure/quantity/icons/Currency.png | Bin 0 -> 4356 bytes
.../javax/measure/quantity/icons/DataAmount.png | Bin 0 -> 2817 bytes
.../java/javax/measure/quantity/icons/DataRate.png | Bin 0 -> 4701 bytes
.../java/javax/measure/quantity/icons/Energy.png | Bin 0 -> 2457 bytes
.../javax/measure/quantity/icons/Flow_Volume.png | Bin 0 -> 2420 bytes
.../java/javax/measure/quantity/icons/Force.png | Bin 0 -> 2085 bytes
.../measure/quantity/icons/FuelConsumption.png | Bin 0 -> 2376 bytes
.../java/javax/measure/quantity/icons/Kitchen.png | Bin 0 -> 3162 bytes
.../java/javax/measure/quantity/icons/Length.png | Bin 0 -> 3052 bytes
.../javax/measure/quantity/icons/Luminance.png | Bin 0 -> 3255 bytes
.../java/javax/measure/quantity/icons/Power.png | Bin 0 -> 3548 bytes
.../java/javax/measure/quantity/icons/Prefixes.png | Bin 0 -> 763 bytes
.../java/javax/measure/quantity/icons/Pressure.png | Bin 0 -> 3893 bytes
.../java/javax/measure/quantity/icons/Speed.png | Bin 0 -> 2989 bytes
.../javax/measure/quantity/icons/Temperature.png | Bin 0 -> 2651 bytes
.../java/javax/measure/quantity/icons/Time.png | Bin 0 -> 4528 bytes
.../java/javax/measure/quantity/icons/Torque.png | Bin 0 -> 2716 bytes
.../java/javax/measure/quantity/icons/Volume.png | Bin 0 -> 3367 bytes
.../java/javax/measure/quantity/icons/Weight.png | Bin 0 -> 2376 bytes
.../java/javax/measure/quantity/icons/close.png | Bin 0 -> 2176 bytes
.../java/javax/measure/quantity/icons/nav_dis.png | Bin 0 -> 1853 bytes
.../java/javax/measure/quantity/icons/nav_down.png | Bin 0 -> 2113 bytes
.../java/javax/measure/quantity/icons/nav_up.png | Bin 0 -> 2300 bytes
.../java/javax/measure/unit/AlternateUnit.java | 133 +++
.../java/javax/measure/unit/AnnotatedUnit.java | 125 +++
src/main/java/javax/measure/unit/BaseUnit.java | 113 +++
src/main/java/javax/measure/unit/CompoundUnit.java | 139 +++
src/main/java/javax/measure/unit/DerivedUnit.java | 48 +
src/main/java/javax/measure/unit/Dimension.java | 291 ++++++
src/main/java/javax/measure/unit/NonSI.java | 1070 ++++++++++++++++++++
src/main/java/javax/measure/unit/ProductUnit.java | 478 +++++++++
src/main/java/javax/measure/unit/SI.java | 744 ++++++++++++++
.../java/javax/measure/unit/SystemOfUnits.java | 50 +
.../java/javax/measure/unit/TransformedUnit.java | 127 +++
src/main/java/javax/measure/unit/Unit.java | 571 +++++++++++
src/main/java/javax/measure/unit/UnitFormat.java | 164 +++
.../javax/measure/unit/format/LocalFormat.java | 522 ++++++++++
.../measure/unit/format/LocalFormat.properties | 139 +++
.../measure/unit/format/LocalFormat_de.properties | 21 +
.../unit/format/LocalFormat_en_GB.properties | 4 +
.../javax/measure/unit/format/ParseException.java | 192 ++++
.../java/javax/measure/unit/format/Prefix.java | 81 ++
.../measure/unit/format/SimpleCharStream.java | 439 ++++++++
.../java/javax/measure/unit/format/SymbolMap.java | 222 ++++
src/main/java/javax/measure/unit/format/Token.java | 81 ++
.../javax/measure/unit/format/TokenMgrError.java | 133 +++
src/main/java/javax/measure/unit/format/UCUM.java | 630 ++++++++++++
.../java/javax/measure/unit/format/UCUMFormat.java | 405 ++++++++
.../java/javax/measure/unit/format/UCUMParser.java | 496 +++++++++
.../java/javax/measure/unit/format/UCUMParser.jj | 189 ++++
.../measure/unit/format/UCUMParserConstants.java | 42 +
.../unit/format/UCUMParserTokenManager.java | 399 ++++++++
.../javax/measure/unit/format/UCUM_CI.properties | 248 +++++
.../javax/measure/unit/format/UCUM_CS.properties | 250 +++++
.../measure/unit/format/UCUM_Print.properties | 252 +++++
.../java/javax/measure/unit/format/UnitParser.java | 759 ++++++++++++++
.../java/javax/measure/unit/format/UnitParser.jj | 332 ++++++
.../measure/unit/format/UnitParserConstants.java | 54 +
.../unit/format/UnitParserTokenManager.java | 449 ++++++++
127 files changed, 15178 insertions(+)
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..7318fb5
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,242 @@
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <!-- Project Information -->
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>javax.measure</groupId>
+ <artifactId>jsr-275</artifactId>
+ <packaging>jar</packaging>
+ <version>0.9.1</version>
+ <name>JSR-275</name>
+ <url>http://jcp.org/en/jsr/detail?id=275</url>
+ <description>JSR-275 specifies Java packages for the programmatic handling
+ of physical quantities and their expression as numbers of units.
+ </description>
+ <licenses>
+ <license>
+ <name>BSD License</name>
+ <url>http://jscience.org/LICENSE.txt</url>
+ </license>
+ </licenses>
+ <organization>
+ <name>JScience</name>
+ <url>http://jscience.org</url>
+ </organization>
+ <scm>
+ <connection>scm:cvs:pserver:guest at cvs.dev.java.net:/cvs:jsr-275</connection>
+ <developerConnection>scm:cvs:pserver:${maven.username}@cvs.dev.java.net:/cvs:jsr-275</developerConnection>
+ <url>https://jsr-275.dev.java.net/source/browse/jsr-275/</url>
+ </scm>
+ <dependencies>
+ <dependency> <!-- Validation tests -->
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <!-- ==================================================== -->
+ <!-- Developers and contributors -->
+ <!-- ==================================================== -->
+ <developers>
+ <developer>
+ <name>Jean-Marie Dautelle</name>
+ <id>dautelle</id>
+ <email>jean-marie at dautelle.com</email>
+ <organization>Thales</organization>
+ <organizationUrl>http://www.thalesraytheon-fr.com</organizationUrl>
+ <timezone>CET</timezone>
+ <roles>
+ <role>Spec Lead</role>
+ <role>Java Developer</role>
+ <role>Architect</role>
+ </roles>
+ </developer>
+ <developer>
+ <name>Werner Keil</name>
+ <id>cat</id>
+ <organization>Creative Arts & Technologies</organization>
+ <organizationUrl>http://www.catmedia.us</organizationUrl>
+ <email>jsr275 at catmedia.us</email>
+ <timezone>CET</timezone>
+ <roles>
+ <role>Spec Lead</role>
+ <role>Architect</role>
+ <role>Java Developer</role>
+ </roles>
+ </developer>
+ <developer>
+ <name>Karen Legrand</name>
+ <organization>Innovation Emergency Management (IEM)</organization>
+ <organizationUrl>http://www.iem.com</organizationUrl>
+ <email>karen.legrand at iem.com</email>
+ <timezone>EST</timezone>
+ <roles>
+ <role>Architect</role>
+ <role>Java Developer</role>
+ </roles>
+ </developer>
+ <developer>
+ <name>Chris Senior</name>
+ <organization>Teradyne</organization>
+ <email>chris.senior at teradyne.com</email>
+ <roles>
+ <role>Java Developer</role>
+ </roles>
+ </developer>
+ <developer>
+ <name>Daniel Leuck</name>
+ <organization>Ikayzo</organization>
+ <email>dan at ikayzo.com</email>
+ <timezone>HST</timezone>
+ <roles>
+ <role>Java Developer</role>
+ </roles>
+ </developer>
+ <developer>
+ <name>Martin Desruisseaux</name>
+ <id>desruisseaux</id>
+ <email>desruisseaux at users.sourceforge.net</email>
+ <organization>Institut de Recherche pour le Developpement (IRD)</organization>
+ <timezone>CET</timezone>
+ <roles>
+ <role>Java Developer</role>
+ </roles>
+ </developer>
+ <developer>
+ <name>Michael Gruebsch</name>
+ <email>michael at mkm-rabis.de</email>
+ <roles>
+ <role>Java Developer</role>
+ </roles>
+ </developer>
+ <developer>
+ <name>Eric Russell</name>
+ <email>eric-r at northwestern.edu</email>
+ <timezone>CDT</timezone>
+ <roles>
+ <role>Java Developer</role>
+ </roles>
+ </developer>
+ </developers>
+
+ <contributors>
+ <contributor>
+ <name>Brian Frank</name>
+ <organization>Tridium</organization>
+ <email>bfrank at tridium.com</email>
+ <roles>
+ <role>EG Member</role>
+ </roles>
+ </contributor>
+ <contributor>
+ <name>Bruce Hamilton</name>
+ <organization>Agilent</organization>
+ <email>bruce_hamilton at agilent.com</email>
+ <roles>
+ <role>EG Member</role>
+ </roles>
+ </contributor>
+ <contributor>
+ <name>Chris Downey</name>
+ <email>cdowney at gmail.com</email>
+ <roles>
+ <role>EG Member</role>
+ </roles>
+ </contributor>
+ <contributor>
+ <name>John Murray</name>
+ <organization>Sobetech</organization>
+ <email>john.murray at sobetech.com</email>
+ <roles>
+ <role>EG Member</role>
+ </roles>
+ </contributor>
+ <contributor>
+ <name>Gordan Vosicki</name>
+ <roles>
+ <role>EG Member</role>
+ </roles>
+ </contributor>
+ <contributor>
+ <name>Steve Metsker</name>
+ <organization>CapTech Ventures</organization>
+ <roles>
+ <role>Spec Lead (Emeritus)</role>
+ </roles>
+ </contributor>
+ </contributors>
+
+ <!-- Build Settings -->
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <configuration>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.javolution</groupId>
+ <artifactId>colapi</artifactId>
+ <version>1.0.0</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>colorize</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+ </plugins>
+ <extensions>
+ <extension>
+ <groupId>org.jvnet.wagon-svn</groupId>
+ <artifactId>wagon-svn</artifactId>
+ <version>1.9</version>
+ </extension>
+ </extensions>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <docfilessubdirs>true</docfilessubdirs>
+ <quiet>true</quiet>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ <!-- Environment Settings -->
+ <pluginRepositories>
+ <pluginRepository>
+ <id>maven2-repository.dev.java.net</id>
+ <name>Java.net Repository for Maven</name>
+ <url>http://download.java.net/maven/2/</url>
+ </pluginRepository>
+ </pluginRepositories>
+ <distributionManagement>
+ <repository>
+ <uniqueVersion>false</uniqueVersion>
+ <id>java.net-maven2-repository</id>
+ <url>java-net:/maven2-repository/trunk/repository/</url>
+ </repository>
+ </distributionManagement>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/src/main/java/javax/measure/Measurable.java b/src/main/java/javax/measure/Measurable.java
new file mode 100644
index 0000000..b592a57
--- /dev/null
+++ b/src/main/java/javax/measure/Measurable.java
@@ -0,0 +1,148 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import javax.measure.quantity.Quantity;
+import javax.measure.unit.Unit;
+
+/**
+ * <p> This interface represents the measurable, countable, or comparable
+ * property or aspect of a thing.</p>
+ *
+ * <p> Measurable instances are for the most part scalar quantities.[code]
+ * class Delay implements Measurable<Duration> {
+ * private final double seconds; // Implicit internal unit.
+ * public Delay(double value, Unit<Duration> unit) {
+ * seconds = unit.getConverterTo(SI.SECOND).convert(value);
+ * }
+ * public double doubleValue(Unit<Duration> unit) {
+ * return SI.SECOND.getConverterTo(unit).convert(seconds);
+ * }
+ * ...
+ * }
+ * Thread.wait(new Delay(24, NonSI.HOUR)); // Assuming Thread.wait(Measurable<Duration>) method.
+ * [/code]
+ * Non-scalar quantities are nevertheless allowed as long as an aggregate
+ * value makes sense.[code]
+ * class Velocity3D implements Measurable<Velocity> {
+ * private double x, y, z; // Meters per second.
+ * public double doubleValue(Unit<Velocity> unit) { // Returns the vector norm.
+ * double meterPerSecond = Math.sqrt(x * x + y * y + z * z);
+ * return SI.METER_PER_SECOND.getConverterTo(unit).convert(meterPerSecond);
+ * }
+ * ...
+ * }
+ * class ComplexCurrent implements extends Measurable<ElectricCurrent> {
+ * private Complex amperes;
+ * public double doubleValue(Unit<ElectricCurrent> unit) { // Returns the magnitude.
+ * return AMPERE.getConverterTo(unit).convert(amperes.magnitude());
+ * }
+ * ...
+ * public Complex complexValue(Unit<ElectricCurrent> unit) { ... }
+ * } [/code]</p>
+ *
+ * <p> For convenience, measurable instances of any type can be created
+ * using the {@link Measure} factory methods.[code]
+ * Thread.wait(Measure.valueOf(24, NonSI.HOUR));[/code]</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Measurable<Q extends Quantity> extends Comparable<Measurable<Q>> {
+
+ /**
+ * Returns the integral <code>int</code> value of this measurable when
+ * stated in the specified unit.
+ *
+ * <p> Note: This method differs from the <code>Number.intValue()</code>
+ * in the sense that an ArithmeticException is raised instead
+ * of a bit truncation in case of overflow (safety critical).</p>
+ *
+ * @param unit the unit in which the returned value is stated.
+ * @return the numeric value after conversion to type <code>int</code>.
+ * @throws ArithmeticException if this measurable cannot be represented
+ * by a <code>int</code> number in the specified unit.
+ */
+ int intValue(Unit<Q> unit) throws ArithmeticException;
+
+ /**
+ * Returns the integral <code>long</code> value of this measurable when
+ * stated in the specified unit.
+ *
+ * <p> Note: This method differs from the <code>Number.longValue()</code>
+ * in the sense that an ArithmeticException is raised instead
+ * of a bit truncation in case of overflow (safety critical).</p>
+ *
+ * @param unit the unit in which the returned value is stated.
+ * @return the numeric value after conversion to type <code>long</code>.
+ * @throws ArithmeticException if this measurable cannot be represented
+ * by a <code>int</code> number in the specified unit.
+ */
+ long longValue(Unit<Q> unit) throws ArithmeticException;
+
+ /**
+ * Returns the <code>float</code> value of this measurable
+ * when stated in the specified unit. If the measurable has too great of
+ * a magnitude to be represented as a <code>float</code>,
+ * <code>FLOAT.NEGATIVE_INFINITY</code> or
+ * <code>FLOAT.POSITIVE_INFINITY</code> is returned as appropriate.
+ *
+ * @param unit the unit in which this returned value is stated.
+ * @return the numeric value after conversion to type <code>float</code>.
+ */
+ float floatValue(Unit<Q> unit);
+
+ /**
+ * Returns the <code>double</code> value of this measurable
+ * when stated in the specified unit. If the measurable has too great of
+ * a magnitude to be represented as a <code>double</code>,
+ * <code>Double.NEGATIVE_INFINITY</code> or
+ * <code>Double.POSITIVE_INFINITY</code> is returned as appropriate.
+ *
+ * @param unit the unit in which this returned value is stated.
+ * @return the numeric value after conversion to type <code>double</code>.
+ */
+ double doubleValue(Unit<Q> unit);
+
+ /**
+ * Returns the <code>BigDecimal</code> value of this measurable when
+ * stated in the specified unit.
+ *
+ * @param unit the unit in which the returned value is stated.
+ * @param ctx the math context being used for conversion.
+ * @return the decimal value after conversion.
+ * @throws ArithmeticException if the result is inexact but the
+ * rounding mode is <code>UNNECESSARY</code> or
+ * <code>mathContext.precision == 0</code> and the quotient has a
+ * non-terminating decimal expansion.
+ */
+ BigDecimal decimalValue(Unit<Q> unit, MathContext ctx) throws ArithmeticException;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/Measure.java b/src/main/java/javax/measure/Measure.java
new file mode 100644
index 0000000..1165058
--- /dev/null
+++ b/src/main/java/javax/measure/Measure.java
@@ -0,0 +1,598 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.MathContext;
+
+import java.text.ParsePosition;
+import javax.measure.converter.UnitConverter;
+import javax.measure.quantity.Quantity;
+import javax.measure.unit.Unit;
+
+/**
+ * <p> This class represents the immutable result of a scalar measurement stated
+ * in a known unit.</p>
+ *
+ * <p> To avoid any lost of precision, known exact measure (e.g. physical
+ * constants) should not be created from <code>double</code> constants but
+ * from their decimal representation.[code]
+ * public static final Measure<Velocity> C = Measure.valueOf("299792458 m/s", Velocity.class); // Speed of Light (exact).
+ * [/code]</p>
+ *
+ * <p> Measures can be converted to different units, the conversion precision is
+ * determined by the specified {@link MathContext}.[code]
+ * Measure<Velocity> milesPerHour = C.to(MILES_PER_HOUR, MathContext.DECIMAL128); // Use BigDecimal implementation.
+ * System.out.println(milesPerHour);
+ *
+ * > 670616629.3843951324266284896206156 [mi_i]/h
+ * [/code]
+ * If no precision is specified <code>double</code> precision is assumed.[code]
+ * Measure<Velocity> milesPerHour = C.to(MILES_PER_HOUR); // Use double implementation (fast).
+ * System.out.println(milesPerHour);
+ *
+ * > 670616629.3843951 [mi_i]/h
+ * [/code]</p>
+ *
+ * <p> Applications may sub-class {@link Measure} for particular measurements
+ * types.[code]
+ * // Measurement of type Mass based on <code>double</code> primitive types.
+ * public class Weight extends Measure<Mass> {
+ * private final double _kilograms; // Internal SI representation.
+ * private Weight(double kilograms) { _kilograms = kilograms; }
+ * public static Weight valueOf(double value, Unit<Mass> unit) {
+ * return new Weight(unit.getConverterTo(SI.KILOGRAM).convert(value));
+ * }
+ * public Unit<Mass> getUnit() { return SI.KILOGRAM; }
+ * public Double getValue() { return _kilograms; }
+ * ...
+ * }
+ *
+ * // Complex numbers measurements.
+ * public class ComplexMeasure<Q extends Quantity> extends Measure<Q> {
+ * public Complex getValue() { ... } // Assuming Complex is a Number.
+ * ...
+ * }
+ *
+ * // Specializations of complex numbers measurements.
+ * public class Current extends ComplexMeasure<ElectricCurrent> {...}
+ * public class Tension extends ComplexMeasure<ElectricPotential> {...}
+ * [/code]</p>
+ *
+ * <p> All instances of this class shall be immutable.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public abstract class Measure<Q extends Quantity> implements Measurable<Q>,
+ Serializable {
+
+ /**
+ * Default constructor.
+ */
+ protected Measure() {
+ }
+
+ /**
+ * Returns the measurement numeric value.
+ *
+ * @return the measurement value.
+ */
+ public abstract Number getValue();
+
+ /**
+ * Returns the measurement unit.
+ *
+ * @return the measurement unit.
+ */
+ public abstract Unit<Q> getUnit();
+
+ /**
+ * Convenient method equivalent to {@link #to(javax.measure.unit.Unit)
+ * to(this.getUnit().toSI())}.
+ *
+ * @return this measure or a new measure equivalent to this measure but
+ * stated in SI units.
+ * @throws ArithmeticException if the result is inexact and the quotient
+ * has a non-terminating decimal expansion.
+ */
+ public Measure<Q> toSI() {
+ return to(this.getUnit().toSI());
+ }
+
+ /**
+ * Returns this measure after conversion to specified unit. The default
+ * implementation returns
+ * <code>Measure.valueOf(doubleValue(unit), unit)</code>. If this measure is
+ * already stated in the specified unit, then this measure is returned and
+ * no conversion is performed.
+ *
+ * @param unit the unit in which the returned measure is stated.
+ * @return this measure or a new measure equivalent to this measure but
+ * stated in the specified unit.
+ * @throws ArithmeticException if the result is inexact and the quotient has
+ * a
+ * non-terminating decimal expansion.
+ */
+ public Measure<Q> to(Unit<Q> unit) {
+ if (unit.equals(this.getUnit()))
+ return this;
+ return Measure.valueOf(doubleValue(unit), unit);
+ }
+
+ /**
+ * Returns this measure after conversion to specified unit. The default
+ * implementation returns
+ * <code>Measure.valueOf(decimalValue(unit, ctx), unit)</code>. If this
+ * measure is already stated in the specified unit, then this measure is
+ * returned and no conversion is performed.
+ *
+ * @param unit
+ * the unit in which the returned measure is stated.
+ * @param ctx
+ * the math context to use for conversion.
+ * @return this measure or a new measure equivalent to this measure but
+ * stated in the specified unit.
+ * @throws ArithmeticException
+ * if the result is inexact but the rounding mode is
+ * <code>UNNECESSARY</code> or
+ * <code>mathContext.precision == 0</code> and the quotient has
+ * a non-terminating decimal expansion.
+ */
+ public Measure<Q> to(Unit<Q> unit, MathContext ctx) {
+ if (unit.equals(this.getUnit()))
+ return this;
+ return Measure.valueOf(decimalValue(unit, ctx), unit);
+ }
+
+ /**
+ * Compares this measure and the specified measurable to the given accuracy.
+ * Measurements are considered approximately equals if their absolute
+ * differences when stated in the same unit is less than the specified
+ * accuracy.
+ *
+ * @param that
+ * the measurable to compare with.
+ * @param accuracy
+ * the absolute error allowed.
+ * @return
+ * <code>abs(this.doubleValue(getUnit())- that.doubleValue(getUnit())) <= accuracy</code>
+ */
+ public boolean approximates(Measurable<Q> that, double accuracy) {
+ Unit<Q> unit = this.getUnit();
+ return Math.abs(this.doubleValue(unit) - that.doubleValue(unit)) <= accuracy;
+ }
+
+ /**
+ * Compares this measure to the specified measurable quantity. The default
+ * implementation compares the {@link Measurable#doubleValue(Unit)} of both
+ * this measure and the specified measurable stated in the same unit (this
+ * measure's {@link #getUnit() unit}).
+ *
+ * @return a negative integer, zero, or a positive integer as this measure
+ * is less than, equal to, or greater than the specified measurable
+ * quantity.
+ * @return <code>Double.compare(this.doubleValue(getUnit()),
+ * that.doubleValue(getUnit()))</code>
+ */
+ public int compareTo(Measurable<Q> that) {
+ Unit<Q> unit = getUnit();
+ return Double.compare(doubleValue(unit), that.doubleValue(unit));
+ }
+
+ /**
+ * Compares this measure against the specified object for <b>strict</b>
+ * equality (same unit and same amount).
+ *
+ * <p> Similarly to the {@link BigDecimal#equals} method which consider 2.0
+ * and 2.00 as different objects because of different internal scales,
+ * measurements such as <code>Measure.valueOf(3.0, KILOGRAM)</code>
+ * <code>Measure.valueOf(3, KILOGRAM)</code> and
+ * <code>Measure.valueOf("3 kg")</code> might not be considered equals
+ * because of possible differences in their implementations.</p>
+ *
+ * <p> To compare measures stated using different units or using different
+ * amount implementations the {@link #compareTo} or
+ * {@link #approximates} methods should be used.</p>
+ *
+ * @param obj the object to compare with.
+ * @return <code>this.getUnit.equals(obj.getUnit())
+ * && this.getValue().equals(obj.getValue())</code>
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Measure))
+ return false;
+ Measure<?> that = (Measure<?>) obj;
+ return this.getUnit().equals(that.getUnit())
+ && this.getValue().equals(that.getValue());
+ }
+
+ /**
+ * Returns the hash code for this measure.
+ *
+ * @return the hash code value.
+ */
+ @Override
+ public int hashCode() {
+ return getUnit().hashCode() + getValue().hashCode();
+ }
+
+ /**
+ * Returns the <code>String</code> representation of this measure. The
+ * string produced for a given measure is always the same; it is not
+ * affected by locale. This means that it can be used as a canonical string
+ * representation for exchanging measure, or as a key for a Hashtable, etc.
+ * Locale-sensitive measure formatting and parsing is handled by the
+ * {@link MeasureFormat} class and its subclasses.
+ *
+ * @return <code>UnitFormat.getInternational().format(this)</code>
+ */
+ @Override
+ public final String toString() {
+ return MeasureFormat.getStandard().format(this);
+ }
+
+ // Implements Measurable
+ public final int intValue(Unit<Q> unit) throws ArithmeticException {
+ long longValue = longValue(unit);
+ if ((longValue < Integer.MIN_VALUE) || (longValue > Integer.MAX_VALUE))
+ throw new ArithmeticException("Cannot convert " + longValue
+ + " to int (overflow)");
+ return (int) longValue;
+ }
+
+ // Implements Measurable
+ public long longValue(Unit<Q> unit) throws ArithmeticException {
+ double result = doubleValue(unit);
+ if ((result < Long.MIN_VALUE) || (result > Long.MAX_VALUE))
+ throw new ArithmeticException("Overflow (" + result + ")");
+ return (long) result;
+ }
+
+ // Implements Measurable
+ public final float floatValue(Unit<Q> unit) {
+ return (float) doubleValue(unit);
+ }
+
+ /**
+ * Casts this measure to a parameterized unit of specified nature or throw a
+ * <code>ClassCastException</code> if the dimension of the specified
+ * quantity and this measure unit's dimension do not match. For
+ * example:[code]
+ * Measure<Length> length = Measure.valueOf("2 km").asType(Length.class);
+ * [/code]
+ *
+ * @param type the quantity class identifying the nature of the measure.
+ * @return this measure parameterized with the specified type.
+ * @throws ClassCastException if the dimension of this unit is different
+ * from the specified quantity dimension.
+ * @throws UnsupportedOperationException
+ * if the specified quantity class does not have a public static
+ * field named "UNIT" holding the SI unit for the quantity.
+ * @see Unit#asType(Class)
+ */
+ @SuppressWarnings("unchecked")
+ public final <T extends Quantity> Measure<T> asType(Class<T> type)
+ throws ClassCastException {
+ this.getUnit().asType(type); // Raises ClassCastException is dimension
+ // mismatches.
+ return (Measure<T>) this;
+ }
+
+ /**
+ * Returns the
+ * {@link #valueOf(java.math.BigDecimal, javax.measure.unit.Unit) decimal}
+ * measure of unknown type corresponding to the specified representation.
+ * This method can be used to parse dimensionless quantities.[code]
+ * Measure<Dimensionless> proportion = Measure.valueOf("0.234").asType(Dimensionless.class);
+ * [/code]
+ *
+ * <p> Note: This method handles only
+ * {@link javax.measure.unit.UnitFormat#getStandard standard} unit format
+ * (<a href="http://unitsofmeasure.org/">UCUM</a> based). Locale-sensitive
+ * measure formatting and parsing are handled by the {@link MeasureFormat}
+ * class and its subclasses.</p>
+ *
+ * @param csq the decimal value and its unit (if any) separated by space(s).
+ * @return <code>MeasureFormat.getInternational().parse(csq, new ParsePosition(0))</code>
+ */
+ public static Measure<?> valueOf(CharSequence csq) {
+ return MeasureFormat.getStandard().parse(csq, new ParsePosition(0));
+ }
+
+ /**
+ * Returns the scalar measure for the specified <code>int</code> stated in
+ * the specified unit.
+ *
+ * @param intValue the measurement value.
+ * @param unit the measurement unit.
+ * @return the corresponding <code>int</code> measure.
+ */
+ public static <Q extends Quantity> Measure<Q> valueOf(int intValue,
+ Unit<Q> unit) {
+ return new IntegerMeasure<Q>(intValue, unit);
+ }
+
+ private static class IntegerMeasure<T extends Quantity> extends Measure<T> {
+
+ int _value;
+
+ Unit<T> _unit;
+
+ public IntegerMeasure(int value, Unit<T> unit) {
+ _value = value;
+ _unit = unit;
+ }
+
+ @Override
+ public Integer getValue() {
+ return _value;
+ }
+
+ @Override
+ public Unit<T> getUnit() {
+ return _unit;
+ }
+
+ // Implements Measurable
+ public double doubleValue(Unit<T> unit) {
+ return (_unit.equals(unit)) ? _value : _unit.getConverterTo(unit)
+ .convert(_value);
+ }
+
+ // Implements Measurable
+ public BigDecimal decimalValue(Unit<T> unit, MathContext ctx)
+ throws ArithmeticException {
+ BigDecimal decimal = BigDecimal.valueOf(_value);
+ return (_unit.equals(unit)) ? decimal : _unit.getConverterTo(unit)
+ .convert(decimal, ctx);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ }
+
+ /**
+ * Returns the scalar measure for the specified <code>long</code> stated in
+ * the specified unit.
+ *
+ * @param longValue the measurement value.
+ * @param unit the measurement unit.
+ * @return the corresponding <code>long</code> measure.
+ */
+ public static <Q extends Quantity> Measure<Q> valueOf(long longValue,
+ Unit<Q> unit) {
+ return new LongMeasure<Q>(longValue, unit);
+ }
+
+ private static class LongMeasure<T extends Quantity> extends Measure<T> {
+
+ long _value;
+
+ Unit<T> _unit;
+
+ public LongMeasure(long value, Unit<T> unit) {
+ _value = value;
+ _unit = unit;
+ }
+
+ @Override
+ public Long getValue() {
+ return _value;
+ }
+
+ @Override
+ public Unit<T> getUnit() {
+ return _unit;
+ }
+
+ @Override
+ // Avoid loss of precision if no conversion.
+ public long longValue(Unit<T> unit) {
+ return ((_unit.equals(unit)) || (_unit.getConverterTo(unit) == UnitConverter.IDENTITY)) ? _value
+ : super.longValue(unit);
+ }
+
+ // Implements Measurable
+ public double doubleValue(Unit<T> unit) {
+ return (_unit.equals(unit)) ? _value : _unit.getConverterTo(unit)
+ .convert(_value);
+ }
+
+ // Implements Measurable
+ public BigDecimal decimalValue(Unit<T> unit, MathContext ctx)
+ throws ArithmeticException {
+ BigDecimal decimal = BigDecimal.valueOf(_value);
+ return (_unit.equals(unit)) ? decimal : _unit.getConverterTo(unit)
+ .convert(decimal, ctx);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ }
+
+ /**
+ * Returns the scalar measure for the specified <code>float</code> stated in
+ * the specified unit.
+ *
+ * @param floatValue the measurement value.
+ * @param unit the measurement unit.
+ * @return the corresponding <code>float</code> measure.
+ */
+ public static <Q extends Quantity> Measure<Q> valueOf(float floatValue,
+ Unit<Q> unit) {
+ return new FloatMeasure<Q>(floatValue, unit);
+ }
+
+ private static class FloatMeasure<T extends Quantity> extends Measure<T> {
+
+ float _value;
+
+ Unit<T> _unit;
+
+ public FloatMeasure(float value, Unit<T> unit) {
+ _value = value;
+ _unit = unit;
+ }
+
+ @Override
+ public Float getValue() {
+ return _value;
+ }
+
+ @Override
+ public Unit<T> getUnit() {
+ return _unit;
+ }
+
+ // Implements Measurable
+ public double doubleValue(Unit<T> unit) {
+ return (_unit.equals(unit)) ? _value : _unit.getConverterTo(unit)
+ .convert(_value);
+ }
+
+ // Implements Measurable
+ public BigDecimal decimalValue(Unit<T> unit, MathContext ctx)
+ throws ArithmeticException {
+ BigDecimal decimal = BigDecimal.valueOf(_value);
+ return (_unit.equals(unit)) ? decimal : _unit.getConverterTo(unit)
+ .convert(decimal, ctx);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ }
+
+ /**
+ * Returns the scalar measure for the specified <code>double</code> stated
+ * in the specified unit.
+ *
+ * @param doubleValue the measurement value.
+ * @param unit the measurement unit.
+ * @return the corresponding <code>double</code> measure.
+ */
+ public static <Q extends Quantity> Measure<Q> valueOf(double doubleValue,
+ Unit<Q> unit) {
+ return new DoubleMeasure<Q>(doubleValue, unit);
+ }
+
+ private static class DoubleMeasure<T extends Quantity> extends Measure<T> {
+
+ double _value;
+
+ Unit<T> _unit;
+
+ public DoubleMeasure(double value, Unit<T> unit) {
+ _value = value;
+ _unit = unit;
+ }
+
+ @Override
+ public Double getValue() {
+ return _value;
+ }
+
+ @Override
+ public Unit<T> getUnit() {
+ return _unit;
+ }
+
+ // Implements Measurable
+ public double doubleValue(Unit<T> unit) {
+ return (_unit.equals(unit)) ? _value : _unit.getConverterTo(unit)
+ .convert(_value);
+ }
+
+ // Implements Measurable
+ public BigDecimal decimalValue(Unit<T> unit, MathContext ctx)
+ throws ArithmeticException {
+ BigDecimal decimal = BigDecimal.valueOf(_value);
+ return (_unit.equals(unit)) ? decimal : _unit.getConverterTo(unit)
+ .convert(decimal, ctx);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ }
+
+ /**
+ * Returns the scalar measure for the specified <code>BigDecimal</code>
+ * stated in the specified unit.
+ *
+ * @param decimalValue the measurement value.
+ * @param unit the measurement unit.
+ * @return the corresponding <code>BigDecimal</code> measure.
+ */
+ public static <Q extends Quantity> Measure<Q> valueOf(
+ BigDecimal decimalValue, Unit<Q> unit) {
+ return new DecimalMeasure<Q>(decimalValue, unit);
+ }
+
+ private static class DecimalMeasure<T extends Quantity> extends Measure<T> {
+
+ BigDecimal _value;
+
+ Unit<T> _unit;
+
+ public DecimalMeasure(BigDecimal value, Unit<T> unit) {
+ _value = value;
+ _unit = unit;
+ }
+
+ @Override
+ public BigDecimal getValue() {
+ return _value;
+ }
+
+ @Override
+ public Unit<T> getUnit() {
+ return _unit;
+ }
+
+ // Implements Measurable
+ public double doubleValue(Unit<T> unit) {
+ return (_unit.equals(unit)) ? _value.doubleValue() : _unit
+ .getConverterTo(unit).convert(_value.doubleValue());
+ }
+
+ // Implements Measurable
+ public BigDecimal decimalValue(Unit<T> unit, MathContext ctx)
+ throws ArithmeticException {
+ return (_unit.equals(unit)) ? _value : _unit.getConverterTo(unit)
+ .convert(_value, ctx);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/MeasureFormat.java b/src/main/java/javax/measure/MeasureFormat.java
new file mode 100644
index 0000000..c3c4233
--- /dev/null
+++ b/src/main/java/javax/measure/MeasureFormat.java
@@ -0,0 +1,316 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure;
+
+import java.math.BigDecimal;
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.NumberFormat;
+import java.text.ParsePosition;
+import java.io.IOException;
+
+import java.math.MathContext;
+import javax.measure.unit.CompoundUnit;
+import javax.measure.unit.Unit;
+import javax.measure.unit.UnitFormat;
+
+/**
+ * <p> This class provides the interface for formatting and parsing {@link Measure
+ * measurements}.</p>
+ *
+ * <p> Instances of this class should be able to format measurements stated in
+ * {@link CompoundUnit}. See {@link #formatCompound formatCompound(...)}.
+ * </p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public abstract class MeasureFormat extends Format {
+
+ /**
+ * Holds the default format instance.
+ */
+ private static final NumberSpaceUnit DEFAULT = new NumberSpaceUnit(
+ NumberFormat.getInstance(), UnitFormat.getInstance());
+
+ /**
+ * Holds the standard format instance.
+ */
+ private static final Standard STANDARD = new Standard();
+
+ /**
+ * Returns the measure format for the default locale. The default format
+ * assumes the measure is composed of a decimal number and a {@link Unit}
+ * separated by whitespace(s).
+ *
+ * @return <code>MeasureFormat.getInstance(NumberFormat.getInstance(), UnitFormat.getInstance())</code>
+ */
+ public static MeasureFormat getInstance() {
+ return DEFAULT;
+ }
+
+ /**
+ * Returns the measure format using the specified number format and unit
+ * format (the number and unit are separated by one space).
+ *
+ * @param numberFormat the number format.
+ * @param unitFormat the unit format.
+ * @return the corresponding format.
+ */
+ public static MeasureFormat getInstance(NumberFormat numberFormat,
+ UnitFormat unitFormat) {
+ return new NumberSpaceUnit(numberFormat, unitFormat);
+ }
+
+ /**
+ * Returns the culture invariant format based upon {@link BigDecimal}
+ * canonical format and the {@link UnitFormat#getStandard() standard} unit
+ * format. This format <b>is not</b> locale-sensitive and can be used for
+ * unambiguous electronic communication of quantities together with their
+ * units without loss of information. For example:
+ * <code>"1.23456789 kg.m/s2"</code> returns
+ * <code>Measure.valueOf(new BigDecimal("1.23456789"), Unit.valueOf("kg.m/s2")));</code>
+ *
+ * @return the standard measure format.
+ */
+ public static MeasureFormat getStandard() {
+ return STANDARD;
+ }
+
+ /**
+ * Formats the specified measure into an <code>Appendable</code>.
+ *
+ * @param measure the measure to format.
+ * @param dest the appendable destination.
+ * @return the specified <code>Appendable</code>.
+ * @throws IOException if an I/O exception occurs.
+ */
+ public abstract Appendable format(Measure<?> measure, Appendable dest)
+ throws IOException;
+
+ /**
+ * Parses a portion of the specified <code>CharSequence</code> from the
+ * specified position to produce an object. If parsing succeeds, then the
+ * index of the <code>cursor</code> argument is updated to the index after
+ * the last character used.
+ *
+ * @param csq the <code>CharSequence</code> to parse.
+ * @param cursor the cursor holding the current parsing index.
+ * @return the object parsed from the specified character sub-sequence.
+ * @throws IllegalArgumentException
+ * if any problem occurs while parsing the specified character
+ * sequence (e.g. illegal syntax).
+ */
+ public abstract Measure<?> parse(CharSequence csq, ParsePosition cursor)
+ throws IllegalArgumentException;
+
+ /**
+ * Formats the specified value using {@link CompoundUnit} compound units}.
+ * The default implementation is locale sensitive and does not use space to
+ * separate units. For example:[code]
+ * Unit<Length> FOOT_INCH = FOOT.compound(INCH);
+ * Measure<Length> height = Measure.valueOf(1.81, METER);
+ * System.out.println(height.to(FOOT_INCH));
+ *
+ * > 5ft11,26in // French Local
+ *
+ * Unit<Angle> DMS = DEGREE_ANGLE.compound(MINUTE_ANGLE).compound(SECOND_ANGLE);
+ * Measure<Angle> rotation = Measure.valueOf(35.857497, DEGREE_ANGLE);
+ * System.out.println(rotation.to(DMS));
+ *
+ * > 35°51'26,989" // French Local
+ * [/code]
+ *
+ * @param value the value to format using compound units.
+ * @param unit the compound unit.
+ * @param dest the appendable destination.
+ * @return the specified <code>Appendable</code>.
+ * @throws IOException if an I/O exception occurs.
+ */
+ @SuppressWarnings("unchecked")
+ protected Appendable formatCompound(double value, CompoundUnit<?> unit,
+ Appendable dest) throws IOException {
+ Unit high = unit.getHigh();
+ Unit low = unit.getLow(); // The unit in which the value is stated.
+ long highValue = (long) low.getConverterTo(high).convert(value);
+ double lowValue = value - high.getConverterTo(low).convert(highValue);
+ if (high instanceof CompoundUnit)
+ formatCompound(highValue, (CompoundUnit) high, dest);
+ else {
+ dest.append(DEFAULT._numberFormat.format(highValue));
+ DEFAULT._unitFormat.format(high, dest);
+ }
+ dest.append(DEFAULT._numberFormat.format(lowValue));
+ return DEFAULT._unitFormat.format(low, dest);
+ }
+
+ @Override
+ public final StringBuffer format(Object obj, final StringBuffer toAppendTo,
+ FieldPosition pos) {
+ if (!(obj instanceof Measure))
+ throw new IllegalArgumentException(
+ "obj: Not an instance of Measure");
+ if ((toAppendTo == null) || (pos == null))
+ throw new NullPointerException();
+ try {
+ return (StringBuffer) format((Measure<?>) obj,
+ (Appendable) toAppendTo);
+ } catch (IOException ex) {
+ throw new Error(ex); // Cannot happen.
+ }
+ }
+
+ @Override
+ public final Measure<?> parseObject(String source, ParsePosition pos) {
+ try {
+ return parse(source, pos);
+ } catch (IllegalArgumentException e) {
+ return null; // Unfortunately the message why the parsing failed
+ } // is lost; but we have to follow the Format spec.
+
+ }
+
+ /**
+ * Convenience method equivalent to {@link #format(Measure, Appendable)}
+ * except it does not raise an IOException.
+ *
+ * @param measure the measure to format.
+ * @param dest the appendable destination.
+ * @return the specified <code>StringBuilder</code>.
+ */
+ public final StringBuilder format(Measure<?> measure, StringBuilder dest) {
+ try {
+ return (StringBuilder) this.format(measure, (Appendable) dest);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex); // Should not happen.
+ }
+ }
+
+ // Holds default implementation.
+ private static final class NumberSpaceUnit extends MeasureFormat {
+
+ private final NumberFormat _numberFormat;
+
+ private final UnitFormat _unitFormat;
+
+ private NumberSpaceUnit(NumberFormat numberFormat, UnitFormat unitFormat) {
+ _numberFormat = numberFormat;
+ _unitFormat = unitFormat;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Appendable format(Measure<?> measure, Appendable dest)
+ throws IOException {
+ Unit unit = measure.getUnit();
+ if (unit instanceof CompoundUnit)
+ return formatCompound(measure.doubleValue(unit),
+ (CompoundUnit) unit, dest);
+ else {
+ dest.append(_numberFormat.format(measure.getValue()));
+ if (measure.getUnit().equals(Unit.ONE))
+ return dest;
+ dest.append(' ');
+ return _unitFormat.format(measure.getUnit(), dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Measure<?> parse(CharSequence csq, ParsePosition cursor)
+ throws IllegalArgumentException {
+ String str = csq.toString();
+ Number number = _numberFormat.parse(str, cursor);
+ if (number == null)
+ throw new IllegalArgumentException("Number cannot be parsed");
+ Unit unit = _unitFormat.parse(csq, cursor);
+ if (number instanceof BigDecimal)
+ return Measure.valueOf((BigDecimal) number, unit);
+ else if (number instanceof Long)
+ return Measure.valueOf(((Long) number).longValue(), unit);
+ else if (number instanceof Double)
+ return Measure.valueOf(((Double) number).doubleValue(), unit);
+ else
+ throw new UnsupportedOperationException("Number of type "
+ + number.getClass() + " are not supported");
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ }
+
+ // Holds standard implementation.
+ private static final class Standard extends MeasureFormat {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Appendable format(Measure measure, Appendable dest)
+ throws IOException {
+ Unit unit = measure.getUnit();
+ if (unit instanceof CompoundUnit)
+ return formatCompound(measure.doubleValue(unit),
+ (CompoundUnit) unit, dest);
+ else {
+ BigDecimal decimal = measure.decimalValue(unit,
+ MathContext.UNLIMITED);
+ dest.append(decimal.toString());
+ if (measure.getUnit().equals(Unit.ONE))
+ return dest;
+ dest.append(' ');
+ return UnitFormat.getStandard().format(unit, dest);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Measure<?> parse(CharSequence csq, ParsePosition cursor)
+ throws IllegalArgumentException {
+ int startDecimal = cursor.getIndex();
+ while ((startDecimal < csq.length())
+ && Character.isWhitespace(csq.charAt(startDecimal))) {
+ startDecimal++;
+ }
+ int endDecimal = startDecimal + 1;
+ while ((endDecimal < csq.length())
+ && !Character.isWhitespace(csq.charAt(endDecimal))) {
+ endDecimal++;
+ }
+ BigDecimal decimal = new BigDecimal(csq.subSequence(startDecimal,
+ endDecimal).toString());
+ cursor.setIndex(endDecimal + 1);
+ Unit unit = UnitFormat.getStandard().parse(csq, cursor);
+ return Measure.valueOf(decimal, unit);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/converter/AddConverter.java b/src/main/java/javax/measure/converter/AddConverter.java
new file mode 100644
index 0000000..7cf97b8
--- /dev/null
+++ b/src/main/java/javax/measure/converter/AddConverter.java
@@ -0,0 +1,117 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.converter;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+
+/**
+ * <p> This class represents a converter adding a constant offset
+ * to numeric values (<code>double</code> based).</p>
+ *
+ * <p> Instances of this class are immutable.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public final class AddConverter extends UnitConverter {
+
+ /**
+ * Holds the offset.
+ */
+ private final double _offset;
+
+ /**
+ * Creates an add converter with the specified offset.
+ *
+ * @param offset the offset value.
+ * @throws IllegalArgumentException if offset is <code>0.0</code>
+ * (would result in identity converter).
+ */
+ public AddConverter(double offset) {
+ if (offset == 0.0) {
+ throw new IllegalArgumentException("Would result in identity converter");
+ }
+ _offset = offset;
+ }
+
+ /**
+ * Returns the offset value for this add converter.
+ *
+ * @return the offset value.
+ */
+ public double getOffset() {
+ return _offset;
+ }
+
+ @Override
+ public UnitConverter concatenate(UnitConverter converter) {
+ if (converter instanceof AddConverter) {
+ double offset = _offset + ((AddConverter) converter)._offset;
+ return offset == 0.0 ? IDENTITY : new AddConverter(offset);
+ } else {
+ return super.concatenate(converter);
+ }
+ }
+
+ @Override
+ public AddConverter inverse() {
+ return new AddConverter(-_offset);
+ }
+
+ @Override
+ public double convert(double value) {
+ return value + _offset;
+ }
+
+ @Override
+ public BigDecimal convert(BigDecimal value, MathContext ctx) throws ArithmeticException {
+ return value.add(BigDecimal.valueOf(_offset), ctx);
+ }
+
+ @Override
+ public final String toString() {
+ return "AddConverter(" + _offset + ")";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof AddConverter)) {
+ return false;
+ }
+ AddConverter that = (AddConverter) obj;
+ return this._offset == that._offset;
+ }
+
+ @Override
+ public int hashCode() {
+ long bits = Double.doubleToLongBits(_offset);
+ return (int) (bits ^ (bits >>> 32));
+ }
+ private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/converter/ConversionException.java b/src/main/java/javax/measure/converter/ConversionException.java
new file mode 100644
index 0000000..5d16d2a
--- /dev/null
+++ b/src/main/java/javax/measure/converter/ConversionException.java
@@ -0,0 +1,57 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.converter;
+
+/**
+ * Signals that a problem of some sort has occurred either when creating a
+ * converter between two units or during the conversion itself.
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public class ConversionException extends RuntimeException {
+
+ /**
+ * Constructs a <code>ConversionException</code> with no detail message.
+ */
+ public ConversionException() {
+ super();
+ }
+
+ /**
+ * Constructs a <code>ConversionException</code> with the specified detail
+ * message.
+ *
+ * @param message the detail message.
+ */
+ public ConversionException(String message) {
+ super(message);
+ }
+
+ private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/converter/ExpConverter.java b/src/main/java/javax/measure/converter/ExpConverter.java
new file mode 100644
index 0000000..3cc78e7
--- /dev/null
+++ b/src/main/java/javax/measure/converter/ExpConverter.java
@@ -0,0 +1,110 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.converter;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+
+/**
+ * <p> This class represents a exponential converter of limited precision.
+ * Such converter is typically used to create inverse of logarithmic unit.
+ *
+ * <p> Instances of this class are immutable.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public final class ExpConverter extends UnitConverter {
+
+ /**
+ * Holds the logarithmic base.
+ */
+ private final double _base;
+
+ /**
+ * Holds the natural logarithm of the base.
+ */
+ private final double _logBase;
+
+ /**
+ * Creates a logarithmic converter having the specified base.
+ *
+ * @param base the logarithmic base (e.g. <code>Math.E</code> for
+ * the Natural Logarithm).
+ */
+ public ExpConverter(double base) {
+ _base = base;
+ _logBase = Math.log(base);
+ }
+
+ /**
+ * Returns the exponential base of this converter.
+ *
+ * @return the exponential base (e.g. <code>Math.E</code> for
+ * the Natural Exponential).
+ */
+ public double getBase() {
+ return _base;
+ }
+
+ @Override
+ public UnitConverter inverse() {
+ return new LogConverter(_base);
+ }
+
+ @Override
+ public final String toString() {
+ return "ExpConverter("+ _base + ")";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ExpConverter))
+ return false;
+ ExpConverter that = (ExpConverter) obj;
+ return this._base == that._base;
+ }
+
+ @Override
+ public int hashCode() {
+ long bits = Double.doubleToLongBits(_base);
+ return (int) (bits ^ (bits >>> 32));
+ }
+
+ @Override
+ public double convert(double amount) {
+ return Math.exp(_logBase * amount);
+ }
+
+ @Override
+ public BigDecimal convert(BigDecimal value, MathContext ctx) throws ArithmeticException {
+ return BigDecimal.valueOf(convert(value.doubleValue())); // Reverts to double conversion.
+ }
+
+ private static final long serialVersionUID = 1L;
+}
diff --git a/src/main/java/javax/measure/converter/LinearConverter.java b/src/main/java/javax/measure/converter/LinearConverter.java
new file mode 100644
index 0000000..200d48a
--- /dev/null
+++ b/src/main/java/javax/measure/converter/LinearConverter.java
@@ -0,0 +1,126 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.converter;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+
+/**
+ * <p> This class represents a linear converter. A converter is linear if
+ * <code>convert(u + v) == convert(u) + convert(v)</code> and
+ * <code>convert(r * u) == r * convert(u)</code>. For linear converters the
+ * following property always hold:[code]
+ * y1 = c1.convert(x1);
+ * y2 = c2.convert(x2);
+ * // then y1*y2 == c1.concatenate(c2).convert(x1*x2)
+ * [/code] </p>
+ *
+ * <p> {@link LinearConverter#concatenate Concatenation} of linear converters
+ * always result into a linear converter.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public abstract class LinearConverter extends UnitConverter {
+
+ @Override
+ public UnitConverter concatenate(UnitConverter converter) {
+ if (converter == IDENTITY)
+ return this;
+ if (!(converter instanceof LinearConverter))
+ return super.concatenate(converter); // Compound non-linear
+ // converter.
+ return new CompoundLinear(this, (LinearConverter) converter);
+ }
+
+ @Override
+ public abstract LinearConverter inverse(); // Inverse of a linear converter
+ // should be linear.
+
+ /**
+ * This inner class represents a compound linear converter.
+ */
+ private static class CompoundLinear extends LinearConverter {
+
+ /**
+ * Holds the first converter.
+ */
+ private final LinearConverter _first;
+ /**
+ * Holds the second converter.
+ */
+ private final LinearConverter _second;
+
+ /**
+ * Creates a compound linear converter resulting from the combined
+ * transformation of the specified converters.
+ *
+ * @param first the first converter.
+ * @param second the second converter.
+ */
+ private CompoundLinear(LinearConverter first, LinearConverter second) {
+ _first = first;
+ _second = second;
+ }
+
+ @Override
+ public LinearConverter inverse() {
+ return new CompoundLinear(_second.inverse(), _first.inverse());
+ }
+
+ @Override
+ public double convert(double value) {
+ return _second.convert(_first.convert(value));
+ }
+
+ @Override
+ public BigDecimal convert(BigDecimal value, MathContext ctx) {
+ return _second.convert(_first.convert(value, ctx), ctx);
+ }
+
+ @Override
+ public boolean equals(Object cvtr) {
+ if (this == cvtr)
+ return true;
+ if (!(cvtr instanceof CompoundLinear))
+ return false;
+ CompoundLinear that = (CompoundLinear) cvtr;
+ return (this._first.equals(that._first))
+ && (this._second.equals(that._second));
+ }
+
+ @Override
+ public int hashCode() {
+ return _first.hashCode() + _second.hashCode();
+ }
+
+ private static final long serialVersionUID = 1L;
+ }
+
+ private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/converter/LogConverter.java b/src/main/java/javax/measure/converter/LogConverter.java
new file mode 100644
index 0000000..c726a01
--- /dev/null
+++ b/src/main/java/javax/measure/converter/LogConverter.java
@@ -0,0 +1,112 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.converter;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+
+/**
+ * <p> This class represents a logarithmic converter of limited precision.
+ * Such converter is typically used to create logarithmic unit.
+ * For example:[code]
+ * Unit<Dimensionless> BEL = Unit.ONE.transform(new LogConverter(10).inverse());
+ * [/code]</p>
+ *
+ * <p> Instances of this class are immutable.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public final class LogConverter extends UnitConverter {
+
+ /**
+ * Holds the logarithmic base.
+ */
+ private final double _base;
+ /**
+ * Holds the natural logarithm of the base.
+ */
+ private final double _logBase;
+
+ /**
+ * Creates a logarithmic converter having the specified base.
+ *
+ * @param base the logarithmic base (e.g. <code>Math.E</code> for
+ * the Natural Logarithm).
+ */
+ public LogConverter(double base) {
+ _base = base;
+ _logBase = Math.log(base);
+ }
+
+ /**
+ * Returns the logarithmic base of this converter.
+ *
+ * @return the logarithmic base (e.g. <code>Math.E</code> for
+ * the Natural Logarithm).
+ */
+ public double getBase() {
+ return _base;
+ }
+
+ @Override
+ public UnitConverter inverse() {
+ return new ExpConverter(_base);
+ }
+
+ @Override
+ public final String toString() {
+ return "LogConverter("+ _base + ")";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof LogConverter))
+ return false;
+ LogConverter that = (LogConverter) obj;
+ return this._base ==that._base;
+ }
+
+ @Override
+ public int hashCode() {
+ long bits = Double.doubleToLongBits(_base);
+ return (int) (bits ^ (bits >>> 32));
+ }
+
+ @Override
+ public double convert(double amount) {
+ return Math.log(amount) / _logBase;
+ }
+
+ @Override
+ public BigDecimal convert(BigDecimal value, MathContext ctx) throws ArithmeticException {
+ return BigDecimal.valueOf(convert(value.doubleValue())); // Reverts to double conversion.
+ }
+
+ private static final long serialVersionUID = 1L;
+}
diff --git a/src/main/java/javax/measure/converter/MultiplyConverter.java b/src/main/java/javax/measure/converter/MultiplyConverter.java
new file mode 100644
index 0000000..88f7f65
--- /dev/null
+++ b/src/main/java/javax/measure/converter/MultiplyConverter.java
@@ -0,0 +1,116 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.converter;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+
+/**
+ * <p> This class represents a converter multiplying numeric values by a
+ * constant scaling factor (<code>double</code> based).</p>
+ *
+ * <p> Instances of this class are immutable.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public final class MultiplyConverter extends LinearConverter {
+
+ /**
+ * Holds the scale factor.
+ */
+ private final double _factor;
+
+ /**
+ * Creates a multiply converter with the specified scale factor.
+ *
+ * @param factor the scaling factor.
+ * @throws IllegalArgumentException if coefficient is <code>1.0</code>
+ * (would result in identity converter)
+ */
+ public MultiplyConverter(double factor) {
+ if (factor == 1.0)
+ throw new IllegalArgumentException("Would result in identity converter");
+ _factor = factor;
+ }
+
+ /**
+ * Returns the scale factor of this converter.
+ *
+ * @return the scale factor.
+ */
+ public double getFactor() {
+ return _factor;
+ }
+
+ @Override
+ public UnitConverter concatenate(UnitConverter converter) {
+ if (converter instanceof MultiplyConverter) {
+ double factor = _factor * ((MultiplyConverter) converter)._factor;
+ return factor == 1.0 ? IDENTITY : new MultiplyConverter(factor);
+ } else
+ return super.concatenate(converter);
+ }
+
+ @Override
+ public MultiplyConverter inverse() {
+ return new MultiplyConverter(1.0 / _factor);
+ }
+
+ @Override
+ public double convert(double value) {
+ return value * _factor;
+ }
+
+ @Override
+ public BigDecimal convert(BigDecimal value, MathContext ctx) throws ArithmeticException {
+ return value.multiply(BigDecimal.valueOf(_factor), ctx);
+ }
+
+ @Override
+ public final String toString() {
+ return "MultiplyConverter("+ _factor + ")";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof MultiplyConverter))
+ return false;
+ MultiplyConverter that = (MultiplyConverter) obj;
+ return this._factor == that._factor;
+ }
+
+ @Override
+ public int hashCode() {
+ long bits = Double.doubleToLongBits(_factor);
+ return (int)(bits ^ (bits >>> 32));
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/src/main/java/javax/measure/converter/RationalConverter.java b/src/main/java/javax/measure/converter/RationalConverter.java
new file mode 100644
index 0000000..e6b6176
--- /dev/null
+++ b/src/main/java/javax/measure/converter/RationalConverter.java
@@ -0,0 +1,148 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.converter;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+
+/**
+ * <p> This class represents a converter multiplying numeric values by an
+ * exact scaling factor (represented as the quotient of two
+ * <code>BigInteger</code> numbers).</p>
+ *
+ * <p> Instances of this class are immutable.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public final class RationalConverter extends LinearConverter {
+
+ /**
+ * Holds the converter dividend.
+ */
+ private final BigInteger _dividend;
+ /**
+ * Holds the converter divisor (always positive).
+ */
+ private final BigInteger _divisor;
+
+ /**
+ * Creates a rational converter with the specified dividend and
+ * divisor.
+ *
+ * @param dividend the dividend.
+ * @param divisor the positive divisor.
+ * @throws IllegalArgumentException if <code>divisor <= 0</code>
+ * @throws IllegalArgumentException if <code>dividend == divisor</code>
+ */
+ public RationalConverter(BigInteger dividend, BigInteger divisor) {
+ if (divisor.compareTo(BigInteger.ZERO) <= 0)
+ throw new IllegalArgumentException("Negative or zero divisor");
+ if (dividend.equals(divisor))
+ throw new IllegalArgumentException("Would result in identity converter");
+ _dividend = dividend; // Exact conversion.
+ _divisor = divisor; // Exact conversion.
+ }
+
+ /**
+ * Returns the integer dividend for this rational converter.
+ *
+ * @return this converter dividend.
+ */
+ public BigInteger getDividend() {
+ return _dividend;
+ }
+
+ /**
+ * Returns the integer (positive) divisor for this rational converter.
+ *
+ * @return this converter divisor.
+ */
+ public BigInteger getDivisor() {
+ return _divisor;
+ }
+
+ @Override
+ public double convert(double value) {
+ return value * toDouble(_dividend) / toDouble(_divisor);
+ }
+
+ // Optimization of BigInteger.doubleValue() (implementation too inneficient).
+ private static double toDouble(BigInteger integer) {
+ return (integer.bitLength() < 64) ? integer.longValue() : integer.doubleValue();
+ }
+
+ @Override
+ public BigDecimal convert(BigDecimal value, MathContext ctx) throws ArithmeticException {
+ return value.multiply(new BigDecimal(_dividend, ctx), ctx).divide(new BigDecimal(_divisor, ctx), ctx);
+ }
+
+ @Override
+ public UnitConverter concatenate(UnitConverter converter) {
+ if (converter instanceof RationalConverter) {
+ RationalConverter that = (RationalConverter) converter;
+ BigInteger dividend = this.getDividend().multiply(that.getDividend());
+ BigInteger divisor = this.getDivisor().multiply(that.getDivisor());
+ BigInteger gcd = dividend.gcd(divisor);
+ dividend = dividend.divide(gcd);
+ divisor = divisor.divide(gcd);
+ return (dividend.equals(BigInteger.ONE) && divisor.equals(BigInteger.ONE))
+ ? IDENTITY : new RationalConverter(dividend, divisor);
+ } else
+ return super.concatenate(converter);
+ }
+
+ @Override
+ public RationalConverter inverse() {
+ return _dividend.signum() == -1 ? new RationalConverter(getDivisor().negate(), getDividend().negate())
+ : new RationalConverter(getDivisor(), getDividend());
+ }
+
+ @Override
+ public final String toString() {
+ return "RationalConverter("+ _dividend + "," + _divisor + ")";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof RationalConverter))
+ return false;
+ RationalConverter that = (RationalConverter) obj;
+ return this._dividend.equals(that._dividend) &&
+ this._divisor.equals(that._divisor);
+ }
+
+ @Override
+ public int hashCode() {
+ return _dividend.hashCode() + _divisor.hashCode();
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/src/main/java/javax/measure/converter/UnitConverter.java b/src/main/java/javax/measure/converter/UnitConverter.java
new file mode 100644
index 0000000..1568f35
--- /dev/null
+++ b/src/main/java/javax/measure/converter/UnitConverter.java
@@ -0,0 +1,230 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.converter;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.MathContext;
+
+/**
+ * <p> This class represents a converter of numeric values.</p>
+ *
+ * <p> It is not required for sub-classes to be immutable
+ * (e.g. currency converter).</p>
+ *
+ * <p> Sub-classes must ensure unicity of the {@link #IDENTITY identity}
+ * converter. In other words, if the result of an operation is equivalent
+ * to the identity converter, then the unique {@link #IDENTITY} instance
+ * should be returned.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public abstract class UnitConverter implements Serializable {
+
+ /**
+ * Holds the identity converter (unique). This converter does nothing
+ * (<code>ONE.convert(x) == x</code>). This instance is unique.
+ * (
+ */
+ public static final UnitConverter IDENTITY = new Identity();
+
+ /**
+ * Default constructor.
+ */
+ protected UnitConverter() {
+ }
+
+ /**
+ * Returns the inverse of this converter. If <code>x</code> is a valid
+ * value, then <code>x == inverse().convert(convert(x))</code> to within
+ * the accuracy of computer arithmetic.
+ *
+ * @return the inverse of this converter.
+ */
+ public abstract UnitConverter inverse();
+
+ /**
+ * Converts a <code>double</code> value.
+ *
+ * @param value the numeric value to convert.
+ * @return the <code>double</code> value after conversion.
+ */
+ public abstract double convert(double value);
+
+ /**
+ * Converts a {@link BigDecimal} value.
+ *
+ * @param value the numeric value to convert.
+ * @param ctx the math context being used for conversion.
+ * @return the decimal value after conversion.
+ * @throws ArithmeticException if the result is inexact but the
+ * rounding mode is <code>MathContext.UNNECESSARY</code> or
+ * <code>mathContext.precision == 0</code> and the quotient has a
+ * non-terminating decimal expansion.
+ */
+ public abstract BigDecimal convert(BigDecimal value, MathContext ctx) throws ArithmeticException;
+
+ /**
+ * Indicates whether this converter is considered to be the the same as the
+ * one specified.
+ *
+ * @param cvtr the converter with which to compare.
+ * @return <code>true</code> if the specified object is a converter
+ * considered equals to this converter;<code>false</code> otherwise.
+ */
+ @Override
+ public abstract boolean equals(Object cvtr);
+
+ /**
+ * Returns a hash code value for this converter. Equals object have equal
+ * hash codes.
+ *
+ * @return this converter hash code value.
+ * @see #equals
+ */
+ @Override
+ public abstract int hashCode();
+
+ /**
+ * Concatenates this converter with another converter. The resulting
+ * converter is equivalent to first converting by the specified converter,
+ * and then converting by this converter.
+ *
+ * <p>Note: Implementations must ensure that the {@link #IDENTITY} instance
+ * is returned if the resulting converter is an identity
+ * converter.</p>
+ *
+ * @param converter the other converter.
+ * @return the concatenation of this converter with the other converter.
+ */
+ public UnitConverter concatenate(UnitConverter converter) {
+ return (converter == IDENTITY) ? this : new Compound(converter, this);
+ }
+
+ /**
+ * This inner class represents the identity converter (singleton).
+ */
+ private static final class Identity extends LinearConverter {
+
+ @Override
+ public Identity inverse() {
+ return this;
+ }
+
+ @Override
+ public double convert(double value) {
+ return value;
+ }
+
+ @Override
+ public BigDecimal convert(BigDecimal value, MathContext ctx) {
+ return value;
+ }
+
+ @Override
+ public UnitConverter concatenate(UnitConverter converter) {
+ return converter;
+ }
+
+ @Override
+ public boolean equals(Object cvtr) {
+ return this == cvtr; // Unique instance.
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ }
+
+ /**
+ * This inner class represents a compound converter (non-linear).
+ */
+ private static final class Compound extends UnitConverter {
+
+ /**
+ * Holds the first converter.
+ */
+ private final UnitConverter _first;
+ /**
+ * Holds the second converter.
+ */
+ private final UnitConverter _second;
+
+ /**
+ * Creates a compound converter resulting from the combined
+ * transformation of the specified converters.
+ *
+ * @param first the first converter.
+ * @param second the second converter.
+ */
+ private Compound(UnitConverter first, UnitConverter second) {
+ _first = first;
+ _second = second;
+ }
+
+ @Override
+ public UnitConverter inverse() {
+ return new Compound(_second.inverse(), _first.inverse());
+ }
+
+ @Override
+ public double convert(double value) {
+ return _second.convert(_first.convert(value));
+ }
+
+ @Override
+ public BigDecimal convert(BigDecimal value, MathContext ctx) {
+ return _second.convert(_first.convert(value, ctx), ctx);
+ }
+
+ @Override
+ public boolean equals(Object cvtr) {
+ if (this == cvtr)
+ return true;
+ if (!(cvtr instanceof Compound))
+ return false;
+ Compound that = (Compound) cvtr;
+ return (this._first.equals(that._first)) &&
+ (this._second.equals(that._second));
+ }
+
+ @Override
+ public int hashCode() {
+ return _first.hashCode() + _second.hashCode();
+ }
+
+ private static final long serialVersionUID = 1L;
+ }
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Acceleration.java b/src/main/java/javax/measure/quantity/Acceleration.java
new file mode 100644
index 0000000..f546604
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Acceleration.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the rate of change of velocity with respect to
+ * time. The system unit for this quantity is "m/s²" (metre per square second).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Acceleration extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Acceleration> UNIT = SI.METRES_PER_SQUARE_SECOND;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Action.java b/src/main/java/javax/measure/quantity/Action.java
new file mode 100644
index 0000000..0be0e66
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Action.java
@@ -0,0 +1,50 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents an energy multiplied by a duration (quantity associated
+ * to the <a href="http://en.wikipedia.org/wiki/Planck%27s_constant">Planck Constant</a>).
+ * The system unit for this quantity is "J·s" (joules second).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ * @see <a href="http://en.wikipedia.org/wiki/Action_(physics)">Wikipedia's Action</a>
+ *
+ */
+public interface Action extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Action> UNIT = new ProductUnit<Action>(SI.JOULE.times(SI.SECOND));
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/AmountOfSubstance.java b/src/main/java/javax/measure/quantity/AmountOfSubstance.java
new file mode 100644
index 0000000..0381f3f
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/AmountOfSubstance.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the number of elementary entities (molecules, for
+ * example) of a substance. The system unit for this quantity is "mol" (mole).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface AmountOfSubstance extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<AmountOfSubstance> UNIT = SI.MOLE;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Angle.java b/src/main/java/javax/measure/quantity/Angle.java
new file mode 100644
index 0000000..7499cdd
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Angle.java
@@ -0,0 +1,47 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the figure formed by two lines diverging from a
+ * common point. The system unit for this quantity is "rad" (radian).
+ * This quantity is dimensionless.
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Angle extends Dimensionless {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Angle> UNIT = SI.RADIAN;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/AngularAcceleration.java b/src/main/java/javax/measure/quantity/AngularAcceleration.java
new file mode 100644
index 0000000..ba5c8e7
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/AngularAcceleration.java
@@ -0,0 +1,49 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the rate of change of angular velocity with respect
+ * to time. The system unit for this quantity is "rad/s²" (radian per
+ * square second).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface AngularAcceleration extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<AngularAcceleration> UNIT
+ = new ProductUnit<AngularAcceleration>(SI.RADIAN.divide(SI.SECOND.pow(2)));
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/AngularVelocity.java b/src/main/java/javax/measure/quantity/AngularVelocity.java
new file mode 100644
index 0000000..a9097f4
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/AngularVelocity.java
@@ -0,0 +1,49 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the rate of change of angular displacement
+ * with respect to time. The system unit for this quantity is "rad/s"
+ * (radian per second).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface AngularVelocity extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<AngularVelocity> UNIT
+ = new ProductUnit<AngularVelocity>(SI.RADIAN.divide(SI.SECOND));
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Area.java b/src/main/java/javax/measure/quantity/Area.java
new file mode 100644
index 0000000..b761ca7
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Area.java
@@ -0,0 +1,47 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the extent of a planar region or of the surface of
+ * a solid measured in square units. The system unit for this quantity
+ * is "m²" (square metre).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Area extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Area> UNIT = SI.SQUARE_METRE;
+
+}
diff --git a/src/main/java/javax/measure/quantity/CatalyticActivity.java b/src/main/java/javax/measure/quantity/CatalyticActivity.java
new file mode 100644
index 0000000..d4f2b3c
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/CatalyticActivity.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a catalytic activity. The system unit for this
+ * quantity is "kat" (katal).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface CatalyticActivity extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<CatalyticActivity> UNIT = SI.KATAL;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/DataAmount.java b/src/main/java/javax/measure/quantity/DataAmount.java
new file mode 100644
index 0000000..77f2528
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/DataAmount.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a measure of data amount.
+ * The system unit for this quantity is "bit". This quantity is dimensionless.
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface DataAmount extends Dimensionless {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<DataAmount> UNIT = SI.BIT;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/DataRate.java b/src/main/java/javax/measure/quantity/DataRate.java
new file mode 100644
index 0000000..dd19333
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/DataRate.java
@@ -0,0 +1,47 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the speed of data-transmission.
+ * The system unit for this quantity is "bit/s" (bit per second).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface DataRate extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<DataRate> UNIT = new ProductUnit<DataRate>(SI.BIT.divide(SI.SECOND));
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Dimensionless.java b/src/main/java/javax/measure/quantity/Dimensionless.java
new file mode 100644
index 0000000..b6d6ec1
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Dimensionless.java
@@ -0,0 +1,44 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a dimensionless quantity.
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Dimensionless extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Dimensionless> UNIT = Unit.ONE;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Duration.java b/src/main/java/javax/measure/quantity/Duration.java
new file mode 100644
index 0000000..be155a3
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Duration.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a period of existence or persistence. The system
+ * unit for this quantity is "s" (second).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Duration extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Duration> UNIT = SI.SECOND;
+
+}
diff --git a/src/main/java/javax/measure/quantity/DynamicViscosity.java b/src/main/java/javax/measure/quantity/DynamicViscosity.java
new file mode 100644
index 0000000..6548cc6
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/DynamicViscosity.java
@@ -0,0 +1,51 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the dynamic viscosity.
+ * The system unit for this quantity is "Pa·s" (Pascal-Second).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 3.0, March 2, 2006
+ * @see <a href="http://en.wikipedia.org/wiki/Viscosity">
+ * Wikipedia: Viscosity</a>
+ */
+public interface DynamicViscosity extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<DynamicViscosity> UNIT
+ = new ProductUnit<DynamicViscosity>(SI.PASCAL.times(SI.SECOND));
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/ElectricCapacitance.java b/src/main/java/javax/measure/quantity/ElectricCapacitance.java
new file mode 100644
index 0000000..aee3b02
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/ElectricCapacitance.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents an electric capacitance. The system unit for this
+ * quantity is "F" (Farad).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface ElectricCapacitance extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<ElectricCapacitance> UNIT = SI.FARAD;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/ElectricCharge.java b/src/main/java/javax/measure/quantity/ElectricCharge.java
new file mode 100644
index 0000000..207e95c
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/ElectricCharge.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents an electric charge. The system unit for this
+ * quantity is "C" (Coulomb).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface ElectricCharge extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<ElectricCharge> UNIT = SI.COULOMB;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/ElectricConductance.java b/src/main/java/javax/measure/quantity/ElectricConductance.java
new file mode 100644
index 0000000..9521b0d
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/ElectricConductance.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents an electric conductance. The system unit for this
+ * quantity "S" (Siemens).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface ElectricConductance extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<ElectricConductance> UNIT = SI.SIEMENS;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/ElectricCurrent.java b/src/main/java/javax/measure/quantity/ElectricCurrent.java
new file mode 100644
index 0000000..d3c46d1
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/ElectricCurrent.java
@@ -0,0 +1,47 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the amount of electric charge flowing past
+ * a specified circuit point per unit time. The system unit for
+ * this quantity is "A" (Ampere).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface ElectricCurrent extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<ElectricCurrent> UNIT = SI.AMPERE;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/ElectricInductance.java b/src/main/java/javax/measure/quantity/ElectricInductance.java
new file mode 100644
index 0000000..f2e1f6f
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/ElectricInductance.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents an electric inductance. The system unit for this
+ * quantity is "H" (Henry).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface ElectricInductance extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<ElectricInductance> UNIT = SI.HENRY;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/ElectricPermittivity.java b/src/main/java/javax/measure/quantity/ElectricPermittivity.java
new file mode 100644
index 0000000..4b5278c
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/ElectricPermittivity.java
@@ -0,0 +1,50 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents how an electric field affects, and is affected by
+ * a dielectric medium. The system unit for this quantity is "F/m"
+ * (farads per meter).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ * @see <a href="http://en.wikipedia.org/wiki/Electric_permittivity">Wikipedia's Electric Permittivity</a>
+ *
+ */
+public interface ElectricPermittivity extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<ElectricPermittivity> UNIT = new ProductUnit<ElectricPermittivity>(SI.FARAD.divide(SI.METER));
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/ElectricPotential.java b/src/main/java/javax/measure/quantity/ElectricPotential.java
new file mode 100644
index 0000000..554643a
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/ElectricPotential.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents an electric potential or electromotive force.
+ * The system unit for this quantity is "V" (Volt).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface ElectricPotential extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<ElectricPotential> UNIT = SI.VOLT;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/ElectricResistance.java b/src/main/java/javax/measure/quantity/ElectricResistance.java
new file mode 100644
index 0000000..151f909
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/ElectricResistance.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents an electric resistance.
+ * The system unit for this quantity is "Ω" (Ohm).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface ElectricResistance extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<ElectricResistance> UNIT = SI.OHM;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Energy.java b/src/main/java/javax/measure/quantity/Energy.java
new file mode 100644
index 0000000..2e07e51
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Energy.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the capacity of a physical system to do work.
+ * The system unit for this quantity "J" (Joule).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Energy extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Energy> UNIT = SI.JOULE;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Force.java b/src/main/java/javax/measure/quantity/Force.java
new file mode 100644
index 0000000..599187e
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Force.java
@@ -0,0 +1,47 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a quantity that tends to produce an acceleration
+ * of a body in the direction of its application. The system unit for
+ * this quantity is "N" (Newton).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Force extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Force> UNIT = SI.NEWTON;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Frequency.java b/src/main/java/javax/measure/quantity/Frequency.java
new file mode 100644
index 0000000..17a0e06
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Frequency.java
@@ -0,0 +1,47 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the number of times a specified phenomenon occurs
+ * within a specified interval. The system unit for this quantity is "Hz"
+ * (Hertz).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Frequency extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Frequency> UNIT = SI.HERTZ;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Illuminance.java b/src/main/java/javax/measure/quantity/Illuminance.java
new file mode 100644
index 0000000..697d17b
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Illuminance.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents an illuminance. The system unit for this quantity
+ * is "lx" (lux).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Illuminance extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Illuminance> UNIT = SI.LUX;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/IonizingRadiation.java b/src/main/java/javax/measure/quantity/IonizingRadiation.java
new file mode 100644
index 0000000..5f21c03
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/IonizingRadiation.java
@@ -0,0 +1,50 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the quantity of subatomic particles or
+ * electromagnetic waves that are energetic enough to detach electrons
+ * from atoms or molecules, ionizing them.
+ * The system unit for this quantity is "C/kg ("coulomb per kilogram).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ * @see <a href="http://en.wikipedia.org/wiki/Ionizing_radiation">Wikipedia's Ionizing Radiation</a>
+ */
+public interface IonizingRadiation extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<IonizingRadiation> UNIT = new ProductUnit<IonizingRadiation>(SI.COULOMB.divide(SI.KILOGRAM));
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/KinematicViscosity.java b/src/main/java/javax/measure/quantity/KinematicViscosity.java
new file mode 100644
index 0000000..a1295a6
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/KinematicViscosity.java
@@ -0,0 +1,50 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the diffusion of momentum.
+ * The system unit for this quantity is "m²/s".
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 3.0, March 2, 2006
+ * @see <a href="http://en.wikipedia.org/wiki/Viscosity">
+ * Wikipedia: Viscosity</a>
+ */
+public interface KinematicViscosity extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<KinematicViscosity> UNIT
+ = new ProductUnit<KinematicViscosity>(SI.METRE.pow(2).divide(SI.SECOND));
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Length.java b/src/main/java/javax/measure/quantity/Length.java
new file mode 100644
index 0000000..21dc649
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Length.java
@@ -0,0 +1,47 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the extent of something along its greatest
+ * dimension or the extent of space between two objects or places.
+ * The system unit for this quantity is "m" (metre).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Length extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Length> UNIT = SI.METRE;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Luminance.java b/src/main/java/javax/measure/quantity/Luminance.java
new file mode 100644
index 0000000..1cb4886
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Luminance.java
@@ -0,0 +1,48 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the luminous intensity per unit area of light
+ * travelling in a given direction. The system unit for this quantity
+ * is "cd/m²" (candela per square meter).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Luminance extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Luminance> UNIT = new ProductUnit<Luminance>(SI.CANDELA.divide(SI.SQUARE_METRE));
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/LuminousFlux.java b/src/main/java/javax/measure/quantity/LuminousFlux.java
new file mode 100644
index 0000000..74dbddf
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/LuminousFlux.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a luminous flux. The system unit for this quantity
+ * is "lm" (lumen).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface LuminousFlux extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<LuminousFlux> UNIT = SI.LUMEN;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/LuminousIntensity.java b/src/main/java/javax/measure/quantity/LuminousIntensity.java
new file mode 100644
index 0000000..20c4731
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/LuminousIntensity.java
@@ -0,0 +1,47 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the luminous flux density per solid angle as
+ * measured in a given direction relative to the emitting source.
+ * The system unit for this quantity is "cd" (candela).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface LuminousIntensity extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<LuminousIntensity> UNIT = SI.CANDELA;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/MagneticFieldStrength.java b/src/main/java/javax/measure/quantity/MagneticFieldStrength.java
new file mode 100644
index 0000000..b838fb7
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/MagneticFieldStrength.java
@@ -0,0 +1,47 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a magnetic field strength. The system unit for this
+ * quantity is "A/m" (ampere per meter).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface MagneticFieldStrength extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<MagneticFieldStrength> UNIT = new ProductUnit<MagneticFieldStrength>(SI.AMPERE.divide(SI.METER));
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/MagneticFlux.java b/src/main/java/javax/measure/quantity/MagneticFlux.java
new file mode 100644
index 0000000..757339b
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/MagneticFlux.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a magnetic flux. The system unit for this quantity
+ * is "Wb" (Weber).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface MagneticFlux extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<MagneticFlux> UNIT = SI.WEBER;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/MagneticFluxDensity.java b/src/main/java/javax/measure/quantity/MagneticFluxDensity.java
new file mode 100644
index 0000000..1385498
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/MagneticFluxDensity.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a magnetic flux density. The system unit for this
+ * quantity is "T" (Tesla).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface MagneticFluxDensity extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<MagneticFluxDensity> UNIT = SI.TESLA;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/MagneticPermeability.java b/src/main/java/javax/measure/quantity/MagneticPermeability.java
new file mode 100644
index 0000000..8e7483a
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/MagneticPermeability.java
@@ -0,0 +1,50 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the degree of magnetization of a material that
+ * responds linearly to an applied magnetic field.
+ * The system unit for this quantity is "H/m" (henry per meter).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ * @see <a href="http://en.wikipedia.org/wiki/Permeability_(electromagnetism)">Wikipedia's Permeability</a>
+ *
+ */
+public interface MagneticPermeability extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<MagneticPermeability> UNIT = new ProductUnit<MagneticPermeability>(SI.HENRY.divide(SI.METER));
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/MagnetomotiveForce.java b/src/main/java/javax/measure/quantity/MagnetomotiveForce.java
new file mode 100644
index 0000000..b1d84c7
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/MagnetomotiveForce.java
@@ -0,0 +1,49 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a force that produces magnetic flux.
+ *
+ * The system unit for this quantity is "At" (ampere-turn).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ * @see <a href="http://en.wikipedia.org/wiki/Magnetomotive_force">Wikipedia's Magnetomotive Force</a>
+ *
+ */
+public interface MagnetomotiveForce extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<MagnetomotiveForce> UNIT = SI.AMPERE.alternate("At");
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Mass.java b/src/main/java/javax/measure/quantity/Mass.java
new file mode 100644
index 0000000..6f8fafd
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Mass.java
@@ -0,0 +1,48 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the measure of the quantity of matter that a body
+ * or an object contains. The mass of the body is not dependent on gravity
+ * and therefore is different from but proportional to its weight.
+ * The system unit for this quantity is "kg" (kilogram).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Mass extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Mass> UNIT = SI.KILOGRAM;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/MassFlowRate.java b/src/main/java/javax/measure/quantity/MassFlowRate.java
new file mode 100644
index 0000000..da8f6a4
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/MassFlowRate.java
@@ -0,0 +1,50 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the movement of mass per time.
+ * The system unit for this quantity is "kg/s" (kilogram per second).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 3.0, March 2, 2006
+ * @see <a href="http://en.wikipedia.org/wiki/Mass_flow_rate">
+ * Wikipedia: Mass Flow Rate</a>
+ */
+public interface MassFlowRate extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<MassFlowRate> UNIT
+ = new ProductUnit<MassFlowRate>(SI.KILOGRAM.divide(SI.SECOND));
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Power.java b/src/main/java/javax/measure/quantity/Power.java
new file mode 100644
index 0000000..1d26734
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Power.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the rate at which work is done. The system unit
+ * for this quantity is "W" (Watt).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Power extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Power> UNIT = SI.WATT;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Pressure.java b/src/main/java/javax/measure/quantity/Pressure.java
new file mode 100644
index 0000000..aa14b19
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Pressure.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a force applied uniformly over a surface.
+ * The system unit for this quantity is "Pa" (Pascal).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Pressure extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Pressure> UNIT = SI.PASCAL;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Quantity.java b/src/main/java/javax/measure/quantity/Quantity.java
new file mode 100644
index 0000000..ff2b2be
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Quantity.java
@@ -0,0 +1,50 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+
+/**
+ * <p> This interface represents any type of quantitative properties or
+ * attributes of thing. Mass, time, distance, heat, and angular separation
+ * are among the familiar examples of quantitative properties.</p>
+ *
+ * <p> Distinct quantities have usually different physical dimensions; although
+ * it is not required nor necessary, for example {@link Torque} and
+ * {@link Energy} have same dimension but are of different nature
+ * (vector for torque, scalar for energy).</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, February 25, 2007
+ * @see <a href="http://en.wikipedia.org/wiki/Quantity">Wikipedia: Quantity</a>
+ * @see <a href="http://en.wikipedia.org/wiki/Dimensional_analysis">
+ * Wikipedia: Dimensional Analysis</a>
+ */
+public interface Quantity {
+
+ // No method - Tagging interface.
+
+}
diff --git a/src/main/java/javax/measure/quantity/RadiationDoseAbsorbed.java b/src/main/java/javax/measure/quantity/RadiationDoseAbsorbed.java
new file mode 100644
index 0000000..b1a826c
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/RadiationDoseAbsorbed.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the amount of energy deposited per unit of
+ * mass. The system unit for this quantity is "Gy" (Gray).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface RadiationDoseAbsorbed extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<RadiationDoseAbsorbed> UNIT = SI.GRAY;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/RadiationDoseEffective.java b/src/main/java/javax/measure/quantity/RadiationDoseEffective.java
new file mode 100644
index 0000000..f125368
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/RadiationDoseEffective.java
@@ -0,0 +1,47 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the effective (or "equivalent") dose of radiation
+ * received by a human or some other living organism. The system unit for
+ * this quantity is "Sv" (Sievert).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface RadiationDoseEffective extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<RadiationDoseEffective> UNIT = SI.SIEVERT;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/RadioactiveActivity.java b/src/main/java/javax/measure/quantity/RadioactiveActivity.java
new file mode 100644
index 0000000..96cef4b
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/RadioactiveActivity.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a radioactive activity. The system unit for
+ * this quantity is "Bq" (Becquerel).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface RadioactiveActivity extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<RadioactiveActivity> UNIT = SI.BECQUEREL;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/SolidAngle.java b/src/main/java/javax/measure/quantity/SolidAngle.java
new file mode 100644
index 0000000..eea689e
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/SolidAngle.java
@@ -0,0 +1,47 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the angle formed by three or more planes intersecting
+ * at a common point. The system unit for this quantity is "sr" (steradian).
+ * This quantity is dimensionless.
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface SolidAngle extends Dimensionless {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<SolidAngle> UNIT = SI.STERADIAN;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Temperature.java b/src/main/java/javax/measure/quantity/Temperature.java
new file mode 100644
index 0000000..31b24a8
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Temperature.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This class represents the degree of hotness or coldness of a body or
+ * an environment. The system unit for this quantity is "K" (Kelvin).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Temperature extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Temperature> UNIT = SI.KELVIN;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Torque.java b/src/main/java/javax/measure/quantity/Torque.java
new file mode 100644
index 0000000..fb9fdff
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Torque.java
@@ -0,0 +1,53 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the moment of a force. The system unit for this
+ * quantity is "N·m" (Newton-Metre).
+ *
+ * <p> Note: The Newton-metre ("N·m") is also a way of exressing a Joule (unit
+ * of energy). However, torque is not energy. So, to avoid confusion, we
+ * will use the units "N·m" for torque and not "J". This distinction occurs
+ * due to the scalar nature of energy and the vector nature of torque.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Torque extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Torque> UNIT =
+ new ProductUnit<Torque>(SI.NEWTON.times(SI.METRE));
+
+}
diff --git a/src/main/java/javax/measure/quantity/Velocity.java b/src/main/java/javax/measure/quantity/Velocity.java
new file mode 100644
index 0000000..97e0da1
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Velocity.java
@@ -0,0 +1,46 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a distance traveled divided by the time of travel.
+ * The system unit for this quantity is "m/s" (metre per second).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Velocity extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Velocity> UNIT = SI.METRES_PER_SECOND;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Volume.java b/src/main/java/javax/measure/quantity/Volume.java
new file mode 100644
index 0000000..f3198e7
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Volume.java
@@ -0,0 +1,47 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the amount of space occupied by a three-dimensional
+ * object or region of space, expressed in cubic units. The system unit for
+ * this quantity is "m³" (cubic metre).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface Volume extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Volume> UNIT = SI.CUBIC_METRE;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/VolumetricDensity.java b/src/main/java/javax/measure/quantity/VolumetricDensity.java
new file mode 100644
index 0000000..298c58e
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/VolumetricDensity.java
@@ -0,0 +1,49 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a mass per unit volume of a substance under
+ * specified conditions of pressure and temperature. The system unit for
+ * this quantity is "kg/m³" (kilogram per cubic metre).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public interface VolumetricDensity extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<VolumetricDensity> UNIT = new ProductUnit<VolumetricDensity>(
+ SI.KILOGRAM.divide(SI.METRE.pow(3)));
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/VolumetricFlowRate.java b/src/main/java/javax/measure/quantity/VolumetricFlowRate.java
new file mode 100644
index 0000000..390862f
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/VolumetricFlowRate.java
@@ -0,0 +1,51 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents the volume of fluid passing a point in a system
+ * per unit of time. The system unit for this quantity is "m³/s"
+ * (cubic metre per second).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 3.0, March 2, 2006
+ * @see <a href="http://en.wikipedia.org/wiki/Rate_of_fluid_flow">
+ * Wikipedia: Volumetric Flow Rate</a>
+ */
+public interface VolumetricFlowRate extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<VolumetricFlowRate> UNIT
+ = new ProductUnit<VolumetricFlowRate>(SI.METRE.pow(3).divide(SI.SECOND));
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/Wavenumber.java b/src/main/java/javax/measure/quantity/Wavenumber.java
new file mode 100644
index 0000000..adda242
--- /dev/null
+++ b/src/main/java/javax/measure/quantity/Wavenumber.java
@@ -0,0 +1,49 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.quantity;
+import javax.measure.unit.ProductUnit;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+
+/**
+ * This interface represents a wave property inversely related to wavelength.
+ * The system unit for this quantity is "1/m" (reciprocal meters).
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ * @see <a href="http://en.wikipedia.org/wiki/Wavenumber">Wikipedia's Wavenumber</a>
+ *
+ */
+public interface Wavenumber extends Quantity {
+
+ /**
+ * Holds the SI unit (Système International d'Unités) for this quantity.
+ */
+ public final static Unit<Wavenumber> UNIT = new ProductUnit<Wavenumber>(Unit.ONE.divide(SI.METER));
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/quantity/icons/Acceleration.png b/src/main/java/javax/measure/quantity/icons/Acceleration.png
new file mode 100644
index 0000000..a11dd6f
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Acceleration.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Angle.png b/src/main/java/javax/measure/quantity/icons/Angle.png
new file mode 100644
index 0000000..02c4edf
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Angle.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Area.png b/src/main/java/javax/measure/quantity/icons/Area.png
new file mode 100644
index 0000000..e3d83a8
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Area.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Clothing.png b/src/main/java/javax/measure/quantity/icons/Clothing.png
new file mode 100644
index 0000000..8a029fa
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Clothing.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Currency.png b/src/main/java/javax/measure/quantity/icons/Currency.png
new file mode 100644
index 0000000..4e175c1
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Currency.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/DataAmount.png b/src/main/java/javax/measure/quantity/icons/DataAmount.png
new file mode 100644
index 0000000..8a21672
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/DataAmount.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/DataRate.png b/src/main/java/javax/measure/quantity/icons/DataRate.png
new file mode 100644
index 0000000..e39d67f
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/DataRate.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Energy.png b/src/main/java/javax/measure/quantity/icons/Energy.png
new file mode 100644
index 0000000..2d460d8
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Energy.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Flow_Volume.png b/src/main/java/javax/measure/quantity/icons/Flow_Volume.png
new file mode 100644
index 0000000..2fd14c0
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Flow_Volume.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Force.png b/src/main/java/javax/measure/quantity/icons/Force.png
new file mode 100644
index 0000000..f2051c0
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Force.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/FuelConsumption.png b/src/main/java/javax/measure/quantity/icons/FuelConsumption.png
new file mode 100644
index 0000000..713907a
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/FuelConsumption.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Kitchen.png b/src/main/java/javax/measure/quantity/icons/Kitchen.png
new file mode 100644
index 0000000..8cf4425
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Kitchen.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Length.png b/src/main/java/javax/measure/quantity/icons/Length.png
new file mode 100644
index 0000000..3867f66
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Length.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Luminance.png b/src/main/java/javax/measure/quantity/icons/Luminance.png
new file mode 100644
index 0000000..e7e8b85
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Luminance.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Power.png b/src/main/java/javax/measure/quantity/icons/Power.png
new file mode 100644
index 0000000..2deb5f1
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Power.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Prefixes.png b/src/main/java/javax/measure/quantity/icons/Prefixes.png
new file mode 100644
index 0000000..6ce3ac6
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Prefixes.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Pressure.png b/src/main/java/javax/measure/quantity/icons/Pressure.png
new file mode 100644
index 0000000..9e39ece
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Pressure.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Speed.png b/src/main/java/javax/measure/quantity/icons/Speed.png
new file mode 100644
index 0000000..a435f5f
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Speed.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Temperature.png b/src/main/java/javax/measure/quantity/icons/Temperature.png
new file mode 100644
index 0000000..9496acb
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Temperature.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Time.png b/src/main/java/javax/measure/quantity/icons/Time.png
new file mode 100644
index 0000000..8067ff8
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Time.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Torque.png b/src/main/java/javax/measure/quantity/icons/Torque.png
new file mode 100644
index 0000000..1be38b5
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Torque.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Volume.png b/src/main/java/javax/measure/quantity/icons/Volume.png
new file mode 100644
index 0000000..2da1df0
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Volume.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/Weight.png b/src/main/java/javax/measure/quantity/icons/Weight.png
new file mode 100644
index 0000000..2493f6f
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/Weight.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/close.png b/src/main/java/javax/measure/quantity/icons/close.png
new file mode 100644
index 0000000..964f1fe
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/close.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/nav_dis.png b/src/main/java/javax/measure/quantity/icons/nav_dis.png
new file mode 100644
index 0000000..0821aeb
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/nav_dis.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/nav_down.png b/src/main/java/javax/measure/quantity/icons/nav_down.png
new file mode 100644
index 0000000..2bba1a9
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/nav_down.png differ
diff --git a/src/main/java/javax/measure/quantity/icons/nav_up.png b/src/main/java/javax/measure/quantity/icons/nav_up.png
new file mode 100644
index 0000000..94de580
Binary files /dev/null and b/src/main/java/javax/measure/quantity/icons/nav_up.png differ
diff --git a/src/main/java/javax/measure/unit/AlternateUnit.java b/src/main/java/javax/measure/unit/AlternateUnit.java
new file mode 100644
index 0000000..730f6de
--- /dev/null
+++ b/src/main/java/javax/measure/unit/AlternateUnit.java
@@ -0,0 +1,133 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit;
+
+import javax.measure.converter.UnitConverter;
+import javax.measure.quantity.Quantity;
+
+/**
+ * <p> This class represents the units used in expressions to distinguish
+ * between quantities of a different nature but of the same dimensions.</p>
+ *
+ * <p> Instances of this class are created through the
+ * {@link Unit#alternate(String)} method.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public final class AlternateUnit<Q extends Quantity> extends DerivedUnit<Q> {
+
+ /**
+ * Holds the symbol.
+ */
+ private final String _symbol;
+
+ /**
+ * Holds the parent unit (a system unit).
+ */
+ private final Unit<?> _parent;
+
+ /**
+ * Creates an alternate unit for the specified unit identified by the
+ * specified symbol.
+ *
+ * @param symbol the symbol for this alternate unit.
+ * @param parent the system unit from which this alternate unit is
+ * derived.
+ * @throws UnsupportedOperationException if the source is not
+ * a standard unit.
+ * @throws IllegalArgumentException if the specified symbol is
+ * associated to a different unit.
+ */
+ AlternateUnit(String symbol, Unit<?> parent) {
+ if (!parent.isSI())
+ throw new UnsupportedOperationException(this + " is not a standard unit");
+ _symbol = symbol;
+ _parent = parent;
+ // Checks if the symbol is associated to a different unit.
+ synchronized (Unit.SYMBOL_TO_UNIT) {
+ Unit<?> unit = Unit.SYMBOL_TO_UNIT.get(symbol);
+ if (unit == null) {
+ Unit.SYMBOL_TO_UNIT.put(symbol, this);
+ return;
+ }
+ if (unit instanceof AlternateUnit) {
+ AlternateUnit<?> existingUnit = (AlternateUnit<?>) unit;
+ if (symbol.equals(existingUnit._symbol) && _parent.equals(existingUnit._parent))
+ return; // OK, same unit.
+ }
+ throw new IllegalArgumentException("Symbol " + symbol + " is associated to a different unit");
+ }
+ }
+
+ /**
+ * Returns the symbol for this alternate unit.
+ *
+ * @return this alternate unit symbol.
+ */
+ public final String getSymbol() {
+ return _symbol;
+ }
+
+ /**
+ * Returns the parent unit from which this alternate unit is derived
+ * (a system unit itself).
+ *
+ * @return the parent of the alternate unit.
+ */
+ public final Unit<?> getParent() {
+ return _parent;
+ }
+
+ @Override
+ public final Unit<Q> toSI() {
+ return this;
+ }
+
+ @Override
+ public final UnitConverter getConverterTo(Unit<Q> unit) {
+ return unit.equals(this) ? UnitConverter.IDENTITY : super.getConverterTo(unit);
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (this == that)
+ return true;
+ if (!(that instanceof AlternateUnit))
+ return false;
+ AlternateUnit<?> thatUnit = (AlternateUnit<?>) that;
+ return this._symbol.equals(thatUnit._symbol); // Symbols are unique.
+ }
+
+ @Override
+ public int hashCode() {
+ return _symbol.hashCode();
+ }
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/unit/AnnotatedUnit.java b/src/main/java/javax/measure/unit/AnnotatedUnit.java
new file mode 100644
index 0000000..828baec
--- /dev/null
+++ b/src/main/java/javax/measure/unit/AnnotatedUnit.java
@@ -0,0 +1,125 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit;
+
+import javax.measure.converter.UnitConverter;
+import javax.measure.quantity.Quantity;
+
+/**
+ * <p> This class represents an annotated unit. It allows for unit specialization
+ * and annotation without changing the unit semantic. For example:[code]
+ * public class Size extends Measurable<Length> {
+ * private double meters;
+ * ...
+ * public static class Unit extends AnnotatedUnit<Length> {
+ * private Unit(javax.measure.unit.Unit<Length> realUnit, String annotation) {
+ * super(realUnit, annotation);
+ * }
+ * public static Size.Unit METER = new Size.Unit(SI.METER, "SIZE"); // Equivalent to SI.METER
+ * public static Size.Unit INCH = new Size.Unit(NonSI.INCH, "SIZE"); // Equivalent to NonSI.INCH
+ * }
+ * }[/code]</p>
+ * <p> Annotation are often written between curly braces behind units
+ * but they do not change, for example "%{vol}", "kg{total}", or
+ * "{RBC}" (for "red blood cells") are equivalent to "%", "kg", and "1"
+ * respectively.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public class AnnotatedUnit<Q extends Quantity> extends DerivedUnit<Q> {
+
+ /**
+ * Holds the annotation.
+ */
+ private final String _annotation;
+
+ /**
+ * Holds the real unit.
+ */
+ private final Unit<Q> _realUnit;
+
+ /**
+ * Creates an annotated unit for the specified unit.
+ *
+ * @param realUnit the real unit.
+ * @param annotation the annotation.
+ */
+ public AnnotatedUnit(Unit<Q> realUnit, String annotation) {
+ _realUnit = (realUnit instanceof AnnotatedUnit)
+ ? ((AnnotatedUnit<Q>) realUnit).getRealUnit() : realUnit;
+ _annotation = annotation;
+ }
+
+ /**
+ * Returns the annotation of this unit.
+ *
+ * @return the annotation of this unit.
+ */
+ public String getAnnotation() {
+ return _annotation;
+ }
+
+ /**
+ * Returns the equivalent non-annotated unit.
+ *
+ * @return the real unit.
+ */
+ public final Unit<Q> getRealUnit() {
+ return _realUnit;
+ }
+
+ @Override
+ public final Unit<Q> toSI() {
+ return _realUnit.toSI();
+ }
+
+ @Override
+ public final UnitConverter getConverterTo(Unit<Q> unit) {
+ return _realUnit.getConverterTo(unit);
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (this == that)
+ return true;
+ if (!(that instanceof AnnotatedUnit))
+ return false;
+ AnnotatedUnit<?> thatUnit = (AnnotatedUnit<?>) that;
+ return this._realUnit.equals(thatUnit._realUnit) &&
+ this._annotation.equals(thatUnit._annotation);
+ }
+
+ @Override
+ public int hashCode() {
+ return _realUnit.hashCode() + _annotation.hashCode();
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/unit/BaseUnit.java b/src/main/java/javax/measure/unit/BaseUnit.java
new file mode 100644
index 0000000..19b3fb8
--- /dev/null
+++ b/src/main/java/javax/measure/unit/BaseUnit.java
@@ -0,0 +1,113 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit;
+
+import javax.measure.converter.UnitConverter;
+import javax.measure.quantity.Quantity;
+
+/**
+ * <p> This class represents the building blocks on top of which all others
+ * units are created. Base units are typically dimensionally independent.
+ * Although, the actual unit dimension is determinate by the current
+ * {@link Dimension.Model model}. Using the {@link
+ * Dimension.Model#STANDARD standard} model, all seven SI base units
+ * are dimensionally independent.</p>
+ *
+ * <p> This class defines the "standard base units" which includes SI base
+ * units and possibly others user-defined base units. It does not represent
+ * the base units of a specific {@link SystemOfUnits}.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ * @see <a href="http://en.wikipedia.org/wiki/SI_base_unit">
+ * Wikipedia: SI base unit</a>
+ */
+public class BaseUnit<Q extends Quantity> extends Unit<Q> {
+
+ /**
+ * Holds the symbol.
+ */
+ private final String _symbol;
+
+ /**
+ * Creates a base unit having the specified symbol.
+ *
+ * @param symbol the symbol of this base unit.
+ * @throws IllegalArgumentException if the specified symbol is
+ * associated to a different unit.
+ */
+ public BaseUnit(String symbol) {
+ _symbol = symbol;
+ // Checks if the symbol is associated to a different unit.
+ synchronized (Unit.SYMBOL_TO_UNIT) {
+ Unit<?> unit = Unit.SYMBOL_TO_UNIT.get(symbol);
+ if (unit == null) {
+ Unit.SYMBOL_TO_UNIT.put(symbol, this);
+ return;
+ }
+ if (!(unit instanceof BaseUnit))
+ throw new IllegalArgumentException("Symbol " + symbol + " is associated to a different unit");
+ }
+ }
+
+ /**
+ * Returns the unique symbol for this base unit.
+ *
+ * @return this base unit symbol.
+ */
+ public final String getSymbol() {
+ return _symbol;
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (this == that)
+ return true;
+ if (!(that instanceof BaseUnit))
+ return false;
+ BaseUnit<?> thatUnit = (BaseUnit<?>) that;
+ return this._symbol.equals(thatUnit._symbol);
+ }
+
+ @Override
+ public int hashCode() {
+ return _symbol.hashCode();
+ }
+
+ @Override
+ public Unit<Q> toSI() {
+ return this;
+ }
+
+ @Override
+ public final UnitConverter getConverterTo(Unit<Q> unit) {
+ return unit.equals(this) ? UnitConverter.IDENTITY : super.getConverterTo(unit);
+ }
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/unit/CompoundUnit.java b/src/main/java/javax/measure/unit/CompoundUnit.java
new file mode 100644
index 0000000..ccadb42
--- /dev/null
+++ b/src/main/java/javax/measure/unit/CompoundUnit.java
@@ -0,0 +1,139 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit;
+
+import javax.measure.converter.UnitConverter;
+import javax.measure.quantity.Quantity;
+
+/**
+ * <p> This class represents the multi-radix units (such as "hour:min:sec").
+ * Instances of this class are created using the {@link Unit#compound
+ * Unit.compound} method. Instances of this class are used mostly for
+ * {@link javax.measure.MeasureFormat formatting} purpose.</p>
+ *
+ * <p> Examples of compound units:[code]
+ * Unit<Duration> HOUR_MINUTE_SECOND = HOUR.compound(MINUTE).compound(SECOND);
+ * Unit<Angle> DEGREE_MINUTE_ANGLE = DEGREE_ANGLE.compound(MINUTE_ANGLE);
+ * Unit<Length> FOOT_INCH = FOOT.compound(INCH);
+ * [/code]</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public final class CompoundUnit<Q extends Quantity> extends DerivedUnit<Q> {
+
+ /**
+ * Holds the lowest (main) unit.
+ */
+ private final Unit<Q> _low;
+
+ /**
+ * Holds the highest unit(s).
+ */
+ private final Unit<Q> _high;
+
+ /**
+ * Creates a compound unit from the specified units.
+ *
+ * @param high the highest unit(s).
+ * @param low the lowest unit(s).
+ * @throws IllegalArgumentException if both units are not of same type
+ * (<code>!high.toSI().equals(low.toSI())</code>).
+ */
+ CompoundUnit(Unit<Q> high, Unit<Q> low) {
+ if (!high.toSI().equals(low.toSI()))
+ throw new IllegalArgumentException(
+ "Cannot compound " + high + " with " + low);
+ if (low instanceof CompoundUnit) {
+ _high = high.compound(((CompoundUnit<Q>) low).getHigh());
+ _low = ((CompoundUnit<Q>) low).getLow();
+ } else {
+ _high = high;
+ _low = low;
+ }
+ }
+
+ /**
+ * Returns the lowest unit or main unit of this compound unit
+ * (never a {@link CompoundUnit}).
+ *
+ * @return the lower unit.
+ */
+ public Unit<Q> getLow() {
+ return _low;
+ }
+
+ /**
+ * Returns the high unit(s) of this compound unit (can be a
+ * {@link CompoundUnit} itself).
+ *
+ * @return the high unit(s).
+ */
+ public Unit<Q> getHigh() {
+ return _high;
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (this == that)
+ return true;
+ if (!(that instanceof CompoundUnit))
+ return false;
+ CompoundUnit<?> thatUnit = (CompoundUnit<?>) that;
+ return this._low.equals(thatUnit._low) && this._high.equals(thatUnit._high);
+ }
+
+ @Override
+ public int hashCode() {
+ return _high.hashCode() ^ _low.hashCode();
+ }
+
+ /**
+ * Overrides the {@link Unit#toString() default implementation} as
+ * compound units are not recognized by the standard UCUM format.
+ *
+ * @return the textual representation of this compound unit.
+ */
+ @Override
+ public String toString() {
+ return _high + ":" + _low;
+ }
+
+ @Override
+ public Unit<Q> toSI() {
+ return _low.toSI();
+ }
+
+ @Override
+ public final UnitConverter getConverterTo(Unit<Q> unit) {
+ return _low.getConverterTo(unit);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/unit/DerivedUnit.java b/src/main/java/javax/measure/unit/DerivedUnit.java
new file mode 100644
index 0000000..cf4a6b7
--- /dev/null
+++ b/src/main/java/javax/measure/unit/DerivedUnit.java
@@ -0,0 +1,48 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit;
+
+import javax.measure.quantity.Quantity;
+
+/**
+ * <p> This class identifies the units created by combining or transforming
+ * other units.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public abstract class DerivedUnit<Q extends Quantity> extends Unit<Q> {
+
+ /**
+ * Default constructor.
+ */
+ protected DerivedUnit() {
+ }
+
+ private static final long serialVersionUID = 1L;
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/unit/Dimension.java b/src/main/java/javax/measure/unit/Dimension.java
new file mode 100644
index 0000000..1f5a075
--- /dev/null
+++ b/src/main/java/javax/measure/unit/Dimension.java
@@ -0,0 +1,291 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit;
+
+import java.io.Serializable;
+
+import javax.measure.converter.UnitConverter;
+import javax.measure.quantity.Dimensionless;
+
+/**
+ * <p> This class represents the dimension of an unit. Two units <code>u1</code>
+ * and <code>u2</code> are {@link Unit#isCompatible compatible} if and
+ * only if <code>(u1.getDimension().equals(u2.getDimension())))</code>
+ * </p>
+ *
+ * <p> Instances of this class are immutable.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ * @see <a href="http://en.wikipedia.org/wiki/Dimensional_analysis">
+ * Wikipedia: Dimensional Analysis</a>
+ */
+public final class Dimension implements Serializable {
+
+ /**
+ * Holds the current physical model.
+ */
+ private static Model CurrentModel = Model.STANDARD;
+
+ /**
+ * Holds dimensionless.
+ */
+ public static final Dimension NONE = new Dimension(Unit.ONE);
+
+ /**
+ * Holds length dimension (L).
+ */
+ public static final Dimension LENGTH = new Dimension('L');
+
+ /**
+ * Holds mass dimension (M).
+ */
+ public static final Dimension MASS = new Dimension('M');
+
+ /**
+ * Holds time dimension (T).
+ */
+ public static final Dimension TIME = new Dimension('T');
+
+ /**
+ * Holds electric current dimension (I).
+ */
+ public static final Dimension ELECTRIC_CURRENT = new Dimension('I');
+
+ /**
+ * Holds temperature dimension (Q).
+ */
+ public static final Dimension TEMPERATURE = new Dimension('Q');
+
+ /**
+ * Holds amount of substance dimension (N).
+ */
+ public static final Dimension AMOUNT_OF_SUBSTANCE = new Dimension('N');
+
+ /**
+ * Holds luminous intensity dimension (J).
+ */
+ public static final Dimension LUMINOUS_INTENSITY = new Dimension('J');
+
+ /**
+ * Holds the pseudo unit associated to this dimension.
+ */
+ private final Unit<?> _pseudoUnit;
+
+ /**
+ * Creates a new dimension associated to the specified symbol.
+ *
+ * @param symbol the associated symbol.
+ */
+ public Dimension(char symbol) {
+ _pseudoUnit = new BaseUnit<Dimensionless>("[" + symbol + "]");
+ }
+
+ /**
+ * Creates a dimension having the specified pseudo-unit
+ * (base unit or product of base unit).
+ *
+ * @param pseudoUnit the pseudo-unit identifying this dimension.
+ */
+ private Dimension(Unit<?> pseudoUnit) {
+ _pseudoUnit = pseudoUnit;
+ }
+
+ /**
+ * Returns the product of this dimension with the one specified.
+ *
+ * @param that the dimension multiplicand.
+ * @return <code>this * that</code>
+ */
+ public final Dimension times(Dimension that) {
+ return new Dimension(this._pseudoUnit.times(that._pseudoUnit));
+ }
+
+ /**
+ * Returns the quotient of this dimension with the one specified.
+ *
+ * @param that the dimension divisor.
+ * @return <code>this / that</code>
+ */
+ public final Dimension divide(Dimension that) {
+ return new Dimension(this._pseudoUnit.divide(that._pseudoUnit));
+ }
+
+ /**
+ * Returns this dimension raised to an exponent.
+ *
+ * @param n the exponent.
+ * @return the result of raising this dimension to the exponent.
+ */
+ public final Dimension pow(int n) {
+ return new Dimension(this._pseudoUnit.pow(n));
+ }
+
+ /**
+ * Returns the given root of this dimension.
+ *
+ * @param n the root's order.
+ * @return the result of taking the given root of this dimension.
+ * @throws ArithmeticException if <code>n == 0</code>.
+ */
+ public final Dimension root(int n) {
+ return new Dimension(this._pseudoUnit.root(n));
+ }
+
+ /**
+ * Returns the representation of this dimension.
+ *
+ * @return the representation of this dimension.
+ */
+ @Override
+ public String toString() {
+ return _pseudoUnit.toString();
+ }
+
+ /**
+ * Indicates if the specified dimension is equals to the one specified.
+ *
+ * @param that the object to compare to.
+ * @return <code>true</code> if this dimension is equals to that dimension;
+ * <code>false</code> otherwise.
+ */
+ @Override
+ public boolean equals(Object that) {
+ if (this == that)
+ return true;
+ return (that instanceof Dimension) && _pseudoUnit.equals(((Dimension) that)._pseudoUnit);
+ }
+
+ /**
+ * Returns the hash code for this dimension.
+ *
+ * @return this dimension hashcode value.
+ */
+ @Override
+ public int hashCode() {
+ return _pseudoUnit.hashCode();
+ }
+
+ /**
+ * Sets the model used to determinate the units dimensions.
+ *
+ * @param model the new model to be used when calculating unit dimensions.
+ */
+ public static void setModel(Model model) {
+ Dimension.CurrentModel = model;
+ }
+
+ /**
+ * Returns the model used to determinate the units dimensions
+ * (default {@link Model#STANDARD STANDARD}).
+ *
+ * @return the model used when calculating unit dimensions.
+ */
+ public static Model getModel() {
+ return Dimension.CurrentModel;
+ }
+
+ /**
+ * This interface represents the mapping between {@link BaseUnit base units}
+ * and {@link Dimension dimensions}. Custom models may allow
+ * conversions not possible using the {@link #STANDARD standard} model.
+ * For example:[code]
+ * public static void main(String[] args) {
+ * Dimension.Model relativistic = new Dimension.Model() {
+ * RationalConverter metreToSecond = new RationalConverter(BigInteger.ONE, BigInteger.valueOf(299792458)); // 1/c
+ *
+ * public Dimension getDimension(BaseUnit unit) {
+ * if (unit.equals(METRE)) return Dimension.TIME;
+ * return Dimension.Model.STANDARD.getDimension(unit);
+ * }
+ *
+ * public UnitConverter getTransform(BaseUnit unit) {
+ * if (unit.equals(METRE)) return metreToSecond;
+ * return Dimension.Model.STANDARD.getTransform(unit);
+ * }};
+ * Dimension.setModel(relativistic);
+ *
+ * // Converts 1.0 GeV (energy) to kg (mass).
+ * System.out.println(Unit.valueOf("GeV").getConverterTo(KILOGRAM).convert(1.0));
+ * }
+ *
+ * > 1.7826617302520883E-27[/code]
+ */
+ public interface Model {
+
+ /**
+ * Holds the standard model (default).
+ */
+ public Model STANDARD = new Model() {
+
+ public Dimension getDimension(BaseUnit<?> unit) {
+ if (unit.equals(SI.METRE))
+ return Dimension.LENGTH;
+ if (unit.equals(SI.KILOGRAM))
+ return Dimension.MASS;
+ if (unit.equals(SI.KELVIN))
+ return Dimension.TEMPERATURE;
+ if (unit.equals(SI.SECOND))
+ return Dimension.TIME;
+ if (unit.equals(SI.AMPERE))
+ return Dimension.ELECTRIC_CURRENT;
+ if (unit.equals(SI.MOLE))
+ return Dimension.AMOUNT_OF_SUBSTANCE;
+ if (unit.equals(SI.CANDELA))
+ return Dimension.LUMINOUS_INTENSITY;
+ return new Dimension(new BaseUnit<Dimensionless>("[" + unit.getSymbol() + "]"));
+ }
+
+ public UnitConverter getTransform(BaseUnit<?> unit) {
+ return UnitConverter.IDENTITY;
+ }
+ };
+
+ /**
+ * Returns the dimension of the specified base unit (a dimension
+ * particular to the base unit if the base unit is not recognized).
+ *
+ * @param unit the base unit for which the dimension is returned.
+ * @return the dimension of the specified unit.
+ */
+ Dimension getDimension(BaseUnit<?> unit);
+
+ /**
+ * Returns the normalization transform of the specified base unit
+ * ({@link UnitConverter#IDENTITY IDENTITY} if the base unit is
+ * not recognized).
+ *
+ * @param unit the base unit for which the transform is returned.
+ * @return the normalization transform.
+ */
+ UnitConverter getTransform(BaseUnit<?> unit);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/unit/NonSI.java b/src/main/java/javax/measure/unit/NonSI.java
new file mode 100644
index 0000000..c2fec0a
--- /dev/null
+++ b/src/main/java/javax/measure/unit/NonSI.java
@@ -0,0 +1,1070 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences Copyright
+ * (c) 2005-2009, JScience (http://jscience.org/) All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit;
+
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.measure.converter.LogConverter;
+import javax.measure.converter.RationalConverter;
+import javax.measure.quantity.*;
+
+import static javax.measure.unit.SI.*;
+
+/**
+ * <p> This class contains units that are not part of the International System
+ * of Units, that is, they are outside the SI, but are important and widely
+ * used.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public final class NonSI extends SystemOfUnits {
+
+ /**
+ * Holds collection of NonSI units.
+ */
+ private static HashSet<Unit<?>> UNITS = new HashSet<Unit<?>>();
+
+ /**
+ * Holds the standard gravity constant: 9.80665 m/s² exact.
+ */
+ private static final int STANDARD_GRAVITY_DIVIDEND = 980665;
+
+ private static final int STANDARD_GRAVITY_DIVISOR = 100000;
+
+ /**
+ * Holds the international foot: 0.3048 m exact.
+ */
+ private static final int INTERNATIONAL_FOOT_DIVIDEND = 3048;
+
+ private static final int INTERNATIONAL_FOOT_DIViSOR = 10000;
+
+ /**
+ * Holds the avoirdupois pound: 0.45359237 kg exact
+ */
+ private static final int AVOIRDUPOIS_POUND_DIVIDEND = 45359237;
+
+ private static final int AVOIRDUPOIS_POUND_DIVISOR = 100000000;
+
+ /**
+ * Holds the Avogadro constant.
+ */
+ private static final double AVOGADRO_CONSTANT = 6.02214199e23; // (1/mol).
+
+ /**
+ * Holds the electric charge of one electron.
+ */
+ private static final double ELEMENTARY_CHARGE = 1.602176462e-19; // (C).
+
+ /**
+ * Default constructor (prevents this class from being instantiated).
+ */
+ private NonSI() {
+ }
+
+ /**
+ * Returns the unique instance of this class.
+ *
+ * @return the NonSI instance.
+ */
+ public static NonSI getInstance() {
+ return INSTANCE;
+ }
+
+ private static final NonSI INSTANCE = new NonSI();
+
+ // /////////////////
+ // Dimensionless //
+ // /////////////////
+ /**
+ * A dimensionless unit equals to <code>pi</code> (standard name
+ * <code>π</code>).
+ */
+ public static final Unit<Dimensionless> PI = nonSI(Unit.ONE
+ .times(StrictMath.PI));
+
+ /**
+ * A dimensionless unit equals to <code>0.01</code> (standard name
+ * <code>%</code>).
+ */
+ public static final Unit<Dimensionless> PERCENT = nonSI(Unit.ONE
+ .divide(100));
+
+ /**
+ * A logarithmic unit used to describe a ratio (standard name
+ * <code>dB</code>).
+ */
+ public static final Unit<Dimensionless> DECIBEL = nonSI(Unit.ONE
+ .transform(new LogConverter(10).inverse().concatenate(
+ new RationalConverter(BigInteger.ONE, BigInteger.TEN))));
+
+ // ///////////////////////
+ // Amount of substance //
+ // ///////////////////////
+ /**
+ * A unit of amount of substance equals to one atom (standard name
+ * <code>atom</code>).
+ */
+ public static final Unit<AmountOfSubstance> ATOM = nonSI(MOLE
+ .divide(AVOGADRO_CONSTANT));
+
+ // //////////
+ // Length //
+ // //////////
+ /**
+ * A unit of length equal to <code>0.3048 m</code> (standard name
+ * <code>ft</code>).
+ */
+ public static final Unit<Length> FOOT = nonSI(METRE.times(
+ INTERNATIONAL_FOOT_DIVIDEND).divide(INTERNATIONAL_FOOT_DIViSOR));
+
+ /**
+ * A unit of length equal to <code>1200/3937 m</code> (standard name
+ * <code>foot_survey_us</code>). See also: <a
+ * href="http://www.sizes.com/units/foot.htm">foot</a>
+ */
+ public static final Unit<Length> FOOT_SURVEY_US = nonSI(METRE.times(1200)
+ .divide(3937));
+
+ /**
+ * A unit of length equal to <code>0.9144 m</code> (standard name
+ * <code>yd</code>).
+ */
+ public static final Unit<Length> YARD = nonSI(FOOT.times(3));
+
+ /**
+ * A unit of length equal to <code>0.0254 m</code> (standard name
+ * <code>in</code>).
+ */
+ public static final Unit<Length> INCH = nonSI(FOOT.divide(12));
+
+ /**
+ * A unit of length equal to <code>1609.344 m</code> (standard name
+ * <code>mi</code>).
+ */
+ public static final Unit<Length> MILE = nonSI(METRE.times(1609344).divide(
+ 1000));
+
+ /**
+ * A unit of length equal to <code>1852.0 m</code> (standard name
+ * <code>nmi</code>).
+ */
+ public static final Unit<Length> NAUTICAL_MILE = nonSI(METRE.times(1852));
+
+ /**
+ * A unit of length equal to <code>1E-10 m</code> (standard name
+ * <code>Å</code>).
+ */
+ public static final Unit<Length> ANGSTROM = nonSI(METRE
+ .divide(10000000000L));
+
+ /**
+ * A unit of length equal to the average distance from the center of the
+ * Earth to the center of the Sun (standard name <code>ua</code>).
+ */
+ public static final Unit<Length> ASTRONOMICAL_UNIT = nonSI(METRE
+ .times(149597870691.0));
+
+ /**
+ * A unit of length equal to the distance that light travels in one year
+ * through a vacuum (standard name <code>ly</code>).
+ */
+ public static final Unit<Length> LIGHT_YEAR = nonSI(METRE
+ .times(9.460528405e15));
+
+ /**
+ * A unit of length equal to the distance at which a star would appear to
+ * shift its position by one arcsecond over the course the time (about 3
+ * months) in which the Earth moves a distance of {@link #ASTRONOMICAL_UNIT}
+ * in the direction perpendicular to the direction to the star (standard
+ * name <code>pc</code>).
+ */
+ public static final Unit<Length> PARSEC = nonSI(METRE.times(30856770e9));
+
+ /**
+ * A unit of length equal to <code>0.013837 {@link #INCH}</code> exactly (standard name
+ * <code>pt</code>).
+ *
+ * @see #PIXEL
+ */
+ public static final Unit<Length> POINT = nonSI(INCH.times(13837).divide(
+ 1000000));
+
+ /**
+ * A unit of length equal to <code>1/72 {@link #INCH}</code> (standard name <code>pixel</code>). It is
+ * the American point rounded to an even 1/72 inch.
+ *
+ * @see #POINT
+ */
+ public static final Unit<Length> PIXEL = nonSI(INCH.divide(72));
+
+ /**
+ * Equivalent {@link #PIXEL}
+ */
+ public static final Unit<Length> COMPUTER_POINT = PIXEL;
+
+ // ////////////
+ // Duration //
+ // ////////////
+ /**
+ * A unit of duration equal to <code>60 s</code> (standard name
+ * <code>min</code>).
+ */
+ public static final Unit<Duration> MINUTE = nonSI(SI.SECOND.times(60));
+
+ /**
+ * A unit of duration equal to <code>60 {@link #MINUTE}</code> (standard name <code>h</code>).
+ */
+ public static final Unit<Duration> HOUR = nonSI(MINUTE.times(60));
+
+ /**
+ * A unit of duration equal to <code>24 {@link #HOUR}</code> (standard name <code>d</code>).
+ */
+ public static final Unit<Duration> DAY = nonSI(HOUR.times(24));
+
+ /**
+ * A unit of duration equal to the time required for a complete rotation of
+ * the earth in reference to any star or to the vernal equinox at the
+ * meridian, equal to 23 hours, 56 minutes, 4.09 seconds (standard name
+ * <code>day_sidereal</code>).
+ */
+ public static final Unit<Duration> DAY_SIDEREAL = nonSI(SECOND
+ .times(86164.09));
+
+ /**
+ * A unit of duration equal to 7 {@link #DAY} (standard name
+ * <code>week</code>).
+ */
+ public static final Unit<Duration> WEEK = nonSI(DAY.times(7));
+
+ /**
+ * A unit of duration equal to 365 {@link #DAY} (standard name
+ * <code>year</code>).
+ */
+ public static final Unit<Duration> YEAR_CALENDAR = nonSI(DAY.times(365));
+
+ /**
+ * A unit of duration equal to one complete revolution of the earth about
+ * the sun, relative to the fixed stars, or 365 days, 6 hours, 9 minutes,
+ * 9.54 seconds (standard name <code>year_sidereal</code>).
+ */
+ public static final Unit<Duration> YEAR_SIDEREAL = nonSI(SECOND
+ .times(31558149.54));
+
+ /**
+ * The Julian year, as used in astronomy and other sciences, is a time unit
+ * defined as exactly 365.25 days. This is the normal meaning of the unit
+ * "year" (symbol "a" from the Latin annus, annata) used in various
+ * scientific contexts.
+ */
+ public static final Unit<Duration> YEAR_JULIEN = nonSI(SECOND
+ .times(31557600));
+
+ // ////////
+ // Mass //
+ // ////////
+ /**
+ * A unit of mass equal to 1/12 the mass of the carbon-12 atom (standard
+ * name <code>u</code>).
+ */
+ public static final Unit<Mass> ATOMIC_MASS = nonSI(KILOGRAM
+ .times(1e-3 / AVOGADRO_CONSTANT));
+
+ /**
+ * A unit of mass equal to the mass of the electron (standard name
+ * <code>me</code>).
+ */
+ public static final Unit<Mass> ELECTRON_MASS = nonSI(KILOGRAM
+ .times(9.10938188e-31));
+
+ /**
+ * A unit of mass equal to <code>453.59237 grams</code> (avoirdupois pound,
+ * standard name <code>lb</code>).
+ */
+ public static final Unit<Mass> POUND = nonSI(KILOGRAM.times(
+ AVOIRDUPOIS_POUND_DIVIDEND).divide(AVOIRDUPOIS_POUND_DIVISOR));
+
+ /**
+ * A unit of mass equal to <code>1 / 16 {@link #POUND}</code> (standard name <code>oz</code>).
+ */
+ public static final Unit<Mass> OUNCE = nonSI(POUND.divide(16));
+
+ /**
+ * A unit of mass equal to <code>2000 {@link #POUND}</code> (short ton, standard name
+ * <code>ton_us</code>).
+ */
+ public static final Unit<Mass> TON_US = nonSI(POUND.times(2000));
+
+ /**
+ * A unit of mass equal to <code>2240 {@link #POUND}</code> (long ton, standard name
+ * <code>ton_uk</code>).
+ */
+ public static final Unit<Mass> TON_UK = nonSI(POUND.times(2240));
+
+ /**
+ * A unit of mass equal to <code>1000 kg</code> (metric ton, standard name
+ * <code>t</code>).
+ */
+ public static final Unit<Mass> METRIC_TON = nonSI(KILOGRAM.times(1000));
+
+ // ///////////////////
+ // Electric charge //
+ // ///////////////////
+ /**
+ * A unit of electric charge equal to the charge on one electron (standard
+ * name <code>e</code>).
+ */
+ public static final Unit<ElectricCharge> E = nonSI(COULOMB
+ .times(ELEMENTARY_CHARGE));
+
+ /**
+ * A unit of electric charge equal to equal to the product of Avogadro's
+ * number (see {@link SI#MOLE}) and the charge (1 e) on a single electron
+ * (standard name <code>Fd</code>).
+ */
+ public static final Unit<ElectricCharge> FARADAY = nonSI(COULOMB
+ .times(ELEMENTARY_CHARGE * AVOGADRO_CONSTANT)); // e/mol
+
+ /**
+ * A unit of electric charge which exerts a force of one dyne on an equal
+ * charge at a distance of one centimeter (standard name <code>Fr</code>).
+ */
+ public static final Unit<ElectricCharge> FRANKLIN = nonSI(COULOMB
+ .times(3.3356e-10));
+
+ // ///////////////
+ // Temperature //
+ // ///////////////
+ /**
+ * A unit of temperature equal to <code>5/9 °K</code> (standard name
+ * <code>°R</code>).
+ */
+ public static final Unit<Temperature> RANKINE = nonSI(KELVIN.times(5)
+ .divide(9));
+
+ /**
+ * A unit of temperature equal to degree Rankine minus
+ * <code>459.67 °R</code> (standard name <code>°F</code>).
+ *
+ * @see #RANKINE
+ */
+ public static final Unit<Temperature> FAHRENHEIT = nonSI(RANKINE
+ .plus(459.67));
+
+ // /////////
+ // Angle //
+ // /////////
+ /**
+ * A unit of angle equal to a full circle or <code>2<i>π</i>
+ * {@link SI#RADIAN}</code> (standard name <code>rev</code>).
+ */
+ public static final Unit<Angle> REVOLUTION = nonSI(RADIAN.times(2)
+ .times(PI).asType(Angle.class));
+
+ /**
+ * A unit of angle equal to <code>1/360 {@link #REVOLUTION}</code> (standard name <code>°</code>).
+ */
+ public static final Unit<Angle> DEGREE_ANGLE = nonSI(REVOLUTION.divide(360));
+
+ /**
+ * A unit of angle equal to <code>1/60 {@link #DEGREE_ANGLE}</code> (standard name <code>′</code>).
+ */
+ public static final Unit<Angle> MINUTE_ANGLE = nonSI(DEGREE_ANGLE
+ .divide(60));
+
+ /**
+ * A unit of angle equal to <code>1/60 {@link #MINUTE_ANGLE}</code> (standard name <code>"</code>).
+ */
+ public static final Unit<Angle> SECOND_ANGLE = nonSI(MINUTE_ANGLE
+ .divide(60));
+
+ /**
+ * A unit of angle equal to <code>0.01 {@link SI#RADIAN}</code> (standard name
+ * <code>centiradian</code>).
+ */
+ public static final Unit<Angle> CENTIRADIAN = nonSI(RADIAN.divide(100));
+
+ /**
+ * A unit of angle measure equal to <code>1/400 {@link #REVOLUTION}</code> (standard name <code>grade</code>
+ * ).
+ */
+ public static final Unit<Angle> GRADE = nonSI(REVOLUTION.divide(400));
+
+ // ////////////
+ // Velocity //
+ // ////////////
+ /**
+ * A unit of velocity expressing the number of {@link NonSI#FOOT feet} per
+ * {@link SI#SECOND second}.
+ */
+ public static final Unit<Velocity> FOOT_PER_SECOND = nonSI(
+ NonSI.FOOT.divide(SI.SECOND)).asType(Velocity.class);
+
+ /**
+ * A unit of velocity expressing the number of international {@link #MILE
+ * miles} per {@link #HOUR hour} (abbreviation <code>mph</code>).
+ */
+ public static final Unit<Velocity> MILES_PER_HOUR = nonSI(
+ NonSI.MILE.divide(NonSI.HOUR)).asType(Velocity.class);
+
+ /**
+ * A unit of velocity expressing the number of {@link SI#KILOMETRE} per
+ * {@link #HOUR hour}.
+ */
+ public static final Unit<Velocity> KILOMETRES_PER_HOUR = nonSI(
+ SI.KILOMETRE.divide(NonSI.HOUR)).asType(Velocity.class);
+
+ /**
+ * Equivalent to {@link #KILOMETRES_PER_HOUR}.
+ */
+ public static final Unit<Velocity> KILOMETERS_PER_HOUR = KILOMETRES_PER_HOUR;
+
+ /**
+ * A unit of velocity expressing the number of {@link #NAUTICAL_MILE
+ * nautical miles} per {@link #HOUR hour} (abbreviation <code>kn</code>).
+ */
+ public static final Unit<Velocity> KNOT = nonSI(
+ NonSI.NAUTICAL_MILE.divide(NonSI.HOUR)).asType(Velocity.class);
+
+ /**
+ * A unit of velocity relative to the speed of light (standard name
+ * <code>c</code>).
+ */
+ public static final Unit<Velocity> C = nonSI(METRES_PER_SECOND
+ .times(299792458));
+
+ // ////////////////
+ // Acceleration //
+ // ////////////////
+ /**
+ * A unit of acceleration equal to the gravity at the earth's surface
+ * (standard name <code>grav</code>).
+ */
+ public static final Unit<Acceleration> G = nonSI(METRES_PER_SQUARE_SECOND
+ .times(STANDARD_GRAVITY_DIVIDEND).divide(STANDARD_GRAVITY_DIVISOR));
+
+ // ////////
+ // Area //
+ // ////////
+ /**
+ * A unit of area equal to <code>100 m²</code> (standard name <code>a</code>
+ * ).
+ */
+ public static final Unit<Area> ARE = nonSI(SQUARE_METRE.times(100));
+
+ /**
+ * A unit of area equal to <code>100 {@link #ARE}</code> (standard name <code>ha</code>).
+ */
+ public static final Unit<Area> HECTARE = nonSI(ARE.times(100)); // Exact.
+
+ // ///////////////
+ // Data Amount //
+ // ///////////////
+ /**
+ * A unit of data amount equal to <code>8 {@link SI#BIT}</code> (BinarY TErm, standard name
+ * <code>byte</code>).
+ */
+ public static final Unit<DataAmount> BYTE = nonSI(BIT.times(8));
+
+ /**
+ * Equivalent {@link #BYTE}
+ */
+ public static final Unit<DataAmount> OCTET = BYTE;
+
+ // ////////////////////
+ // Electric current //
+ // ////////////////////
+ /**
+ * A unit of electric charge equal to the centimeter-gram-second
+ * electromagnetic unit of magnetomotive force, equal to <code>10/4
+ * πampere-turn</code> (standard name <code>Gi</code>).
+ */
+ public static final Unit<ElectricCurrent> GILBERT = nonSI(SI.AMPERE.times(
+ 10).divide(4).times(PI).asType(ElectricCurrent.class));
+
+ // //////////
+ // Energy //
+ // //////////
+ /**
+ * A unit of energy equal to <code>1E-7 J</code> (standard name
+ * <code>erg</code>).
+ */
+ public static final Unit<Energy> ERG = nonSI(JOULE.divide(10000000));
+
+ /**
+ * A unit of energy equal to one electron-volt (standard name
+ * <code>eV</code>, also recognized <code>keV, MeV, GeV</code>).
+ */
+ public static final Unit<Energy> ELECTRON_VOLT = nonSI(JOULE
+ .times(ELEMENTARY_CHARGE));
+
+ // ///////////////
+ // Illuminance //
+ // ///////////////
+ /**
+ * A unit of illuminance equal to <code>1E4 Lx</code> (standard name
+ * <code>La</code>).
+ */
+ public static final Unit<Illuminance> LAMBERT = nonSI(LUX.times(10000));
+
+ // /////////////////
+ // Magnetic Flux //
+ // /////////////////
+ /**
+ * A unit of magnetic flux equal <code>1E-8 Wb</code> (standard name
+ * <code>Mx</code>).
+ */
+ public static final Unit<MagneticFlux> MAXWELL = nonSI(WEBER
+ .divide(100000000));
+
+ // /////////////////////////
+ // Magnetic Flux Density //
+ // /////////////////////////
+ /**
+ * A unit of magnetic flux density equal <code>1000 A/m</code> (standard
+ * name <code>G</code>).
+ */
+ public static final Unit<MagneticFluxDensity> GAUSS = nonSI(TESLA
+ .divide(10000));
+
+ // /////////
+ // Force //
+ // /////////
+ /**
+ * A unit of force equal to <code>1E-5 N</code> (standard name
+ * <code>dyn</code>).
+ */
+ public static final Unit<Force> DYNE = nonSI(NEWTON.divide(100000));
+
+ /**
+ * A unit of force equal to <code>9.80665 N</code> (standard name
+ * <code>kgf</code>).
+ */
+ public static final Unit<Force> KILOGRAM_FORCE = nonSI(NEWTON.times(
+ STANDARD_GRAVITY_DIVIDEND).divide(STANDARD_GRAVITY_DIVISOR));
+
+ /**
+ * A unit of force equal to <code>{@link #POUND}·{@link #G}</code> (standard name <code>lbf</code>).
+ */
+ public static final Unit<Force> POUND_FORCE = nonSI(NEWTON.times(
+ 1L * AVOIRDUPOIS_POUND_DIVIDEND * STANDARD_GRAVITY_DIVIDEND)
+ .divide(1L * AVOIRDUPOIS_POUND_DIVISOR * STANDARD_GRAVITY_DIVISOR));
+
+ // /////////
+ // Power //
+ // /////////
+ /**
+ * A unit of power equal to the power required to raise a mass of 75
+ * kilograms at a velocity of 1 meter per second (metric, standard name
+ * <code>hp</code>).
+ */
+ public static final Unit<Power> HORSEPOWER = nonSI(WATT.times(735.499));
+
+ // ////////////
+ // Pressure //
+ // ////////////
+ /**
+ * A unit of pressure equal to the average pressure of the Earth's
+ * atmosphere at sea level (standard name <code>atm</code>).
+ */
+ public static final Unit<Pressure> ATMOSPHERE = nonSI(PASCAL.times(101325));
+
+ /**
+ * A unit of pressure equal to <code>100 kPa</code> (standard name
+ * <code>bar</code>).
+ */
+ public static final Unit<Pressure> BAR = nonSI(PASCAL.times(100000));
+
+ /**
+ * A unit of pressure equal to the pressure exerted at the Earth's surface
+ * by a column of mercury 1 millimeter high (standard name <code>mmHg</code>
+ * ).
+ */
+ public static final Unit<Pressure> MILLIMETER_OF_MERCURY = nonSI(PASCAL
+ .times(133.322));
+
+ /**
+ * A unit of pressure equal to the pressure exerted at the Earth's surface
+ * by a column of mercury 1 inch high (standard name <code>inHg</code>).
+ */
+ public static final Unit<Pressure> INCH_OF_MERCURY = nonSI(PASCAL
+ .times(3386.388));
+
+ // ///////////////////////////
+ // Radiation dose absorbed //
+ // ///////////////////////////
+ /**
+ * A unit of radiation dose absorbed equal to a dose of 0.01 joule of energy
+ * per kilogram of mass (J/kg) (standard name <code>rd</code>).
+ */
+ public static final Unit<RadiationDoseAbsorbed> RAD = nonSI(GRAY
+ .divide(100));
+
+ /**
+ * A unit of radiation dose effective equal to <code>0.01 Sv</code>
+ * (standard name <code>rem</code>).
+ */
+ public static final Unit<RadiationDoseEffective> REM = nonSI(SIEVERT
+ .divide(100));
+
+ // ////////////////////////
+ // Radioactive activity //
+ // ////////////////////////
+ /**
+ * A unit of radioctive activity equal to the activity of a gram of radium
+ * (standard name <code>Ci</code>).
+ */
+ public static final Unit<RadioactiveActivity> CURIE = nonSI(BECQUEREL
+ .times(37000000000L));
+
+ /**
+ * A unit of radioctive activity equal to 1 million radioactive
+ * disintegrations per second (standard name <code>Rd</code>).
+ */
+ public static final Unit<RadioactiveActivity> RUTHERFORD = nonSI(SI.BECQUEREL
+ .times(1000000));
+
+ // ///////////////
+ // Solid angle //
+ // ///////////////
+ /**
+ * A unit of solid angle equal to <code>4 <i>π</i> steradians</code>
+ * (standard name <code>sphere</code>).
+ */
+ public static final Unit<SolidAngle> SPHERE = nonSI(STERADIAN.times(4)
+ .times(PI).asType(SolidAngle.class));
+
+ // //////////
+ // Volume //
+ // //////////
+ /**
+ * A unit of volume equal to one cubic decimeter (default label
+ * <code>L</code>, also recognized <code>µL, mL, cL, dL</code>).
+ */
+ public static final Unit<Volume> LITRE = nonSI(CUBIC_METRE.divide(1000));
+
+ /**
+ * Equivalent to {@link #LITRE} (American spelling).
+ */
+ public static final Unit<Volume> LITER = LITRE;
+
+ /**
+ * A unit of volume equal to one cubic inch (<code>in³</code>).
+ */
+ public static final Unit<Volume> CUBIC_INCH = nonSI(INCH.pow(3).asType(
+ Volume.class));
+
+ /**
+ * A unit of volume equal to one US gallon, Liquid Unit. The U.S. liquid
+ * gallon is based on the Queen Anne or Wine gallon occupying 231 cubic
+ * inches (standard name <code>gal</code>).
+ */
+ public static final Unit<Volume> GALLON_LIQUID_US = nonSI(CUBIC_INCH
+ .times(231));
+
+ /**
+ * A unit of volume equal to <code>1 / 128 {@link #GALLON_LIQUID_US}</code> (standard name
+ * <code>oz_fl</code>).
+ */
+ public static final Unit<Volume> OUNCE_LIQUID_US = nonSI(GALLON_LIQUID_US
+ .divide(128));
+
+ /**
+ * A unit of volume equal to one US dry gallon. (standard name
+ * <code>gallon_dry_us</code>).
+ */
+ public static final Unit<Volume> GALLON_DRY_US = nonSI(CUBIC_INCH.times(
+ 2688025).divide(10000));
+
+ /**
+ * A unit of volume equal to <code>4.546 09 {@link #LITRE}</code> (standard name <code>gal_uk</code>).
+ */
+ public static final Unit<Volume> GALLON_UK = nonSI(LITRE.times(454609)
+ .divide(100000));
+
+ /**
+ * A unit of volume equal to <code>1 / 160 {@link #GALLON_UK}</code> (standard name
+ * <code>oz_fl_uk</code>).
+ */
+ public static final Unit<Volume> OUNCE_LIQUID_UK = nonSI(GALLON_UK
+ .divide(160));
+
+ // /////////////
+ // Viscosity //
+ // /////////////
+ /**
+ * A unit of dynamic viscosity equal to <code>1 g/(cm·s)</code> (cgs unit).
+ */
+ @SuppressWarnings("unchecked")
+ public static final Unit<DynamicViscosity> POISE = nonSI((Unit<DynamicViscosity>) GRAM
+ .divide(CENTI(METRE).times(SECOND)));
+
+ /**
+ * A unit of kinematic viscosity equal to <code>1 cm²/s</code> (cgs unit).
+ */
+ @SuppressWarnings("unchecked")
+ public static final Unit<KinematicViscosity> STOKE = nonSI((Unit<KinematicViscosity>) CENTI(
+ METRE).pow(2).divide(SECOND));
+
+ // //////////
+ // Others //
+ // //////////
+ /**
+ * A unit used to measure the ionizing ability of radiation (standard name
+ * <code>Roentgen</code>).
+ */
+ public static final Unit<?> ROENTGEN = nonSI(COULOMB.divide(KILOGRAM)
+ .times(2.58e-4));
+
+ // ///////////////////
+ // Collection View //
+ // ///////////////////
+ /**
+ * Returns a read only view over the units defined in this class.
+ *
+ * @return the collection of NonSI units.
+ */
+ public Set<Unit<?>> getUnits() {
+ return Collections.unmodifiableSet(UNITS);
+ }
+
+ /**
+ * Adds a new unit to the collection.
+ *
+ * @param unit the unit being added.
+ * @return <code>unit</code>.
+ */
+ private static <U extends Unit<?>> U nonSI(U unit) {
+ UNITS.add(unit);
+ return unit;
+ }
+
+ // ///////////////////
+ // NON-SI PREFIXES //
+ // ///////////////////
+
+ /**
+ * Inner class holding binary prefixes.
+ */
+ public static class BinaryPrefix {
+
+ private BinaryPrefix() {
+ // Utility class no visible constructor.
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>2<sup>10</sup></code> (binary prefix).
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1024)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> KIBI(Unit<Q> unit) {
+ return unit.times(1024);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>2<sup>20</sup></code> (binary prefix).
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1048576)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> MEBI(Unit<Q> unit) {
+ return unit.times(1048576);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>2<sup>30</sup></code> (binary prefix).
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1073741824)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> GIBI(Unit<Q> unit) {
+ return unit.times(1073741824);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>2<sup>40</sup></code> (binary prefix).
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1099511627776L)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> TEBI(Unit<Q> unit) {
+ return unit.times(1099511627776L);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>2<sup>50</sup></code> (binary prefix).
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1125899906842624L)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> PEBI(Unit<Q> unit) {
+ return unit.times(1125899906842624L);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>2<sup>60</sup></code> (binary prefix).
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1152921504606846976L)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> EXBI(Unit<Q> unit) {
+ return unit.times(1152921504606846976L);
+ }
+
+ }
+
+ /**
+ * Inner class holding prefixes used today in India, Pakistan, Bangladesh,
+ * Nepal and Myanmar (Burma); based on grouping by two decimal places,
+ * rather than the three decimal places common in most parts of the world.
+ * [code]
+ * import static javax.measure.unit.NonSI.IndianPrefix.*; // Static import.
+ * ...
+ * Unit<Pressure> LAKH_PASCAL = LAKH(PASCAL);
+ * Unit<Length> CRORE_METER = CRORE(METER);
+ * [/code]
+ *
+ * @author <a href="mailto:jsr275 at catmedia.us">Werner Keil</a>
+ * @version 1.0
+ * @see <a
+ * href="http://en.wikipedia.org/wiki/Indian_numbering_system">Wikipedia:
+ * Indian numbering system</a>
+ */
+ public static class IndianPrefix {
+
+ private IndianPrefix() {
+ // Utility class no visible constructor.
+ }
+
+ /**
+ * <p>
+ * एक (Ek)
+ * </p>
+ * Returns the specified unit multiplied by the factor <code>1</code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.multiply(1)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> EK(Unit<Q> unit) {
+ return unit;
+ }
+
+ /**
+ * <p>
+ * दस (Das)
+ * </p>
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>1</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.multiply(10)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> DAS(Unit<Q> unit) {
+ return unit.transform(E1);
+ }
+
+ /**
+ * <p>
+ * सौ (Sau)
+ * </p>
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>2</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.multiply(100)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> SAU(Unit<Q> unit) {
+ return unit.transform(E2);
+ }
+
+ /**
+ * <p>
+ * सहस्र (Sahasr)
+ * </p>
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>3</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.multiply(1e3)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> SAHASR(Unit<Q> unit) {
+ return unit.transform(E3);
+ }
+
+ /**
+ * <p>
+ * हजार (Hazaar)
+ * </p>
+ * Equivalent to {@link #SAHASR}.
+ */
+ public static <Q extends Quantity> Unit<Q> HAZAAR(Unit<Q> unit) {
+ return SAHASR(unit);
+ }
+
+ /**
+ * <p>
+ * लाख (Lakh)
+ * </p>
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>5</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.multiply(1e5)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> LAKH(Unit<Q> unit) {
+ return unit.transform(E5);
+ }
+
+ static final RationalConverter E5 = new RationalConverter(
+ BigInteger.TEN.pow(5), BigInteger.ONE);
+
+ /**
+ * <p>
+ * करोड़ (Crore)
+ * </p>
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>7</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.multiply(1e7)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> CRORE(Unit<Q> unit) {
+ return unit.transform(E7);
+ }
+
+ static final RationalConverter E7 = new RationalConverter(
+ BigInteger.TEN.pow(7), BigInteger.ONE);
+
+ /**
+ * <p>
+ * अरब (Arawb)
+ * </p>
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>9</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.multiply(1e9)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> ARAWB(Unit<Q> unit) {
+ return unit.transform(E9);
+ }
+
+ /**
+ * <p>
+ * खरब (Kharawb)
+ * </p>
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>11</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.multiply(1e11)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> KHARAWB(Unit<Q> unit) {
+ return unit.transform(E11);
+ }
+
+ static final RationalConverter E11 = new RationalConverter(
+ BigInteger.TEN.pow(11), BigInteger.ONE);
+
+ /**
+ * <p>
+ * नील (Neel)
+ * </p>
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>13</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.multiply(1e13)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> NEEL(Unit<Q> unit) {
+ return unit.transform(E13);
+ }
+
+ static final RationalConverter E13 = new RationalConverter(
+ BigInteger.TEN.pow(13), BigInteger.ONE);
+
+ /**
+ * <p>
+ * पद्म (Padma)
+ * </p>
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>15</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.multiply(1e15)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> PADMA(Unit<Q> unit) {
+ return unit.transform(E15);
+ }
+
+ /**
+ * <p>
+ * शंख (Shankh)
+ * </p>
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>17</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.multiply(1e17)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> SHANKH(Unit<Q> unit) {
+ return unit.transform(E17);
+ }
+
+ static final RationalConverter E17 = new RationalConverter(
+ BigInteger.TEN.pow(17), BigInteger.ONE);
+
+ /**
+ * <p>
+ * महाशंख (Mahashankh)
+ * </p>
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>19</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.multiply(1e19)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> MAHASHANKH(Unit<Q> unit) {
+ return unit.transform(E19);
+ }
+
+ static final RationalConverter E19 = new RationalConverter(
+ BigInteger.TEN.pow(19), BigInteger.ONE);
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/unit/ProductUnit.java b/src/main/java/javax/measure/unit/ProductUnit.java
new file mode 100644
index 0000000..8d87108
--- /dev/null
+++ b/src/main/java/javax/measure/unit/ProductUnit.java
@@ -0,0 +1,478 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit;
+
+import java.io.Serializable;
+
+import javax.measure.converter.ConversionException;
+import javax.measure.converter.LinearConverter;
+import javax.measure.converter.UnitConverter;
+import javax.measure.quantity.Quantity;
+
+/**
+ * <p> This class represents units formed by the product of rational powers of
+ * existing units.</p>
+ *
+ * <p> This class maintains the canonical form of this product (simplest form
+ * after factorization). For example: <code>METRE.pow(2).divide(METRE)</code>
+ * returns <code>METRE</code>.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ * @see Unit#times(Unit)
+ * @see Unit#divide(Unit)
+ * @see Unit#pow(int)
+ * @see Unit#root(int)
+ */
+public final class ProductUnit<Q extends Quantity> extends DerivedUnit<Q> {
+
+ /**
+ * Holds the units composing this product unit.
+ */
+ private final Element[] _elements;
+
+ /**
+ * Holds the hashcode (optimization).
+ */
+ private int _hashCode;
+
+ /**
+ * Default constructor (used solely to create <code>ONE</code> instance).
+ */
+ ProductUnit() {
+ _elements = new Element[0];
+ }
+
+ /**
+ * Copy constructor (allows for parameterization of product units).
+ *
+ * @param productUnit the product unit source.
+ * @throws ClassCastException if the specified unit is not a product unit.
+ */
+ public ProductUnit(Unit<?> productUnit) {
+ _elements = ((ProductUnit<?>) productUnit)._elements;
+ }
+
+ /**
+ * Product unit constructor.
+ *
+ * @param elements the product elements.
+ */
+ private ProductUnit(Element[] elements) {
+ _elements = elements;
+ }
+
+ /**
+ * Returns the unit defined from the product of the specified elements.
+ *
+ * @param leftElems left multiplicand elements.
+ * @param rightElems right multiplicand elements.
+ * @return the corresponding unit.
+ */
+ @SuppressWarnings("unchecked")
+ private static Unit<? extends Quantity> getInstance(Element[] leftElems,
+ Element[] rightElems) {
+
+ // Merges left elements with right elements.
+ Element[] result = new Element[leftElems.length + rightElems.length];
+ int resultIndex = 0;
+ for (int i = 0; i < leftElems.length; i++) {
+ Unit unit = leftElems[i]._unit;
+ int p1 = leftElems[i]._pow;
+ int r1 = leftElems[i]._root;
+ int p2 = 0;
+ int r2 = 1;
+ for (int j = 0; j < rightElems.length; j++) {
+ if (unit.equals(rightElems[j]._unit)) {
+ p2 = rightElems[j]._pow;
+ r2 = rightElems[j]._root;
+ break; // No duplicate.
+ }
+ }
+ int pow = (p1 * r2) + (p2 * r1);
+ int root = r1 * r2;
+ if (pow != 0) {
+ int gcd = gcd(Math.abs(pow), root);
+ result[resultIndex++] = new Element(unit, pow / gcd, root / gcd);
+ }
+ }
+
+ // Appends remaining right elements not merged.
+ for (int i = 0; i < rightElems.length; i++) {
+ Unit unit = rightElems[i]._unit;
+ boolean hasBeenMerged = false;
+ for (int j = 0; j < leftElems.length; j++) {
+ if (unit.equals(leftElems[j]._unit)) {
+ hasBeenMerged = true;
+ break;
+ }
+ }
+ if (!hasBeenMerged)
+ result[resultIndex++] = rightElems[i];
+ }
+
+ // Returns or creates instance.
+ if (resultIndex == 0)
+ return ONE;
+ else if ((resultIndex == 1) && (result[0]._pow == result[0]._root))
+ return result[0]._unit;
+ else {
+ Element[] elems = new Element[resultIndex];
+ for (int i = 0; i < resultIndex; i++) {
+ elems[i] = result[i];
+ }
+ return new ProductUnit<Quantity>(elems);
+ }
+ }
+
+ /**
+ * Returns the product of the specified units.
+ *
+ * @param left the left unit operand.
+ * @param right the right unit operand.
+ * @return <code>left * right</code>
+ */
+ static Unit<? extends Quantity> getProductInstance(Unit<?> left,
+ Unit<?> right) {
+ Element[] leftElems;
+ if (left instanceof ProductUnit)
+ leftElems = ((ProductUnit<?>) left)._elements;
+ else
+ leftElems = new Element[] { new Element(left, 1, 1) };
+ Element[] rightElems;
+ if (right instanceof ProductUnit)
+ rightElems = ((ProductUnit<?>) right)._elements;
+ else
+ rightElems = new Element[] { new Element(right, 1, 1) };
+ return getInstance(leftElems, rightElems);
+ }
+
+ /**
+ * Returns the quotient of the specified units.
+ *
+ * @param left the dividend unit operand.
+ * @param right the divisor unit operand.
+ * @return <code>dividend / divisor</code>
+ */
+ static Unit<? extends Quantity> getQuotientInstance(Unit<?> left,
+ Unit<?> right) {
+ Element[] leftElems;
+ if (left instanceof ProductUnit)
+ leftElems = ((ProductUnit<?>) left)._elements;
+ else
+ leftElems = new Element[] { new Element(left, 1, 1) };
+ Element[] rightElems;
+ if (right instanceof ProductUnit) {
+ Element[] elems = ((ProductUnit<?>) right)._elements;
+ rightElems = new Element[elems.length];
+ for (int i = 0; i < elems.length; i++) {
+ rightElems[i] = new Element(elems[i]._unit, -elems[i]._pow,
+ elems[i]._root);
+ }
+ } else
+ rightElems = new Element[] { new Element(right, -1, 1) };
+ return getInstance(leftElems, rightElems);
+ }
+
+ /**
+ * Returns the product unit corresponding to the specified root of the
+ * specified unit.
+ *
+ * @param unit the unit.
+ * @param n the root's order (n > 0).
+ * @return <code>unit^(1/nn)</code>
+ * @throws ArithmeticException if <code>n == 0</code>.
+ */
+ static Unit<? extends Quantity> getRootInstance(Unit<?> unit, int n) {
+ Element[] unitElems;
+ if (unit instanceof ProductUnit) {
+ Element[] elems = ((ProductUnit<?>) unit)._elements;
+ unitElems = new Element[elems.length];
+ for (int i = 0; i < elems.length; i++) {
+ int gcd = gcd(Math.abs(elems[i]._pow), elems[i]._root * n);
+ unitElems[i] = new Element(elems[i]._unit, elems[i]._pow / gcd,
+ elems[i]._root * n / gcd);
+ }
+ } else
+ unitElems = new Element[] { new Element(unit, 1, n) };
+ return getInstance(unitElems, new Element[0]);
+ }
+
+ /**
+ * Returns the product unit corresponding to this unit raised to the
+ * specified exponent.
+ *
+ * @param unit the unit.
+ * @param nn the exponent (nn > 0).
+ * @return <code>unit^n</code>
+ */
+ static Unit<? extends Quantity> getPowInstance(Unit<?> unit, int n) {
+ Element[] unitElems;
+ if (unit instanceof ProductUnit) {
+ Element[] elems = ((ProductUnit<?>) unit)._elements;
+ unitElems = new Element[elems.length];
+ for (int i = 0; i < elems.length; i++) {
+ int gcd = gcd(Math.abs(elems[i]._pow * n), elems[i]._root);
+ unitElems[i] = new Element(elems[i]._unit, elems[i]._pow * n
+ / gcd, elems[i]._root / gcd);
+ }
+ } else
+ unitElems = new Element[] { new Element(unit, n, 1) };
+ return getInstance(unitElems, new Element[0]);
+ }
+
+ /**
+ * Returns the number of units in this product.
+ *
+ * @return the number of units being multiplied.
+ */
+ public int getUnitCount() {
+ return _elements.length;
+ }
+
+ /**
+ * Returns the unit at the specified position.
+ *
+ * @param index the index of the unit to return.
+ * @return the unit at the specified position.
+ * @throws IndexOutOfBoundsException if index is out of range
+ * <code>(index < 0 || index >= size())</code>.
+ */
+ public Unit<? extends Quantity> getUnit(int index) {
+ return _elements[index].getUnit();
+ }
+
+ /**
+ * Returns the power exponent of the unit at the specified position.
+ *
+ * @param index the index of the unit to return.
+ * @return the unit power exponent at the specified position.
+ * @throws IndexOutOfBoundsException if index is out of range
+ * <code>(index < 0 || index >= size())</code>.
+ */
+ public int getUnitPow(int index) {
+ return _elements[index].getPow();
+ }
+
+ /**
+ * Returns the root exponent of the unit at the specified position.
+ *
+ * @param index the index of the unit to return.
+ * @return the unit root exponent at the specified position.
+ * @throws IndexOutOfBoundsException if index is out of range
+ * <code>(index < 0 || index >= size())</code>.
+ */
+ public int getUnitRoot(int index) {
+ return _elements[index].getRoot();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (this == that)
+ return true;
+ if (!(that instanceof ProductUnit))
+ return false;
+ // Two products are equals if they have the same elements
+ // regardless of the elements' order.
+ Element[] elems = ((ProductUnit<?>) that)._elements;
+ if (_elements.length != elems.length)
+ return false;
+ for (int i = 0; i < _elements.length; i++) {
+ boolean unitFound = false;
+ Element e = _elements[i];
+ for (int j = 0; j < elems.length; j++) {
+ if (e._unit.equals(elems[j]._unit))
+ if ((e._pow != elems[j]._pow)
+ || (e._root != elems[j]._root))
+ return false;
+ else {
+ unitFound = true;
+ break;
+ }
+ }
+ if (!unitFound)
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ if (_hashCode != 0)
+ return _hashCode;
+ int code = 0;
+ for (int i = 0; i < _elements.length; i++) {
+ code += _elements[i]._unit.hashCode()
+ * (_elements[i]._pow * 3 - _elements[i]._root * 2);
+ }
+ _hashCode = code;
+ return code;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Unit<Q> toSI() {
+ if (hasOnlyStandardUnit())
+ return this;
+ Unit<?> systemUnit = ONE;
+ for (int i = 0; i < _elements.length; i++) {
+ Unit<?> unit = _elements[i]._unit.toSI();
+ unit = unit.pow(_elements[i]._pow);
+ unit = unit.root(_elements[i]._root);
+ systemUnit = systemUnit.times(unit);
+ }
+ return (Unit<Q>) systemUnit;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public final UnitConverter getConverterTo(Unit<Q> unit) {
+ if (this.equals(unit))
+ return UnitConverter.IDENTITY;
+ if (!unit.equals(this.toSI()))
+ return super.getConverterTo(unit);
+ UnitConverter converter = UnitConverter.IDENTITY;
+ for (int i = 0; i < _elements.length; i++) {
+ Element e = _elements[i];
+ UnitConverter cvtr = e._unit.getConverterTo((Unit)e._unit.toSI());
+ if (!(cvtr instanceof LinearConverter))
+ throw new ConversionException(e._unit
+ + " is non-linear, cannot convert");
+ if (e._root != 1)
+ throw new ConversionException(e._unit
+ + " holds a base unit with fractional exponent");
+ int pow = e._pow;
+ if (pow < 0) { // Negative power.
+ pow = -pow;
+ cvtr = cvtr.inverse();
+ }
+ for (int j = 0; j < pow; j++) {
+ converter = converter.concatenate(cvtr);
+ }
+ }
+ return converter;
+ }
+
+ /**
+ * Indicates if this product unit is a standard unit.
+ *
+ * @return <code>true</code> if all elements are standard units;
+ * <code>false</code> otherwise.
+ */
+ private boolean hasOnlyStandardUnit() {
+ for (int i = 0; i < _elements.length; i++) {
+ Unit<?> u = _elements[i]._unit;
+ if (!u.isSI())
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns the greatest common divisor (Euclid's algorithm).
+ *
+ * @param m the first number.
+ * @param nn the second number.
+ * @return the greatest common divisor.
+ */
+ private static int gcd(int m, int n) {
+ if (n == 0)
+ return m;
+ else
+ return gcd(n, m % n);
+ }
+
+ /**
+ * Inner product element represents a rational power of a single unit.
+ */
+ private final static class Element implements Serializable {
+
+ /**
+ * Holds the single unit.
+ */
+ private final Unit<?> _unit;
+
+ /**
+ * Holds the power exponent.
+ */
+ private final int _pow;
+
+ /**
+ * Holds the root exponent.
+ */
+ private final int _root;
+
+ /**
+ * Structural constructor.
+ *
+ * @param unit the unit.
+ * @param pow the power exponent.
+ * @param root the root exponent.
+ */
+ private Element(Unit<?> unit, int pow, int root) {
+ _unit = unit;
+ _pow = pow;
+ _root = root;
+ }
+
+ /**
+ * Returns this element's unit.
+ *
+ * @return the single unit.
+ */
+ public Unit<?> getUnit() {
+ return _unit;
+ }
+
+ /**
+ * Returns the power exponent. The power exponent can be negative but is
+ * always different from zero.
+ *
+ * @return the power exponent of the single unit.
+ */
+ public int getPow() {
+ return _pow;
+ }
+
+ /**
+ * Returns the root exponent. The root exponent is always greater than
+ * zero.
+ *
+ * @return the root exponent of the single unit.
+ */
+ public int getRoot() {
+ return _root;
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/unit/SI.java b/src/main/java/javax/measure/unit/SI.java
new file mode 100644
index 0000000..6fffc53
--- /dev/null
+++ b/src/main/java/javax/measure/unit/SI.java
@@ -0,0 +1,744 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit;
+
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.measure.converter.RationalConverter;
+import javax.measure.quantity.*;
+
+/**
+ * <p> This class contains SI (Système International d'Unités) base units,
+ * and derived units.</p>
+ *
+ * <p> It also defines the 20 SI prefixes used to form decimal multiples and
+ * submultiples of SI units. For example:[code]
+ * import static org.jscience.physics.units.SI.*; // Static import.
+ * ...
+ * Unit<Pressure> HECTOPASCAL = HECTO(PASCAL);
+ * Unit<Length> KILOMETRE = KILO(METRE);
+ * [/code]</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ * @see <a href="http://en.wikipedia.org/wiki/International_System_of_Units">Wikipedia: International System of Units</a>
+ */
+public final class SI extends SystemOfUnits {
+
+ /**
+ * Holds collection of SI units.
+ */
+ private static HashSet<Unit<?>> UNITS = new HashSet<Unit<?>>();
+
+ /**
+ * Default constructor (prevents this class from being instantiated).
+ */
+ private SI() {
+ }
+
+ /**
+ * Returns the unique instance of this class.
+ *
+ * @return the SI instance.
+ */
+ public static SI getInstance() {
+ return INSTANCE;
+ }
+ private static final SI INSTANCE = new SI();
+ ////////////////
+ // BASE UNITS //
+ ////////////////
+
+ /**
+ * The base unit for electric current quantities (<code>A</code>).
+ * The Ampere is that constant current which, if maintained in two straight
+ * parallel conductors of infinite length, of negligible circular
+ * cross-section, and placed 1 meter apart in vacuum, would produce between
+ * these conductors a force equal to 2 × 10-7 newton per meter of length.
+ * It is named after the French physicist Andre Ampere (1775-1836).
+ */
+ public static final BaseUnit<ElectricCurrent> AMPERE = si(new BaseUnit<ElectricCurrent>(
+ "A"));
+
+ /**
+ * The base unit for luminous intensity quantities (<code>cd</code>).
+ * The candela is the luminous intensity, in a given direction,
+ * of a source that emits monochromatic radiation of frequency
+ * 540 × 1012 hertz and that has a radiant intensity in that
+ * direction of 1/683 watt per steradian
+ * @see <a href="http://en.wikipedia.org/wiki/Candela">
+ * Wikipedia: Candela</a>
+ */
+ public static final BaseUnit<LuminousIntensity> CANDELA = si(new BaseUnit<LuminousIntensity>(
+ "cd"));
+
+ /**
+ * The base unit for thermodynamic temperature quantities (<code>K</code>).
+ * The kelvin is the 1/273.16th of the thermodynamic temperature of the
+ * triple point of water. It is named after the Scottish mathematician and
+ * physicist William Thomson 1st Lord Kelvin (1824-1907)
+ */
+ public static final BaseUnit<Temperature> KELVIN = si(new BaseUnit<Temperature>(
+ "K"));
+
+ /**
+ * The base unit for mass quantities (<code>kg</code>).
+ * It is the only SI unit with a prefix as part of its name and symbol.
+ * The kilogram is equal to the mass of an international prototype in the
+ * form of a platinum-iridium cylinder kept at Sevres in France.
+ * @see #GRAM
+ */
+ public static final BaseUnit<Mass> KILOGRAM = si(new BaseUnit<Mass>("kg"));
+
+ /**
+ * The base unit for length quantities (<code>m</code>).
+ * One metre was redefined in 1983 as the distance traveled by light in
+ * a vacuum in 1/299,792,458 of a second.
+ */
+ public static final BaseUnit<Length> METRE = si(new BaseUnit<Length>("m"));
+
+ /**
+ * Equivalent to {@link #METRE} (American spelling).
+ */
+ public static final Unit<Length> METER = METRE;
+
+ /**
+ * The base unit for amount of substance quantities (<code>mol</code>).
+ * The mole is the amount of substance of a system which contains as many
+ * elementary entities as there are atoms in 0.012 kilogram of carbon 12.
+ */
+ public static final BaseUnit<AmountOfSubstance> MOLE = si(new BaseUnit<AmountOfSubstance>(
+ "mol"));
+
+ /**
+ * The base unit for duration quantities (<code>s</code>).
+ * It is defined as the duration of 9,192,631,770 cycles of radiation
+ * corresponding to the transition between two hyperfine levels of
+ * the ground state of cesium (1967 Standard).
+ */
+ public static final BaseUnit<Duration> SECOND = si(new BaseUnit<Duration>(
+ "s"));
+ ////////////////////////////////
+ // SI DERIVED ALTERNATE UNITS //
+ ////////////////////////////////
+
+ /**
+ * The derived unit for mass quantities (<code>g</code>).
+ * The base unit for mass quantity is {@link #KILOGRAM}.
+ */
+ public static final Unit<Mass> GRAM = KILOGRAM.divide(1000);
+
+ /**
+ * The unit for plane angle quantities (<code>rad</code>).
+ * One radian is the angle between two radii of a circle such that the
+ * length of the arc between them is equal to the radius.
+ */
+ public static final AlternateUnit<Angle> RADIAN = si(new AlternateUnit<Angle>(
+ "rad", Unit.ONE));
+
+ /**
+ * The unit for solid angle quantities (<code>sr</code>).
+ * One steradian is the solid angle subtended at the center of a sphere by
+ * an area on the surface of the sphere that is equal to the radius squared.
+ * The total solid angle of a sphere is 4*Pi steradians.
+ */
+ public static final AlternateUnit<SolidAngle> STERADIAN = si(new AlternateUnit<SolidAngle>(
+ "sr", Unit.ONE));
+
+ /**
+ * The unit for binary information (<code>bit</code>).
+ */
+ public static final AlternateUnit<DataAmount> BIT = si(new AlternateUnit<DataAmount>(
+ "bit", Unit.ONE));
+
+ /**
+ * The derived unit for frequency (<code>Hz</code>).
+ * A unit of frequency equal to one cycle per second.
+ * After Heinrich Rudolf Hertz (1857-1894), German physicist who was the
+ * first to produce radio waves artificially.
+ */
+ public static final AlternateUnit<Frequency> HERTZ = si(new AlternateUnit<Frequency>(
+ "Hz", Unit.ONE.divide(SECOND)));
+
+ /**
+ * The derived unit for force (<code>N</code>).
+ * One newton is the force required to give a mass of 1 kilogram an Force
+ * of 1 metre per second per second. It is named after the English
+ * mathematician and physicist Sir Isaac Newton (1642-1727).
+ */
+ public static final AlternateUnit<Force> NEWTON = si(new AlternateUnit<Force>(
+ "N", METRE.times(KILOGRAM).divide(SECOND.pow(2))));
+
+ /**
+ * The derived unit for pressure, stress (<code>Pa</code>).
+ * One pascal is equal to one newton per square meter. It is named after
+ * the French philosopher and mathematician Blaise Pascal (1623-1662).
+ */
+ public static final AlternateUnit<Pressure> PASCAL = si(new AlternateUnit<Pressure>(
+ "Pa", NEWTON.divide(METRE.pow(2))));
+
+ /**
+ * The derived unit for energy, work, quantity of heat (<code>J</code>).
+ * One joule is the amount of work done when an applied force of 1 newton
+ * moves through a distance of 1 metre in the direction of the force.
+ * It is named after the English physicist James Prescott Joule (1818-1889).
+ */
+ public static final AlternateUnit<Energy> JOULE = si(new AlternateUnit<Energy>(
+ "J", NEWTON.times(METRE)));
+
+ /**
+ * The derived unit for power, radiant, flux (<code>W</code>).
+ * One watt is equal to one joule per second. It is named after the British
+ * scientist James Watt (1736-1819).
+ */
+ public static final AlternateUnit<Power> WATT = si(new AlternateUnit<Power>(
+ "W", JOULE.divide(SECOND)));
+
+ /**
+ * The derived unit for electric charge, quantity of electricity
+ * (<code>C</code>).
+ * One Coulomb is equal to the quantity of charge transferred in one second
+ * by a steady current of one ampere. It is named after the French physicist
+ * Charles Augustin de Coulomb (1736-1806).
+ */
+ public static final AlternateUnit<ElectricCharge> COULOMB = si(new AlternateUnit<ElectricCharge>(
+ "C", SECOND.times(AMPERE)));
+
+ /**
+ * The derived unit for electric potential difference, electromotive force
+ * (<code>V</code>).
+ * One Volt is equal to the difference of electric potential between two
+ * points on a conducting wire carrying a constant current of one ampere
+ * when the power dissipated between the points is one watt. It is named
+ * after the Italian physicist Count Alessandro Volta (1745-1827).
+ */
+ public static final AlternateUnit<ElectricPotential> VOLT = si(new AlternateUnit<ElectricPotential>(
+ "V", WATT.divide(AMPERE)));
+
+ /**
+ * The derived unit for capacitance (<code>F</code>).
+ * One Farad is equal to the capacitance of a capacitor having an equal
+ * and opposite charge of 1 coulomb on each plate and a potential difference
+ * of 1 volt between the plates. It is named after the British physicist
+ * and chemist Michael Faraday (1791-1867).
+ */
+ public static final AlternateUnit<ElectricCapacitance> FARAD = si(new AlternateUnit<ElectricCapacitance>(
+ "F", COULOMB.divide(VOLT)));
+
+ /**
+ * The derived unit for electric resistance (<code>Ω</code> or
+ * <code>Ohm</code>).
+ * One Ohm is equal to the resistance of a conductor in which a current of
+ * one ampere is produced by a potential of one volt across its terminals.
+ * It is named after the German physicist Georg Simon Ohm (1789-1854).
+ */
+ public static final AlternateUnit<ElectricResistance> OHM = si(new AlternateUnit<ElectricResistance>(
+ "Ω", VOLT.divide(AMPERE)));
+
+ /**
+ * The derived unit for electric conductance (<code>S</code>).
+ * One Siemens is equal to one ampere per volt. It is named after
+ * the German engineer Ernst Werner von Siemens (1816-1892).
+ */
+ public static final AlternateUnit<ElectricConductance> SIEMENS = si(new AlternateUnit<ElectricConductance>(
+ "S", AMPERE.divide(VOLT)));
+
+ /**
+ * The derived unit for magnetic flux (<code>Wb</code>).
+ * One Weber is equal to the magnetic flux that in linking a circuit of one
+ * turn produces in it an electromotive force of one volt as it is uniformly
+ * reduced to zero within one second. It is named after the German physicist
+ * Wilhelm Eduard Weber (1804-1891).
+ */
+ public static final AlternateUnit<MagneticFlux> WEBER = si(new AlternateUnit<MagneticFlux>(
+ "Wb", VOLT.times(SECOND)));
+
+ /**
+ * The derived unit for magnetic flux density (<code>T</code>).
+ * One Tesla is equal equal to one weber per square metre. It is named
+ * after the Serbian-born American electrical engineer and physicist
+ * Nikola Tesla (1856-1943).
+ */
+ public static final AlternateUnit<MagneticFluxDensity> TESLA = si(new AlternateUnit<MagneticFluxDensity>(
+ "T", WEBER.divide(METRE.pow(2))));
+
+ /**
+ * The derived unit for inductance (<code>H</code>).
+ * One Henry is equal to the inductance for which an induced electromotive
+ * force of one volt is produced when the current is varied at the rate of
+ * one ampere per second. It is named after the American physicist
+ * Joseph Henry (1791-1878).
+ */
+ public static final AlternateUnit<ElectricInductance> HENRY = si(new AlternateUnit<ElectricInductance>(
+ "H", WEBER.divide(AMPERE)));
+
+ /**
+ * The derived unit for Celsius temperature (<code>℃</code>).
+ * This is a unit of temperature such as the freezing point of water
+ * (at one atmosphere of pressure) is 0 ℃, while the boiling point is
+ * 100 ℃.
+ */
+ public static final Unit<Temperature> CELSIUS = si(KELVIN.plus(273.15));
+
+ /**
+ * The derived unit for luminous flux (<code>lm</code>).
+ * One Lumen is equal to the amount of light given out through a solid angle
+ * by a source of one candela intensity radiating equally in all directions.
+ */
+ public static final AlternateUnit<LuminousFlux> LUMEN = si(new AlternateUnit<LuminousFlux>(
+ "lm", CANDELA.times(STERADIAN)));
+
+ /**
+ * The derived unit for illuminance (<code>lx</code>).
+ * One Lux is equal to one lumen per square metre.
+ */
+ public static final AlternateUnit<Illuminance> LUX = si(new AlternateUnit<Illuminance>(
+ "lx", LUMEN.divide(METRE.pow(2))));
+
+ /**
+ * The derived unit for activity of a radionuclide (<code>Bq</code>).
+ * One becquerel is the radiation caused by one disintegration per second.
+ * It is named after the French physicist, Antoine-Henri Becquerel
+ * (1852-1908).
+ */
+ public static final AlternateUnit<RadioactiveActivity> BECQUEREL = si(new AlternateUnit<RadioactiveActivity>(
+ "Bq", Unit.ONE.divide(SECOND)));
+
+ /**
+ * The derived unit for absorbed dose, specific energy (imparted), kerma
+ * (<code>Gy</code>).
+ * One gray is equal to the dose of one joule of energy absorbed per one
+ * kilogram of matter. It is named after the British physician
+ * L. H. Gray (1905-1965).
+ */
+ public static final AlternateUnit<RadiationDoseAbsorbed> GRAY = si(new AlternateUnit<RadiationDoseAbsorbed>(
+ "Gy", JOULE.divide(KILOGRAM)));
+
+ /**
+ * The derived unit for dose equivalent (<code>Sv</code>).
+ * One Sievert is equal is equal to the actual dose, in grays, multiplied
+ * by a "quality factor" which is larger for more dangerous forms of
+ * radiation. It is named after the Swedish physicist Rolf Sievert
+ * (1898-1966).
+ */
+ public static final AlternateUnit<RadiationDoseEffective> SIEVERT = si(new AlternateUnit<RadiationDoseEffective>(
+ "Sv", JOULE.divide(KILOGRAM)));
+
+ /**
+ * The derived unit for catalytic activity (<code>kat</code>).
+ */
+ public static final AlternateUnit<CatalyticActivity> KATAL = si(new AlternateUnit<CatalyticActivity>(
+ "kat", MOLE.divide(SECOND)));
+ //////////////////////////////
+ // SI DERIVED PRODUCT UNITS //
+ //////////////////////////////
+
+ /**
+ * The metric unit for velocity quantities (<code>m/s</code>).
+ */
+ public static final Unit<Velocity> METRES_PER_SECOND = si(new ProductUnit<Velocity>(
+ METRE.divide(SECOND)));
+
+ /**
+ * Equivalent to {@link #METRES_PER_SECOND}.
+ */
+ public static final Unit<Velocity> METERS_PER_SECOND = METRES_PER_SECOND;
+
+ /**
+ * The metric unit for acceleration quantities (<code>m/s²</code>).
+ */
+ public static final Unit<Acceleration> METRES_PER_SQUARE_SECOND = si(new ProductUnit<Acceleration>(
+ METRES_PER_SECOND.divide(SECOND)));
+
+ /**
+ * Equivalent to {@link #METRES_PER_SQUARE_SECOND}.
+ */
+ public static final Unit<Acceleration> METERS_PER_SQUARE_SECOND = METRES_PER_SQUARE_SECOND;
+
+ /**
+ * The metric unit for area quantities (<code>m²</code>).
+ */
+ public static final Unit<Area> SQUARE_METRE = si(new ProductUnit<Area>(
+ METRE.times(METRE)));
+
+ /**
+ * Equivalent to {@link #SQUARE_METRE}.
+ */
+ public static final Unit<Area> SQUARE_METER = SQUARE_METRE;
+
+ /**
+ * The metric unit for volume quantities (<code>m³</code>).
+ */
+ public static final Unit<Volume> CUBIC_METRE = si(new ProductUnit<Volume>(
+ SQUARE_METRE.times(METRE)));
+
+ /**
+ * Equivalent to {@link #CUBIC_METRE}.
+ */
+ public static final Unit<Volume> CUBIC_METER = CUBIC_METRE;
+
+ /**
+ * Equivalent to <code>KILO(METRE)</code>.
+ */
+ public static final Unit<Length> KILOMETRE = METER.times(1000);
+
+ /**
+ * Equivalent to {@link #KILOMETRE}.
+ */
+ public static final Unit<Length> KILOMETER = KILOMETRE;
+
+ /**
+ * Equivalent to <code>CENTI(METRE)</code>.
+ */
+ public static final Unit<Length> CENTIMETRE = METRE.divide(100);
+
+ /**
+ * Equivalent to {@link #CENTIMETRE}.
+ */
+ public static final Unit<Length> CENTIMETER = CENTIMETRE;
+
+ /**
+ * Equivalent to <code>MILLI(METRE)</code>.
+ */
+ public static final Unit<Length> MILLIMETRE = METRE.divide(1000);
+
+ /**
+ * Equivalent to {@link #MILLIMETRE}.
+ */
+ public static final Unit<Length> MILLIMETER = MILLIMETRE;
+
+ /////////////////
+ // SI PREFIXES //
+ /////////////////
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>24</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e24)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> YOTTA(Unit<Q> unit) {
+ return unit.transform(E24);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>21</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e21)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> ZETTA(Unit<Q> unit) {
+ return unit.transform(E21);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>18</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e18)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> EXA(Unit<Q> unit) {
+ return unit.transform(E18);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>15</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e15)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> PETA(Unit<Q> unit) {
+ return unit.transform(E15);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>12</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e12)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> TERA(Unit<Q> unit) {
+ return unit.transform(E12);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>9</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e9)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> GIGA(Unit<Q> unit) {
+ return unit.transform(E9);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>6</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e6)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> MEGA(Unit<Q> unit) {
+ return unit.transform(E6);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>3</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e3)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> KILO(Unit<Q> unit) {
+ return unit.transform(E3);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>2</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e2)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> HECTO(Unit<Q> unit) {
+ return unit.transform(E2);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>1</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e1)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> DEKA(Unit<Q> unit) {
+ return unit.transform(E1);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>-1</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e-1)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> DECI(Unit<Q> unit) {
+ return unit.transform(Em1);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>-2</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e-2)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> CENTI(Unit<Q> unit) {
+ return unit.transform(Em2);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>-3</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e-3)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> MILLI(Unit<Q> unit) {
+ return unit.transform(Em3);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>-6</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e-6)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> MICRO(Unit<Q> unit) {
+ return unit.transform(Em6);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>-9</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e-9)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> NANO(Unit<Q> unit) {
+ return unit.transform(Em9);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>-12</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e-12)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> PICO(Unit<Q> unit) {
+ return unit.transform(Em12);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>-15</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e-15)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> FEMTO(Unit<Q> unit) {
+ return unit.transform(Em15);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>-18</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e-18)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> ATTO(Unit<Q> unit) {
+ return unit.transform(Em18);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>-21</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e-21)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> ZEPTO(Unit<Q> unit) {
+ return unit.transform(Em21);
+ }
+
+ /**
+ * Returns the specified unit multiplied by the factor
+ * <code>10<sup>-24</sup></code>
+ *
+ * @param unit any unit.
+ * @return <code>unit.times(1e-24)</code>.
+ */
+ public static <Q extends Quantity> Unit<Q> YOCTO(Unit<Q> unit) {
+ return unit.transform(Em24);
+ }
+
+ /////////////////////
+ // Collection View //
+ /////////////////////
+ /**
+ * Returns a read only view over theunits defined in this class.
+ *
+ * @return the collection of SI units.
+ */
+ public Set<Unit<?>> getUnits() {
+ return Collections.unmodifiableSet(UNITS);
+ }
+
+ /**
+ * Adds a new unit to the collection.
+ *
+ * @param unit the unit being added.
+ * @return <code>unit</code>.
+ */
+ private static <U extends Unit<?>> U si(U unit) {
+ UNITS.add(unit);
+ return unit;
+ }
+ // Holds prefix converters (optimization).
+ static final RationalConverter E24 = new RationalConverter(
+ BigInteger.TEN.pow(24), BigInteger.ONE);
+
+ static final RationalConverter E21 = new RationalConverter(
+ BigInteger.TEN.pow(21), BigInteger.ONE);
+
+ static final RationalConverter E18 = new RationalConverter(
+ BigInteger.TEN.pow(18), BigInteger.ONE);
+
+ static final RationalConverter E15 = new RationalConverter(
+ BigInteger.TEN.pow(15), BigInteger.ONE);
+
+ static final RationalConverter E12 = new RationalConverter(
+ BigInteger.TEN.pow(12), BigInteger.ONE);
+
+ static final RationalConverter E9 = new RationalConverter(
+ BigInteger.TEN.pow(9), BigInteger.ONE);
+
+ static final RationalConverter E6 = new RationalConverter(
+ BigInteger.TEN.pow(6), BigInteger.ONE);
+
+ static final RationalConverter E3 = new RationalConverter(
+ BigInteger.TEN.pow(3), BigInteger.ONE);
+
+ static final RationalConverter E2 = new RationalConverter(
+ BigInteger.TEN.pow(2), BigInteger.ONE);
+
+ static final RationalConverter E1 = new RationalConverter(
+ BigInteger.TEN.pow(1), BigInteger.ONE);
+
+ static final RationalConverter Em1 = new RationalConverter(
+ BigInteger.ONE, BigInteger.TEN.pow(1));
+
+ static final RationalConverter Em2 = new RationalConverter(
+ BigInteger.ONE, BigInteger.TEN.pow(2));
+
+ static final RationalConverter Em3 = new RationalConverter(
+ BigInteger.ONE, BigInteger.TEN.pow(3));
+
+ static final RationalConverter Em6 = new RationalConverter(
+ BigInteger.ONE, BigInteger.TEN.pow(6));
+
+ static final RationalConverter Em9 = new RationalConverter(
+ BigInteger.ONE, BigInteger.TEN.pow(9));
+
+ static final RationalConverter Em12 = new RationalConverter(
+ BigInteger.ONE, BigInteger.TEN.pow(12));
+
+ static final RationalConverter Em15 = new RationalConverter(
+ BigInteger.ONE, BigInteger.TEN.pow(15));
+
+ static final RationalConverter Em18 = new RationalConverter(
+ BigInteger.ONE, BigInteger.TEN.pow(18));
+
+ static final RationalConverter Em21 = new RationalConverter(
+ BigInteger.ONE, BigInteger.TEN.pow(21));
+
+ static final RationalConverter Em24 = new RationalConverter(
+ BigInteger.ONE, BigInteger.TEN.pow(24));
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/unit/SystemOfUnits.java b/src/main/java/javax/measure/unit/SystemOfUnits.java
new file mode 100644
index 0000000..665bc1b
--- /dev/null
+++ b/src/main/java/javax/measure/unit/SystemOfUnits.java
@@ -0,0 +1,50 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit;
+
+import java.util.Set;
+
+/**
+ * <p> This class represents a system of units, it groups units together
+ * for historical or cultural reasons. Nothing prevents a unit from
+ * belonging to several system of units at the same time
+ * (for example an imperial system would have many of the units
+ * held by {@link NonSI}).</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public abstract class SystemOfUnits {
+
+ /**
+ * Returns a read only view over the units defined in this system.
+ *
+ * @return the collection of units.
+ */
+ public abstract Set<Unit<?>> getUnits();
+}
diff --git a/src/main/java/javax/measure/unit/TransformedUnit.java b/src/main/java/javax/measure/unit/TransformedUnit.java
new file mode 100644
index 0000000..2bc0756
--- /dev/null
+++ b/src/main/java/javax/measure/unit/TransformedUnit.java
@@ -0,0 +1,127 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit;
+
+import javax.measure.converter.UnitConverter;
+import javax.measure.quantity.Quantity;
+
+/**
+ * <p> This class represents the units derived from other units using
+ * {@link UnitConverter converters}.</p>
+ *
+ * <p> Examples of transformed units:[code]
+ * CELSIUS = KELVIN.add(273.15);
+ * FOOT = METRE.times(3048).divide(10000);
+ * MILLISECOND = MILLI(SECOND);
+ * [/code]</p>
+ *
+ * <p> Transformed units have no label. But like any other units,
+ * they may have labels attached to them (see {@link javax.measure.unit.format.SymbolMap
+ * SymbolMap}</p>
+ *
+ * <p> Instances of this class are created through the {@link Unit#transform} method.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @version 1.0, April 15, 2009
+ */
+public final class TransformedUnit<Q extends Quantity> extends DerivedUnit<Q> {
+
+ /**
+ * Holds the parent unit (not a transformed unit).
+ */
+ private final Unit<Q> _parentUnit;
+
+ /**
+ * Holds the converter to the parent unit.
+ */
+ private final UnitConverter _toParentUnit;
+
+ /**
+ * Creates a transformed unit from the specified parent unit.
+ *
+ * @param parentUnit the untransformed unit from which this unit is
+ * derived.
+ * @param toParentUnit the converter to the parent units.
+ * @throws IllegalArgumentException if <code>toParentUnit ==
+ * {@link UnitConverter#IDENTITY UnitConverter.IDENTITY}</code>
+ */
+ TransformedUnit(Unit<Q> parentUnit, UnitConverter toParentUnit) {
+ if (toParentUnit == UnitConverter.IDENTITY)
+ throw new IllegalArgumentException("Identity not allowed");
+ _parentUnit = parentUnit;
+ _toParentUnit = toParentUnit;
+ }
+
+ /**
+ * Returns the parent unit for this unit. The parent unit is the
+ * untransformed unit from which this unit is derived.
+ *
+ * @return the untransformed unit from which this unit is derived.
+ */
+ public Unit<Q> getParentUnit() {
+ return _parentUnit;
+ }
+
+ /**
+ * Returns the converter to the parent unit.
+ *
+ * @return the converter to the parent unit.
+ */
+ public UnitConverter toParentUnit() {
+ return _toParentUnit;
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (this == that)
+ return true;
+ if (!(that instanceof TransformedUnit))
+ return false;
+ TransformedUnit<?> thatUnit = (TransformedUnit<?>) that;
+ return this._parentUnit.equals(thatUnit._parentUnit) &&
+ this._toParentUnit.equals(thatUnit._toParentUnit);
+ }
+
+ @Override
+ public int hashCode() {
+ return _parentUnit.hashCode() + _toParentUnit.hashCode();
+ }
+
+ @Override
+ public Unit<Q> toSI() {
+ return _parentUnit.toSI();
+ }
+
+ @Override
+ public final UnitConverter getConverterTo(Unit<Q> unit) {
+ return _parentUnit.getConverterTo(unit).concatenate(_toParentUnit);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/unit/Unit.java b/src/main/java/javax/measure/unit/Unit.java
new file mode 100644
index 0000000..b5a818f
--- /dev/null
+++ b/src/main/java/javax/measure/unit/Unit.java
@@ -0,0 +1,571 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences Copyright
+ * (c) 2005-2009, JScience (http://jscience.org/) All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit;
+
+import java.io.Serializable;
+import java.math.BigInteger;
+import java.text.ParsePosition;
+import java.util.HashMap;
+
+import javax.measure.converter.AddConverter;
+import javax.measure.converter.ConversionException;
+import javax.measure.converter.LinearConverter;
+import javax.measure.converter.MultiplyConverter;
+import javax.measure.converter.RationalConverter;
+import javax.measure.converter.UnitConverter;
+import javax.measure.quantity.Dimensionless;
+import javax.measure.quantity.Quantity;
+
+/**
+ * <p> This class represents a determinate {@link javax.measure.quantity.Quantity
+ * quantity} (as of length, time, heat, or value) adopted as a standard of
+ * measurement.</p>
+ *
+ * <p> It is helpful to think of instances of this class as recording the history by
+ * which they are created. Thus, for example, the string "g/kg" (which is a
+ * dimensionless unit) would result from invoking the method toString() on a
+ * unit that was created by dividing a gram unit by a kilogram unit. Yet, "kg"
+ * divided by "kg" returns {@link #ONE} and not "kg/kg" due to automatic unit
+ * factorization.</p>
+ *
+ * <p> This class supports the multiplication of offsets units. The result is
+ * usually a unit not convertible to its {@link #toSI standard unit}. Such units
+ * may appear in derivative quantities. For example °C/m is an unit of gradient,
+ * which is common in atmospheric and oceanographic research.</p>
+ *
+ * <p> Units raised at rational powers are also supported. For example the cubic
+ * root of liter is a unit compatible with meter.</p>
+ *
+ * <p> Units specializations can only be defined by sub-classing either
+ * {@link BaseUnit}, {@link DerivedUnit} or {@link AnnotatedUnit} (the unit
+ * constructor is package private).For example:[code]
+ * public LengthUnit extends AnnotatedUnit<Length> {
+ * public static LengthUnit METER = new LengthUnit(SI.METER, "myOwnUnitClass"); // Equivalent to SI.METER
+ * LengthUnit(Unit<Length> realUnit, String annotation) { super(realUnit, annotation); }
+ * }[/code]</p>
+ *
+ * <p> Instances of this class and sub-classes are immutable.</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @author <a href="mailto:steve at unidata.ucar.edu">Steve Emmerson</a>
+ * @author Martin Desruisseaux
+ * @version 1.0, April 15, 2009
+ * @see <a href="http://en.wikipedia.org/wiki/Units_of_measurement"> Wikipedia:
+ * Units of measurement</a>
+ */
+public abstract class Unit<Q extends Quantity> implements Serializable {
+
+ /**
+ * Holds the dimensionless unit <code>ONE</code>.
+ */
+ public static final Unit<Dimensionless> ONE = new ProductUnit<Dimensionless>();
+
+ /**
+ * Holds the unique symbols collection (base unit or alternate units).
+ */
+ static final HashMap<String, Unit<?>> SYMBOL_TO_UNIT = new HashMap<String, Unit<?>>();
+
+ /**
+ * Default constructor. Package private visibility. Subclasses should derive
+ * from either BaseUnit, DerivedUnit or AnnotatedUnit.
+ */
+ Unit() {
+ }
+
+ // ////////////////////////////////////////////////////
+ // Contract methods (for sub-classes to implement). //
+ // ////////////////////////////////////////////////////
+ /**
+ * Returns the standard unit from which this unit is derived. The SI unit
+ * identifies the "type" of {@link javax.measure.quantity.Quantity quantity}
+ * for which this unit is employed. For example:[code]
+ * boolean isAngularVelocity(Unit<?> u) {
+ * return u.toSI().equals(RADIAN.divide(SECOND));
+ * }
+ * assert(REVOLUTION.divide(MINUTE).isAngularVelocity());
+ * [/code]
+ * <p><i> Note: Having the same SI unit is not sufficient to ensure that a
+ * converter exists between the two units (e.g. °C/m and K/m).</i></p>
+ *
+ * @return the system unit this unit is derived from.
+ */
+ public abstract Unit<Q> toSI();
+
+ /**
+ * Returns the hash code for this unit.
+ *
+ * @return this unit hashcode value.
+ */
+ @Override
+ public abstract int hashCode();
+
+ /**
+ * Indicates if the specified unit can be considered equals to the one
+ * specified.
+ *
+ * @param that the object to compare to.
+ * @return <code>true</code> if this unit is considered equal to that unit;
+ * <code>false</code> otherwise.
+ */
+ @Override
+ public abstract boolean equals(Object that);
+
+ /**
+ * Indicates if this unit is a standard unit (base units and alternate units
+ * are standard units). The standard unit identifies the "type" of
+ * {@link javax.measure.quantity.Quantity quantity} for which the unit is
+ * employed.
+ *
+ * @return <code>this.toSI().equals(this)</code>
+ */
+ public boolean isSI() {
+ return toSI().equals(this);
+ }
+
+ /**
+ * Indicates if this unit is compatible with the unit specified. Units don't
+ * need to be equals to be compatible. For example:[code]
+ * RADIAN.equals(ONE) == false
+ * RADIAN.isCompatible(ONE) == true
+ * [/code]
+ *
+ * @param that the other unit.
+ * @return <code>this.getDimension().equals(that.getDimension())</code>
+ * @see #getDimension()
+ */
+ public final boolean isCompatible(Unit<?> that) {
+ return (this == that) || this.toSI().equals(that.toSI())
+ || this.getDimension().equals(that.getDimension());
+ }
+
+ /**
+ * Casts this unit to a parameterized unit of specified nature or throw a
+ * <code>ClassCastException</code> if the dimension of the specified
+ * quantity and this unit's dimension do not match. For example:[code]
+ * Unit<Length> LIGHT_YEAR = NonSI.C.times(NonSI.YEAR).asType(Length.class);
+ * [/code]
+ *
+ * @param type the quantity class identifying the nature of the unit.
+ * @return this unit parameterized with the specified type.
+ * @throws ClassCastException if the dimension of this unit is different
+ * from the specified quantity dimension.
+ * @throws UnsupportedOperationException if the specified quantity class
+ * does not have a public static field named "UNIT" holding the SI unit for
+ * the quantity.
+ */
+ @SuppressWarnings("unchecked")
+ public final <T extends Quantity> Unit<T> asType(Class<T> type)
+ throws ClassCastException {
+ Dimension thisDimension = this.getDimension();
+ Unit<T> quantityUnit = null;
+ try {
+ quantityUnit = (Unit<T>) type.getField("UNIT").get(null);
+ } catch (Exception e) {
+ throw new UnsupportedOperationException(
+ "The quantity class "
+ + type
+ + " does not have a public static field UNIT holding the SI unit "
+ + " for the quantity.");
+ }
+ Dimension quantityDimension = quantityUnit.getDimension();
+ if (!thisDimension.equals(quantityDimension))
+ throw new ClassCastException("Dimension of " + this + " is "
+ + thisDimension
+ + ", but the dimension of quantity of type "
+ + type.getName() + " is " + quantityDimension);
+ return (Unit<T>) this;
+ }
+
+ /**
+ * Returns the dimension of this unit (depends upon the current dimensional
+ * {@link Dimension.Model model}).
+ *
+ * @return the dimension of this unit for the current model.
+ */
+ public final Dimension getDimension() {
+ Unit<?> systemUnit = this.toSI();
+ if (systemUnit instanceof BaseUnit)
+ return Dimension.getModel().getDimension((BaseUnit<?>) systemUnit);
+ if (systemUnit instanceof AlternateUnit)
+ return ((AlternateUnit<?>) systemUnit).getParent().getDimension();
+ // Product of units.
+ ProductUnit<?> productUnit = (ProductUnit<?>) systemUnit;
+ Dimension dimension = Dimension.NONE;
+ for (int i = 0; i < productUnit.getUnitCount(); i++) {
+ Unit<?> unit = productUnit.getUnit(i);
+ Dimension d = unit.getDimension().pow(productUnit.getUnitPow(i))
+ .root(productUnit.getUnitRoot(i));
+ dimension = dimension.times(d);
+ }
+ return dimension;
+ }
+
+ /**
+ * Returns a converter of numeric values from this unit to another unit. As
+ * a minimum unit sub-classes should be able to provide a unit converter to
+ * their associated {@link #toSI() standard} unit.
+ *
+ * @param that the unit to which to convert the numeric values.
+ * @return the converter from this unit to <code>that</code> unit.
+ * @throws ConversionException if the converter cannot be constructed (e.g.
+ * <code>!this.isCompatible(that)</code>).
+ */
+ public UnitConverter getConverterTo(Unit<Q> that)
+ throws ConversionException {
+ return ((this == that) || this.equals(that)) ? UnitConverter.IDENTITY
+ : searchConverterTo(that);
+ }
+
+ private UnitConverter searchConverterTo(Unit<Q> that)
+ throws ConversionException {
+ Unit<Q> thisSI = this.toSI();
+ Unit<Q> thatSI = that.toSI();
+ if (thisSI.equals(thatSI))
+ return that.getConverterTo(thatSI).inverse().concatenate(
+ this.getConverterTo(thisSI));
+ // Use dimensional transforms.
+ if (!thisSI.getDimension().equals(thatSI.getDimension()))
+ throw new ConversionException(this + " is not compatible with "
+ + that);
+ // Transform between SystemUnit and BaseUnits is Identity.
+ UnitConverter thisTransform = this.getConverterTo(thisSI).concatenate(
+ transformOf(this.toBaseUnits()));
+ UnitConverter thatTransform = that.getConverterTo(thatSI).concatenate(
+ transformOf(that.toBaseUnits()));
+ return thatTransform.inverse().concatenate(thisTransform);
+ }
+
+ private Unit<?> toBaseUnits() {
+ Unit<?> systemUnit = this.toSI();
+ if (systemUnit instanceof BaseUnit)
+ return systemUnit;
+ if (systemUnit instanceof AlternateUnit)
+ return ((AlternateUnit<?>) systemUnit).getParent().toBaseUnits();
+ if (systemUnit instanceof ProductUnit) {
+ ProductUnit<?> productUnit = (ProductUnit<?>) systemUnit;
+ Unit<?> baseUnits = ONE;
+ for (int i = 0; i < productUnit.getUnitCount(); i++) {
+ Unit<?> unit = productUnit.getUnit(i).toBaseUnits();
+ unit = unit.pow(productUnit.getUnitPow(i));
+ unit = unit.root(productUnit.getUnitRoot(i));
+ baseUnits = baseUnits.times(unit);
+ }
+ return baseUnits;
+ } else
+ throw new InternalError("System Unit cannot be an instance of "
+ + this.getClass());
+ }
+
+ private static UnitConverter transformOf(Unit<?> baseUnits) {
+ if (baseUnits instanceof BaseUnit)
+ return Dimension.getModel().getTransform((BaseUnit<?>) baseUnits);
+ // Product of units.
+ ProductUnit<?> productUnit = (ProductUnit<?>) baseUnits;
+ UnitConverter converter = UnitConverter.IDENTITY;
+ for (int i = 0; i < productUnit.getUnitCount(); i++) {
+ Unit<?> unit = productUnit.getUnit(i);
+ UnitConverter cvtr = transformOf(unit);
+ if (!(cvtr instanceof LinearConverter))
+ throw new ConversionException(baseUnits
+ + " is non-linear, cannot convert");
+ if (productUnit.getUnitRoot(i) != 1)
+ throw new ConversionException(productUnit
+ + " holds a base unit with fractional exponent");
+ int pow = productUnit.getUnitPow(i);
+ if (pow < 0) { // Negative power.
+ pow = -pow;
+ cvtr = cvtr.inverse();
+ }
+ for (int j = 0; j < pow; j++) {
+ converter = converter.concatenate(cvtr);
+ }
+ }
+ return converter;
+ }
+
+ /**
+ * Returns a unit equivalent to this unit but used in expressions to
+ * distinguish between quantities of a different nature but of the same
+ * dimensions.
+ *
+ * <p> Examples of alternate units:[code]
+ * Unit<Angle> RADIAN = ONE.alternate("rad");
+ * Unit<Force> NEWTON = METRE.times(KILOGRAM).divide(SECOND.pow(2)).alternate("N");
+ * Unit<Pressure> PASCAL = NEWTON.divide(METRE.pow(2)).alternate("Pa");
+ * [/code]
+ * </p>
+ *
+ * @param symbol the new symbol for the alternate unit.
+ * @return the alternate unit.
+ * @throws UnsupportedOperationException if this unit is not a standard
+ * unit.
+ * @throws IllegalArgumentException if the specified symbol is already
+ * associated to a different unit.
+ */
+ public final <A extends Quantity> AlternateUnit<A> alternate(String symbol) {
+ return new AlternateUnit<A>(symbol, this);
+ }
+
+ /**
+ * Returns the combination of this unit with the specified sub-unit.
+ * Compound units are typically used for formatting purpose. Examples of
+ * compound units:[code]
+ * Unit<Length> FOOT_INCH = FOOT.compound(INCH);
+ * Unit<Duration> HOUR_MINUTE_SECOND = HOUR.compound(MINUTE).compound(SECOND);
+ * [/code]
+ *
+ * @param that the least significant unit to combine with this unit.
+ * @return the corresponding compound unit.
+ */
+ public final CompoundUnit<Q> compound(Unit<Q> that) {
+ return new CompoundUnit<Q>(this, that);
+ }
+
+ /**
+ * Returns the unit derived from this unit using the specified converter.
+ * The converter does not need to be linear. For example:[code]
+ * Unit<Dimensionless> DECIBEL = Unit.ONE.transform(
+ * new LogConverter(10).inverse().concatenate(
+ * new RationalConverter(1, 10)));
+ * [/code]
+ *
+ * @param operation the converter from the transformed unit to this unit.
+ * @return the unit after the specified transformation.
+ */
+ public final Unit<Q> transform(UnitConverter operation) {
+ if (this instanceof TransformedUnit) {
+ TransformedUnit<Q> tf = (TransformedUnit<Q>) this;
+ Unit<Q> parent = tf.getParentUnit();
+ UnitConverter toParent = tf.toParentUnit().concatenate(operation);
+ if (toParent == UnitConverter.IDENTITY)
+ return parent;
+ return new TransformedUnit<Q>(parent, toParent);
+ }
+ if (operation == UnitConverter.IDENTITY)
+ return this;
+ return new TransformedUnit<Q>(this, operation);
+ }
+
+ /**
+ * Returns the result of adding an offset to this unit. The returned unit is
+ * convertible with all units that are convertible with this unit.
+ *
+ * @param offset the offset added (expressed in this unit, e.g.
+ * <code>CELSIUS = KELVIN.plus(273.15)</code>).
+ * @return <code>this.transform(new AddConverter(offset))</code>
+ */
+ public final Unit<Q> plus(double offset) {
+ if (offset == 0)
+ return this;
+ return transform(new AddConverter(offset));
+ }
+
+ /**
+ * Returns the result of multiplying this unit by an exact factor.
+ *
+ * @param factor the exact scale factor (e.g.
+ * <code>KILOMETRE = METRE.times(1000)</code>).
+ * @return <code>this.transform(new RationalConverter(factor, 1))</code>
+ */
+ public final Unit<Q> times(long factor) {
+ if (factor == 1)
+ return this;
+ return transform(new RationalConverter(BigInteger.valueOf(factor),
+ BigInteger.ONE));
+ }
+
+ /**
+ * Returns the result of multiplying this unit by a an approximate factor.
+ *
+ * @param factor the approximate factor (e.g.
+ * <code>ELECTRON_MASS = KILOGRAM.times(9.10938188e-31)</code>).
+ * @return <code>this.transform(new MultiplyConverter(factor))</code>
+ */
+ public final Unit<Q> times(double factor) {
+ if (factor == 1)
+ return this;
+ return transform(new MultiplyConverter(factor));
+ }
+
+ /**
+ * Returns the product of this unit with the one specified.
+ *
+ * @param that the unit multiplicand.
+ * @return <code>this * that</code>
+ */
+ @SuppressWarnings("unchecked")
+ public final Unit<?> times(Unit<?> that) {
+ if (this.equals(ONE))
+ return that;
+ if (that.equals(ONE))
+ return this;
+ if (this.isRationalFactor())
+ return that.transform(this.getConverterTo((Unit) ONE));
+ if (that.isRationalFactor())
+ return this.transform(that.getConverterTo((Unit) ONE));
+ return ProductUnit.getProductInstance(this, that);
+ }
+
+ private boolean isRationalFactor() {
+ if (!(this instanceof TransformedUnit))
+ return false;
+ TransformedUnit<Q> tu = (TransformedUnit<Q>) this;
+ return tu.getParentUnit().equals(ONE)
+ && (tu.getConverterTo(tu.toSI()) instanceof RationalConverter);
+ }
+
+ /**
+ * Returns the inverse of this unit.
+ *
+ * @return <code>1 / this</code>
+ */
+ @SuppressWarnings("unchecked")
+ public final Unit<?> inverse() {
+ if (this.equals(ONE))
+ return this;
+ if (this.isRationalFactor())
+ return this.transform(this.getConverterTo((Unit) ONE).inverse());
+ return ProductUnit.getQuotientInstance(ONE, this);
+ }
+
+ /**
+ * Returns the result of dividing this unit by an exact divisor.
+ *
+ * @param divisor the exact divisor. (e.g.
+ * <code>QUART = GALLON_LIQUID_US.divide(4)</code>).
+ * @return <code>this.transform(new RationalConverter(1 , divisor))</code>
+ */
+ public final Unit<Q> divide(long divisor) {
+ if (divisor == 1)
+ return this;
+ return transform(new RationalConverter(BigInteger.ONE, BigInteger
+ .valueOf(divisor)));
+ }
+
+ /**
+ * Returns the result of dividing this unit by an approximate divisor.
+ *
+ * @param divisor the approximate divisor.
+ * @return <code>this.transform(new MultiplyConverter(1.0 / divisor))</code>
+ */
+ public final Unit<Q> divide(double divisor) {
+ if (divisor == 1)
+ return this;
+ return transform(new MultiplyConverter(1.0 / divisor));
+ }
+
+ /**
+ * Returns the quotient of this unit with the one specified.
+ *
+ * @param that the unit divisor.
+ * @return <code>this / that</code>
+ */
+ public final Unit<?> divide(Unit<?> that) {
+ return this.times(that.inverse());
+ }
+
+ /**
+ * Returns a unit equals to the given root of this unit.
+ *
+ * @param n the root's order.
+ * @return the result of taking the given root of this unit.
+ * @throws ArithmeticException if <code>n == 0</code>.
+ */
+ public final Unit<?> root(int n) {
+ if (n > 0)
+ return ProductUnit.getRootInstance(this, n);
+ else if (n == 0)
+ throw new ArithmeticException("Root's order of zero");
+ else
+ // n < 0
+ return ONE.divide(this.root(-n));
+ }
+
+ /**
+ * Returns a unit equals to this unit raised to an exponent.
+ *
+ * @param n the exponent.
+ * @return the result of raising this unit to the exponent.
+ */
+ public final Unit<?> pow(int n) {
+ if (n > 0)
+ return this.times(this.pow(n - 1));
+ else if (n == 0)
+ return ONE;
+ else
+ // n < 0
+ return ONE.divide(this.pow(-n));
+ }
+
+ /**
+ * Returns a unit instance that is defined from the specified character
+ * sequence using the {@link UnitFormat#getStandard standard} unit format
+ * (<a href="http://unitsofmeasure.org/">UCUM</a> based). This method is
+ * capable of parsing any units representations produced by
+ * {@link #toString()}. Locale-sensitive unit formatting and parsing are
+ * handled by the {@link UnitFormat} class and its subclasses.
+ *
+ * <p>
+ * This method can be used to parse dimensionless units.[code]
+ * Unit<Dimensionless> PERCENT = Unit.valueOf("100").inverse().asType(Dimensionless.class); [/code]
+ *
+ * @param csq the character sequence to parse.
+ * @return
+ * <code>UnitFormat.getStandard().parse(csq, new ParsePosition(0))</code>
+ * @throws IllegalArgumentException if the specified character sequence
+ * cannot be correctly parsed (e.g. not UCUM compliant).
+ */
+ public static Unit<?> valueOf(CharSequence csq) {
+ return UnitFormat.getStandard().parse(csq, new ParsePosition(0));
+ }
+
+ // ////////////////////
+ // GENERAL CONTRACT //
+ // ////////////////////
+ /**
+ * Returns the international <code>String</code> representation of this unit
+ * (<a href="http://unitsofmeasure.org/">UCUM</a> based). The string
+ * produced for a given unit is always the same; it is not affected by the
+ * locale. This means that it can be used as a canonical string
+ * representation for exchanging units, or as a key for a Hashtable, etc.
+ * Locale-sensitive unit formatting and parsing is handled by the
+ * {@link UnitFormat} class and its subclasses.
+ *
+ * <p>Custom units types should override this method as they will not be
+ * recognized by the UCUM format.</p>
+ *
+ *
+ * @return <code>UnitFormat.getStandard().format(this)</code>
+ */
+ @Override
+ public String toString() {
+ return UnitFormat.getStandard().format(this);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/unit/UnitFormat.java b/src/main/java/javax/measure/unit/UnitFormat.java
new file mode 100644
index 0000000..a2ccdcc
--- /dev/null
+++ b/src/main/java/javax/measure/unit/UnitFormat.java
@@ -0,0 +1,164 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit;
+
+import javax.measure.unit.format.*;
+import java.io.IOException;
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.ParsePosition;
+import java.util.Locale;
+
+/**
+ * <p> This class provides the interface for formatting and parsing {@link
+ * Unit units}.</p>
+ *
+ * <p> For all {@link SI} units, the 20 SI prefixes used to form decimal
+ * multiples and sub-multiples of SI units are recognized.
+ * {@link NonSI} units are directly recognized. For example:[code]
+ * Unit.valueOf("m°C").equals(SI.MILLI(SI.CELSIUS))
+ * Unit.valueOf("kW").equals(SI.KILO(SI.WATT))
+ * Unit.valueOf("ft").equals(SI.METRE.multiply(3048).divide(10000))[/code]</p>
+ *
+ * @author <a href="mailto:jean-marie at dautelle.com">Jean-Marie Dautelle</a>
+ * @author Eric Russell
+ * @version 1.0, April 15, 2009
+ */
+public abstract class UnitFormat extends Format {
+
+ /**
+ * Returns the unit format for the default locale.
+ *
+ * @return {@link LocalFormat#getInstance()}
+ */
+ public static UnitFormat getInstance() {
+ return LocalFormat.getInstance();
+ }
+
+ /**
+ * Returns the unit format for the specified locale.
+ *
+ * @param locale the locale for which the format is returned.
+ * @return {@link LocalFormat#getInstance(java.util.Locale)}
+ */
+ public static UnitFormat getInstance(Locale locale) {
+ return LocalFormat.getInstance(locale);
+ }
+
+ /**
+ * Returns the standard
+ * <a href="http://unitsofmeasure.org/">UCUM </a> unit format.
+ * This is the format used by {@link Unit#valueOf(CharSequence)
+ * Unit.valueOf(CharSequence)} and {@link Unit#toString() Unit.toString()}).
+ *
+ * <p> This format uses characters range <code>0000-007F</code> exclusively
+ * and <b>is not</b> locale-sensitive. For example: <code>kg.m/s2</code></p>
+ *
+ * <p>For a description of the UCUM format including BNF, see:
+ * <a href="http://aurora.regenstrief.org/~ucum/ucum.html">
+ * The Unified Code for Units of Measure</a></p>
+ *
+ * @return {@link UCUMFormat#getCaseSensitiveInstance()}
+ */
+ public static UnitFormat getStandard() {
+ return UCUMFormat.getCaseSensitiveInstance();
+ }
+
+ /**
+ * Base constructor.
+ */
+ protected UnitFormat() {
+ }
+
+ /**
+ * Formats the specified unit.
+ *
+ * @param unit the unit to format.
+ * @param appendable the appendable destination.
+ * @throws IOException if an error occurs.
+ */
+ public abstract Appendable format(Unit<?> unit, Appendable appendable)
+ throws IOException;
+
+ /**
+ * Parses a portion of the specified <code>CharSequence</code> from the
+ * specified position to produce a unit. If there is no unit to parse
+ * {@link Unit#ONE} is returned.
+ *
+ * @param csq the <code>CharSequence</code> to parse.
+ * @param cursor the cursor holding the current parsing index.
+ * @return the unit parsed from the specified character sub-sequence.
+ * @throws IllegalArgumentException if any problem occurs while parsing the
+ * specified character sequence (e.g. illegal syntax).
+ */
+ public abstract Unit<?> parse(CharSequence csq, ParsePosition cursor)
+ throws IllegalArgumentException;
+
+ @Override
+ public final StringBuffer format(Object obj, final StringBuffer toAppendTo,
+ FieldPosition pos) {
+ if (!(obj instanceof Unit))
+ throw new IllegalArgumentException("obj: Not an instance of Unit");
+ if ((toAppendTo == null) || (pos == null))
+ throw new NullPointerException(); // Format contract.
+ try {
+ return (StringBuffer) format((Unit<?>) obj, (Appendable) toAppendTo);
+ } catch (IOException ex) {
+ throw new Error(ex); // Cannot happen.
+ }
+ }
+
+ @Override
+ public final Unit<?> parseObject(String source, ParsePosition pos) {
+ try {
+ return parse(source, pos);
+ } catch (IllegalArgumentException e) {
+ return null; // Unfortunately the message why the parsing failed
+ } // is lost; but we have to follow the Format spec.
+
+ }
+
+ /**
+ * Convenience method equivalent to {@link #format(Unit, Appendable)}
+ * except it does not raise an IOException.
+ *
+ * @param unit the unit to format.
+ * @param dest the appendable destination.
+ * @return the specified <code>StringBuilder</code>.
+ */
+ public final StringBuilder format(Unit<?> unit, StringBuilder dest) {
+ try {
+ return (StringBuilder) this.format(unit, (Appendable) dest);
+ } catch (IOException ex) {
+ throw new Error(ex); // Can never happen.
+ }
+ }
+
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/src/main/java/javax/measure/unit/format/LocalFormat.java b/src/main/java/javax/measure/unit/format/LocalFormat.java
new file mode 100644
index 0000000..d43aedb
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/LocalFormat.java
@@ -0,0 +1,522 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit.format;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.math.BigInteger;
+import java.text.ParsePosition;
+import java.util.*;
+import java.util.ResourceBundle;
+import javax.measure.converter.*;
+import javax.measure.unit.*;
+
+/**
+ * <p> This class represents the local sensitive format.</p>
+ *
+ * <h3>Here is the grammar for Units in Extended Backus-Naur Form (EBNF)</h3>
+ * <p>
+ * Note that the grammar has been left-factored to be suitable for use by a top-down
+ * parser generator such as <a href="https://javacc.dev.java.net/">JavaCC</a>
+ * </p>
+ * <table width="90%" align="center">
+ * <tr>
+ * <th colspan="3" align="left">Lexical Entities:</th>
+ * </tr>
+ * <tr valign="top">
+ * <td><sign></td>
+ * <td>:=</td>
+ * <td>"+" | "-"</td>
+ * </tr>
+ * <tr valign="top">
+ * <td><digit></td>
+ * <td>:=</td>
+ * <td>"0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"</td>
+ * </tr>
+ * <tr valign="top">
+ * <td><superscript_digit></td>
+ * <td>:=</td>
+ * <td>"⁰" | "¹" | "²" | "³" | "⁴" | "⁵" | "⁶" | "⁷" | "⁸" | "⁹"</td>
+ * </tr>
+ * <tr valign="top">
+ * <td><integer></td>
+ * <td>:=</td>
+ * <td>(<digit>)+</td>
+ * </tr>
+ * <tr valign="top">
+ * <td><number></td>
+ * <td>:=</td>
+ * <td>(<sign>)? (<digit>)* (".")? (<digit>)+ (("e" | "E") (<sign>)? (<digit>)+)? </td>
+ * </tr>
+ * <tr valign="top">
+ * <td><exponent></td>
+ * <td>:=</td>
+ * <td>( "^" ( <sign> )? <integer> ) <br>| ( "^(" (<sign>)? <integer> ( "/" (<sign>)? <integer> )? ")" ) <br>| ( <superscript_digit> )+</td>
+ * </tr>
+ * <tr valign="top">
+ * <td><initial_char></td>
+ * <td>:=</td>
+ * <td>? Any Unicode character excluding the following: ASCII control & whitespace (\u0000 - \u0020), decimal digits '0'-'9', '(' (\u0028), ')' (\u0029), '*' (\u002A), '+' (\u002B), '-' (\u002D), '.' (\u002E), '/' (\u005C), ':' (\u003A), '^' (\u005E), '²' (\u00B2), '³' (\u00B3), '·' (\u00B7), '¹' (\u00B9), '⁰' (\u2070), '⁴' (\u2074), '⁵' (\u2075), '⁶' (\u2076), '⁷' (\u2077), '⁸' (\u2078), '⁹' (\u2 [...]
+ * </tr>
+ * <tr valign="top">
+ * <td><unit_identifier></td>
+ * <td>:=</td>
+ * <td><initial_char> ( <initial_char> | <digit> )*</td>
+ * </tr>
+ * <tr>
+ * <th colspan="3" align="left">Non-Terminals:</th>
+ * </tr>
+ * <tr valign="top">
+ * <td><unit_expr></td>
+ * <td>:=</td>
+ * <td><compound_expr></td>
+ * </tr>
+ * <tr valign="top">
+ * <td><compound_expr></td>
+ * <td>:=</td>
+ * <td><add_expr> ( ":" <add_expr> )*</td>
+ * </tr>
+ * <tr valign="top">
+ * <td><add_expr></td>
+ * <td>:=</td>
+ * <td>( <number> <sign> )? <mul_expr> ( <sign> <number> )?</td>
+ * </tr>
+ * <tr valign="top">
+ * <td><mul_expr></td>
+ * <td>:=</td>
+ * <td><exponent_expr> ( ( ( "*" | "·" ) <exponent_expr> ) | ( "/" <exponent_expr> ) )*</td>
+ * </tr>
+ * <tr valign="top">
+ * <td><exponent_expr></td>
+ * <td>:=</td>
+ * <td>( <atomic_expr> ( <exponent> )? ) <br>| (<integer> "^" <atomic_expr>) <br>| ( ( "log" ( <integer> )? ) | "ln" ) "(" <add_expr> ")" )</td>
+ * </tr>
+ * <tr valign="top">
+ * <td><atomic_expr></td>
+ * <td>:=</td>
+ * <td><number> <br>| <unit_identifier> <br>| ( "(" <add_expr> ")" )</td>
+ * </tr>
+ * </table>
+ *
+ * @author <a href="mailto:eric-r at northwestern.edu">Eric Russell</a>
+ * @version 1.0
+ */
+public class LocalFormat extends UnitFormat {
+
+ //////////////////////////////////////////////////////
+ // Class variables //
+ //////////////////////////////////////////////////////
+ /** Default locale instance. If the default locale is changed after the class is
+ initialized, this instance will no longer be used. */
+ private static LocalFormat DEFAULT_INSTANCE = new LocalFormat(new SymbolMap(ResourceBundle.getBundle("javax.measure.unit.format.LocalFormat")));
+ /** Multiplicand character */
+ private static final char MIDDLE_DOT = '\u00b7';
+ /** Operator precedence for the addition and subtraction operations */
+ private static final int ADDITION_PRECEDENCE = 0;
+ /** Operator precedence for the multiplication and division operations */
+ private static final int PRODUCT_PRECEDENCE = ADDITION_PRECEDENCE + 2;
+ /** Operator precedence for the exponentiation and logarithm operations */
+ private static final int EXPONENT_PRECEDENCE = PRODUCT_PRECEDENCE + 2;
+ /**
+ * Operator precedence for a unit identifier containing no mathematical
+ * operations (i.e., consisting exclusively of an identifier and possibly
+ * a prefix). Defined to be <code>Integer.MAX_VALUE</code> so that no
+ * operator can have a higher precedence.
+ */
+ private static final int NOOP_PRECEDENCE = Integer.MAX_VALUE;
+
+ ///////////////////
+ // Class methods //
+ ///////////////////
+ /** Returns the instance for the current default locale (non-ascii characters are allowed) */
+ public static LocalFormat getInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ /**
+ * Returns an instance for the given locale.
+ * @param locale
+ */
+ public static LocalFormat getInstance(Locale locale) {
+ return new LocalFormat(new SymbolMap(ResourceBundle.getBundle("javax.measure.unit.format.LocalFormat", locale)));
+ }
+
+ /** Returns an instance for the given symbol map. */
+ public static LocalFormat getInstance(SymbolMap symbols) {
+ return new LocalFormat(symbols);
+ }
+ ////////////////////////
+ // Instance variables //
+ ////////////////////////
+ /**
+ * The symbol map used by this instance to map between
+ * {@link javax.measure.unit.Unit Unit}s and <code>String</code>s, etc...
+ */
+ private SymbolMap _symbolMap;
+
+ //////////////////
+ // Constructors //
+ //////////////////
+ /**
+ * Base constructor.
+ *
+ * @param symbols the symbol mapping.
+ */
+ private LocalFormat(SymbolMap symbols) {
+ _symbolMap = symbols;
+ }
+
+ ////////////////////////
+ // Instance methods //
+ ////////////////////////
+ /**
+ * Get the symbol map used by this instance to map between
+ * {@link javax.measure.unit.Unit Unit}s and <code>String</code>s, etc...
+ * @return SymbolMap the current symbol map
+ */
+ public SymbolMap getSymbols() {
+ return _symbolMap;
+ }
+
+ ////////////////
+ // Formatting //
+ ////////////////
+ @Override
+ public Appendable format(Unit<?> unit, Appendable appendable) throws IOException {
+ formatInternal(unit, appendable);
+ return appendable;
+ }
+
+ @Override
+ public Unit<?> parse(CharSequence csq, ParsePosition cursor) throws IllegalArgumentException {
+ // Parsing reads the whole character sequence from the parse position.
+ int start = cursor.getIndex();
+ int end = csq.length();
+ if (end <= start) {
+ return Unit.ONE;
+ }
+ String source = csq.subSequence(start, end).toString().trim();
+ if (source.length() == 0) {
+ return Unit.ONE;
+ }
+ try {
+ UnitParser parser = new UnitParser(_symbolMap, new StringReader(source));
+ Unit<?> result = parser.parseUnit();
+ cursor.setIndex(end);
+ return result;
+ } catch (ParseException e) {
+ if (e.currentToken != null) {
+ cursor.setErrorIndex(start + e.currentToken.endColumn);
+ } else {
+ cursor.setErrorIndex(start);
+ }
+ throw new IllegalArgumentException(e.getMessage());
+ } catch (TokenMgrError e) {
+ cursor.setErrorIndex(start);
+ throw new IllegalArgumentException(e.getMessage());
+ }
+ }
+
+ /**
+ * Format the given unit to the given StringBuffer, then return the operator
+ * precedence of the outermost operator in the unit expression that was
+ * formatted. See {@link ConverterFormat} for the constants that define the
+ * various precedence values.
+ * @param unit the unit to be formatted
+ * @param buffer the <code>StringBuffer</code> to be written to
+ * @return the operator precedence of the outermost operator in the unit
+ * expression that was output
+ */
+ private int formatInternal(Unit<?> unit, Appendable buffer) throws IOException {
+ if (unit instanceof AnnotatedUnit) {
+ unit = ((AnnotatedUnit<?>) unit).getRealUnit();
+ }
+ String symbol = _symbolMap.getSymbol(unit);
+ if (symbol != null) {
+ buffer.append(symbol);
+ return NOOP_PRECEDENCE;
+ } else if (unit instanceof ProductUnit) {
+ ProductUnit<?> productUnit = (ProductUnit<?>) unit;
+ int negativeExponentCount = 0;
+ // Write positive exponents first...
+ boolean start = true;
+ for (int i = 0; i < productUnit.getUnitCount(); i += 1) {
+ int pow = productUnit.getUnitPow(i);
+ if (pow >= 0) {
+ formatExponent(productUnit.getUnit(i), pow, productUnit.getUnitRoot(i), !start, buffer);
+ start = false;
+ } else {
+ negativeExponentCount += 1;
+ }
+ }
+ // ..then write negative exponents.
+ if (negativeExponentCount > 0) {
+ if (start) {
+ buffer.append('1');
+ }
+ buffer.append('/');
+ if (negativeExponentCount > 1) {
+ buffer.append('(');
+ }
+ start = true;
+ for (int i = 0; i < productUnit.getUnitCount(); i += 1) {
+ int pow = productUnit.getUnitPow(i);
+ if (pow < 0) {
+ formatExponent(productUnit.getUnit(i), -pow, productUnit.getUnitRoot(i), !start, buffer);
+ start = false;
+ }
+ }
+ if (negativeExponentCount > 1) {
+ buffer.append(')');
+ }
+ }
+ return PRODUCT_PRECEDENCE;
+ } else if ((unit instanceof TransformedUnit) || unit.equals(SI.KILOGRAM)) {
+ UnitConverter converter = null;
+ boolean printSeparator = false;
+ StringBuffer temp = new StringBuffer();
+ int unitPrecedence = NOOP_PRECEDENCE;
+ if (unit.equals(SI.KILOGRAM)) {
+ // A special case because KILOGRAM is a BaseUnit instead of
+ // a transformed unit, even though it has a prefix.
+ converter = Prefix.KILO.getConverter();
+ unitPrecedence = formatInternal(SI.GRAM, temp);
+ printSeparator = true;
+ } else {
+ TransformedUnit<?> transformedUnit = (TransformedUnit<?>) unit;
+ Unit<?> parentUnits = transformedUnit.getParentUnit();
+ converter = transformedUnit.toParentUnit();
+ if (parentUnits.equals(SI.KILOGRAM)) {
+ // More special-case hackery to work around gram/kilogram
+ // incosistency
+ parentUnits = SI.GRAM;
+ converter = converter.concatenate(Prefix.KILO.getConverter());
+ }
+ unitPrecedence = formatInternal(parentUnits, temp);
+ printSeparator = !parentUnits.equals(Unit.ONE);
+ }
+ int result = formatConverter(converter, printSeparator, unitPrecedence, temp);
+ buffer.append(temp);
+ return result;
+ } else if (unit instanceof AlternateUnit) {
+ buffer.append(((AlternateUnit<?>) unit).getSymbol());
+ return NOOP_PRECEDENCE;
+ } else if (unit instanceof BaseUnit) {
+ buffer.append(((BaseUnit<?>) unit).getSymbol());
+ return NOOP_PRECEDENCE;
+ } else {
+ throw new IllegalArgumentException("Cannot format the given Object as a Unit (unsupported unit type " + unit.getClass().getName() + ")");
+ }
+ }
+
+ /**
+ * Format the given unit raised to the given fractional power to the
+ * given <code>StringBuffer</code>.
+ * @param unit Unit the unit to be formatted
+ * @param pow int the numerator of the fractional power
+ * @param root int the denominator of the fractional power
+ * @param continued boolean <code>true</code> if the converter expression
+ * should begin with an operator, otherwise <code>false</code>. This will
+ * always be true unless the unit being modified is equal to Unit.ONE.
+ * @param buffer StringBuffer the buffer to append to. No assumptions should
+ * be made about its content.
+ */
+ private void formatExponent(Unit<?> unit, int pow, int root, boolean continued, Appendable buffer) throws IOException {
+ if (continued) {
+ buffer.append(MIDDLE_DOT);
+ }
+ StringBuffer temp = new StringBuffer();
+ int unitPrecedence = formatInternal(unit, temp);
+ if (unitPrecedence < PRODUCT_PRECEDENCE) {
+ temp.insert(0, '(');
+ temp.append(')');
+ }
+ buffer.append(temp);
+ if ((root == 1) && (pow == 1)) {
+ // do nothing
+ } else if ((root == 1) && (pow > 1)) {
+ String powStr = Integer.toString(pow);
+ for (int i = 0; i < powStr.length(); i += 1) {
+ char c = powStr.charAt(i);
+ switch (c) {
+ case '0':
+ buffer.append('\u2070');
+ break;
+ case '1':
+ buffer.append('\u00b9');
+ break;
+ case '2':
+ buffer.append('\u00b2');
+ break;
+ case '3':
+ buffer.append('\u00b3');
+ break;
+ case '4':
+ buffer.append('\u2074');
+ break;
+ case '5':
+ buffer.append('\u2075');
+ break;
+ case '6':
+ buffer.append('\u2076');
+ break;
+ case '7':
+ buffer.append('\u2077');
+ break;
+ case '8':
+ buffer.append('\u2078');
+ break;
+ case '9':
+ buffer.append('\u2079');
+ break;
+ }
+ }
+ } else if (root == 1) {
+ buffer.append("^");
+ buffer.append(String.valueOf(pow));
+ } else {
+ buffer.append("^(");
+ buffer.append(String.valueOf(pow));
+ buffer.append('/');
+ buffer.append(String.valueOf(root));
+ buffer.append(')');
+ }
+ }
+
+ /**
+ * Formats the given converter to the given StringBuffer and returns the
+ * operator precedence of the converter's mathematical operation. This is
+ * the default implementation, which supports all built-in UnitConverter
+ * implementations. Note that it recursively calls itself in the case of
+ * a {@link javax.measure.converter.UnitConverter.Compound Compound}
+ * converter.
+ * @param converter the converter to be formatted
+ * @param continued <code>true</code> if the converter expression should
+ * begin with an operator, otherwise <code>false</code>.
+ * @param unitPrecedence the operator precedence of the operation expressed
+ * by the unit being modified by the given converter.
+ * @param buffer the <code>StringBuffer</code> to append to.
+ * @return the operator precedence of the given UnitConverter
+ */
+ private int formatConverter(UnitConverter converter,
+ boolean continued,
+ int unitPrecedence,
+ StringBuffer buffer) {
+ Prefix prefix = _symbolMap.getPrefix(converter);
+ if ((prefix != null) && (unitPrecedence == NOOP_PRECEDENCE)) {
+ buffer.insert(0, _symbolMap.getSymbol(prefix));
+ return NOOP_PRECEDENCE;
+ } else if (converter instanceof AddConverter) {
+ if (unitPrecedence < ADDITION_PRECEDENCE) {
+ buffer.insert(0, '(');
+ buffer.append(')');
+ }
+ double offset = ((AddConverter) converter).getOffset();
+ if (offset < 0) {
+ buffer.append("-");
+ offset = -offset;
+ } else if (continued) {
+ buffer.append("+");
+ }
+ long lOffset = (long) offset;
+ if (lOffset == offset) {
+ buffer.append(lOffset);
+ } else {
+ buffer.append(offset);
+ }
+ return ADDITION_PRECEDENCE;
+ } else if (converter instanceof LogConverter) {
+ double base = ((LogConverter) converter).getBase();
+ StringBuffer expr = new StringBuffer();
+ if (base == StrictMath.E) {
+ expr.append("ln");
+ } else {
+ expr.append("log");
+ if (base != 10) {
+ expr.append((int) base);
+ }
+ }
+ expr.append("(");
+ buffer.insert(0, expr);
+ buffer.append(")");
+ return EXPONENT_PRECEDENCE;
+ } else if (converter instanceof ExpConverter) {
+ if (unitPrecedence < EXPONENT_PRECEDENCE) {
+ buffer.insert(0, '(');
+ buffer.append(')');
+ }
+ StringBuffer expr = new StringBuffer();
+ double base = ((ExpConverter) converter).getBase();
+ if (base == StrictMath.E) {
+ expr.append('e');
+ } else {
+ expr.append((int) base);
+ }
+ expr.append('^');
+ buffer.insert(0, expr);
+ return EXPONENT_PRECEDENCE;
+ } else if (converter instanceof MultiplyConverter) {
+ if (unitPrecedence < PRODUCT_PRECEDENCE) {
+ buffer.insert(0, '(');
+ buffer.append(')');
+ }
+ if (continued) {
+ buffer.append(MIDDLE_DOT);
+ }
+ double factor = ((MultiplyConverter) converter).getFactor();
+ long lFactor = (long) factor;
+ if (lFactor == factor) {
+ buffer.append(lFactor);
+ } else {
+ buffer.append(factor);
+ }
+ return PRODUCT_PRECEDENCE;
+ } else if (converter instanceof RationalConverter) {
+ if (unitPrecedence < PRODUCT_PRECEDENCE) {
+ buffer.insert(0, '(');
+ buffer.append(')');
+ }
+ RationalConverter rationalConverter = (RationalConverter) converter;
+ if (!rationalConverter.getDividend().equals(BigInteger.ONE)) {
+ if (continued) {
+ buffer.append(MIDDLE_DOT);
+ }
+ buffer.append(rationalConverter.getDividend());
+ }
+ if (!rationalConverter.getDivisor().equals(BigInteger.ONE)) {
+ buffer.append('/');
+ buffer.append(rationalConverter.getDivisor());
+ }
+ return PRODUCT_PRECEDENCE;
+ } else {
+ throw new IllegalArgumentException("Unable to format the given UnitConverter: " + converter.getClass());
+ }
+ }
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/src/main/java/javax/measure/unit/format/LocalFormat.properties b/src/main/java/javax/measure/unit/format/LocalFormat.properties
new file mode 100644
index 0000000..cee0ac3
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/LocalFormat.properties
@@ -0,0 +1,139 @@
+# NOTE: as a Java properties file, this file must use the
+# ISO 8859-1 encoding, so all non-ASCII Unicode characters
+# must be escaped using the \uXXXX syntax.
+# See http://java.sun.com/j2se/1.5.0/docs/api/java/util/Properties.html#encoding
+
+# SI Prefixes
+
+javax.measure.unit.format.Prefix.YOTTA=Y
+javax.measure.unit.format.Prefix.ZETTA=Z
+javax.measure.unit.format.Prefix.EXA=E
+javax.measure.unit.format.Prefix.PETA=P
+javax.measure.unit.format.Prefix.TERA=T
+javax.measure.unit.format.Prefix.GIGA=G
+javax.measure.unit.format.Prefix.MEGA=M
+javax.measure.unit.format.Prefix.KILO=k
+javax.measure.unit.format.Prefix.HECTO=h
+javax.measure.unit.format.Prefix.DEKA=da
+javax.measure.unit.format.Prefix.DECI=d
+javax.measure.unit.format.Prefix.CENTI=c
+javax.measure.unit.format.Prefix.MILLI=m
+javax.measure.unit.format.Prefix.MICRO=\u00B5
+javax.measure.unit.format.Prefix.NANO=n
+javax.measure.unit.format.Prefix.PICO=p
+javax.measure.unit.format.Prefix.FEMTO=f
+javax.measure.unit.format.Prefix.ATTO=a
+javax.measure.unit.format.Prefix.ZEPTO=z
+javax.measure.unit.format.Prefix.YOCTO=y
+
+# SI Units
+
+javax.measure.unit.SI.AMPERE=A
+javax.measure.unit.SI.BECQUEREL=Bq
+javax.measure.unit.SI.CANDELA=cd
+javax.measure.unit.SI.CELSIUS=\u00B0C
+javax.measure.unit.SI.CELSIUS.1=\u2103
+javax.measure.unit.SI.CELSIUS.2=Celsius
+javax.measure.unit.SI.COULOMB=C
+javax.measure.unit.SI.FARAD=F
+javax.measure.unit.SI.GRAM=g
+javax.measure.unit.SI.GRAY=Gy
+javax.measure.unit.SI.HENRY=H
+javax.measure.unit.SI.HERTZ=Hz
+javax.measure.unit.SI.JOULE=J
+javax.measure.unit.SI.KATAL=kat
+javax.measure.unit.SI.KELVIN=K
+javax.measure.unit.SI.LUMEN=lm
+javax.measure.unit.SI.LUX=lx
+javax.measure.unit.SI.METRE=m
+javax.measure.unit.SI.MOLE=mol
+javax.measure.unit.SI.NEWTON=N
+javax.measure.unit.SI.OHM=\u03A9
+javax.measure.unit.SI.PASCAL=Pa
+javax.measure.unit.SI.RADIAN=rad
+javax.measure.unit.SI.SECOND=s
+javax.measure.unit.SI.SIEMENS=S
+javax.measure.unit.SI.SIEVERT=Sv
+javax.measure.unit.SI.STERADIAN=sr
+javax.measure.unit.SI.TESLA=T
+javax.measure.unit.SI.VOLT=V
+javax.measure.unit.SI.WATT=W
+javax.measure.unit.SI.WEBER=Wb
+
+# Non-SI Units
+
+javax.measure.unit.NonSI.PERCENT=%
+javax.measure.unit.NonSI.DECIBEL=dB
+javax.measure.unit.NonSI.G=grav
+javax.measure.unit.NonSI.ATOM=atom
+javax.measure.unit.NonSI.REVOLUTION=rev
+javax.measure.unit.NonSI.DEGREE_ANGLE=\u00B0
+javax.measure.unit.NonSI.MINUTE_ANGLE='
+javax.measure.unit.NonSI.SECOND_ANGLE="
+javax.measure.unit.NonSI.CENTIRADIAN=centiradian
+javax.measure.unit.NonSI.GRADE=grade
+javax.measure.unit.NonSI.ARE=a
+javax.measure.unit.NonSI.HECTARE=ha
+javax.measure.unit.NonSI.BYTE=byte
+javax.measure.unit.NonSI.MINUTE=min
+javax.measure.unit.NonSI.HOUR=h
+javax.measure.unit.NonSI.DAY=day
+javax.measure.unit.NonSI.WEEK=week
+javax.measure.unit.NonSI.DAY_SIDEREAL=day_sidereal
+javax.measure.unit.NonSI.YEAR_SIDEREAL=year_sidereal
+javax.measure.unit.NonSI.YEAR_CALENDAR=year
+javax.measure.unit.NonSI.E=e
+javax.measure.unit.NonSI.FARADAY=Fd
+javax.measure.unit.NonSI.FRANKLIN=Fr
+javax.measure.unit.NonSI.GILBERT=Gi
+javax.measure.unit.NonSI.ERG=erg
+javax.measure.unit.NonSI.ELECTRON_VOLT=eV
+javax.measure.unit.NonSI.LAMBERT=La
+javax.measure.unit.NonSI.FOOT=ft
+javax.measure.unit.NonSI.FOOT_SURVEY_US=foot_survey_us
+javax.measure.unit.NonSI.YARD=yd
+javax.measure.unit.NonSI.INCH=in
+javax.measure.unit.NonSI.MILE=mi
+javax.measure.unit.NonSI.NAUTICAL_MILE=nmi
+javax.measure.unit.NonSI.MILES_PER_HOUR=mph
+javax.measure.unit.NonSI.ANGSTROM=\u00C5
+javax.measure.unit.NonSI.ASTRONOMICAL_UNIT=ua
+javax.measure.unit.NonSI.LIGHT_YEAR=ly
+javax.measure.unit.NonSI.PARSEC=pc
+javax.measure.unit.NonSI.POINT=pt
+javax.measure.unit.NonSI.PIXEL=pixel
+javax.measure.unit.NonSI.MAXWELL=Mx
+javax.measure.unit.NonSI.GAUSS=G
+javax.measure.unit.NonSI.ATOMIC_MASS=u
+javax.measure.unit.NonSI.ELECTRON_MASS=me
+javax.measure.unit.NonSI.POUND=lb
+javax.measure.unit.NonSI.OUNCE=oz
+javax.measure.unit.NonSI.TON_US=ton_us
+javax.measure.unit.NonSI.TON_UK=ton_uk
+javax.measure.unit.NonSI.METRIC_TON=t
+javax.measure.unit.NonSI.DYNE=dyn
+javax.measure.unit.NonSI.KILOGRAM_FORCE=kgf
+javax.measure.unit.NonSI.POUND_FORCE=lbf
+javax.measure.unit.NonSI.HORSEPOWER=hp
+javax.measure.unit.NonSI.ATMOSPHERE=atm
+javax.measure.unit.NonSI.BAR=bar
+javax.measure.unit.NonSI.MILLIMETER_OF_MERCURY=mmHg
+javax.measure.unit.NonSI.INCH_OF_MERCURY=inHg
+javax.measure.unit.NonSI.RAD=rd
+javax.measure.unit.NonSI.REM=rem
+javax.measure.unit.NonSI.CURIE=Ci
+javax.measure.unit.NonSI.RUTHERFORD=Rd
+javax.measure.unit.NonSI.SPHERE=sphere
+javax.measure.unit.NonSI.RANKINE=\u00B0R
+javax.measure.unit.NonSI.FAHRENHEIT=\u00B0F
+javax.measure.unit.NonSI.FAHRENHEIT.1=\u2109
+javax.measure.unit.NonSI.KNOT=kn
+javax.measure.unit.NonSI.C=c
+javax.measure.unit.NonSI.LITRE=L
+javax.measure.unit.NonSI.GALLON_LIQUID_US=gal
+javax.measure.unit.NonSI.OUNCE_LIQUID_US=oz
+javax.measure.unit.NonSI.GALLON_DRY_US=gallon_dry_us
+javax.measure.unit.NonSI.GALLON_UK=gallon_uk
+javax.measure.unit.NonSI.OUNCE_LIQUID_UK=oz_uk
+javax.measure.unit.NonSI.ROENTGEN=Roentgen
+javax.measure.unit.NonSI.PI=\u03C0
diff --git a/src/main/java/javax/measure/unit/format/LocalFormat_de.properties b/src/main/java/javax/measure/unit/format/LocalFormat_de.properties
new file mode 100644
index 0000000..925ced9
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/LocalFormat_de.properties
@@ -0,0 +1,21 @@
+#Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net)
+#$Id: LocalFormat_de.properties,v 1.1 2009/06/13 22:40:18 dautelle Exp $
+javax.measure.unit.NonSI.DAY = tag
+javax.measure.unit.NonSI.DAY_SIDEREAL = tag_sidereal
+javax.measure.unit.NonSI.FOOT_SURVEY_US = fu\u00DF_survey_us
+javax.measure.unit.NonSI.GALLON_DRY_US = gallone_trocken_us
+javax.measure.unit.NonSI.GALLON_UK = gallone_uk
+javax.measure.unit.NonSI.GRADE = grad
+javax.measure.unit.NonSI.HORSEPOWER = ps
+javax.measure.unit.NonSI.LIGHT_YEAR = lj
+javax.measure.unit.NonSI.MILES_PER_HOUR = mps
+javax.measure.unit.NonSI.OUNCE = uz
+javax.measure.unit.NonSI.OUNCE_LIQUID_UK = uz_uk
+javax.measure.unit.NonSI.OUNCE_LIQUID_US = uz
+javax.measure.unit.NonSI.POINT = pkt
+javax.measure.unit.NonSI.ROENTGEN = R\u00F6ntgen
+javax.measure.unit.NonSI.TON_UK = tonne_uk
+javax.measure.unit.NonSI.TON_US = tonne_us
+javax.measure.unit.NonSI.WEEK = woche
+javax.measure.unit.NonSI.YEAR_CALENDAR = jahr
+javax.measure.unit.NonSI.YEAR_SIDEREAL = jahr_sidereal
diff --git a/src/main/java/javax/measure/unit/format/LocalFormat_en_GB.properties b/src/main/java/javax/measure/unit/format/LocalFormat_en_GB.properties
new file mode 100644
index 0000000..182fb3d
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/LocalFormat_en_GB.properties
@@ -0,0 +1,4 @@
+javax.measure.unit.NonSI.GALLON_UK=gal
+javax.measure.unit.NonSI.OUNCE_LIQUID_UK=oz
+javax.measure.unit.NonSI.GALLON_LIQUID_US=gal_us
+javax.measure.unit.NonSI.OUNCE_LIQUID_US=oz_us
diff --git a/src/main/java/javax/measure/unit/format/ParseException.java b/src/main/java/javax/measure/unit/format/ParseException.java
new file mode 100644
index 0000000..05e12b1
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/ParseException.java
@@ -0,0 +1,192 @@
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */
+package javax.measure.unit.format;
+
+/**
+ * This exception is thrown when parse errors are encountered.
+ * You can explicitly create objects of this exception type by
+ * calling the method generateParseException in the generated
+ * parser.
+ *
+ * You can modify this class to customize your error reporting
+ * mechanisms so long as you retain the public fields.
+ */
+class ParseException extends Exception {
+
+ /**
+ * This constructor is used by the method "generateParseException"
+ * in the generated parser. Calling this constructor generates
+ * a new object of this type with the fields "currentToken",
+ * "expectedTokenSequences", and "tokenImage" set. The boolean
+ * flag "specialConstructor" is also set to true to indicate that
+ * this constructor was used to create this object.
+ * This constructor calls its super class with the empty string
+ * to force the "toString" method of parent class "Throwable" to
+ * print the error message in the form:
+ * ParseException: <result of getMessage>
+ */
+ public ParseException(Token currentTokenVal,
+ int[][] expectedTokenSequencesVal,
+ String[] tokenImageVal
+ )
+ {
+ super("");
+ specialConstructor = true;
+ currentToken = currentTokenVal;
+ expectedTokenSequences = expectedTokenSequencesVal;
+ tokenImage = tokenImageVal;
+ }
+
+ /**
+ * The following constructors are for use by you for whatever
+ * purpose you can think of. Constructing the exception in this
+ * manner makes the exception behave in the normal way - i.e., as
+ * documented in the class "Throwable". The fields "errorToken",
+ * "expectedTokenSequences", and "tokenImage" do not contain
+ * relevant information. The JavaCC generated code does not use
+ * these constructors.
+ */
+
+ public ParseException() {
+ super();
+ specialConstructor = false;
+ }
+
+ public ParseException(String message) {
+ super(message);
+ specialConstructor = false;
+ }
+
+ /**
+ * This variable determines which constructor was used to create
+ * this object and thereby affects the semantics of the
+ * "getMessage" method (see below).
+ */
+ protected boolean specialConstructor;
+
+ /**
+ * This is the last token that has been consumed successfully. If
+ * this object has been created due to a parse error, the token
+ * followng this token will (therefore) be the first error token.
+ */
+ public Token currentToken;
+
+ /**
+ * Each entry in this array is an array of integers. Each array
+ * of integers represents a sequence of tokens (by their ordinal
+ * values) that is expected at this point of the parse.
+ */
+ public int[][] expectedTokenSequences;
+
+ /**
+ * This is a reference to the "tokenImage" array of the generated
+ * parser within which the parse error occurred. This array is
+ * defined in the generated ...Constants interface.
+ */
+ public String[] tokenImage;
+
+ /**
+ * This method has the standard behavior when this object has been
+ * created using the standard constructors. Otherwise, it uses
+ * "currentToken" and "expectedTokenSequences" to generate a parse
+ * error message and returns it. If this object has been created
+ * due to a parse error, and you do not catch it (it gets thrown
+ * from the parser), then this method is called during the printing
+ * of the final stack trace, and hence the correct error message
+ * gets displayed.
+ */
+ public String getMessage() {
+ if (!specialConstructor) {
+ return super.getMessage();
+ }
+ StringBuffer expected = new StringBuffer();
+ int maxSize = 0;
+ for (int i = 0; i < expectedTokenSequences.length; i++) {
+ if (maxSize < expectedTokenSequences[i].length) {
+ maxSize = expectedTokenSequences[i].length;
+ }
+ for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+ expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" ");
+ }
+ if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+ expected.append("...");
+ }
+ expected.append(eol).append(" ");
+ }
+ String retval = "Encountered \"";
+ Token tok = currentToken.next;
+ for (int i = 0; i < maxSize; i++) {
+ if (i != 0) retval += " ";
+ if (tok.kind == 0) {
+ retval += tokenImage[0];
+ break;
+ }
+ retval += add_escapes(tok.image);
+ tok = tok.next;
+ }
+ retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+ retval += "." + eol;
+ if (expectedTokenSequences.length == 1) {
+ retval += "Was expecting:" + eol + " ";
+ } else {
+ retval += "Was expecting one of:" + eol + " ";
+ }
+ retval += expected.toString();
+ return retval;
+ }
+
+ /**
+ * The end of line string for this machine.
+ */
+ protected String eol = System.getProperty("line.separator", "\n");
+
+ /**
+ * Used to convert raw characters to their escaped version
+ * when these raw version cannot be used as part of an ASCII
+ * string literal.
+ */
+ protected String add_escapes(String str) {
+ StringBuffer retval = new StringBuffer();
+ char ch;
+ for (int i = 0; i < str.length(); i++) {
+ switch (str.charAt(i))
+ {
+ case 0 :
+ continue;
+ case '\b':
+ retval.append("\\b");
+ continue;
+ case '\t':
+ retval.append("\\t");
+ continue;
+ case '\n':
+ retval.append("\\n");
+ continue;
+ case '\f':
+ retval.append("\\f");
+ continue;
+ case '\r':
+ retval.append("\\r");
+ continue;
+ case '\"':
+ retval.append("\\\"");
+ continue;
+ case '\'':
+ retval.append("\\\'");
+ continue;
+ case '\\':
+ retval.append("\\\\");
+ continue;
+ default:
+ if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+ String s = "0000" + Integer.toString(ch, 16);
+ retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+ } else {
+ retval.append(ch);
+ }
+ continue;
+ }
+ }
+ return retval.toString();
+ }
+
+}
diff --git a/src/main/java/javax/measure/unit/format/Prefix.java b/src/main/java/javax/measure/unit/format/Prefix.java
new file mode 100644
index 0000000..99c39b2
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/Prefix.java
@@ -0,0 +1,81 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit.format;
+
+import java.math.BigInteger;
+import javax.measure.converter.UnitConverter;
+import javax.measure.converter.RationalConverter;
+
+/**
+ * This class represents the prefixes recognized when parsing/formatting.
+ *
+ * @version 1.0
+ */
+enum Prefix {
+
+ YOTTA(new RationalConverter(BigInteger.TEN.pow(24), BigInteger.ONE)),
+ ZETTA(new RationalConverter(BigInteger.TEN.pow(21), BigInteger.ONE)),
+ EXA(new RationalConverter(BigInteger.TEN.pow(18), BigInteger.ONE)),
+ PETA(new RationalConverter(BigInteger.TEN.pow(15), BigInteger.ONE)),
+ TERA(new RationalConverter(BigInteger.TEN.pow(12), BigInteger.ONE)),
+ GIGA(new RationalConverter(BigInteger.TEN.pow(9), BigInteger.ONE)),
+ MEGA(new RationalConverter(BigInteger.TEN.pow(6), BigInteger.ONE)),
+ KILO(new RationalConverter(BigInteger.TEN.pow(3), BigInteger.ONE)),
+ HECTO(new RationalConverter(BigInteger.TEN.pow(2), BigInteger.ONE)),
+ DEKA(new RationalConverter(BigInteger.TEN.pow(1), BigInteger.ONE)),
+ DECI(new RationalConverter( BigInteger.ONE, BigInteger.TEN.pow(1))),
+ CENTI(new RationalConverter( BigInteger.ONE, BigInteger.TEN.pow(2))),
+ MILLI(new RationalConverter( BigInteger.ONE, BigInteger.TEN.pow(3))),
+ MICRO(new RationalConverter( BigInteger.ONE, BigInteger.TEN.pow(6))),
+ NANO(new RationalConverter( BigInteger.ONE, BigInteger.TEN.pow(9))),
+ PICO(new RationalConverter( BigInteger.ONE, BigInteger.TEN.pow(12))),
+ FEMTO(new RationalConverter( BigInteger.ONE, BigInteger.TEN.pow(15))),
+ ATTO(new RationalConverter( BigInteger.ONE, BigInteger.TEN.pow(18))),
+ ZEPTO(new RationalConverter( BigInteger.ONE, BigInteger.TEN.pow(21))),
+ YOCTO(new RationalConverter( BigInteger.ONE, BigInteger.TEN.pow(24)));
+
+ private final UnitConverter _converter;
+
+ /**
+ * Creates a new prefix.
+ *
+ * @param converter the associated unit converter.
+ */
+ Prefix (UnitConverter converter) {
+ _converter = converter;
+ }
+
+ /**
+ * Returns the corresponding unit converter.
+ *
+ * @return the unit converter.
+ */
+ public UnitConverter getConverter() {
+ return _converter;
+ }
+}
diff --git a/src/main/java/javax/measure/unit/format/SimpleCharStream.java b/src/main/java/javax/measure/unit/format/SimpleCharStream.java
new file mode 100644
index 0000000..878d272
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/SimpleCharStream.java
@@ -0,0 +1,439 @@
+/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.0 */
+package javax.measure.unit.format;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (without unicode processing).
+ */
+
+class SimpleCharStream
+{
+ public static final boolean staticFlag = false;
+ int bufsize;
+ int available;
+ int tokenBegin;
+ public int bufpos = -1;
+ protected int bufline[];
+ protected int bufcolumn[];
+
+ protected int column = 0;
+ protected int line = 1;
+
+ protected boolean prevCharIsCR = false;
+ protected boolean prevCharIsLF = false;
+
+ protected java.io.Reader inputStream;
+
+ protected char[] buffer;
+ protected int maxNextCharInd = 0;
+ protected int inBuf = 0;
+ protected int tabSize = 8;
+
+ protected void setTabSize(int i) { tabSize = i; }
+ protected int getTabSize(int i) { return tabSize; }
+
+
+ protected void ExpandBuff(boolean wrapAround)
+ {
+ char[] newbuffer = new char[bufsize + 2048];
+ int newbufline[] = new int[bufsize + 2048];
+ int newbufcolumn[] = new int[bufsize + 2048];
+
+ try
+ {
+ if (wrapAround)
+ {
+ System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+ System.arraycopy(buffer, 0, newbuffer,
+ bufsize - tokenBegin, bufpos);
+ buffer = newbuffer;
+
+ System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+ System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+ bufline = newbufline;
+
+ System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+ System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+ bufcolumn = newbufcolumn;
+
+ maxNextCharInd = (bufpos += (bufsize - tokenBegin));
+ }
+ else
+ {
+ System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+ buffer = newbuffer;
+
+ System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+ bufline = newbufline;
+
+ System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+ bufcolumn = newbufcolumn;
+
+ maxNextCharInd = (bufpos -= tokenBegin);
+ }
+ }
+ catch (Throwable t)
+ {
+ throw new Error(t.getMessage());
+ }
+
+
+ bufsize += 2048;
+ available = bufsize;
+ tokenBegin = 0;
+ }
+
+ protected void FillBuff() throws java.io.IOException
+ {
+ if (maxNextCharInd == available)
+ {
+ if (available == bufsize)
+ {
+ if (tokenBegin > 2048)
+ {
+ bufpos = maxNextCharInd = 0;
+ available = tokenBegin;
+ }
+ else if (tokenBegin < 0)
+ bufpos = maxNextCharInd = 0;
+ else
+ ExpandBuff(false);
+ }
+ else if (available > tokenBegin)
+ available = bufsize;
+ else if ((tokenBegin - available) < 2048)
+ ExpandBuff(true);
+ else
+ available = tokenBegin;
+ }
+
+ int i;
+ try {
+ if ((i = inputStream.read(buffer, maxNextCharInd,
+ available - maxNextCharInd)) == -1)
+ {
+ inputStream.close();
+ throw new java.io.IOException();
+ }
+ else
+ maxNextCharInd += i;
+ return;
+ }
+ catch(java.io.IOException e) {
+ --bufpos;
+ backup(0);
+ if (tokenBegin == -1)
+ tokenBegin = bufpos;
+ throw e;
+ }
+ }
+
+ public char BeginToken() throws java.io.IOException
+ {
+ tokenBegin = -1;
+ char c = readChar();
+ tokenBegin = bufpos;
+
+ return c;
+ }
+
+ protected void UpdateLineColumn(char c)
+ {
+ column++;
+
+ if (prevCharIsLF)
+ {
+ prevCharIsLF = false;
+ line += (column = 1);
+ }
+ else if (prevCharIsCR)
+ {
+ prevCharIsCR = false;
+ if (c == '\n')
+ {
+ prevCharIsLF = true;
+ }
+ else
+ line += (column = 1);
+ }
+
+ switch (c)
+ {
+ case '\r' :
+ prevCharIsCR = true;
+ break;
+ case '\n' :
+ prevCharIsLF = true;
+ break;
+ case '\t' :
+ column--;
+ column += (tabSize - (column % tabSize));
+ break;
+ default :
+ break;
+ }
+
+ bufline[bufpos] = line;
+ bufcolumn[bufpos] = column;
+ }
+
+ public char readChar() throws java.io.IOException
+ {
+ if (inBuf > 0)
+ {
+ --inBuf;
+
+ if (++bufpos == bufsize)
+ bufpos = 0;
+
+ return buffer[bufpos];
+ }
+
+ if (++bufpos >= maxNextCharInd)
+ FillBuff();
+
+ char c = buffer[bufpos];
+
+ UpdateLineColumn(c);
+ return (c);
+ }
+
+ /**
+ * @deprecated
+ * @see #getEndColumn
+ */
+
+ public int getColumn() {
+ return bufcolumn[bufpos];
+ }
+
+ /**
+ * @deprecated
+ * @see #getEndLine
+ */
+
+ public int getLine() {
+ return bufline[bufpos];
+ }
+
+ public int getEndColumn() {
+ return bufcolumn[bufpos];
+ }
+
+ public int getEndLine() {
+ return bufline[bufpos];
+ }
+
+ public int getBeginColumn() {
+ return bufcolumn[tokenBegin];
+ }
+
+ public int getBeginLine() {
+ return bufline[tokenBegin];
+ }
+
+ public void backup(int amount) {
+
+ inBuf += amount;
+ if ((bufpos -= amount) < 0)
+ bufpos += bufsize;
+ }
+
+ public SimpleCharStream(java.io.Reader dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ inputStream = dstream;
+ line = startline;
+ column = startcolumn - 1;
+
+ available = bufsize = buffersize;
+ buffer = new char[buffersize];
+ bufline = new int[buffersize];
+ bufcolumn = new int[buffersize];
+ }
+
+ public SimpleCharStream(java.io.Reader dstream, int startline,
+ int startcolumn)
+ {
+ this(dstream, startline, startcolumn, 4096);
+ }
+
+ public SimpleCharStream(java.io.Reader dstream)
+ {
+ this(dstream, 1, 1, 4096);
+ }
+ public void ReInit(java.io.Reader dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ inputStream = dstream;
+ line = startline;
+ column = startcolumn - 1;
+
+ if (buffer == null || buffersize != buffer.length)
+ {
+ available = bufsize = buffersize;
+ buffer = new char[buffersize];
+ bufline = new int[buffersize];
+ bufcolumn = new int[buffersize];
+ }
+ prevCharIsLF = prevCharIsCR = false;
+ tokenBegin = inBuf = maxNextCharInd = 0;
+ bufpos = -1;
+ }
+
+ public void ReInit(java.io.Reader dstream, int startline,
+ int startcolumn)
+ {
+ ReInit(dstream, startline, startcolumn, 4096);
+ }
+
+ public void ReInit(java.io.Reader dstream)
+ {
+ ReInit(dstream, 1, 1, 4096);
+ }
+ public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+ {
+ this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+ }
+
+ public SimpleCharStream(java.io.InputStream dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+ }
+
+ public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn) throws java.io.UnsupportedEncodingException
+ {
+ this(dstream, encoding, startline, startcolumn, 4096);
+ }
+
+ public SimpleCharStream(java.io.InputStream dstream, int startline,
+ int startcolumn)
+ {
+ this(dstream, startline, startcolumn, 4096);
+ }
+
+ public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+ {
+ this(dstream, encoding, 1, 1, 4096);
+ }
+
+ public SimpleCharStream(java.io.InputStream dstream)
+ {
+ this(dstream, 1, 1, 4096);
+ }
+
+ public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+ {
+ ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+ }
+
+ public void ReInit(java.io.InputStream dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+ }
+
+ public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+ {
+ ReInit(dstream, encoding, 1, 1, 4096);
+ }
+
+ public void ReInit(java.io.InputStream dstream)
+ {
+ ReInit(dstream, 1, 1, 4096);
+ }
+ public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn) throws java.io.UnsupportedEncodingException
+ {
+ ReInit(dstream, encoding, startline, startcolumn, 4096);
+ }
+ public void ReInit(java.io.InputStream dstream, int startline,
+ int startcolumn)
+ {
+ ReInit(dstream, startline, startcolumn, 4096);
+ }
+ public String GetImage()
+ {
+ if (bufpos >= tokenBegin)
+ return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+ else
+ return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+ new String(buffer, 0, bufpos + 1);
+ }
+
+ public char[] GetSuffix(int len)
+ {
+ char[] ret = new char[len];
+
+ if ((bufpos + 1) >= len)
+ System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+ else
+ {
+ System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+ len - bufpos - 1);
+ System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+ }
+
+ return ret;
+ }
+
+ public void Done()
+ {
+ buffer = null;
+ bufline = null;
+ bufcolumn = null;
+ }
+
+ /**
+ * Method to adjust line and column numbers for the start of a token.
+ */
+ public void adjustBeginLineColumn(int newLine, int newCol)
+ {
+ int start = tokenBegin;
+ int len;
+
+ if (bufpos >= tokenBegin)
+ {
+ len = bufpos - tokenBegin + inBuf + 1;
+ }
+ else
+ {
+ len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+ }
+
+ int i = 0, j = 0, k = 0;
+ int nextColDiff = 0, columnDiff = 0;
+
+ while (i < len &&
+ bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
+ {
+ bufline[j] = newLine;
+ nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+ bufcolumn[j] = newCol + columnDiff;
+ columnDiff = nextColDiff;
+ i++;
+ }
+
+ if (i < len)
+ {
+ bufline[j] = newLine++;
+ bufcolumn[j] = newCol + columnDiff;
+
+ while (i++ < len)
+ {
+ if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+ bufline[j] = newLine++;
+ else
+ bufline[j] = newLine;
+ }
+ }
+
+ line = bufline[j];
+ column = bufcolumn[j];
+ }
+
+}
diff --git a/src/main/java/javax/measure/unit/format/SymbolMap.java b/src/main/java/javax/measure/unit/format/SymbolMap.java
new file mode 100644
index 0000000..818b32e
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/SymbolMap.java
@@ -0,0 +1,222 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit.format;
+
+import java.lang.reflect.Field;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.ResourceBundle;
+import javax.measure.converter.UnitConverter;
+import javax.measure.unit.Unit;
+
+/**
+ * <p> The SymbolMap class provides a set of mappings between
+ * {@link javax.measure.unit.Unit Units} and symbols (both ways),
+ * between {@link Prefix Prefix}es and symbols
+ * (both ways), and from {@link javax.measure.converter.UnitConverter
+ * UnitConverter}s to {@link Prefix Prefix}es (one way).
+ * No attempt is made to verify the uniqueness of the mappings.</p>
+ *
+ * <p> Mappings are read from a <code>ResourceBundle</code>, the keys
+ * of which should consist of a fully-qualified class name, followed
+ * by a dot ('.'), and then the name of a static field belonging
+ * to that class, followed optionally by another dot and a number.
+ * If the trailing dot and number are not present, the value
+ * associated with the key is treated as a
+ * {@link SymbolMap#label(javax.measure.unit.Unit, String) label},
+ * otherwise if the trailing dot and number are present, the value
+ * is treated as an {@link SymbolMap#alias(javax.measure.unit.Unit,String) alias}.
+ * Aliases map from String to Unit only, whereas labels map in both
+ * directions. A given unit may have any number of aliases, but may
+ * have only one label.</p>
+ *
+ * @author <a href="mailto:eric-r at northwestern.edu">Eric Russell</a>
+ * @version 1.0
+ */
+public class SymbolMap {
+
+ private Map<String, Unit<?>> _symbolToUnit;
+ private Map<Unit<?>, String> _unitToSymbol;
+ private Map<String, Object> _symbolToPrefix;
+ private Map<Object, String> _prefixToSymbol;
+ private Map<UnitConverter, Prefix> _converterToPrefix;
+
+ /**
+ * Creates an empty mapping.
+ */
+ public SymbolMap () {
+ _symbolToUnit = new HashMap<String, Unit<?>>();
+ _unitToSymbol = new HashMap<Unit<?>, String>();
+ _symbolToPrefix = new HashMap<String, Object>();
+ _prefixToSymbol = new HashMap<Object, String>();
+ _converterToPrefix = new HashMap<UnitConverter, Prefix>();
+ }
+
+ /**
+ * Creates a symbol map from the specified resource bundle,
+ *
+ * @param rb the resource bundle.
+ */
+ public SymbolMap (ResourceBundle rb) {
+ this();
+ for (Enumeration<String> i = rb.getKeys(); i.hasMoreElements();) {
+ String fqn = i.nextElement();
+ String symbol = rb.getString(fqn);
+ boolean isAlias = false;
+ int lastDot = fqn.lastIndexOf('.');
+ String className = fqn.substring(0, lastDot);
+ String fieldName = fqn.substring(lastDot+1, fqn.length());
+ if (Character.isDigit(fieldName.charAt(0))) {
+ isAlias = true;
+ fqn = className;
+ lastDot = fqn.lastIndexOf('.');
+ className = fqn.substring(0, lastDot);
+ fieldName = fqn.substring(lastDot+1, fqn.length());
+ }
+ try {
+ Class<?> c = Class.forName(className);
+ Field field = c.getField(fieldName);
+ Object value = field.get(null);
+ if (value instanceof Unit) {
+ if (isAlias) {
+ alias((Unit<?>)value, symbol);
+ } else {
+ label((Unit<?>)value, symbol);
+ }
+ } else if (value instanceof Prefix) {
+ label((Prefix)value, symbol);
+ } else {
+ throw new ClassCastException("unable to cast "+value+" to Unit or Prefix");
+ }
+ } catch (Exception e) {
+ System.err.println("ERROR reading Unit names: " + e.toString());
+ }
+ }
+ }
+
+ /**
+ * Attaches a label to the specified unit. For example:[code]
+ * symbolMap.label(DAY.multiply(365), "year");
+ * symbolMap.label(NonSI.FOOT, "ft");
+ * [/code]
+ *
+ * @param unit the unit to label.
+ * @param symbol the new symbol for the unit.
+ */
+ public void label (Unit<?> unit, String symbol) {
+ _symbolToUnit.put(symbol, unit);
+ _unitToSymbol.put(unit, symbol);
+ }
+
+ /**
+ * Attaches an alias to the specified unit. Multiple aliases may be
+ * attached to the same unit. Aliases are used during parsing to
+ * recognize different variants of the same unit.[code]
+ * symbolMap.alias(NonSI.FOOT, "foot");
+ * symbolMap.alias(NonSI.FOOT, "feet");
+ * symbolMap.alias(SI.METER, "meter");
+ * symbolMap.alias(SI.METER, "metre");
+ * [/code]
+ *
+ * @param unit the unit to label.
+ * @param symbol the new symbol for the unit.
+ */
+ public void alias (Unit<?> unit, String symbol) {
+ _symbolToUnit.put(symbol, unit);
+ }
+
+ /**
+ * Attaches a label to the specified prefix. For example:[code]
+ * symbolMap.label(Prefix.GIGA, "G");
+ * symbolMap.label(Prefix.MICRO, "µ");
+ * [/code]
+ */
+ public void label(Prefix prefix, String symbol) {
+ _symbolToPrefix.put(symbol, prefix);
+ _prefixToSymbol.put(prefix, symbol);
+ _converterToPrefix.put(prefix.getConverter(), prefix);
+ }
+
+ /**
+ * Returns the unit for the specified symbol.
+ *
+ * @param symbol the symbol.
+ * @return the corresponding unit or <code>null</code> if none.
+ */
+ public Unit<?> getUnit (String symbol) {
+ return _symbolToUnit.get(symbol);
+ }
+
+ /**
+ * Returns the symbol (label) for the specified unit.
+ *
+ * @param unit the corresponding symbol.
+ * @return the corresponding symbol or <code>null</code> if none.
+ */
+ public String getSymbol (Unit<?> unit) {
+ return _unitToSymbol.get(unit);
+ }
+
+ /**
+ * Returns the prefix (if any) for the specified symbol.
+ *
+ * @param symbol the unit symbol.
+ * @return the corresponding prefix or <code>null</code> if none.
+ */
+ public Prefix getPrefix (String symbol) {
+ for (Iterator<String> i = _symbolToPrefix.keySet().iterator(); i.hasNext(); ) {
+ String pfSymbol = i.next();
+ if (symbol.startsWith(pfSymbol)) {
+ return (Prefix)_symbolToPrefix.get(pfSymbol);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the prefix for the specified converter.
+ *
+ * @param converter the unit converter.
+ * @return the corresponding prefix or <code>null</code> if none.
+ */
+ public Prefix getPrefix (UnitConverter converter) {
+ return (Prefix)_converterToPrefix.get(converter);
+ }
+
+ /**
+ * Returns the symbol for the specified prefix.
+ *
+ * @param prefix the prefix.
+ * @return the corresponding symbol or <code>null</code> if none.
+ */
+ public String getSymbol (Prefix prefix) {
+ return _prefixToSymbol.get(prefix);
+ }
+}
diff --git a/src/main/java/javax/measure/unit/format/Token.java b/src/main/java/javax/measure/unit/format/Token.java
new file mode 100644
index 0000000..dbfd190
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/Token.java
@@ -0,0 +1,81 @@
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */
+package javax.measure.unit.format;
+
+/**
+ * Describes the input token stream.
+ */
+
+class Token {
+
+ /**
+ * An integer that describes the kind of this token. This numbering
+ * system is determined by JavaCCParser, and a table of these numbers is
+ * stored in the file ...Constants.java.
+ */
+ public int kind;
+
+ /**
+ * beginLine and beginColumn describe the position of the first character
+ * of this token; endLine and endColumn describe the position of the
+ * last character of this token.
+ */
+ public int beginLine, beginColumn, endLine, endColumn;
+
+ /**
+ * The string image of the token.
+ */
+ public String image;
+
+ /**
+ * A reference to the next regular (non-special) token from the input
+ * stream. If this is the last token from the input stream, or if the
+ * token manager has not read tokens beyond this one, this field is
+ * set to null. This is true only if this token is also a regular
+ * token. Otherwise, see below for a description of the contents of
+ * this field.
+ */
+ public Token next;
+
+ /**
+ * This field is used to access special tokens that occur prior to this
+ * token, but after the immediately preceding regular (non-special) token.
+ * If there are no such special tokens, this field is set to null.
+ * When there are more than one such special token, this field refers
+ * to the last of these special tokens, which in turn refers to the next
+ * previous special token through its specialToken field, and so on
+ * until the first special token (whose specialToken field is null).
+ * The next fields of special tokens refer to other special tokens that
+ * immediately follow it (without an intervening regular token). If there
+ * is no such token, this field is null.
+ */
+ public Token specialToken;
+
+ /**
+ * Returns the image.
+ */
+ public String toString()
+ {
+ return image;
+ }
+
+ /**
+ * Returns a new Token object, by default. However, if you want, you
+ * can create and return subclass objects based on the value of ofKind.
+ * Simply add the cases to the switch for all those special cases.
+ * For example, if you have a subclass of Token called IDToken that
+ * you want to create if ofKind is ID, simlpy add something like :
+ *
+ * case MyParserConstants.ID : return new IDToken();
+ *
+ * to the following switch statement. Then you can cast matchedToken
+ * variable to the appropriate type and use it in your lexical actions.
+ */
+ public static final Token newToken(int ofKind)
+ {
+ switch(ofKind)
+ {
+ default : return new Token();
+ }
+ }
+
+}
diff --git a/src/main/java/javax/measure/unit/format/TokenMgrError.java b/src/main/java/javax/measure/unit/format/TokenMgrError.java
new file mode 100644
index 0000000..8492b10
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/TokenMgrError.java
@@ -0,0 +1,133 @@
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */
+package javax.measure.unit.format;
+
+class TokenMgrError extends Error
+{
+ /*
+ * Ordinals for various reasons why an Error of this type can be thrown.
+ */
+
+ /**
+ * Lexical error occured.
+ */
+ static final int LEXICAL_ERROR = 0;
+
+ /**
+ * An attempt wass made to create a second instance of a static token manager.
+ */
+ static final int STATIC_LEXER_ERROR = 1;
+
+ /**
+ * Tried to change to an invalid lexical state.
+ */
+ static final int INVALID_LEXICAL_STATE = 2;
+
+ /**
+ * Detected (and bailed out of) an infinite loop in the token manager.
+ */
+ static final int LOOP_DETECTED = 3;
+
+ /**
+ * Indicates the reason why the exception is thrown. It will have
+ * one of the above 4 values.
+ */
+ int errorCode;
+
+ /**
+ * Replaces unprintable characters by their espaced (or unicode escaped)
+ * equivalents in the given string
+ */
+ protected static final String addEscapes(String str) {
+ StringBuffer retval = new StringBuffer();
+ char ch;
+ for (int i = 0; i < str.length(); i++) {
+ switch (str.charAt(i))
+ {
+ case 0 :
+ continue;
+ case '\b':
+ retval.append("\\b");
+ continue;
+ case '\t':
+ retval.append("\\t");
+ continue;
+ case '\n':
+ retval.append("\\n");
+ continue;
+ case '\f':
+ retval.append("\\f");
+ continue;
+ case '\r':
+ retval.append("\\r");
+ continue;
+ case '\"':
+ retval.append("\\\"");
+ continue;
+ case '\'':
+ retval.append("\\\'");
+ continue;
+ case '\\':
+ retval.append("\\\\");
+ continue;
+ default:
+ if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+ String s = "0000" + Integer.toString(ch, 16);
+ retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+ } else {
+ retval.append(ch);
+ }
+ continue;
+ }
+ }
+ return retval.toString();
+ }
+
+ /**
+ * Returns a detailed message for the Error when it is thrown by the
+ * token manager to indicate a lexical error.
+ * Parameters :
+ * EOFSeen : indicates if EOF caused the lexicl error
+ * curLexState : lexical state in which this error occured
+ * errorLine : line number when the error occured
+ * errorColumn : column number when the error occured
+ * errorAfter : prefix that was seen before this error occured
+ * curchar : the offending character
+ * Note: You can customize the lexical error message by modifying this method.
+ */
+ protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
+ return("Lexical error at line " +
+ errorLine + ", column " +
+ errorColumn + ". Encountered: " +
+ (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+ "after : \"" + addEscapes(errorAfter) + "\"");
+ }
+
+ /**
+ * You can also modify the body of this method to customize your error messages.
+ * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+ * of end-users concern, so you can return something like :
+ *
+ * "Internal Error : Please file a bug report .... "
+ *
+ * from this method for such cases in the release version of your parser.
+ */
+ public String getMessage() {
+ return super.getMessage();
+ }
+
+ /*
+ * Constructors of various flavors follow.
+ */
+
+ public TokenMgrError() {
+ }
+
+ public TokenMgrError(String message, int reason) {
+ super(message);
+ errorCode = reason;
+ }
+
+ public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
+ this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+ }
+}
diff --git a/src/main/java/javax/measure/unit/format/UCUM.java b/src/main/java/javax/measure/unit/format/UCUM.java
new file mode 100644
index 0000000..1c24520
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/UCUM.java
@@ -0,0 +1,630 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit.format;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import javax.measure.quantity.*;
+import javax.measure.unit.*;
+
+/**
+ * <p> This class contains the units ({@link SI} and {@link NonSI}) as defined
+ * in the <a href="http://unitsofmeasure.org/">
+ * Uniform Code for Units of Measure</a>.</p>
+ *
+ * <p> Compatability with existing {@link javax.measure.unit.SI SI}/
+ * {@link javax.measure.unit.NonSI NonSI} units has been given
+ * priority over strict adherence to the standard. We have attempted to note
+ * every place where the definitions in this class deviate from the
+ * UCUM standard, but such notes are likely to be incomplete.</p>
+ *
+ * @author <a href="mailto:eric-r at northwestern.edu">Eric Russell</a>
+ * @version 1.0
+ * @see <a href="http://aurora.regenstrief.org/UCUM/ucum.html">UCUM</a>
+ */
+ at SuppressWarnings("unchecked")
+final class UCUM extends SystemOfUnits {
+
+ /** Holds collection of all UCUM units. */
+ private static HashSet<Unit<?>> UNITS = new HashSet<Unit<?>>();
+
+ /**
+ * Returns the unique instance of this class.
+ *
+ * @return the UCUM instance.
+ */
+ public static UCUM getInstance() {
+ return INSTANCE;
+ }
+ private static final UCUM INSTANCE = new UCUM();
+
+ /**
+ * Adds a new unit to the collection.
+ * @param unit the unit being added.
+ * @return <code>unit</code>.
+ */
+ private static <U extends Unit<?>> U ucum(U unit) {
+ UNITS.add(unit);
+ return unit;
+ }
+
+ /**
+ * Default constructor (prevents this class from being instantiated).
+ */
+ private UCUM() {
+ }
+
+ /**
+ * Returns a read only view over the units defined in this class.
+ * @return the collection of SI units.
+ */
+ public Set<Unit<?>> getUnits() {
+ return Collections.unmodifiableSet(UNITS);
+ }
+ //////////////////////////////
+ // BASE UNITS: UCUM 4.2 §25 //
+ //////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final BaseUnit<Length> METER = ucum(SI.METRE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final BaseUnit<Duration> SECOND = ucum(SI.SECOND);
+ /**
+ * We deviate slightly from the standard here, to maintain compatability
+ * with the existing SI units. In UCUM, the gram is the base unit of mass,
+ * rather than the kilogram. This doesn't have much effect on the units
+ * themselves, but it does make formatting the units a challenge.
+ */
+ public static final Unit<Mass> GRAM = ucum(SI.GRAM);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final AlternateUnit<Angle> RADIAN = ucum(SI.RADIAN);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final BaseUnit<Temperature> KELVIN = ucum(SI.KELVIN);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final AlternateUnit<ElectricCharge> COULOMB = ucum(SI.COULOMB);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final BaseUnit<LuminousIntensity> CANDELA = ucum(SI.CANDELA);
+ ///////////////////////////////////////////////
+ // DIMENSIONLESS DERIVED UNITS: UCUM 4.3 §26 //
+ ///////////////////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> TRIILLIONS = ucum(Unit.ONE.times(1000000000000L));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> BILLIONS = ucum(Unit.ONE.times(1000000000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> MILLIONS = ucum(Unit.ONE.times(1000000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> THOUSANDS = ucum(Unit.ONE.times(1000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> HUNDREDS = ucum(Unit.ONE.times(100));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> PI = ucum(Unit.ONE.times(StrictMath.PI));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> PERCENT = ucum(Unit.ONE.divide(100));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> PER_THOUSAND = ucum(Unit.ONE.divide(1000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> PER_MILLION = ucum(Unit.ONE.divide(1000000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> PER_BILLION = ucum(Unit.ONE.divide(1000000000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> PER_TRILLION = ucum(Unit.ONE.divide(1000000000000L));
+ ////////////////////////////
+ // SI UNITS: UCUM 4.3 §27 //
+ ////////////////////////////
+ /**
+ * We deviate slightly from the standard here, to maintain compatability
+ * with the existing SI units. In UCUM, the mole is no longer a base unit,
+ * but is defined as <code>Unit.ONE.times(6.0221367E23)</code>.
+ */
+ public static final Unit<AmountOfSubstance> MOLE = ucum(SI.MOLE);
+ /**
+ * We deviate slightly from the standard here, to maintain compatability
+ * with the existing SI units. In UCUM, the steradian is defined as
+ * <code>RADIAN.pow(2)</code>.
+ */
+ public static final Unit<SolidAngle> STERADIAN = ucum(SI.STERADIAN);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Frequency> HERTZ = (Unit<Frequency>) ucum(SI.HERTZ);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Force> NEWTON = ucum(SI.NEWTON);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Pressure> PASCAL = ucum(SI.PASCAL);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> JOULE = ucum(SI.JOULE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Power> WATT = ucum(SI.WATT);
+ /**
+ * We deviate slightly from the standard here, to maintain compatability
+ * with the existing SI units. In UCUM, the ampere is defined as
+ * <code>COULOMB.divide(SECOND)</code>.
+ */
+ public static final Unit<ElectricCurrent> AMPERE = ucum(SI.AMPERE);
+ /**
+ * We deviate slightly from the standard here, to maintain compatability
+ * with the existing SI units. In UCUM, the volt is defined as
+ * <code>JOULE.divide(COULOMB)</code>.
+ */
+ public static final Unit<ElectricPotential> VOLT = ucum(SI.VOLT);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<ElectricCapacitance> FARAD = ucum(SI.FARAD);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<ElectricResistance> OHM = ucum(SI.OHM);
+ /**
+ * We deviate slightly from the standard here, to maintain compatability
+ * with the existing SI units. In UCUM, the volt is defined as
+ * <code>Unit.ONE.divide(OHM)</code>.
+ */
+ public static final Unit<ElectricConductance> SIEMENS = ucum(SI.SIEMENS);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<MagneticFlux> WEBER = ucum(SI.WEBER);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Temperature> CELSIUS = ucum(SI.CELSIUS);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<MagneticFluxDensity> TESLA = ucum(SI.TESLA);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<ElectricInductance> HENRY = ucum(SI.HENRY);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<LuminousFlux> LUMEN = ucum(SI.LUMEN);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Illuminance> LUX = ucum(SI.LUX);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<RadioactiveActivity> BECQUEREL = ucum(SI.BECQUEREL);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<RadiationDoseAbsorbed> GRAY = ucum(SI.GRAY);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<RadiationDoseEffective> SIEVERT = ucum(SI.SIEVERT);
+ ///////////////////////////////////////////////////////////////////////
+ // OTHER UNITS FROM ISO 1000, ISO 2955, AND ANSI X3.50: UCUM 4.3 §28 //
+ ///////////////////////////////////////////////////////////////////////
+ // The order of GON and DEGREE has been inverted because GON is defined in terms of DEGREE
+ /**
+ * We deviate slightly from the standard here, to maintain compatability
+ * with the existing NonSI units. In UCUM, the degree is defined as
+ * <code>PI.times(RADIAN.divide(180))</code>.
+ */
+ public static final Unit<Angle> DEGREE = ucum(NonSI.DEGREE_ANGLE);
+ /**
+ * We deviate slightly from the standard here, to maintain compatability
+ * with the existing NonSI units. In UCUM, the grade is defined as
+ * <code>DEGREE.times(0.9)</code>.
+ */
+ public static final Unit<Angle> GRADE = ucum(NonSI.GRADE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Angle> GON = GRADE;
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Angle> MINUTE_ANGLE = ucum(NonSI.MINUTE_ANGLE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Angle> SECOND_ANGLE = ucum(NonSI.SECOND_ANGLE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> LITER = ucum(NonSI.LITRE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Area> ARE = ucum(NonSI.ARE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Duration> MINUTE = ucum(NonSI.MINUTE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Duration> HOUR = ucum(NonSI.HOUR);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Duration> DAY = ucum(NonSI.DAY);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Duration> YEAR_TROPICAL = ucum(DAY.times(365.24219));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Duration> YEAR_JULIAN = ucum(DAY.times(365.25));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Duration> YEAR_GREGORIAN = ucum(DAY.times(365.2425));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Duration> YEAR = ucum(DAY.times(365.25));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Duration> MONTH_SYNODAL = ucum(DAY.times(29.53059));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Duration> MONTH_JULIAN = ucum(YEAR_JULIAN.divide(12));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Duration> MONTH_GREGORIAN = ucum(YEAR_GREGORIAN.divide(12));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Duration> MONTH = ucum(YEAR_JULIAN.divide(12));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> TONNE = ucum(NonSI.METRIC_TON);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Pressure> BAR = ucum(NonSI.BAR);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> ATOMIC_MASS_UNIT = ucum(NonSI.ATOMIC_MASS);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> ELECTRON_VOLT = ucum(NonSI.ELECTRON_VOLT);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> ASTRONOMIC_UNIT = ucum(NonSI.ASTRONOMICAL_UNIT);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> PARSEC = ucum(NonSI.PARSEC);
+ /////////////////////////////////
+ // NATURAL UNITS: UCUM 4.3 §29 //
+ /////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Velocity> C = ucum(NonSI.C);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Action> PLANCK = (Unit<Action>) ucum(JOULE.times(SECOND).times(6.6260755E-24));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> BOLTZMAN = (Unit<Dimensionless>) ucum(JOULE.divide(KELVIN).times(1.380658E-23));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<ElectricPermittivity> PERMITTIVITY_OF_VACUUM = (Unit<ElectricPermittivity>) ucum(FARAD.divide(METER).times(8.854187817E-12));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<MagneticPermeability> PERMEABILITY_OF_VACUUM = (Unit<MagneticPermeability>) ucum(NEWTON.times(4E-7 * StrictMath.PI).divide(AMPERE.pow(2)));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<ElectricCharge> ELEMENTARY_CHARGE = ucum(NonSI.E);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> ELECTRON_MASS = ucum(NonSI.ELECTRON_MASS);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> PROTON_MASS = ucum(GRAM.times(1.6726231E-24));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> NEWTON_CONSTANT_OF_GRAVITY = (Unit<Dimensionless>) ucum(METER.pow(3).times(SI.KILOGRAM.pow(-1)).times(SECOND.pow(-2)).times(6.67259E-11));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Acceleration> ACCELLERATION_OF_FREEFALL = ucum(NonSI.G);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Pressure> ATMOSPHERE = ucum(NonSI.ATMOSPHERE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> LIGHT_YEAR = (Unit<Length>) ucum(NonSI.LIGHT_YEAR);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Force> GRAM_FORCE = (Unit<Force>) ucum(GRAM.times(ACCELLERATION_OF_FREEFALL));
+ // POUND_FORCE contains a forward reference to avoirdupois pound weight, so it has been moved after section §36 below
+ /////////////////////////////
+ // CGS UNITS: UCUM 4.3 §30 //
+ /////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Wavenumber> KAYSER = (Unit<Wavenumber>) ucum(Unit.ONE.divide(SI.CENTI(METER)));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Acceleration> GAL = (Unit<Acceleration>) ucum(SI.CENTI(METER).divide(SECOND.pow(2)));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Force> DYNE = ucum(NonSI.DYNE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> ERG = ucum(NonSI.ERG);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<DynamicViscosity> POISE = ucum(NonSI.POISE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<ElectricCurrent> BIOT = ucum(AMPERE.times(10));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<KinematicViscosity> STOKES = ucum(NonSI.STOKE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<MagneticFlux> MAXWELL = ucum(NonSI.MAXWELL);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<MagneticFluxDensity> GAUSS = ucum(NonSI.GAUSS);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<MagneticFieldStrength> OERSTED = (Unit<MagneticFieldStrength>) ucum(Unit.ONE.divide(PI).times(AMPERE).divide(METER).times(250));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<MagnetomotiveForce> GILBERT = (Unit<MagnetomotiveForce>) ucum(OERSTED.times(SI.CENTI(METER)));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Luminance> STILB = (Unit<Luminance>) ucum(CANDELA.divide(SI.CENTI(METER).pow(2)));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Illuminance> LAMBERT = ucum(NonSI.LAMBERT);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Illuminance> PHOT = ucum(LUX.divide(10000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<RadioactiveActivity> CURIE = ucum(NonSI.CURIE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<IonizingRadiation> ROENTGEN = (Unit<IonizingRadiation>) ucum(NonSI.ROENTGEN);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<RadiationDoseAbsorbed> RAD = ucum(NonSI.RAD);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<RadiationDoseEffective> REM = ucum(NonSI.REM);
+ /////////////////////////////////////////////////
+ // INTERNATIONAL CUSTOMARY UNITS: UCUM 4.4 §31 //
+ /////////////////////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> INCH_INTERNATIONAL = ucum(SI.CENTI(METER).times(254).divide(100));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> FOOT_INTERNATIONAL = ucum(INCH_INTERNATIONAL.times(12));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> YARD_INTERNATIONAL = ucum(FOOT_INTERNATIONAL.times(3));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> MILE_INTERNATIONAL = ucum(FOOT_INTERNATIONAL.times(5280));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> FATHOM_INTERNATIONAL = ucum(FOOT_INTERNATIONAL.times(6));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> NAUTICAL_MILE_INTERNATIONAL = ucum(METER.times(1852));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Velocity> KNOT_INTERNATIONAL = (Unit<Velocity>) ucum(NAUTICAL_MILE_INTERNATIONAL.divide(HOUR));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Area> SQUARE_INCH_INTERNATIONAL = (Unit<Area>) ucum(INCH_INTERNATIONAL.pow(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Area> SQUARE_FOOT_INTERNATIONAL = (Unit<Area>) ucum(FOOT_INTERNATIONAL.pow(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Area> SQUARE_YARD_INTERNATIONAL = (Unit<Area>) ucum(YARD_INTERNATIONAL.pow(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> CUBIC_INCH_INTERNATIONAL = (Unit<Volume>) ucum(INCH_INTERNATIONAL.pow(3));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> CUBIC_FOOT_INTERNATIONAL = (Unit<Volume>) ucum(FOOT_INTERNATIONAL.pow(3));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> CUBIC_YARD_INTERNATIONAL = (Unit<Volume>) ucum(YARD_INTERNATIONAL.pow(3));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> BOARD_FOOT_INTERNATIONAL = ucum(CUBIC_INCH_INTERNATIONAL.times(144));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> CORD_INTERNATIONAL = ucum(CUBIC_FOOT_INTERNATIONAL.times(128));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> MIL_INTERNATIONAL = ucum(INCH_INTERNATIONAL.divide(1000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Area> CIRCULAR_MIL_INTERNATIONAL = (Unit<Area>) ucum(MIL_INTERNATIONAL.times(PI).divide(4));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> HAND_INTERNATIONAL = ucum(INCH_INTERNATIONAL.times(4));
+ //////////////////////////////////////////
+ // US SURVEY LENGTH UNITS: UCUM 4.4 §32 //
+ //////////////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> FOOT_US_SURVEY = ucum(METER.times(1200).divide(3937));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> YARD_US_SURVEY = ucum(FOOT_US_SURVEY.times(3));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> INCH_US_SURVEY = ucum(FOOT_US_SURVEY.divide(12));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> ROD_US_SURVEY = ucum(FOOT_US_SURVEY.times(33).divide(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> CHAIN_US_SURVEY = ucum(ROD_US_SURVEY.times(4));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> LINK_US_SURVEY = ucum(CHAIN_US_SURVEY.divide(100));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> RAMDEN_CHAIN_US_SURVEY = ucum(FOOT_US_SURVEY.times(100));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> RAMDEN_LINK_US_SURVEY = ucum(CHAIN_US_SURVEY.divide(100));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> FATHOM_US_SURVEY = ucum(FOOT_US_SURVEY.times(6));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> FURLONG_US_SURVEY = ucum(ROD_US_SURVEY.times(40));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> MILE_US_SURVEY = ucum(FURLONG_US_SURVEY.times(8));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Area> ACRE_US_SURVEY = (Unit<Area>) ucum(ROD_US_SURVEY.pow(2).times(160));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Area> SQUARE_ROD_US_SURVEY = (Unit<Area>) ucum(ROD_US_SURVEY.pow(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Area> SQUARE_MILE_US_SURVEY = (Unit<Area>) ucum(MILE_US_SURVEY.pow(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Area> SECTION_US_SURVEY = (Unit<Area>) ucum(MILE_US_SURVEY.pow(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Area> TOWNSHP_US_SURVEY = (Unit<Area>) ucum(SECTION_US_SURVEY.times(36));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> MIL_US_SURVEY = ucum(INCH_US_SURVEY.divide(1000));
+ /////////////////////////////////////////////////
+ // BRITISH IMPERIAL LENGTH UNITS: UCUM 4.4 §33 //
+ /////////////////////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> INCH_BRITISH = ucum(SI.CENTI(METER).times(2539998).divide(1000000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> FOOT_BRITISH = ucum(INCH_BRITISH.times(12));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> ROD_BRITISH = ucum(FOOT_BRITISH.times(33).divide(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> CHAIN_BRITISH = ucum(ROD_BRITISH.times(4));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> LINK_BRITISH = ucum(CHAIN_BRITISH.divide(100));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> FATHOM_BRITISH = ucum(FOOT_BRITISH.times(6));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> PACE_BRITISH = ucum(FOOT_BRITISH.times(5).divide(20));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> YARD_BRITISH = ucum(FOOT_BRITISH.times(3));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> MILE_BRITISH = ucum(FOOT_BRITISH.times(5280));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> NAUTICAL_MILE_BRITISH = ucum(FOOT_BRITISH.times(6080));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> KNOT_BRITISH = (Unit<Length>) ucum(NAUTICAL_MILE_BRITISH.divide(HOUR));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Area> ACRE_BRITISH = (Unit<Area>) ucum(YARD_BRITISH.pow(2).times(4840));
+ ///////////////////////////////////
+ // US VOLUME UNITS: UCUM 4.4 §34 //
+ ///////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> GALLON_US = ucum(CUBIC_INCH_INTERNATIONAL.times(231));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> BARREL_US = ucum(GALLON_US.times(42));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> QUART_US = ucum(GALLON_US.divide(4));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> PINT_US = ucum(QUART_US.divide(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> GILL_US = ucum(PINT_US.divide(4));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> FLUID_OUNCE_US = ucum(GILL_US.divide(4));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> FLUID_DRAM_US = ucum(FLUID_OUNCE_US.divide(8));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> MINIM_US = ucum(FLUID_DRAM_US.divide(60));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> CORD_US = ucum(CUBIC_FOOT_INTERNATIONAL.times(128));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> BUSHEL_US = ucum(CUBIC_INCH_INTERNATIONAL.times(215042).divide(100));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> GALLON_WINCHESTER = ucum(BUSHEL_US.divide(8));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> PECK_US = ucum(BUSHEL_US.divide(4));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> DRY_QUART_US = ucum(PECK_US.divide(8));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> DRY_PINT_US = ucum(DRY_QUART_US.divide(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> TABLESPOON_US = ucum(FLUID_OUNCE_US.divide(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> TEASPOON_US = ucum(TABLESPOON_US.divide(3));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> CUP_US = ucum(TABLESPOON_US.times(16));
+ /////////////////////////////////////////////////
+ // BRITISH IMPERIAL VOLUME UNITS: UCUM 4.4 §35 //
+ /////////////////////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> GALLON_BRITISH = ucum(LITER.times(454609).divide(100000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> PECK_BRITISH = ucum(GALLON_BRITISH.times(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> BUSHEL_BRITISH = ucum(PECK_BRITISH.times(4));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> QUART_BRITISH = ucum(GALLON_BRITISH.divide(4));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> PINT_BRITISH = ucum(QUART_BRITISH.divide(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> GILL_BRITISH = ucum(PINT_BRITISH.divide(4));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> FLUID_OUNCE_BRITISH = ucum(GILL_BRITISH.divide(5));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> FLUID_DRAM_BRITISH = ucum(FLUID_OUNCE_BRITISH.divide(8));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> MINIM_BRITISH = ucum(FLUID_DRAM_BRITISH.divide(60));
+ ////////////////////////////////////////////
+ // AVOIRDUPOIS WIEGHT UNITS: UCUM 4.4 §36 //
+ ////////////////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> GRAIN = ucum(SI.MILLI(GRAM).times(6479891).divide(100000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> POUND = ucum(GRAM.times(7000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> OUNCE = ucum(POUND.divide(16));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> DRAM = ucum(OUNCE.divide(16));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> SHORT_HUNDREDWEIGHT = ucum(POUND.times(100));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> LONG_HUNDREDWEIGHT = ucum(POUND.times(112));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> SHORT_TON = ucum(SHORT_HUNDREDWEIGHT.times(20));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> LONG_TON = ucum(LONG_HUNDREDWEIGHT.times(20));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> STONE = ucum(POUND.times(14));
+ // CONTINUED FROM SECTION §29
+ // contains a forward reference to POUND, so we had to move it here, below section §36
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Force> POUND_FORCE = (Unit<Force>) ucum(POUND.times(ACCELLERATION_OF_FREEFALL));
+ /////////////////////////////////////
+ // TROY WIEGHT UNITS: UCUM 4.4 §37 //
+ /////////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> PENNYWEIGHT_TROY = ucum(GRAIN.times(24));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> OUNCE_TROY = ucum(PENNYWEIGHT_TROY.times(24));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> POUND_TROY = ucum(OUNCE_TROY.times(12));
+ /////////////////////////////////////////////
+ // APOTECARIES' WEIGHT UNITS: UCUM 4.4 §38 //
+ /////////////////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> SCRUPLE_APOTHECARY = ucum(GRAIN.times(20));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> DRAM_APOTHECARY = ucum(SCRUPLE_APOTHECARY.times(3));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> OUNCE_APOTHECARY = ucum(DRAM_APOTHECARY.times(8));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> POUND_APOTHECARY = ucum(OUNCE_APOTHECARY.times(12));
+ /////////////////////////////////////////////
+ // TYPESETTER'S LENGTH UNITS: UCUM 4.4 §39 //
+ /////////////////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> LINE = ucum(INCH_INTERNATIONAL.divide(12));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> POINT = ucum(LINE.divide(6));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> PICA = ucum(POINT.times(12));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> POINT_PRINTER = ucum(INCH_INTERNATIONAL.times(13837).divide(1000000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> PICA_PRINTER = ucum(POINT_PRINTER.times(12));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> PIED = ucum(SI.CENTI(METER).times(3248).divide(100));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> POUCE = ucum(PIED.divide(12));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> LINGE = ucum(POUCE.divide(12));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> DIDOT = ucum(LINGE.divide(6));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> CICERO = ucum(DIDOT.times(12));
+ //////////////////////////////////////
+ // OTHER LEGACY UNITS: UCUM 4.5 §40 //
+ //////////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Temperature> FAHRENHEIT = ucum(KELVIN.times(5).divide(9).plus(459.67));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> CALORIE_AT_15C = ucum(JOULE.times(41858).divide(10000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> CALORIE_AT_20C = ucum(JOULE.times(41819).divide(10000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> CALORIE_MEAN = ucum(JOULE.times(419002).divide(100000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> CALORIE_INTERNATIONAL_TABLE = ucum(JOULE.times(41868).divide(10000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> CALORIE_THERMOCHEMICAL = ucum(JOULE.times(4184).divide(1000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> CALORIE = ucum(CALORIE_THERMOCHEMICAL);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> CALORIE_FOOD = ucum(SI.KILO(CALORIE_THERMOCHEMICAL));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> BTU_AT_39F = ucum(SI.KILO(JOULE).times(105967).divide(100000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> BTU_AT_59F = ucum(SI.KILO(JOULE).times(105480).divide(100000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> BTU_AT_60F = ucum(SI.KILO(JOULE).times(105468).divide(100000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> BTU_MEAN = ucum(SI.KILO(JOULE).times(105587).divide(100000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> BTU_INTERNATIONAL_TABLE = ucum(SI.KILO(JOULE).times(105505585262L).divide(100000000000L));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> BTU_THERMOCHEMICAL = ucum(SI.KILO(JOULE).times(105735).divide(100000));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Energy> BTU = ucum(BTU_THERMOCHEMICAL);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Power> HORSEPOWER = (Unit<Power>) ucum(FOOT_INTERNATIONAL.times(POUND_FORCE).divide(SECOND));
+ /////////////////////////////////////////////////////////
+ // SECTIONS §41-§43 skipped; implement later if needed //
+ /////////////////////////////////////////////////////////
+ ///////////////////////////////////////
+ // MISCELLANEOUS UNITS: UCUM 4.5 §44 //
+ ///////////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Volume> STERE = (Unit<Volume>) ucum(METER.pow(3));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Length> ANGSTROM = ucum(SI.NANO(METER).divide(10));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Area> BARN = (Unit<Area>) ucum(SI.FEMTO(METER).pow(2).times(100));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Pressure> ATMOSPHERE_TECHNICAL = (Unit<Pressure>) ucum(SI.KILO(GRAM_FORCE).divide(SI.CENTI(METER).pow(2)));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<ElectricConductance> MHO = ucum(SIEMENS.alternate("mho").asType(ElectricConductance.class));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Pressure> POUND_PER_SQUARE_INCH = (Unit<Pressure>) ucum(POUND_FORCE.divide(INCH_INTERNATIONAL.pow(2)));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Pressure> CIRCLE = (Unit<Pressure>) ucum(PI.times(RADIAN).times(2));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Pressure> SPHERE = (Unit<Pressure>) ucum(PI.times(STERADIAN).times(4));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Mass> CARAT_METRIC = ucum(GRAM.divide(5));
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<Dimensionless> CARAT_GOLD = ucum(Unit.ONE.divide(24));
+ ////////////////////////////////////////////////
+ // INFORMATION TECHNOLOGY UNITS: UCUM 4.6 §45 //
+ ////////////////////////////////////////////////
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<DataAmount> BIT = ucum(SI.BIT);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<DataAmount> BYTE = ucum(NonSI.BYTE);
+ /** As per <a href="http://unitsofmeasure.org/">UCUM</a> standard. */
+ public static final Unit<DataRate> BAUD = (Unit<DataRate>) ucum(Unit.ONE.divide(SECOND));
+}
diff --git a/src/main/java/javax/measure/unit/format/UCUMFormat.java b/src/main/java/javax/measure/unit/format/UCUMFormat.java
new file mode 100644
index 0000000..64cd8f7
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/UCUMFormat.java
@@ -0,0 +1,405 @@
+/*
+ * JScience - Java Tools and Libraries for the Advancement of Sciences
+ * Copyright (c) 2005-2009, JScience (http://jscience.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package javax.measure.unit.format;
+
+import javax.measure.unit.UnitFormat;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.text.*;
+import java.util.ResourceBundle;
+import javax.measure.converter.MultiplyConverter;
+import javax.measure.converter.RationalConverter;
+import javax.measure.converter.UnitConverter;
+import javax.measure.unit.*;
+import javax.measure.quantity.Quantity;
+
+/**
+ * <p>
+ * This class provides the interface for formatting and parsing
+ * {@link javax.measure.unit.Unit units} according to the <a
+ * href="http://unitsofmeasure.org/">Uniform Code for Units of Measure</a>
+ * (UCUM).
+ * </p>
+ *
+ * <p>
+ * For a technical/historical overview of this format please read <a
+ * href="http://www.pubmedcentral.nih.gov/articlerender.fcgi?artid=61354"> Units
+ * of Measure in Clinical Information Systems</a>.
+ * </p>
+ *
+ * <p>
+ * As of revision 1.16, the BNF in the UCUM standard contains an <a
+ * href="http://unitsofmeasure.org/ticket/4">error</a>. I've attempted to work
+ * around the problem by modifying the BNF productions for <Term>. Once
+ * the error in the standard is corrected, it may be necessary to modify the
+ * productions in the UCUMParser.jj file to conform to the standard.
+ * </p>
+ *
+ * @author <a href="mailto:eric-r at northwestern.edu">Eric Russell</a>
+ * @version 1.0
+ */
+public abstract class UCUMFormat extends UnitFormat {
+
+ // /////////////////
+ // Class methods //
+ // /////////////////
+ /** Returns the instance for formatting using "print" symbols */
+ public static UCUMFormat getPrintInstance() {
+ return Print.DEFAULT;
+ }
+
+ /** Returns the instance for formatting using user defined symbols */
+ public static UCUMFormat getPrintInstance(SymbolMap symbolMap) {
+ return new Print(symbolMap);
+ }
+
+ /**
+ * Returns the instance for formatting and parsing using case sensitive
+ * symbols
+ */
+ public static UCUMFormat getCaseSensitiveInstance() {
+ return Parsing.DEFAULT_CS;
+ }
+
+ /**
+ * Returns a case sensitive instance for formatting and parsing using user
+ * defined symbols
+ */
+ public static UCUMFormat getCaseSensitiveInstance(SymbolMap symbolMap) {
+ return new Parsing(symbolMap, true);
+ }
+
+ /**
+ * Returns the instance for formatting and parsing using case insensitive
+ * symbols
+ */
+ public static UCUMFormat getCaseInsensitiveInstance() {
+ return Parsing.DEFAULT_CI;
+ }
+
+ /**
+ * Returns a case insensitive instance for formatting and parsing using user
+ * defined symbols
+ */
+ public static UCUMFormat getCaseInsensitiveInstance(SymbolMap symbolMap) {
+ return new Parsing(symbolMap, false);
+ }
+
+ /**
+ * The symbol map used by this instance to map between
+ * {@link javax.measure.unit.Unit Unit}s and <code>String</code>s.
+ */
+ final SymbolMap _symbolMap;
+
+ // ////////////////
+ // Constructors //
+ // ////////////////
+ /**
+ * Base constructor.
+ */
+ UCUMFormat(SymbolMap symbolMap) {
+ _symbolMap = symbolMap;
+ }
+
+ // //////////////
+ // Formatting //
+ // //////////////
+ public Appendable format(Unit<?> unit, Appendable appendable)
+ throws IOException {
+ CharSequence symbol;
+ CharSequence annotation = null;
+ if (unit instanceof AnnotatedUnit) {
+ unit = ((AnnotatedUnit<?>) unit).getRealUnit();
+ annotation = ((AnnotatedUnit<?>) unit).getAnnotation();
+ }
+ String mapSymbol = _symbolMap.getSymbol(unit);
+ if (mapSymbol != null) {
+ symbol = mapSymbol;
+ } else if (unit instanceof ProductUnit) {
+ ProductUnit<?> productUnit = (ProductUnit<?>) unit;
+ StringBuffer app = new StringBuffer();
+ for (int i = 0; i < productUnit.getUnitCount(); i++) {
+ if (productUnit.getUnitRoot(i) != 1) {
+ throw new IllegalArgumentException(
+ "Unable to format units in UCUM (fractional powers not supported)");
+ }
+ StringBuffer temp = new StringBuffer();
+ temp = (StringBuffer) format(productUnit.getUnit(i), temp);
+ if ((temp.indexOf(".") >= 0) || (temp.indexOf("/") >= 0)) {
+ temp.insert(0, '(');
+ temp.append(')');
+ }
+ int pow = productUnit.getUnitPow(i);
+ if (i > 0) {
+ if (pow >= 0) {
+ app.append('.');
+ } else if (i < (productUnit.getUnitCount() - 1)) {
+ app.append('.');
+ } else {
+ app.append('/');
+ pow = -pow;
+ }
+ } else if (pow < 0) {
+ app.append('/');
+ pow = -pow;
+ }
+ app.append(temp);
+ if (pow != 1) {
+ app.append(Integer.toString(pow));
+ }
+ }
+ symbol = app;
+ } else if ((unit instanceof TransformedUnit)
+ || unit.equals(SI.KILOGRAM)) {
+ StringBuffer temp = new StringBuffer();
+ UnitConverter converter;
+ boolean printSeparator;
+ if (unit.equals(SI.KILOGRAM)) {
+ // A special case because KILOGRAM is a BaseUnit instead of
+ // a transformed unit, for compatability with existing SI
+ // unit system.
+ temp = format(UCUM.GRAM, temp, new FieldPosition(0));
+ converter = Prefix.KILO.getConverter();
+ printSeparator = true;
+ } else {
+ TransformedUnit<?> transformedUnit = (TransformedUnit<?>) unit;
+ Unit<?> parentUnits = transformedUnit.getParentUnit();
+ converter = transformedUnit.toParentUnit();
+ if (parentUnits.equals(SI.KILOGRAM)) {
+ // More special-case hackery to work around gram/kilogram
+ // incosistency
+ parentUnits = UCUM.GRAM;
+ converter = converter.concatenate(Prefix.KILO
+ .getConverter());
+ }
+ temp = format(parentUnits, temp, new FieldPosition(0));
+ printSeparator = !parentUnits.equals(Unit.ONE);
+ }
+ formatConverter(converter, printSeparator, temp);
+ symbol = temp;
+ } else if (unit instanceof BaseUnit) {
+ symbol = ((BaseUnit<?>) unit).getSymbol();
+ } else if (unit instanceof AlternateUnit) {
+ symbol = ((AlternateUnit<?>) unit).getSymbol();
+ } else {
+ throw new IllegalArgumentException(
+ "Cannot format the given Object as UCUM units (unsupported unit "
+ + unit.getClass().getName()
+ + "). "
+ + "Custom units types should override the toString() method as the default implementation uses the UCUM format.");
+ }
+
+ appendable.append(symbol);
+ if (annotation != null && annotation.length() > 0) {
+ appendAnnotation(unit, symbol, annotation, appendable);
+ }
+
+ return appendable;
+ }
+
+ void appendAnnotation(Unit<?> unit, CharSequence symbol,
+ CharSequence annotation, Appendable appendable) throws IOException {
+ appendable.append('{');
+ appendable.append(annotation);
+ appendable.append('}');
+ }
+
+ /**
+ * Formats the given converter to the given StringBuffer. This is similar to
+ * what {@link ConverterFormat} does, but there's no need to worry about
+ * operator precedence here, since UCUM only supports multiplication,
+ * division, and exponentiation and expressions are always evaluated left-
+ * to-right.
+ *
+ * @param converter
+ * the converter to be formatted
+ * @param continued
+ * <code>true</code> if the converter expression should begin
+ * with an operator, otherwise <code>false</code>. This will
+ * always be true unless the unit being modified is equal to
+ * Unit.ONE.
+ * @param buffer
+ * the <code>StringBuffer</code> to append to. Contains the
+ * already-formatted unit being modified by the given converter.
+ */
+ void formatConverter(UnitConverter converter, boolean continued,
+ StringBuffer buffer) {
+ boolean unitIsExpression = ((buffer.indexOf(".") >= 0) || (buffer
+ .indexOf("/") >= 0));
+ Prefix prefix = _symbolMap.getPrefix(converter);
+ if ((prefix != null) && (!unitIsExpression)) {
+ buffer.insert(0, _symbolMap.getSymbol(prefix));
+ } else if (converter == UnitConverter.IDENTITY) {
+ // do nothing
+ } else if (converter instanceof MultiplyConverter) {
+ if (unitIsExpression) {
+ buffer.insert(0, '(');
+ buffer.append(')');
+ }
+ MultiplyConverter multiplyConverter = (MultiplyConverter) converter;
+ double factor = multiplyConverter.getFactor();
+ long lFactor = (long) factor;
+ if ((lFactor != factor) || (lFactor < -9007199254740992L)
+ || (lFactor > 9007199254740992L)) {
+ throw new IllegalArgumentException(
+ "Only integer factors are supported in UCUM");
+ }
+ if (continued) {
+ buffer.append('.');
+ }
+ buffer.append(lFactor);
+ } else if (converter instanceof RationalConverter) {
+ if (unitIsExpression) {
+ buffer.insert(0, '(');
+ buffer.append(')');
+ }
+ RationalConverter rationalConverter = (RationalConverter) converter;
+ if (!rationalConverter.getDividend().equals(BigInteger.ONE)) {
+ if (continued) {
+ buffer.append('.');
+ }
+ buffer.append(rationalConverter.getDividend());
+ }
+ if (!rationalConverter.getDivisor().equals(BigInteger.ONE)) {
+ buffer.append('/');
+ buffer.append(rationalConverter.getDivisor());
+ }
+ } else {
+ throw new IllegalArgumentException(
+ "Unable to format units in UCUM (unsupported UnitConverter "
+ + converter + ")");
+ }
+ }
+
+ // /////////////////
+ // Inner classes //
+ // /////////////////
+ /**
+ * The Print format is used to output units according to the "print" column
+ * in the UCUM standard. Because "print" symbols in UCUM are not unique,
+ * this class of UCUMFormat may not be used for parsing, only for
+ * formatting.
+ */
+ private static class Print extends UCUMFormat {
+
+ private static final SymbolMap PRINT_SYMBOLS = new SymbolMap(
+ ResourceBundle
+ .getBundle("javax.measure.unit.format.UCUM_Print"));
+ private static final Print DEFAULT = new Print(PRINT_SYMBOLS);
+
+ public Print(SymbolMap symbols) {
+ super(symbols);
+ }
+
+ @Override
+ public Unit<? extends Quantity> parse(CharSequence csq,
+ ParsePosition pos) throws IllegalArgumentException {
+ throw new UnsupportedOperationException(
+ "The print format is for pretty-printing of units only. Parsing is not supported.");
+ }
+
+ @Override
+ void appendAnnotation(Unit<?> unit, CharSequence symbol,
+ CharSequence annotation, Appendable appendable)
+ throws IOException {
+ if (symbol != null && symbol.length() > 0) {
+ appendable.append('(');
+ appendable.append(annotation);
+ appendable.append(')');
+ } else {
+ appendable.append(annotation);
+ }
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ }
+
+ /**
+ * The Parsing format outputs formats and parses units according to the
+ * "c/s" or "c/i" column in the UCUM standard, depending on which SymbolMap
+ * is passed to its constructor.
+ */
+ private static class Parsing extends UCUMFormat {
+
+ private static final SymbolMap CASE_SENSITIVE_SYMBOLS = new SymbolMap(
+ ResourceBundle.getBundle("javax.measure.unit.format.UCUM_CS"));
+ private static final SymbolMap CASE_INSENSITIVE_SYMBOLS = new SymbolMap(
+ ResourceBundle.getBundle("javax.measure.unit.format.UCUM_CI"));
+ private static final Parsing DEFAULT_CS = new Parsing(
+ CASE_SENSITIVE_SYMBOLS, true);
+ private static final Parsing DEFAULT_CI = new Parsing(
+ CASE_INSENSITIVE_SYMBOLS, false);
+ private final boolean _caseSensitive;
+
+ public Parsing(SymbolMap symbols, boolean caseSensitive) {
+ super(symbols);
+ _caseSensitive = caseSensitive;
+ }
+
+ @Override
+ public Unit<? extends Quantity> parse(CharSequence csq,
+ ParsePosition cursor) throws IllegalArgumentException {
+ // Parsing reads the whole character sequence from the parse
+ // position.
+ int start = cursor.getIndex();
+ int end = csq.length();
+ if (end <= start)
+ return Unit.ONE;
+ String source = csq.subSequence(start, end).toString().trim();
+ if (source.length() == 0)
+ return Unit.ONE;
+ if (!_caseSensitive) {
+ source = source.toUpperCase();
+ }
+ UCUMParser parser = new UCUMParser(_symbolMap,
+ new ByteArrayInputStream(source.getBytes()));
+ try {
+ Unit<?> result = parser.parseUnit();
+ cursor.setIndex(end);
+ return result;
+ } catch (javax.measure.unit.format.ParseException e) {
+ if (e.currentToken != null) {
+ cursor.setErrorIndex(start + e.currentToken.endColumn);
+ } else {
+ cursor.setErrorIndex(start);
+ }
+ throw new IllegalArgumentException(e.getMessage());
+ } catch (TokenMgrError e) {
+ cursor.setErrorIndex(start);
+ throw new IllegalArgumentException(e.getMessage());
+ }
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ }
+
+ private static final long serialVersionUID = 1L;
+}
diff --git a/src/main/java/javax/measure/unit/format/UCUMParser.java b/src/main/java/javax/measure/unit/format/UCUMParser.java
new file mode 100644
index 0000000..ef506a3
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/UCUMParser.java
@@ -0,0 +1,496 @@
+/* Generated By:JavaCC: Do not edit this line. UCUMParser.java */
+package javax.measure.unit.format;
+
+import javax.measure.unit.AnnotatedUnit;
+
+/**
+ * <p>
+ * Parser definition for parsing {@link javax.measure.unit.Unit Unit}s
+ * according to the <a href="http://aurora.regenstrief.org/UCUM/ucum.html">
+ * Uniform Code for Units of Measure</a>.
+ *
+ * @author <a href="mailto:eric-r at northwestern.edu">Eric Russell</a>
+ * @version 1.0
+ * @see <a href="http://aurora.regenstrief.org/UCUM/ucum.html">UCUM</a>
+ */
+class UCUMParser implements UCUMParserConstants {
+
+ private SymbolMap _symbols;
+
+ public UCUMParser (SymbolMap symbols, java.io.InputStream in) {
+ this(in);
+ _symbols = symbols;
+ }
+
+//
+// Parser productions
+//
+ final public javax.measure.unit.Unit parseUnit() throws ParseException {
+ javax.measure.unit.Unit u;
+ u = Term();
+ jj_consume_token(0);
+ {if (true) return u;}
+ throw new Error("Missing return statement in function");
+ }
+
+ final public javax.measure.unit.Unit Term() throws ParseException {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ javax.measure.unit.Unit temp = javax.measure.unit.Unit.ONE;
+ result = Component();
+ label_1:
+ while (true) {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case DOT:
+ case SOLIDUS:
+ ;
+ break;
+ default:
+ jj_la1[0] = jj_gen;
+ break label_1;
+ }
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case DOT:
+ jj_consume_token(DOT);
+ temp = Component();
+ result = result.times(temp);
+ break;
+ case SOLIDUS:
+ jj_consume_token(SOLIDUS);
+ temp = Component();
+ result = result.divide(temp);
+ break;
+ default:
+ jj_la1[1] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ }
+ {if (true) return result;}
+ throw new Error("Missing return statement in function");
+ }
+
+ final public javax.measure.unit.Unit Component() throws ParseException {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ Token token = null;
+ if (jj_2_1(2147483647)) {
+ result = Annotatable();
+ token = jj_consume_token(ANNOTATION);
+ {if (true) return new AnnotatedUnit(result, token.image.substring(1, token.image.length()-1));}
+ } else {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case ATOM:
+ result = Annotatable();
+ {if (true) return result;}
+ break;
+ case ANNOTATION:
+ token = jj_consume_token(ANNOTATION);
+ {if (true) return new AnnotatedUnit(result, token.image.substring(1, token.image.length()-1));}
+ break;
+ case FACTOR:
+ token = jj_consume_token(FACTOR);
+ long factor = Long.parseLong(token.image);
+ {if (true) return result.times(factor);}
+ break;
+ case SOLIDUS:
+ jj_consume_token(SOLIDUS);
+ result = Component();
+ {if (true) return javax.measure.unit.Unit.ONE.divide(result);}
+ break;
+ case 14:
+ jj_consume_token(14);
+ result = Term();
+ jj_consume_token(15);
+ {if (true) return result;}
+ break;
+ default:
+ jj_la1[2] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+ final public javax.measure.unit.Unit Annotatable() throws ParseException {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ Token token1 = null;
+ Token token2 = null;
+ if (jj_2_2(2147483647)) {
+ result = SimpleUnit();
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case SIGN:
+ token1 = jj_consume_token(SIGN);
+ break;
+ default:
+ jj_la1[3] = jj_gen;
+ ;
+ }
+ token2 = jj_consume_token(FACTOR);
+ int exponent = Integer.parseInt(token2.image);
+ if ((token1 != null) && token1.image.equals("-")) {
+ {if (true) return result.pow(-exponent);}
+ } else {
+ {if (true) return result.pow(exponent);}
+ }
+ } else {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case ATOM:
+ result = SimpleUnit();
+ {if (true) return result;}
+ break;
+ default:
+ jj_la1[4] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+ final public javax.measure.unit.Unit SimpleUnit() throws ParseException {
+ Token token = null;
+ token = jj_consume_token(ATOM);
+ javax.measure.unit.Unit unit = _symbols.getUnit(token.image);
+ if (unit == null) {
+ Prefix prefix = _symbols.getPrefix(token.image);
+ if (prefix != null) {
+ String prefixSymbol = _symbols.getSymbol(prefix);
+ unit = _symbols.getUnit(token.image.substring(prefixSymbol.length()));
+ if (unit != null) {
+ {if (true) return unit.transform(prefix.getConverter());}
+ }
+ }
+ {if (true) throw new ParseException();}
+ } else {
+ {if (true) return unit;}
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+ final private boolean jj_2_1(int xla) {
+ jj_la = xla; jj_lastpos = jj_scanpos = token;
+ try { return !jj_3_1(); }
+ catch(LookaheadSuccess ls) { return true; }
+ finally { jj_save(0, xla); }
+ }
+
+ final private boolean jj_2_2(int xla) {
+ jj_la = xla; jj_lastpos = jj_scanpos = token;
+ try { return !jj_3_2(); }
+ catch(LookaheadSuccess ls) { return true; }
+ finally { jj_save(1, xla); }
+ }
+
+ final private boolean jj_3R_3() {
+ if (jj_scan_token(ATOM)) return true;
+ return false;
+ }
+
+ final private boolean jj_3_1() {
+ if (jj_3R_2()) return true;
+ if (jj_scan_token(ANNOTATION)) return true;
+ return false;
+ }
+
+ final private boolean jj_3R_2() {
+ Token xsp;
+ xsp = jj_scanpos;
+ if (jj_3R_4()) {
+ jj_scanpos = xsp;
+ if (jj_3R_5()) return true;
+ }
+ return false;
+ }
+
+ final private boolean jj_3R_5() {
+ if (jj_3R_3()) return true;
+ return false;
+ }
+
+ final private boolean jj_3R_4() {
+ if (jj_3R_3()) return true;
+ Token xsp;
+ xsp = jj_scanpos;
+ if (jj_scan_token(10)) jj_scanpos = xsp;
+ if (jj_scan_token(FACTOR)) return true;
+ return false;
+ }
+
+ final private boolean jj_3_2() {
+ if (jj_3R_3()) return true;
+ Token xsp;
+ xsp = jj_scanpos;
+ if (jj_scan_token(10)) jj_scanpos = xsp;
+ if (jj_scan_token(FACTOR)) return true;
+ return false;
+ }
+
+ public UCUMParserTokenManager token_source;
+ SimpleCharStream jj_input_stream;
+ public Token token, jj_nt;
+ private int jj_ntk;
+ private Token jj_scanpos, jj_lastpos;
+ private int jj_la;
+ public boolean lookingAhead = false;
+ private boolean jj_semLA;
+ private int jj_gen;
+ final private int[] jj_la1 = new int[5];
+ static private int[] jj_la1_0;
+ static {
+ jj_la1_0();
+ }
+ private static void jj_la1_0() {
+ jj_la1_0 = new int[] {0x1800,0x1800,0x7300,0x400,0x2000,};
+ }
+ final private JJCalls[] jj_2_rtns = new JJCalls[2];
+ private boolean jj_rescan = false;
+ private int jj_gc = 0;
+
+ public UCUMParser(java.io.InputStream stream) {
+ this(stream, null);
+ }
+ public UCUMParser(java.io.InputStream stream, String encoding) {
+ try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+ token_source = new UCUMParserTokenManager(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 5; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ public void ReInit(java.io.InputStream stream) {
+ ReInit(stream, null);
+ }
+ public void ReInit(java.io.InputStream stream, String encoding) {
+ try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+ token_source.ReInit(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 5; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ public UCUMParser(java.io.Reader stream) {
+ jj_input_stream = new SimpleCharStream(stream, 1, 1);
+ token_source = new UCUMParserTokenManager(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 5; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ public void ReInit(java.io.Reader stream) {
+ jj_input_stream.ReInit(stream, 1, 1);
+ token_source.ReInit(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 5; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ public UCUMParser(UCUMParserTokenManager tm) {
+ token_source = tm;
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 5; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ public void ReInit(UCUMParserTokenManager tm) {
+ token_source = tm;
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 5; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ final private Token jj_consume_token(int kind) throws ParseException {
+ Token oldToken;
+ if ((oldToken = token).next != null) token = token.next;
+ else token = token.next = token_source.getNextToken();
+ jj_ntk = -1;
+ if (token.kind == kind) {
+ jj_gen++;
+ if (++jj_gc > 100) {
+ jj_gc = 0;
+ for (int i = 0; i < jj_2_rtns.length; i++) {
+ JJCalls c = jj_2_rtns[i];
+ while (c != null) {
+ if (c.gen < jj_gen) c.first = null;
+ c = c.next;
+ }
+ }
+ }
+ return token;
+ }
+ token = oldToken;
+ jj_kind = kind;
+ throw generateParseException();
+ }
+
+ static private final class LookaheadSuccess extends java.lang.Error { }
+ final private LookaheadSuccess jj_ls = new LookaheadSuccess();
+ final private boolean jj_scan_token(int kind) {
+ if (jj_scanpos == jj_lastpos) {
+ jj_la--;
+ if (jj_scanpos.next == null) {
+ jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
+ } else {
+ jj_lastpos = jj_scanpos = jj_scanpos.next;
+ }
+ } else {
+ jj_scanpos = jj_scanpos.next;
+ }
+ if (jj_rescan) {
+ int i = 0; Token tok = token;
+ while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
+ if (tok != null) jj_add_error_token(kind, i);
+ }
+ if (jj_scanpos.kind != kind) return true;
+ if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
+ return false;
+ }
+
+ final public Token getNextToken() {
+ if (token.next != null) token = token.next;
+ else token = token.next = token_source.getNextToken();
+ jj_ntk = -1;
+ jj_gen++;
+ return token;
+ }
+
+ final public Token getToken(int index) {
+ Token t = lookingAhead ? jj_scanpos : token;
+ for (int i = 0; i < index; i++) {
+ if (t.next != null) t = t.next;
+ else t = t.next = token_source.getNextToken();
+ }
+ return t;
+ }
+
+ final private int jj_ntk() {
+ if ((jj_nt=token.next) == null)
+ return (jj_ntk = (token.next=token_source.getNextToken()).kind);
+ else
+ return (jj_ntk = jj_nt.kind);
+ }
+
+ private java.util.Vector jj_expentries = new java.util.Vector();
+ private int[] jj_expentry;
+ private int jj_kind = -1;
+ private int[] jj_lasttokens = new int[100];
+ private int jj_endpos;
+
+ private void jj_add_error_token(int kind, int pos) {
+ if (pos >= 100) return;
+ if (pos == jj_endpos + 1) {
+ jj_lasttokens[jj_endpos++] = kind;
+ } else if (jj_endpos != 0) {
+ jj_expentry = new int[jj_endpos];
+ for (int i = 0; i < jj_endpos; i++) {
+ jj_expentry[i] = jj_lasttokens[i];
+ }
+ boolean exists = false;
+ for (java.util.Enumeration e = jj_expentries.elements(); e.hasMoreElements();) {
+ int[] oldentry = (int[])(e.nextElement());
+ if (oldentry.length == jj_expentry.length) {
+ exists = true;
+ for (int i = 0; i < jj_expentry.length; i++) {
+ if (oldentry[i] != jj_expentry[i]) {
+ exists = false;
+ break;
+ }
+ }
+ if (exists) break;
+ }
+ }
+ if (!exists) jj_expentries.addElement(jj_expentry);
+ if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
+ }
+ }
+
+ public ParseException generateParseException() {
+ jj_expentries.removeAllElements();
+ boolean[] la1tokens = new boolean[16];
+ for (int i = 0; i < 16; i++) {
+ la1tokens[i] = false;
+ }
+ if (jj_kind >= 0) {
+ la1tokens[jj_kind] = true;
+ jj_kind = -1;
+ }
+ for (int i = 0; i < 5; i++) {
+ if (jj_la1[i] == jj_gen) {
+ for (int j = 0; j < 32; j++) {
+ if ((jj_la1_0[i] & (1<<j)) != 0) {
+ la1tokens[j] = true;
+ }
+ }
+ }
+ }
+ for (int i = 0; i < 16; i++) {
+ if (la1tokens[i]) {
+ jj_expentry = new int[1];
+ jj_expentry[0] = i;
+ jj_expentries.addElement(jj_expentry);
+ }
+ }
+ jj_endpos = 0;
+ jj_rescan_token();
+ jj_add_error_token(0, 0);
+ int[][] exptokseq = new int[jj_expentries.size()][];
+ for (int i = 0; i < jj_expentries.size(); i++) {
+ exptokseq[i] = (int[])jj_expentries.elementAt(i);
+ }
+ return new ParseException(token, exptokseq, tokenImage);
+ }
+
+ final public void enable_tracing() {
+ }
+
+ final public void disable_tracing() {
+ }
+
+ final private void jj_rescan_token() {
+ jj_rescan = true;
+ for (int i = 0; i < 2; i++) {
+ try {
+ JJCalls p = jj_2_rtns[i];
+ do {
+ if (p.gen > jj_gen) {
+ jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
+ switch (i) {
+ case 0: jj_3_1(); break;
+ case 1: jj_3_2(); break;
+ }
+ }
+ p = p.next;
+ } while (p != null);
+ } catch(LookaheadSuccess ls) { }
+ }
+ jj_rescan = false;
+ }
+
+ final private void jj_save(int index, int xla) {
+ JJCalls p = jj_2_rtns[index];
+ while (p.gen > jj_gen) {
+ if (p.next == null) { p = p.next = new JJCalls(); break; }
+ p = p.next;
+ }
+ p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
+ }
+
+ static final class JJCalls {
+ int gen;
+ Token first;
+ int arg;
+ JJCalls next;
+ }
+
+}
diff --git a/src/main/java/javax/measure/unit/format/UCUMParser.jj b/src/main/java/javax/measure/unit/format/UCUMParser.jj
new file mode 100644
index 0000000..4b8c137
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/UCUMParser.jj
@@ -0,0 +1,189 @@
+/*
+ * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
+ * Copyright (C) 2008 - JScience
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software is
+ * freely granted, provided that this notice is preserved.
+ */
+
+options {
+ STATIC = false;
+ DEBUG_PARSER = false;
+ DEBUG_LOOKAHEAD = false;
+ DEBUG_TOKEN_MANAGER = false;
+}
+
+PARSER_BEGIN(UCUMParser)
+
+package javax.measure.unit.ucum;
+
+/**
+ * <p>
+ * Parser definition for parsing {@link javax.measure.unit.Unit Unit}s
+ * according to the <a href="http://aurora.regenstrief.org/UCUM/ucum.html">
+ * Uniform Code for Units of Measure</a>.
+ *
+ * @author <a href="mailto:eric-r at northwestern.edu">Eric Russell</a>
+ * @version 1.0
+ * @see <a href="http://aurora.regenstrief.org/UCUM/ucum.html">UCUM</a>
+ */
+class UCUMParser {
+
+ private SymbolMap _symbols;
+
+ public UCUMParser (SymbolMap symbols, java.io.InputStream in) {
+ this(in);
+ _symbols = symbols;
+ }
+}
+
+PARSER_END(UCUMParser)
+
+//
+// Lexical entities
+//
+
+TOKEN: { <#ATOM_CHAR: ["!","#"-"'","*",",","0"-"Z","\\","^"-"z","|","~"] >
+ | <#ESCAPED_ATOM_CHAR: ["!"-"Z","\\","^"-"~"] >
+ | <#TERMINAL_ATOM_CHAR: ["!","#"-"'","*",",",":"-"Z","\\","^"-"z","|","~"] >
+ | <#LCBRACKET: "{" >
+ | <#RCBRACKET: "}" >
+ | <#LSBRACKET: "[" >
+ | <#RSBRACKET: "]" > }
+TOKEN: { <ANNOTATION: <LCBRACKET> (["!"-"z","|","~" ])* <RCBRACKET> > }
+TOKEN: { <FACTOR: (["0"-"9"])+ > }
+TOKEN: { <SIGN: ["+","-"] > }
+TOKEN: { <DOT: "."> }
+TOKEN: { <SOLIDUS: "/"> }
+TOKEN: { <ATOM: (((<ATOM_CHAR>)*
+ (<TERMINAL_ATOM_CHAR>)+) |
+ ((<ATOM_CHAR>)*
+ (<LSBRACKET> (<ESCAPED_ATOM_CHAR>)+ <RSBRACKET>)
+ ((<ATOM_CHAR>)*
+ (<TERMINAL_ATOM_CHAR>)+)?)) > }
+
+//
+// Parser productions
+//
+
+javax.measure.unit.Unit parseUnit () :
+ {
+ javax.measure.unit.Unit u;
+ }
+{
+ u=Term() <EOF>
+ { return u; }
+}
+
+javax.measure.unit.Unit Term () :
+ {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ javax.measure.unit.Unit temp = javax.measure.unit.Unit.ONE;
+ }
+{
+(
+ result=Component()
+ (
+ (<DOT> temp=Component() { result = result.times(temp); })
+ |
+ (<SOLIDUS> temp=Component() { result = result.divide(temp); })
+ )*
+ {
+ return result;
+ }
+)
+}
+
+javax.measure.unit.Unit Component () :
+ {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ Token token = null;
+ }
+{
+(
+ LOOKAHEAD(Annotatable() <ANNOTATION>)
+ result=Annotatable() token=<ANNOTATION>
+ {
+ return new AnnotatedUnit(result, token.image.substring(1, token.image.length()-1));
+ }
+|
+ result=Annotatable()
+ {
+ return result;
+ }
+|
+ token=<ANNOTATION>
+ {
+ return new AnnotatedUnit(result, token.image.substring(1, token.image.length()-1));
+ }
+|
+ token=<FACTOR>
+ {
+ long factor = Long.parseLong(token.image);
+ return result.times(factor);
+ }
+|
+ <SOLIDUS> result=Component()
+ {
+ return javax.measure.unit.Unit.ONE.divide(result);
+ }
+|
+ "(" result=Term() ")"
+ {
+ return result;
+ }
+)
+}
+
+javax.measure.unit.Unit Annotatable () :
+ {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ Token token1 = null;
+ Token token2 = null;
+ }
+{
+(
+ LOOKAHEAD(SimpleUnit() (<SIGN>)? <FACTOR>)
+ result=SimpleUnit() (token1=<SIGN>)? token2=<FACTOR>
+ {
+ int exponent = Integer.parseInt(token2.image);
+ if ((token1 != null) && token1.image.equals("-")) {
+ return result.pow(-exponent);
+ } else {
+ return result.pow(exponent);
+ }
+ }
+|
+ result=SimpleUnit()
+ {
+ return result;
+ }
+)
+}
+
+javax.measure.unit.Unit SimpleUnit () :
+ {
+ Token token = null;
+ }
+{
+(
+ token=<ATOM>
+ {
+ javax.measure.unit.Unit unit = _symbols.getUnit(token.image);
+ if (unit == null) {
+ Prefix prefix = _symbols.getPrefix(token.image);
+ if (prefix != null) {
+ String prefixSymbol = _symbols.getSymbol(prefix);
+ unit = _symbols.getUnit(token.image.substring(prefixSymbol.length()));
+ if (unit != null) {
+ return unit.transform(prefix.getConverter());
+ }
+ }
+ throw new ParseException();
+ } else {
+ return unit;
+ }
+ }
+)
+}
diff --git a/src/main/java/javax/measure/unit/format/UCUMParserConstants.java b/src/main/java/javax/measure/unit/format/UCUMParserConstants.java
new file mode 100644
index 0000000..f2f39c9
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/UCUMParserConstants.java
@@ -0,0 +1,42 @@
+/* Generated By:JavaCC: Do not edit this line. UCUMParserConstants.java */
+package javax.measure.unit.format;
+
+interface UCUMParserConstants {
+
+ int EOF = 0;
+ int ATOM_CHAR = 1;
+ int ESCAPED_ATOM_CHAR = 2;
+ int TERMINAL_ATOM_CHAR = 3;
+ int LCBRACKET = 4;
+ int RCBRACKET = 5;
+ int LSBRACKET = 6;
+ int RSBRACKET = 7;
+ int ANNOTATION = 8;
+ int FACTOR = 9;
+ int SIGN = 10;
+ int DOT = 11;
+ int SOLIDUS = 12;
+ int ATOM = 13;
+
+ int DEFAULT = 0;
+
+ String[] tokenImage = {
+ "<EOF>",
+ "<ATOM_CHAR>",
+ "<ESCAPED_ATOM_CHAR>",
+ "<TERMINAL_ATOM_CHAR>",
+ "\"{\"",
+ "\"}\"",
+ "\"[\"",
+ "\"]\"",
+ "<ANNOTATION>",
+ "<FACTOR>",
+ "<SIGN>",
+ "\".\"",
+ "\"/\"",
+ "<ATOM>",
+ "\"(\"",
+ "\")\"",
+ };
+
+}
diff --git a/src/main/java/javax/measure/unit/format/UCUMParserTokenManager.java b/src/main/java/javax/measure/unit/format/UCUMParserTokenManager.java
new file mode 100644
index 0000000..8b705be
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/UCUMParserTokenManager.java
@@ -0,0 +1,399 @@
+/* Generated By:JavaCC: Do not edit this line. UCUMParserTokenManager.java */
+package javax.measure.unit.format;
+
+class UCUMParserTokenManager implements UCUMParserConstants
+{
+ public java.io.PrintStream debugStream = System.out;
+ public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
+private final int jjStopStringLiteralDfa_0(int pos, long active0)
+{
+ switch (pos)
+ {
+ default :
+ return -1;
+ }
+}
+private final int jjStartNfa_0(int pos, long active0)
+{
+ return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
+}
+private final int jjStopAtPos(int pos, int kind)
+{
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ return pos + 1;
+}
+private final int jjStartNfaWithStates_0(int pos, int kind, int state)
+{
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return pos + 1; }
+ return jjMoveNfa_0(state, pos + 1);
+}
+private final int jjMoveStringLiteralDfa0_0()
+{
+ switch(curChar)
+ {
+ case 40:
+ return jjStopAtPos(0, 14);
+ case 41:
+ return jjStopAtPos(0, 15);
+ case 46:
+ return jjStopAtPos(0, 11);
+ case 47:
+ return jjStopAtPos(0, 12);
+ default :
+ return jjMoveNfa_0(0, 0);
+ }
+}
+private final void jjCheckNAdd(int state)
+{
+ if (jjrounds[state] != jjround)
+ {
+ jjstateSet[jjnewStateCnt++] = state;
+ jjrounds[state] = jjround;
+ }
+}
+private final void jjAddStates(int start, int end)
+{
+ do {
+ jjstateSet[jjnewStateCnt++] = jjnextStates[start];
+ } while (start++ != end);
+}
+private final void jjCheckNAddTwoStates(int state1, int state2)
+{
+ jjCheckNAdd(state1);
+ jjCheckNAdd(state2);
+}
+private final void jjCheckNAddStates(int start, int end)
+{
+ do {
+ jjCheckNAdd(jjnextStates[start]);
+ } while (start++ != end);
+}
+private final void jjCheckNAddStates(int start)
+{
+ jjCheckNAdd(jjnextStates[start]);
+ jjCheckNAdd(jjnextStates[start + 1]);
+}
+private final int jjMoveNfa_0(int startState, int curPos)
+{
+ int[] nextStates;
+ int startsAt = 0;
+ jjnewStateCnt = 14;
+ int i = 1;
+ jjstateSet[0] = startState;
+ int j, kind = 0x7fffffff;
+ for (;;)
+ {
+ if (++jjround == 0x7fffffff)
+ ReInitRounds();
+ if (curChar < 64)
+ {
+ long l = 1L << curChar;
+ MatchLoop: do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ if ((0xffff14fa00000000L & l) != 0L)
+ jjCheckNAddStates(0, 3);
+ else if ((0x280000000000L & l) != 0L)
+ {
+ if (kind > 10)
+ kind = 10;
+ }
+ if ((0xfc0014fa00000000L & l) != 0L)
+ {
+ if (kind > 13)
+ kind = 13;
+ jjCheckNAdd(5);
+ }
+ else if ((0x3ff000000000000L & l) != 0L)
+ {
+ if (kind > 9)
+ kind = 9;
+ jjCheckNAdd(3);
+ }
+ break;
+ case 1:
+ if ((0xfffffffe00000000L & l) != 0L)
+ jjAddStates(4, 5);
+ break;
+ case 3:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 9)
+ kind = 9;
+ jjCheckNAdd(3);
+ break;
+ case 4:
+ if ((0x280000000000L & l) != 0L && kind > 10)
+ kind = 10;
+ break;
+ case 5:
+ if ((0xfc0014fa00000000L & l) == 0L)
+ break;
+ if (kind > 13)
+ kind = 13;
+ jjCheckNAdd(5);
+ break;
+ case 7:
+ if ((0xfffffffe00000000L & l) != 0L)
+ jjAddStates(6, 7);
+ break;
+ case 9:
+ if ((0xffff14fa00000000L & l) != 0L)
+ jjCheckNAddTwoStates(9, 10);
+ break;
+ case 10:
+ if ((0xfc0014fa00000000L & l) == 0L)
+ break;
+ if (kind > 13)
+ kind = 13;
+ jjCheckNAdd(10);
+ break;
+ case 11:
+ if ((0xffff14fa00000000L & l) != 0L)
+ jjCheckNAddStates(0, 3);
+ break;
+ case 12:
+ if ((0xffff14fa00000000L & l) != 0L)
+ jjCheckNAddTwoStates(12, 5);
+ break;
+ case 13:
+ if ((0xffff14fa00000000L & l) != 0L)
+ jjCheckNAddTwoStates(13, 6);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ long l = 1L << (curChar & 077);
+ MatchLoop: do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ if ((0x57ffffffd7ffffffL & l) != 0L)
+ jjCheckNAddStates(0, 3);
+ else if (curChar == 91)
+ jjCheckNAdd(7);
+ else if (curChar == 123)
+ jjCheckNAddTwoStates(1, 2);
+ if ((0x57ffffffd7ffffffL & l) != 0L)
+ {
+ if (kind > 13)
+ kind = 13;
+ jjCheckNAdd(5);
+ }
+ break;
+ case 1:
+ if ((0x57ffffffffffffffL & l) != 0L)
+ jjCheckNAddTwoStates(1, 2);
+ break;
+ case 2:
+ if (curChar == 125 && kind > 8)
+ kind = 8;
+ break;
+ case 5:
+ if ((0x57ffffffd7ffffffL & l) == 0L)
+ break;
+ if (kind > 13)
+ kind = 13;
+ jjCheckNAdd(5);
+ break;
+ case 6:
+ if (curChar == 91)
+ jjCheckNAdd(7);
+ break;
+ case 7:
+ if ((0x7fffffffd7ffffffL & l) != 0L)
+ jjCheckNAddTwoStates(7, 8);
+ break;
+ case 8:
+ if (curChar != 93)
+ break;
+ if (kind > 13)
+ kind = 13;
+ jjCheckNAddTwoStates(9, 10);
+ break;
+ case 9:
+ if ((0x57ffffffd7ffffffL & l) != 0L)
+ jjCheckNAddTwoStates(9, 10);
+ break;
+ case 10:
+ if ((0x57ffffffd7ffffffL & l) == 0L)
+ break;
+ if (kind > 13)
+ kind = 13;
+ jjCheckNAdd(10);
+ break;
+ case 11:
+ if ((0x57ffffffd7ffffffL & l) != 0L)
+ jjCheckNAddStates(0, 3);
+ break;
+ case 12:
+ if ((0x57ffffffd7ffffffL & l) != 0L)
+ jjCheckNAddTwoStates(12, 5);
+ break;
+ case 13:
+ if ((0x57ffffffd7ffffffL & l) != 0L)
+ jjCheckNAddTwoStates(13, 6);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else
+ {
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 1L << (curChar & 077);
+ MatchLoop: do
+ {
+ switch(jjstateSet[--i])
+ {
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 14 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return curPos; }
+ }
+}
+static final int[] jjnextStates = {
+ 12, 5, 13, 6, 1, 2, 7, 8,
+};
+public static final String[] jjstrLiteralImages = {
+"", null, null, null, null, null, null, null, null, null, null, "\56", "\57",
+null, "\50", "\51", };
+public static final String[] lexStateNames = {
+ "DEFAULT",
+};
+protected SimpleCharStream input_stream;
+private final int[] jjrounds = new int[14];
+private final int[] jjstateSet = new int[28];
+protected char curChar;
+public UCUMParserTokenManager(SimpleCharStream stream){
+ if (SimpleCharStream.staticFlag)
+ throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+ input_stream = stream;
+}
+public UCUMParserTokenManager(SimpleCharStream stream, int lexState){
+ this(stream);
+ SwitchTo(lexState);
+}
+public void ReInit(SimpleCharStream stream)
+{
+ jjmatchedPos = jjnewStateCnt = 0;
+ curLexState = defaultLexState;
+ input_stream = stream;
+ ReInitRounds();
+}
+private final void ReInitRounds()
+{
+ int i;
+ jjround = 0x80000001;
+ for (i = 14; i-- > 0;)
+ jjrounds[i] = 0x80000000;
+}
+public void ReInit(SimpleCharStream stream, int lexState)
+{
+ ReInit(stream);
+ SwitchTo(lexState);
+}
+public void SwitchTo(int lexState)
+{
+ if (lexState >= 1 || lexState < 0)
+ throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+ else
+ curLexState = lexState;
+}
+
+protected Token jjFillToken()
+{
+ Token t = Token.newToken(jjmatchedKind);
+ t.kind = jjmatchedKind;
+ String im = jjstrLiteralImages[jjmatchedKind];
+ t.image = (im == null) ? input_stream.GetImage() : im;
+ t.beginLine = input_stream.getBeginLine();
+ t.beginColumn = input_stream.getBeginColumn();
+ t.endLine = input_stream.getEndLine();
+ t.endColumn = input_stream.getEndColumn();
+ return t;
+}
+
+int curLexState = 0;
+int defaultLexState = 0;
+int jjnewStateCnt;
+int jjround;
+int jjmatchedPos;
+int jjmatchedKind;
+
+public Token getNextToken()
+{
+ int kind;
+ Token specialToken = null;
+ Token matchedToken;
+ int curPos = 0;
+
+ EOFLoop :
+ for (;;)
+ {
+ try
+ {
+ curChar = input_stream.BeginToken();
+ }
+ catch(java.io.IOException e)
+ {
+ jjmatchedKind = 0;
+ matchedToken = jjFillToken();
+ return matchedToken;
+ }
+
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_0();
+ if (jjmatchedKind != 0x7fffffff)
+ {
+ if (jjmatchedPos + 1 < curPos)
+ input_stream.backup(curPos - jjmatchedPos - 1);
+ matchedToken = jjFillToken();
+ return matchedToken;
+ }
+ int error_line = input_stream.getEndLine();
+ int error_column = input_stream.getEndColumn();
+ String error_after = null;
+ boolean EOFSeen = false;
+ try { input_stream.readChar(); input_stream.backup(1); }
+ catch (java.io.IOException e1) {
+ EOFSeen = true;
+ error_after = curPos <= 1 ? "" : input_stream.GetImage();
+ if (curChar == '\n' || curChar == '\r') {
+ error_line++;
+ error_column = 0;
+ }
+ else
+ error_column++;
+ }
+ if (!EOFSeen) {
+ input_stream.backup(1);
+ error_after = curPos <= 1 ? "" : input_stream.GetImage();
+ }
+ throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
+ }
+}
+
+}
diff --git a/src/main/java/javax/measure/unit/format/UCUM_CI.properties b/src/main/java/javax/measure/unit/format/UCUM_CI.properties
new file mode 100644
index 0000000..6d04469
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/UCUM_CI.properties
@@ -0,0 +1,248 @@
+
+# Prefixes
+
+javax.measure.unit.format.Prefix.YOTTA=YA
+javax.measure.unit.format.Prefix.ZETTA=ZA
+javax.measure.unit.format.Prefix.EXA=EX
+javax.measure.unit.format.Prefix.PETA=PT
+javax.measure.unit.format.Prefix.TERA=TR
+javax.measure.unit.format.Prefix.GIGA=GA
+javax.measure.unit.format.Prefix.MEGA=MA
+javax.measure.unit.format.Prefix.KILO=K
+javax.measure.unit.format.Prefix.HECTO=H
+javax.measure.unit.format.Prefix.DEKA=DA
+javax.measure.unit.format.Prefix.DECI=D
+javax.measure.unit.format.Prefix.CENTI=C
+javax.measure.unit.format.Prefix.MILLI=M
+javax.measure.unit.format.Prefix.MICRO=U
+javax.measure.unit.format.Prefix.NANO=N
+javax.measure.unit.format.Prefix.PICO=P
+javax.measure.unit.format.Prefix.FEMTO=F
+javax.measure.unit.format.Prefix.ATTO=A
+javax.measure.unit.format.Prefix.ZEPTO=ZO
+javax.measure.unit.format.Prefix.YOCTO=YO
+
+# Units
+
+javax.measure.unit.format.UCUM.METER=M
+javax.measure.unit.format.UCUM.SECOND=S
+javax.measure.unit.format.UCUM.GRAM=G
+javax.measure.unit.format.UCUM.RADIAN=RAD
+javax.measure.unit.format.UCUM.KELVIN=K
+javax.measure.unit.format.UCUM.COULOMB=C
+javax.measure.unit.format.UCUM.CANDELA=CD
+javax.measure.unit.format.UCUM.TRIILLIONS=10^12
+javax.measure.unit.format.UCUM.BILLIONS=10^9
+javax.measure.unit.format.UCUM.MILLIONS=10^6
+javax.measure.unit.format.UCUM.THOUSANDS=10^3
+javax.measure.unit.format.UCUM.HUNDREDS=10^2
+javax.measure.unit.format.UCUM.PI=[PI]
+javax.measure.unit.format.UCUM.PERCENT=%
+javax.measure.unit.format.UCUM.PER_THOUSAND=[PPTH]
+javax.measure.unit.format.UCUM.PER_MILLION=[PPM]
+javax.measure.unit.format.UCUM.PER_BILLION=[PPB]
+javax.measure.unit.format.UCUM.PER_TRILLION=[PPTR]
+javax.measure.unit.format.UCUM.MOLE=MOL
+javax.measure.unit.format.UCUM.STERADIAN=SR
+javax.measure.unit.format.UCUM.HERTZ=HZ
+javax.measure.unit.format.UCUM.NEWTON=N
+javax.measure.unit.format.UCUM.PASCAL=PAL
+javax.measure.unit.format.UCUM.JOULE=J
+javax.measure.unit.format.UCUM.WATT=W
+javax.measure.unit.format.UCUM.AMPERE=A
+javax.measure.unit.format.UCUM.VOLT=V
+javax.measure.unit.format.UCUM.FARAD=F
+javax.measure.unit.format.UCUM.OHM=OHM
+javax.measure.unit.format.UCUM.SIEMENS=SIE
+javax.measure.unit.format.UCUM.WEBER=WB
+javax.measure.unit.format.UCUM.CELSIUS=CEL
+javax.measure.unit.format.UCUM.TESLA=T
+javax.measure.unit.format.UCUM.HENRY=H
+javax.measure.unit.format.UCUM.LUMEN=LM
+javax.measure.unit.format.UCUM.LUX=LX
+javax.measure.unit.format.UCUM.BECQUEREL=BQ
+javax.measure.unit.format.UCUM.GRAY=GY
+javax.measure.unit.format.UCUM.SIEVERT=SV
+javax.measure.unit.format.UCUM.DEGREE=DEG
+javax.measure.unit.format.UCUM.GRADE=GON
+javax.measure.unit.format.UCUM.MINUTE_ANGLE='
+javax.measure.unit.format.UCUM.SECOND_ANGLE=''
+javax.measure.unit.format.UCUM.LITER=L
+javax.measure.unit.format.UCUM.ARE=AR
+javax.measure.unit.format.UCUM.MINUTE=MIN
+javax.measure.unit.format.UCUM.HOUR=HR
+javax.measure.unit.format.UCUM.DAY=D
+javax.measure.unit.format.UCUM.YEAR_TROPICAL=ANN_T
+javax.measure.unit.format.UCUM.YEAR_JULIAN=ANN_J
+javax.measure.unit.format.UCUM.YEAR_GREGORIAN=ANN_G
+javax.measure.unit.format.UCUM.YEAR=ANN
+javax.measure.unit.format.UCUM.MONTH_SYNODAL=MO_S
+javax.measure.unit.format.UCUM.MONTH_JULIAN=MO_J
+javax.measure.unit.format.UCUM.MONTH_GREGORIAN=MO_G
+javax.measure.unit.format.UCUM.MONTH=MO
+javax.measure.unit.format.UCUM.TONNE=TNE
+javax.measure.unit.format.UCUM.BAR=BAR
+javax.measure.unit.format.UCUM.ATOMIC_MASS_UNIT=AMU
+javax.measure.unit.format.UCUM.ELECTRON_VOLT=EV
+javax.measure.unit.format.UCUM.ASTRONOMIC_UNIT=ASU
+javax.measure.unit.format.UCUM.PARSEC=PRS
+javax.measure.unit.format.UCUM.C=[C]
+javax.measure.unit.format.UCUM.PLANCK=[H]
+javax.measure.unit.format.UCUM.BOLTZMAN=[K]
+javax.measure.unit.format.UCUM.PERMITTIVITY_OF_VACUUM=[EPS_0]
+javax.measure.unit.format.UCUM.PERMEABILITY_OF_VACUUM=[MU_0]
+javax.measure.unit.format.UCUM.ELEMENTARY_CHARGE=[E]
+javax.measure.unit.format.UCUM.ELECTRON_MASS=[M_E]
+javax.measure.unit.format.UCUM.PROTON_MASS=[M_P]
+javax.measure.unit.format.UCUM.NEWTON_CONSTANT_OF_GRAVITY=[GC]
+javax.measure.unit.format.UCUM.ACCELLERATION_OF_FREEFALL=[G]
+javax.measure.unit.format.UCUM.ATMOSPHERE=ATM
+javax.measure.unit.format.UCUM.LIGHT_YEAR=[LY]
+javax.measure.unit.format.UCUM.GRAM_FORCE=GF
+javax.measure.unit.format.UCUM.KAYSER=KY
+javax.measure.unit.format.UCUM.GAL=GL
+javax.measure.unit.format.UCUM.DYNE=DYN
+javax.measure.unit.format.UCUM.ERG=ERG
+javax.measure.unit.format.UCUM.POISE=P
+javax.measure.unit.format.UCUM.BIOT=BI
+javax.measure.unit.format.UCUM.STOKES=ST
+javax.measure.unit.format.UCUM.MAXWELL=MX
+javax.measure.unit.format.UCUM.GAUSS=GS
+javax.measure.unit.format.UCUM.OERSTED=OE
+javax.measure.unit.format.UCUM.GILBERT=GB
+javax.measure.unit.format.UCUM.STILB=SB
+javax.measure.unit.format.UCUM.LAMBERT=LMB
+javax.measure.unit.format.UCUM.PHOT=PHT
+javax.measure.unit.format.UCUM.CURIE=CI
+javax.measure.unit.format.UCUM.ROENTGEN=ROE
+javax.measure.unit.format.UCUM.RAD=[RAD]
+javax.measure.unit.format.UCUM.REM=[REM]
+javax.measure.unit.format.UCUM.INCH_INTERNATIONAL=[IN_I]
+javax.measure.unit.format.UCUM.FOOT_INTERNATIONAL=[FT_I]
+javax.measure.unit.format.UCUM.YARD_INTERNATIONAL=[YD_I]
+javax.measure.unit.format.UCUM.MILE_INTERNATIONAL=[MI_I]
+javax.measure.unit.format.UCUM.FATHOM_INTERNATIONAL=[FTH_I]
+javax.measure.unit.format.UCUM.NAUTICAL_MILE_INTERNATIONAL=[NMI_I]
+javax.measure.unit.format.UCUM.KNOT_INTERNATIONAL=[KN_I]
+javax.measure.unit.format.UCUM.SQUARE_INCH_INTERNATIONAL=[SIN_I]
+javax.measure.unit.format.UCUM.SQUARE_FOOT_INTERNATIONAL=[SFT_I]
+javax.measure.unit.format.UCUM.SQUARE_YARD_INTERNATIONAL=[SYD_I]
+javax.measure.unit.format.UCUM.CUBIC_INCH_INTERNATIONAL=[CIN_I]
+javax.measure.unit.format.UCUM.CUBIC_FOOT_INTERNATIONAL=[CFT_I]
+javax.measure.unit.format.UCUM.CUBIC_YARD_INTERNATIONAL=[CYD_I]
+javax.measure.unit.format.UCUM.BOARD_FOOT_INTERNATIONAL=[BF_I]
+javax.measure.unit.format.UCUM.CORD_INTERNATIONAL=[CR_I]
+javax.measure.unit.format.UCUM.MIL_INTERNATIONAL=[MIL_I]
+javax.measure.unit.format.UCUM.CIRCULAR_MIL_INTERNATIONAL=[CML_I]
+javax.measure.unit.format.UCUM.HAND_INTERNATIONAL=[HD_I]
+javax.measure.unit.format.UCUM.FOOT_US_SURVEY=[FT_US]
+javax.measure.unit.format.UCUM.YARD_US_SURVEY=[YD_US]
+javax.measure.unit.format.UCUM.INCH_US_SURVEY=[IN_US]
+javax.measure.unit.format.UCUM.ROD_US_SURVEY=[RD_US]
+javax.measure.unit.format.UCUM.CHAIN_US_SURVEY=[CH_US]
+javax.measure.unit.format.UCUM.LINK_US_SURVEY=[LK_US]
+javax.measure.unit.format.UCUM.RAMDEN_CHAIN_US_SURVEY=[RCH_US]
+javax.measure.unit.format.UCUM.RAMDEN_LINK_US_SURVEY=[RLK_US]
+javax.measure.unit.format.UCUM.FATHOM_US_SURVEY=[FTH_US]
+javax.measure.unit.format.UCUM.FURLONG_US_SURVEY=[FUR_US]
+javax.measure.unit.format.UCUM.MILE_US_SURVEY=[MI_US]
+javax.measure.unit.format.UCUM.ACRE_US_SURVEY=[ACR_US]
+javax.measure.unit.format.UCUM.SQUARE_ROD_US_SURVEY=[SRD_US]
+javax.measure.unit.format.UCUM.SQUARE_MILE_US_SURVEY=[SMI_US]
+javax.measure.unit.format.UCUM.SECTION_US_SURVEY=[SCT]
+javax.measure.unit.format.UCUM.TOWNSHP_US_SURVEY=[TWP]
+javax.measure.unit.format.UCUM.MIL_US_SURVEY=[MIL_US]
+javax.measure.unit.format.UCUM.INCH_BRITISH=[IN_BR]
+javax.measure.unit.format.UCUM.FOOT_BRITISH=[FT_BR]
+javax.measure.unit.format.UCUM.ROD_BRITISH=[RD_BR]
+javax.measure.unit.format.UCUM.CHAIN_BRITISH=[CH_BR]
+javax.measure.unit.format.UCUM.LINK_BRITISH=[LK_BR]
+javax.measure.unit.format.UCUM.FATHOM_BRITISH=[FTH_BR]
+javax.measure.unit.format.UCUM.PACE_BRITISH=[PC_BR]
+javax.measure.unit.format.UCUM.YARD_BRITISH=[YD_BR]
+javax.measure.unit.format.UCUM.MILE_BRITISH=[MI_BR]
+javax.measure.unit.format.UCUM.NAUTICAL_MILE_BRITISH=[NMI_BR]
+javax.measure.unit.format.UCUM.KNOT_BRITISH=[KN_BR]
+javax.measure.unit.format.UCUM.ACRE_BRITISH=[ACR_BR]
+javax.measure.unit.format.UCUM.GALLON_US=[GAL_US]
+javax.measure.unit.format.UCUM.BARREL_US=[BBL_US]
+javax.measure.unit.format.UCUM.QUART_US=[QT_US]
+javax.measure.unit.format.UCUM.PINT_US=[PT_US]
+javax.measure.unit.format.UCUM.GILL_US=[GIL_US]
+javax.measure.unit.format.UCUM.FLUID_OUNCE_US=[FOZ_US]
+javax.measure.unit.format.UCUM.FLUID_DRAM_US=[FDR_US]
+javax.measure.unit.format.UCUM.MINIM_US=[MIN_US]
+javax.measure.unit.format.UCUM.CORD_US=[CRD_US]
+javax.measure.unit.format.UCUM.BUSHEL_US=[BU_US]
+javax.measure.unit.format.UCUM.GALLON_WINCHESTER=[GAL_WI]
+javax.measure.unit.format.UCUM.PECK_US=[PK_US]
+javax.measure.unit.format.UCUM.DRY_QUART_US=[DQT_US]
+javax.measure.unit.format.UCUM.DRY_PINT_US=[DPT_US]
+javax.measure.unit.format.UCUM.TABLESPOON_US=[TBS_US]
+javax.measure.unit.format.UCUM.TEASPOON_US=[TSP_US]
+javax.measure.unit.format.UCUM.CUP_US=[CUP_US]
+javax.measure.unit.format.UCUM.GALLON_BRITISH=[GAL_BR]
+javax.measure.unit.format.UCUM.PECK_BRITISH=[PK_BR]
+javax.measure.unit.format.UCUM.BUSHEL_BRITISH=[BU_BR]
+javax.measure.unit.format.UCUM.QUART_BRITISH=[QT_BR]
+javax.measure.unit.format.UCUM.PINT_BRITISH=[PT_BR]
+javax.measure.unit.format.UCUM.GILL_BRITISH=[GIL_BR]
+javax.measure.unit.format.UCUM.FLUID_OUNCE_BRITISH=[FOZ_BR]
+javax.measure.unit.format.UCUM.FLUID_DRAM_BRITISH=[FDR_BR]
+javax.measure.unit.format.UCUM.MINIM_BRITISH=[MIN_BR]
+javax.measure.unit.format.UCUM.GRAIN=[GR]
+javax.measure.unit.format.UCUM.POUND=[LB_AV]
+javax.measure.unit.format.UCUM.OUNCE=[OZ_AV]
+javax.measure.unit.format.UCUM.DRAM=[DR_AV]
+javax.measure.unit.format.UCUM.SHORT_HUNDREDWEIGHT=[SCWT_AV]
+javax.measure.unit.format.UCUM.LONG_HUNDREDWEIGHT=[LCWT_AV]
+javax.measure.unit.format.UCUM.SHORT_TON=[STON_AV]
+javax.measure.unit.format.UCUM.LONG_TON=[LTON_AV]
+javax.measure.unit.format.UCUM.STONE=[STONE_AV]
+javax.measure.unit.format.UCUM.POUND_FORCE=[LBF_AV]
+javax.measure.unit.format.UCUM.PENNYWEIGHT_TROY=[PWT_TR]
+javax.measure.unit.format.UCUM.OUNCE_TROY=[OZ_TR]
+javax.measure.unit.format.UCUM.POUND_TROY=[LB_TR]
+javax.measure.unit.format.UCUM.SCRUPLE_APOTHECARY=[SC_AP]
+javax.measure.unit.format.UCUM.DRAM_APOTHECARY=[DR_AP]
+javax.measure.unit.format.UCUM.OUNCE_APOTHECARY=[OZ_AP]
+javax.measure.unit.format.UCUM.POUND_APOTHECARY=[LB_AP]
+javax.measure.unit.format.UCUM.LINE=[LNE]
+javax.measure.unit.format.UCUM.POINT=[PNT]
+javax.measure.unit.format.UCUM.PICA=[PCA]
+javax.measure.unit.format.UCUM.POINT_PRINTER=[PNT_PR]
+javax.measure.unit.format.UCUM.PICA_PRINTER=[PCA_PR]
+javax.measure.unit.format.UCUM.PIED=[PIED]
+javax.measure.unit.format.UCUM.POUCE=[POUCE]
+javax.measure.unit.format.UCUM.LINGE=[LIGNE]
+javax.measure.unit.format.UCUM.DIDOT=[DIDOT]
+javax.measure.unit.format.UCUM.CICERO=[CICERO]
+javax.measure.unit.format.UCUM.FAHRENHEIT=[DEGF]
+javax.measure.unit.format.UCUM.CALORIE_AT_15C=CAL_[15]
+javax.measure.unit.format.UCUM.CALORIE_AT_20C=CAL_[20]
+javax.measure.unit.format.UCUM.CALORIE_MEAN=CAL_M
+javax.measure.unit.format.UCUM.CALORIE_INTERNATIONAL_TABLE=CAL_IT
+javax.measure.unit.format.UCUM.CALORIE_THERMOCHEMICAL=CAL_TH
+javax.measure.unit.format.UCUM.CALORIE=CAL
+javax.measure.unit.format.UCUM.CALORIE_FOOD=[CAL]
+javax.measure.unit.format.UCUM.BTU_AT_39F=[BTU_39]
+javax.measure.unit.format.UCUM.BTU_AT_59F=[BTU_59]
+javax.measure.unit.format.UCUM.BTU_AT_60F=[BTU_60]
+javax.measure.unit.format.UCUM.BTU_MEAN=[BTU_M]
+javax.measure.unit.format.UCUM.BTU_INTERNATIONAL_TABLE=[BTU_IT]
+javax.measure.unit.format.UCUM.BTU_THERMOCHEMICAL=[BTU_TH]
+javax.measure.unit.format.UCUM.BTU=[BTU]
+javax.measure.unit.format.UCUM.HORSEPOWER=[HP]
+javax.measure.unit.format.UCUM.STERE=STR
+javax.measure.unit.format.UCUM.ANGSTROM=AO
+javax.measure.unit.format.UCUM.BARN=BRN
+javax.measure.unit.format.UCUM.ATMOSPHERE_TECHNICAL=ATT
+javax.measure.unit.format.UCUM.MHO=MHO
+javax.measure.unit.format.UCUM.POUND_PER_SQUARE_INCH=[PSI]
+javax.measure.unit.format.UCUM.CIRCLE=CIRC
+javax.measure.unit.format.UCUM.SPHERE=SPH
+javax.measure.unit.format.UCUM.CARAT_METRIC=[CAR_M]
+javax.measure.unit.format.UCUM.CARAT_GOLD=[CAR_AU]
+javax.measure.unit.format.UCUM.BIT=BIT
+javax.measure.unit.format.UCUM.BYTE=BY
+javax.measure.unit.format.UCUM.BAUD=Bd
diff --git a/src/main/java/javax/measure/unit/format/UCUM_CS.properties b/src/main/java/javax/measure/unit/format/UCUM_CS.properties
new file mode 100644
index 0000000..0b9b331
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/UCUM_CS.properties
@@ -0,0 +1,250 @@
+
+# Prefixes
+
+javax.measure.unit.format.Prefix.YOTTA=Y
+javax.measure.unit.format.Prefix.ZETTA=Z
+javax.measure.unit.format.Prefix.EXA=E
+javax.measure.unit.format.Prefix.PETA=P
+javax.measure.unit.format.Prefix.TERA=T
+javax.measure.unit.format.Prefix.GIGA=G
+javax.measure.unit.format.Prefix.MEGA=M
+javax.measure.unit.format.Prefix.KILO=k
+javax.measure.unit.format.Prefix.HECTO=h
+javax.measure.unit.format.Prefix.DEKA=da
+javax.measure.unit.format.Prefix.DECI=d
+javax.measure.unit.format.Prefix.CENTI=c
+javax.measure.unit.format.Prefix.MILLI=m
+javax.measure.unit.format.Prefix.MICRO=u
+javax.measure.unit.format.Prefix.NANO=n
+javax.measure.unit.format.Prefix.PICO=p
+javax.measure.unit.format.Prefix.FEMTO=f
+javax.measure.unit.format.Prefix.ATTO=a
+javax.measure.unit.format.Prefix.ZEPTO=z
+javax.measure.unit.format.Prefix.YOCTO=y
+
+# Units
+
+javax.measure.unit.format.UCUM.METER=m
+javax.measure.unit.format.UCUM.SECOND=s
+javax.measure.unit.format.UCUM.GRAM=g
+javax.measure.unit.format.UCUM.RADIAN=rad
+javax.measure.unit.format.UCUM.KELVIN=K
+javax.measure.unit.format.UCUM.COULOMB=C
+javax.measure.unit.format.UCUM.CANDELA=cd
+javax.measure.unit.format.UCUM.TRIILLIONS=10^12
+javax.measure.unit.format.UCUM.BILLIONS=10^9
+javax.measure.unit.format.UCUM.MILLIONS=10^6
+javax.measure.unit.format.UCUM.THOUSANDS=10^3
+javax.measure.unit.format.UCUM.HUNDREDS=10^2
+javax.measure.unit.format.UCUM.PI=[pi]
+javax.measure.unit.format.UCUM.PERCENT=%
+javax.measure.unit.format.UCUM.PER_THOUSAND=[ppth]
+javax.measure.unit.format.UCUM.PER_MILLION=[ppm]
+javax.measure.unit.format.UCUM.PER_BILLION=[ppb]
+javax.measure.unit.format.UCUM.PER_TRILLION=[pptr]
+javax.measure.unit.format.UCUM.MOLE=mol
+javax.measure.unit.format.UCUM.STERADIAN=sr
+javax.measure.unit.format.UCUM.HERTZ=Hz
+javax.measure.unit.format.UCUM.NEWTON=N
+javax.measure.unit.format.UCUM.PASCAL=Pa
+javax.measure.unit.format.UCUM.JOULE=J
+javax.measure.unit.format.UCUM.WATT=W
+javax.measure.unit.format.UCUM.AMPERE=A
+javax.measure.unit.format.UCUM.VOLT=V
+javax.measure.unit.format.UCUM.FARAD=F
+javax.measure.unit.format.UCUM.OHM=Ohm
+javax.measure.unit.format.UCUM.SIEMENS=S
+javax.measure.unit.format.UCUM.WEBER=Wb
+javax.measure.unit.format.UCUM.CELSIUS=Cel
+javax.measure.unit.format.UCUM.TESLA=T
+javax.measure.unit.format.UCUM.HENRY=H
+javax.measure.unit.format.UCUM.LUMEN=lm
+javax.measure.unit.format.UCUM.LUX=lx
+javax.measure.unit.format.UCUM.BECQUEREL=Bq
+javax.measure.unit.format.UCUM.GRAY=Gy
+javax.measure.unit.format.UCUM.SIEVERT=Sv
+javax.measure.unit.format.UCUM.DEGREE=deg
+javax.measure.unit.format.UCUM.GRADE=gon
+javax.measure.unit.format.UCUM.MINUTE_ANGLE='
+javax.measure.unit.format.UCUM.SECOND_ANGLE=''
+javax.measure.unit.format.UCUM.LITER=l
+javax.measure.unit.format.UCUM.LITER.1=L
+javax.measure.unit.format.UCUM.ARE=ar
+javax.measure.unit.format.UCUM.MINUTE=min
+javax.measure.unit.format.UCUM.HOUR=h
+javax.measure.unit.format.UCUM.DAY=d
+javax.measure.unit.format.UCUM.YEAR_TROPICAL=a_t
+javax.measure.unit.format.UCUM.YEAR_JULIAN=a_j
+javax.measure.unit.format.UCUM.YEAR_GREGORIAN=a_g
+javax.measure.unit.format.UCUM.YEAR=a
+javax.measure.unit.format.UCUM.MONTH_SYNODAL=mo_s
+javax.measure.unit.format.UCUM.MONTH_JULIAN=mo_j
+javax.measure.unit.format.UCUM.MONTH_GREGORIAN=mo_g
+javax.measure.unit.format.UCUM.MONTH=mo
+javax.measure.unit.format.UCUM.TONNE=t
+javax.measure.unit.format.UCUM.BAR=bar
+javax.measure.unit.format.UCUM.ATOMIC_MASS_UNIT=u
+javax.measure.unit.format.UCUM.ELECTRON_VOLT=eV
+javax.measure.unit.format.UCUM.ASTRONOMIC_UNIT=AU
+javax.measure.unit.format.UCUM.PARSEC=pc
+javax.measure.unit.format.UCUM.C=[c]
+javax.measure.unit.format.UCUM.PLANCK=[h]
+javax.measure.unit.format.UCUM.BOLTZMAN=[k]
+javax.measure.unit.format.UCUM.PERMITTIVITY_OF_VACUUM=[eps_0]
+javax.measure.unit.format.UCUM.PERMEABILITY_OF_VACUUM=[mu_0]
+javax.measure.unit.format.UCUM.ELEMENTARY_CHARGE=[e]
+javax.measure.unit.format.UCUM.ELECTRON_MASS=[m_e]
+javax.measure.unit.format.UCUM.PROTON_MASS=[m_p]
+javax.measure.unit.format.UCUM.NEWTON_CONSTANT_OF_GRAVITY=[G]
+javax.measure.unit.format.UCUM.ACCELLERATION_OF_FREEFALL=[g]
+javax.measure.unit.format.UCUM.ATMOSPHERE=atm
+javax.measure.unit.format.UCUM.LIGHT_YEAR=[ly]
+javax.measure.unit.format.UCUM.GRAM_FORCE=gf
+javax.measure.unit.format.UCUM.KAYSER=Ky
+javax.measure.unit.format.UCUM.GAL=Gal
+javax.measure.unit.format.UCUM.DYNE=dyn
+javax.measure.unit.format.UCUM.ERG=erg
+javax.measure.unit.format.UCUM.POISE=P
+javax.measure.unit.format.UCUM.BIOT=Bi
+javax.measure.unit.format.UCUM.STOKES=St
+javax.measure.unit.format.UCUM.MAXWELL=Mx
+javax.measure.unit.format.UCUM.GAUSS=G
+javax.measure.unit.format.UCUM.OERSTED=Oe
+javax.measure.unit.format.UCUM.GILBERT=Gb
+javax.measure.unit.format.UCUM.STILB=sb
+javax.measure.unit.format.UCUM.LAMBERT=Lmb
+javax.measure.unit.format.UCUM.PHOT=ph
+javax.measure.unit.format.UCUM.CURIE=Ci
+javax.measure.unit.format.UCUM.ROENTGEN=R
+javax.measure.unit.format.UCUM.RAD=RAD
+javax.measure.unit.format.UCUM.REM=REM
+javax.measure.unit.format.UCUM.INCH_INTERNATIONAL=[in_i]
+javax.measure.unit.format.UCUM.FOOT_INTERNATIONAL=[ft_i]
+javax.measure.unit.format.UCUM.YARD_INTERNATIONAL=[yd_i]
+javax.measure.unit.format.UCUM.MILE_INTERNATIONAL=[mi_i]
+javax.measure.unit.format.UCUM.FATHOM_INTERNATIONAL=[fth_i]
+javax.measure.unit.format.UCUM.NAUTICAL_MILE_INTERNATIONAL=[nmi_i]
+javax.measure.unit.format.UCUM.KNOT_INTERNATIONAL=[kn_i]
+javax.measure.unit.format.UCUM.SQUARE_INCH_INTERNATIONAL=[sin_i]
+javax.measure.unit.format.UCUM.SQUARE_FOOT_INTERNATIONAL=[sft_i]
+javax.measure.unit.format.UCUM.SQUARE_YARD_INTERNATIONAL=[syd_i]
+javax.measure.unit.format.UCUM.CUBIC_INCH_INTERNATIONAL=[cin_i]
+javax.measure.unit.format.UCUM.CUBIC_FOOT_INTERNATIONAL=[cft_i]
+javax.measure.unit.format.UCUM.CUBIC_YARD_INTERNATIONAL=[cyd_i]
+javax.measure.unit.format.UCUM.BOARD_FOOT_INTERNATIONAL=[bf_i]
+javax.measure.unit.format.UCUM.CORD_INTERNATIONAL=[cr_i]
+javax.measure.unit.format.UCUM.MIL_INTERNATIONAL=[mil_i]
+javax.measure.unit.format.UCUM.CIRCULAR_MIL_INTERNATIONAL=[cml_i]
+javax.measure.unit.format.UCUM.HAND_INTERNATIONAL=[hd_i]
+javax.measure.unit.format.UCUM.FOOT_US_SURVEY=[ft_us]
+javax.measure.unit.format.UCUM.YARD_US_SURVEY=[yd_us]
+javax.measure.unit.format.UCUM.INCH_US_SURVEY=[in_us]
+javax.measure.unit.format.UCUM.ROD_US_SURVEY=[rd_us]
+javax.measure.unit.format.UCUM.CHAIN_US_SURVEY=[ch_us]
+javax.measure.unit.format.UCUM.LINK_US_SURVEY=[lk_us]
+javax.measure.unit.format.UCUM.RAMDEN_CHAIN_US_SURVEY=[rch_us]
+javax.measure.unit.format.UCUM.RAMDEN_LINK_US_SURVEY=[rlk_us]
+javax.measure.unit.format.UCUM.FATHOM_US_SURVEY=[fth_us]
+javax.measure.unit.format.UCUM.FURLONG_US_SURVEY=[fur_us]
+javax.measure.unit.format.UCUM.MILE_US_SURVEY=[mi_us]
+javax.measure.unit.format.UCUM.ACRE_US_SURVEY=[acr_us]
+javax.measure.unit.format.UCUM.SQUARE_ROD_US_SURVEY=[srd_us]
+javax.measure.unit.format.UCUM.SQUARE_MILE_US_SURVEY=[smi_us]
+javax.measure.unit.format.UCUM.SECTION_US_SURVEY=[sct]
+javax.measure.unit.format.UCUM.TOWNSHP_US_SURVEY=[twp]
+javax.measure.unit.format.UCUM.MIL_US_SURVEY=[mil_us]
+javax.measure.unit.format.UCUM.INCH_BRITISH=[in_br]
+javax.measure.unit.format.UCUM.FOOT_BRITISH=[ft_br]
+javax.measure.unit.format.UCUM.ROD_BRITISH=[rd_br]
+javax.measure.unit.format.UCUM.CHAIN_BRITISH=[ch_br]
+javax.measure.unit.format.UCUM.LINK_BRITISH=[lk_br]
+javax.measure.unit.format.UCUM.FATHOM_BRITISH=[fth_br]
+javax.measure.unit.format.UCUM.PACE_BRITISH=[pc_br]
+javax.measure.unit.format.UCUM.YARD_BRITISH=[yd_br]
+javax.measure.unit.format.UCUM.MILE_BRITISH=[mi_br]
+javax.measure.unit.format.UCUM.NAUTICAL_MILE_BRITISH=[nmi_br]
+javax.measure.unit.format.UCUM.KNOT_BRITISH=[kn_br]
+javax.measure.unit.format.UCUM.ACRE_BRITISH=[acr_br]
+javax.measure.unit.format.UCUM.GALLON_US=[gal_us]
+javax.measure.unit.format.UCUM.BARREL_US=[bbl_us]
+javax.measure.unit.format.UCUM.QUART_US=[qt_us]
+javax.measure.unit.format.UCUM.PINT_US=[pt_us]
+javax.measure.unit.format.UCUM.GILL_US=[gil_us]
+javax.measure.unit.format.UCUM.FLUID_OUNCE_US=[foz_us]
+javax.measure.unit.format.UCUM.FLUID_DRAM_US=[fdr_us]
+javax.measure.unit.format.UCUM.MINIM_US=[min_us]
+javax.measure.unit.format.UCUM.CORD_US=[crd_us]
+javax.measure.unit.format.UCUM.BUSHEL_US=[bu_us]
+javax.measure.unit.format.UCUM.GALLON_WINCHESTER=[gal_wi]
+javax.measure.unit.format.UCUM.PECK_US=[pk_us]
+javax.measure.unit.format.UCUM.DRY_QUART_US=[dqt_us]
+javax.measure.unit.format.UCUM.DRY_PINT_US=[dpt_us]
+javax.measure.unit.format.UCUM.TABLESPOON_US=[tbs_us]
+javax.measure.unit.format.UCUM.TEASPOON_US=[tsp_us]
+javax.measure.unit.format.UCUM.CUP_US=[cup_us]
+javax.measure.unit.format.UCUM.GALLON_BRITISH=[gal_br]
+javax.measure.unit.format.UCUM.PECK_BRITISH=[pk_br]
+javax.measure.unit.format.UCUM.BUSHEL_BRITISH=[bu_br]
+javax.measure.unit.format.UCUM.QUART_BRITISH=[qt_br]
+javax.measure.unit.format.UCUM.PINT_BRITISH=[pt_br]
+javax.measure.unit.format.UCUM.GILL_BRITISH=[gil_br]
+javax.measure.unit.format.UCUM.FLUID_OUNCE_BRITISH=[foz_br]
+javax.measure.unit.format.UCUM.FLUID_DRAM_BRITISH=[fdr_br]
+javax.measure.unit.format.UCUM.MINIM_BRITISH=[min_br]
+javax.measure.unit.format.UCUM.GRAIN=[gr]
+javax.measure.unit.format.UCUM.POUND=[lb_av]
+javax.measure.unit.format.UCUM.OUNCE=[oz_av]
+javax.measure.unit.format.UCUM.DRAM=[dr_av]
+javax.measure.unit.format.UCUM.SHORT_HUNDREDWEIGHT=[scwt_av]
+javax.measure.unit.format.UCUM.LONG_HUNDREDWEIGHT=[lcwt_av]
+javax.measure.unit.format.UCUM.SHORT_TON=[ston_av]
+javax.measure.unit.format.UCUM.LONG_TON=[lton_av]
+javax.measure.unit.format.UCUM.STONE=[stone_av]
+javax.measure.unit.format.UCUM.POUND_FORCE=[lbf_av]
+javax.measure.unit.format.UCUM.PENNYWEIGHT_TROY=[pwt_tr]
+javax.measure.unit.format.UCUM.OUNCE_TROY=[oz_tr]
+javax.measure.unit.format.UCUM.POUND_TROY=[lb_tr]
+javax.measure.unit.format.UCUM.SCRUPLE_APOTHECARY=[sc_ap]
+javax.measure.unit.format.UCUM.DRAM_APOTHECARY=[dr_ap]
+javax.measure.unit.format.UCUM.OUNCE_APOTHECARY=[oz_ap]
+javax.measure.unit.format.UCUM.POUND_APOTHECARY=[lb_ap]
+javax.measure.unit.format.UCUM.LINE=[lne]
+javax.measure.unit.format.UCUM.POINT=[pnt]
+javax.measure.unit.format.UCUM.PICA=[pca]
+javax.measure.unit.format.UCUM.POINT_PRINTER=[pnt_pr]
+javax.measure.unit.format.UCUM.PICA_PRINTER=[pca_pr]
+javax.measure.unit.format.UCUM.PIED=[pied]
+javax.measure.unit.format.UCUM.POUCE=[pouce]
+javax.measure.unit.format.UCUM.LINGE=[ligne]
+javax.measure.unit.format.UCUM.DIDOT=[didot]
+javax.measure.unit.format.UCUM.CICERO=[cicero]
+javax.measure.unit.format.UCUM.FAHRENHEIT=[degF]
+javax.measure.unit.format.UCUM.CALORIE_AT_15C=cal_[15]
+javax.measure.unit.format.UCUM.CALORIE_AT_20C=cal_[20]
+javax.measure.unit.format.UCUM.CALORIE_MEAN=cal_m
+javax.measure.unit.format.UCUM.CALORIE_INTERNATIONAL_TABLE=cal_IT
+javax.measure.unit.format.UCUM.CALORIE_THERMOCHEMICAL=cal_th
+javax.measure.unit.format.UCUM.CALORIE=cal
+javax.measure.unit.format.UCUM.CALORIE_FOOD=[Cal]
+javax.measure.unit.format.UCUM.BTU_AT_39F=[Btu_39]
+javax.measure.unit.format.UCUM.BTU_AT_59F=[Btu_59]
+javax.measure.unit.format.UCUM.BTU_AT_60F=[Btu_60]
+javax.measure.unit.format.UCUM.BTU_MEAN=[Btu_m]
+javax.measure.unit.format.UCUM.BTU_INTERNATIONAL_TABLE=[Btu_IT]
+javax.measure.unit.format.UCUM.BTU_THERMOCHEMICAL=[Btu_th]
+javax.measure.unit.format.UCUM.BTU=[Btu]
+javax.measure.unit.format.UCUM.HORSEPOWER=[HP]
+javax.measure.unit.format.UCUM.STERE=st
+javax.measure.unit.format.UCUM.ANGSTROM=Ao
+javax.measure.unit.format.UCUM.BARN=b
+javax.measure.unit.format.UCUM.ATMOSPHERE_TECHNICAL=att
+javax.measure.unit.format.UCUM.MHO=mho
+javax.measure.unit.format.UCUM.POUND_PER_SQUARE_INCH=[psi]
+javax.measure.unit.format.UCUM.CIRCLE=circ
+javax.measure.unit.format.UCUM.SPHERE=sph
+javax.measure.unit.format.UCUM.CARAT_METRIC=[car_m]
+javax.measure.unit.format.UCUM.CARAT_GOLD=[car_Au]
+javax.measure.unit.format.UCUM.BIT=bit
+javax.measure.unit.format.UCUM.BYTE=By
+javax.measure.unit.format.UCUM.BAUD=Bd
+
diff --git a/src/main/java/javax/measure/unit/format/UCUM_Print.properties b/src/main/java/javax/measure/unit/format/UCUM_Print.properties
new file mode 100644
index 0000000..f72d15f
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/UCUM_Print.properties
@@ -0,0 +1,252 @@
+# NOTE: as a Java properties file, this file must use the
+# ISO 8859-1 encoding, so all non-ASCII Unicode characters
+# must be escaped using the \uXXXX syntax.
+# See http://java.sun.com/j2se/1.5.0/docs/api/java/util/Properties.html#encoding
+
+# Prefixes
+
+javax.measure.unit.format.Prefix.YOTTA=Y
+javax.measure.unit.format.Prefix.ZETTA=Z
+javax.measure.unit.format.Prefix.EXA=E
+javax.measure.unit.format.Prefix.PETA=P
+javax.measure.unit.format.Prefix.TERA=T
+javax.measure.unit.format.Prefix.GIGA=G
+javax.measure.unit.format.Prefix.MEGA=M
+javax.measure.unit.format.Prefix.KILO=k
+javax.measure.unit.format.Prefix.HECTO=h
+javax.measure.unit.format.Prefix.DEKA=da
+javax.measure.unit.format.Prefix.DECI=d
+javax.measure.unit.format.Prefix.CENTI=c
+javax.measure.unit.format.Prefix.MILLI=m
+javax.measure.unit.format.Prefix.MICRO=\u03BC
+javax.measure.unit.format.Prefix.NANO=n
+javax.measure.unit.format.Prefix.PICO=p
+javax.measure.unit.format.Prefix.FEMTO=f
+javax.measure.unit.format.Prefix.ATTO=a
+javax.measure.unit.format.Prefix.ZEPTO=z
+javax.measure.unit.format.Prefix.YOCTO=y
+
+# Units
+
+javax.measure.unit.format.UCUM.METER=m
+javax.measure.unit.format.UCUM.SECOND=s
+javax.measure.unit.format.UCUM.GRAM=g
+javax.measure.unit.format.UCUM.RADIAN=rad
+javax.measure.unit.format.UCUM.KELVIN=K
+javax.measure.unit.format.UCUM.COULOMB=C
+javax.measure.unit.format.UCUM.CANDELA=ca
+javax.measure.unit.format.UCUM.TRIILLIONS=10\u00B9\u00B2
+javax.measure.unit.format.UCUM.BILLIONS=10\u2079
+javax.measure.unit.format.UCUM.MILLIONS=10\u2076
+javax.measure.unit.format.UCUM.THOUSANDS=10\u00B3
+javax.measure.unit.format.UCUM.HUNDREDS=10\u00B2
+javax.measure.unit.format.UCUM.PI=\u03C0
+javax.measure.unit.format.UCUM.PERCENT=%
+javax.measure.unit.format.UCUM.PER_THOUSAND=ppth
+javax.measure.unit.format.UCUM.PER_MILLION=ppm
+javax.measure.unit.format.UCUM.PER_BILLION=ppb
+javax.measure.unit.format.UCUM.PER_TRILLION=pptr
+javax.measure.unit.format.UCUM.MOLE=mol
+javax.measure.unit.format.UCUM.STERADIAN=sr
+javax.measure.unit.format.UCUM.HERTZ=Hz
+javax.measure.unit.format.UCUM.NEWTON=N
+javax.measure.unit.format.UCUM.PASCAL=Pa
+javax.measure.unit.format.UCUM.JOULE=J
+javax.measure.unit.format.UCUM.WATT=W
+javax.measure.unit.format.UCUM.AMPERE=A
+javax.measure.unit.format.UCUM.VOLT=V
+javax.measure.unit.format.UCUM.FARAD=F
+javax.measure.unit.format.UCUM.OHM=\u03A9
+javax.measure.unit.format.UCUM.SIEMENS=S
+javax.measure.unit.format.UCUM.WEBER=Wb
+javax.measure.unit.format.UCUM.CELSIUS=\u00B0C
+javax.measure.unit.format.UCUM.TESLA=T
+javax.measure.unit.format.UCUM.HENRY=H
+javax.measure.unit.format.UCUM.LUMEN=lm
+javax.measure.unit.format.UCUM.LUX=lx
+javax.measure.unit.format.UCUM.BECQUEREL=Bq
+javax.measure.unit.format.UCUM.GRAY=Gy
+javax.measure.unit.format.UCUM.SIEVERT=Sv
+javax.measure.unit.format.UCUM.DEGREE=\u00B0
+javax.measure.unit.format.UCUM.GRADE=\u25A1g
+javax.measure.unit.format.UCUM.MINUTE_ANGLE='
+javax.measure.unit.format.UCUM.SECOND_ANGLE=\"
+javax.measure.unit.format.UCUM.LITER=l
+javax.measure.unit.format.UCUM.ARE=a
+javax.measure.unit.format.UCUM.MINUTE=min
+javax.measure.unit.format.UCUM.HOUR=h
+javax.measure.unit.format.UCUM.DAY=d
+javax.measure.unit.format.UCUM.YEAR_TROPICAL=a_t
+javax.measure.unit.format.UCUM.YEAR_JULIAN=a_j
+javax.measure.unit.format.UCUM.YEAR_GREGORIAN=a_g
+javax.measure.unit.format.UCUM.YEAR=a
+javax.measure.unit.format.UCUM.MONTH_SYNODAL=mo_s
+javax.measure.unit.format.UCUM.MONTH_JULIAN=mo_j
+javax.measure.unit.format.UCUM.MONTH_GREGORIAN=mo_g
+javax.measure.unit.format.UCUM.MONTH=mo
+javax.measure.unit.format.UCUM.TONNE=t
+javax.measure.unit.format.UCUM.BAR=bar
+javax.measure.unit.format.UCUM.ATOMIC_MASS_UNIT=u
+javax.measure.unit.format.UCUM.ELECTRON_VOLT=eV
+javax.measure.unit.format.UCUM.ASTRONOMIC_UNIT=AU
+javax.measure.unit.format.UCUM.PARSEC=PC
+javax.measure.unit.format.UCUM.C=c
+javax.measure.unit.format.UCUM.PLANCK=h
+javax.measure.unit.format.UCUM.BOLTZMAN=k
+javax.measure.unit.format.UCUM.PERMITTIVITY_OF_VACUUM=\u03B5\u2080
+javax.measure.unit.format.UCUM.PERMEABILITY_OF_VACUUM=\u03BC\u2080
+javax.measure.unit.format.UCUM.ELEMENTARY_CHARGE=e
+javax.measure.unit.format.UCUM.ELECTRON_MASS=m_e
+javax.measure.unit.format.UCUM.PROTON_MASS=m_p
+javax.measure.unit.format.UCUM.NEWTON_CONSTANT_OF_GRAVITY=G
+javax.measure.unit.format.UCUM.ACCELLERATION_OF_FREEFALL=g_n
+javax.measure.unit.format.UCUM.ATMOSPHERE=atm
+javax.measure.unit.format.UCUM.LIGHT_YEAR=l.y.
+javax.measure.unit.format.UCUM.GRAM_FORCE=gf
+javax.measure.unit.format.UCUM.KAYSER=K
+javax.measure.unit.format.UCUM.GAL=Gal
+javax.measure.unit.format.UCUM.DYNE=dyn
+javax.measure.unit.format.UCUM.ERG=erg
+javax.measure.unit.format.UCUM.POISE=P
+javax.measure.unit.format.UCUM.BIOT=Bi
+javax.measure.unit.format.UCUM.STOKES=St
+javax.measure.unit.format.UCUM.MAXWELL=Mx
+javax.measure.unit.format.UCUM.GAUSS=Gs
+javax.measure.unit.format.UCUM.OERSTED=Oe
+javax.measure.unit.format.UCUM.GILBERT=Gb
+javax.measure.unit.format.UCUM.STILB=sb
+javax.measure.unit.format.UCUM.LAMBERT=L
+javax.measure.unit.format.UCUM.PHOT=ph
+javax.measure.unit.format.UCUM.CURIE=Ci
+javax.measure.unit.format.UCUM.ROENTGEN=R
+javax.measure.unit.format.UCUM.RAD=RAD
+javax.measure.unit.format.UCUM.REM=REM
+javax.measure.unit.format.UCUM.INCH_INTERNATIONAL=in_i
+javax.measure.unit.format.UCUM.FOOT_INTERNATIONAL=ft_i
+javax.measure.unit.format.UCUM.YARD_INTERNATIONAL=yd_i
+javax.measure.unit.format.UCUM.MILE_INTERNATIONAL=mi_i
+javax.measure.unit.format.UCUM.FATHOM_INTERNATIONAL=fth_i
+javax.measure.unit.format.UCUM.NAUTICAL_MILE_INTERNATIONAL=nmi_i
+javax.measure.unit.format.UCUM.KNOT_INTERNATIONAL=kn_i
+javax.measure.unit.format.UCUM.SQUARE_INCH_INTERNATIONAL=sin_i
+javax.measure.unit.format.UCUM.SQUARE_FOOT_INTERNATIONAL=sft_i
+javax.measure.unit.format.UCUM.SQUARE_YARD_INTERNATIONAL=syd_i
+javax.measure.unit.format.UCUM.CUBIC_INCH_INTERNATIONAL=cin_i
+javax.measure.unit.format.UCUM.CUBIC_FOOT_INTERNATIONAL=cft_i
+javax.measure.unit.format.UCUM.CUBIC_YARD_INTERNATIONAL=cyd_i
+javax.measure.unit.format.UCUM.BOARD_FOOT_INTERNATIONAL=bf_i
+javax.measure.unit.format.UCUM.CORD_INTERNATIONAL=cr_i
+javax.measure.unit.format.UCUM.MIL_INTERNATIONAL=mil_i
+javax.measure.unit.format.UCUM.CIRCULAR_MIL_INTERNATIONAL=cml_i
+javax.measure.unit.format.UCUM.HAND_INTERNATIONAL=hd_i
+javax.measure.unit.format.UCUM.FOOT_US_SURVEY=ft_us
+javax.measure.unit.format.UCUM.YARD_US_SURVEY=yd_us
+javax.measure.unit.format.UCUM.INCH_US_SURVEY=in_us
+javax.measure.unit.format.UCUM.ROD_US_SURVEY=rd_us
+javax.measure.unit.format.UCUM.CHAIN_US_SURVEY=ch_us
+javax.measure.unit.format.UCUM.LINK_US_SURVEY=lk_us
+javax.measure.unit.format.UCUM.RAMDEN_CHAIN_US_SURVEY=rch_us
+javax.measure.unit.format.UCUM.RAMDEN_LINK_US_SURVEY=rlk_us
+javax.measure.unit.format.UCUM.FATHOM_US_SURVEY=fth_us
+javax.measure.unit.format.UCUM.FURLONG_US_SURVEY=fur_us
+javax.measure.unit.format.UCUM.MILE_US_SURVEY=mi_us
+javax.measure.unit.format.UCUM.ACRE_US_SURVEY=acr_us
+javax.measure.unit.format.UCUM.SQUARE_ROD_US_SURVEY=src_us
+javax.measure.unit.format.UCUM.SQUARE_MILE_US_SURVEY=smi_us
+javax.measure.unit.format.UCUM.SECTION_US_SURVEY=sct
+javax.measure.unit.format.UCUM.TOWNSHP_US_SURVEY=twp
+javax.measure.unit.format.UCUM.MIL_US_SURVEY=mil_us
+javax.measure.unit.format.UCUM.INCH_BRITISH=in_br
+javax.measure.unit.format.UCUM.FOOT_BRITISH=ft_br
+javax.measure.unit.format.UCUM.ROD_BRITISH=rd_br
+javax.measure.unit.format.UCUM.CHAIN_BRITISH=ch_br
+javax.measure.unit.format.UCUM.LINK_BRITISH=lk_br
+javax.measure.unit.format.UCUM.FATHOM_BRITISH=fth_br
+javax.measure.unit.format.UCUM.PACE_BRITISH=pc_br
+javax.measure.unit.format.UCUM.YARD_BRITISH=yd_br
+javax.measure.unit.format.UCUM.MILE_BRITISH=mi_br
+javax.measure.unit.format.UCUM.NAUTICAL_MILE_BRITISH=nmi_br
+javax.measure.unit.format.UCUM.KNOT_BRITISH=kn_br
+javax.measure.unit.format.UCUM.ACRE_BRITISH=acr_br
+javax.measure.unit.format.UCUM.GALLON_US=gal_us
+javax.measure.unit.format.UCUM.BARREL_US=bbl_us
+javax.measure.unit.format.UCUM.QUART_US=qt_us
+javax.measure.unit.format.UCUM.PINT_US=pt_us
+javax.measure.unit.format.UCUM.GILL_US=gil_us
+javax.measure.unit.format.UCUM.FLUID_OUNCE_US=foz_us
+javax.measure.unit.format.UCUM.FLUID_DRAM_US=fdr_us
+javax.measure.unit.format.UCUM.MINIM_US=min_us
+javax.measure.unit.format.UCUM.CORD_US=crd_us
+javax.measure.unit.format.UCUM.BUSHEL_US=bu_us
+javax.measure.unit.format.UCUM.GALLON_WINCHESTER=gal_wi
+javax.measure.unit.format.UCUM.PECK_US=pk_us
+javax.measure.unit.format.UCUM.DRY_QUART_US=dqt_us
+javax.measure.unit.format.UCUM.DRY_PINT_US=dpt_us
+javax.measure.unit.format.UCUM.TABLESPOON_US=tbs_us
+javax.measure.unit.format.UCUM.TEASPOON_US=tsp_us
+javax.measure.unit.format.UCUM.CUP_US=cup_us
+javax.measure.unit.format.UCUM.GALLON_BRITISH=gal_br
+javax.measure.unit.format.UCUM.PECK_BRITISH=pk_br
+javax.measure.unit.format.UCUM.BUSHEL_BRITISH=bu_br
+javax.measure.unit.format.UCUM.QUART_BRITISH=qt_br
+javax.measure.unit.format.UCUM.PINT_BRITISH=pt_br
+javax.measure.unit.format.UCUM.GILL_BRITISH=gil_br
+javax.measure.unit.format.UCUM.FLUID_OUNCE_BRITISH=foz_br
+javax.measure.unit.format.UCUM.FLUID_DRAM_BRITISH=fdr_br
+javax.measure.unit.format.UCUM.MINIM_BRITISH=min_br
+javax.measure.unit.format.UCUM.GRAIN=gr
+javax.measure.unit.format.UCUM.POUND=lb_av
+javax.measure.unit.format.UCUM.OUNCE=oz_av
+javax.measure.unit.format.UCUM.DRAM=dr_av
+javax.measure.unit.format.UCUM.SHORT_HUNDREDWEIGHT=scwt_av
+javax.measure.unit.format.UCUM.LONG_HUNDREDWEIGHT=lcwt_av
+javax.measure.unit.format.UCUM.SHORT_TON=ston_av
+javax.measure.unit.format.UCUM.LONG_TON=lton_av
+javax.measure.unit.format.UCUM.STONE=stone_av
+javax.measure.unit.format.UCUM.POUND_FORCE=lbf
+javax.measure.unit.format.UCUM.PENNYWEIGHT_TROY=pwt_tr
+javax.measure.unit.format.UCUM.OUNCE_TROY=oz_tr
+javax.measure.unit.format.UCUM.POUND_TROY=lb_tr
+javax.measure.unit.format.UCUM.SCRUPLE_APOTHECARY=sc_ap
+javax.measure.unit.format.UCUM.DRAM_APOTHECARY=dr_ap
+javax.measure.unit.format.UCUM.OUNCE_APOTHECARY=oz_ap
+javax.measure.unit.format.UCUM.POUND_APOTHECARY=lb_ap
+javax.measure.unit.format.UCUM.LINE=lne
+javax.measure.unit.format.UCUM.POINT=pnt
+javax.measure.unit.format.UCUM.PICA=pca
+javax.measure.unit.format.UCUM.POINT_PRINTER=pnt_pr
+javax.measure.unit.format.UCUM.PICA_PRINTER=pca_pr
+javax.measure.unit.format.UCUM.PIED=pied
+javax.measure.unit.format.UCUM.POUCE=pouce
+javax.measure.unit.format.UCUM.LINGE=linge
+javax.measure.unit.format.UCUM.DIDOT=didot
+javax.measure.unit.format.UCUM.CICERO=cicero
+javax.measure.unit.format.UCUM.FAHRENHEIT=\u00B0F
+javax.measure.unit.format.UCUM.CALORIE_AT_15C=cal15\u00B0C
+javax.measure.unit.format.UCUM.CALORIE_AT_20C=cal20\u00B0C
+javax.measure.unit.format.UCUM.CALORIE_MEAN=cal_m
+javax.measure.unit.format.UCUM.CALORIE_INTERNATIONAL_TABLE=cal_IT
+javax.measure.unit.format.UCUM.CALORIE_THERMOCHEMICAL=cal_th
+javax.measure.unit.format.UCUM.CALORIE=cal
+javax.measure.unit.format.UCUM.CALORIE_FOOD=Cal
+javax.measure.unit.format.UCUM.BTU_AT_39F=Btu39\u00B0F
+javax.measure.unit.format.UCUM.BTU_AT_59F=Btu59\u00B0F
+javax.measure.unit.format.UCUM.BTU_AT_60F=Btu60\u00B0F
+javax.measure.unit.format.UCUM.BTU_MEAN=Btu_m
+javax.measure.unit.format.UCUM.BTU_INTERNATIONAL_TABLE=Btu_IT
+javax.measure.unit.format.UCUM.BTU_THERMOCHEMICAL=Btu_th
+javax.measure.unit.format.UCUM.BTU=btu
+javax.measure.unit.format.UCUM.HORSEPOWER=HP
+javax.measure.unit.format.UCUM.STERE=st
+javax.measure.unit.format.UCUM.ANGSTROM=\u00C5
+javax.measure.unit.format.UCUM.BARN=b
+javax.measure.unit.format.UCUM.ATMOSPHERE_TECHNICAL=at
+javax.measure.unit.format.UCUM.MHO=mho
+javax.measure.unit.format.UCUM.POUND_PER_SQUARE_INCH=psi
+javax.measure.unit.format.UCUM.CIRCLE=circ
+javax.measure.unit.format.UCUM.SPHERE=sph
+javax.measure.unit.format.UCUM.CARAT_METRIC=ct_m
+javax.measure.unit.format.UCUM.CARAT_GOLD=ct_Au
+javax.measure.unit.format.UCUM.BIT=bit
+javax.measure.unit.format.UCUM.BYTE=B
+javax.measure.unit.format.UCUM.BAUD=Bd
diff --git a/src/main/java/javax/measure/unit/format/UnitParser.java b/src/main/java/javax/measure/unit/format/UnitParser.java
new file mode 100644
index 0000000..c89ff4b
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/UnitParser.java
@@ -0,0 +1,759 @@
+/* Generated By:JavaCC: Do not edit this line. UnitParser.java */
+package javax.measure.unit.format;
+
+/** */
+class UnitParser implements UnitParserConstants {
+
+ private static class Exponent {
+ public final int pow;
+ public final int root;
+ public Exponent (int pow, int root) {
+ this.pow = pow;
+ this.root = root;
+ }
+ }
+
+ private SymbolMap _symbols;
+
+ public UnitParser (SymbolMap symbols, java.io.Reader in) {
+ this(in);
+ _symbols = symbols;
+ }
+
+//
+// Parser productions
+//
+ final public javax.measure.unit.Unit parseUnit() throws ParseException {
+ javax.measure.unit.Unit result;
+ result = CompoundExpr();
+ jj_consume_token(0);
+ {if (true) return result;}
+ throw new Error("Missing return statement in function");
+ }
+
+ final public javax.measure.unit.Unit CompoundExpr() throws ParseException {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ javax.measure.unit.Unit temp = javax.measure.unit.Unit.ONE;
+ result = AddExpr();
+ label_1:
+ while (true) {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case COLON:
+ ;
+ break;
+ default:
+ jj_la1[0] = jj_gen;
+ break label_1;
+ }
+ jj_consume_token(COLON);
+ temp = AddExpr();
+ result=result.compound(temp);
+ }
+ {if (true) return result;}
+ throw new Error("Missing return statement in function");
+ }
+
+ final public javax.measure.unit.Unit AddExpr() throws ParseException {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ Number n1 = null;
+ Token sign1 = null;
+ Number n2 = null;
+ Token sign2 = null;
+ if (jj_2_1(2147483647)) {
+ n1 = NumberExpr();
+ sign1 = Sign();
+ } else {
+ ;
+ }
+ result = MulExpr();
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case PLUS:
+ case MINUS:
+ sign2 = Sign();
+ n2 = NumberExpr();
+ break;
+ default:
+ jj_la1[1] = jj_gen;
+ ;
+ }
+ if (n1 != null) {
+ if (sign1.image.equals("-")) {
+ result = result.times(-1);
+ }
+ result = result.plus(n1.doubleValue());
+ }
+ if (n2 != null) {
+ double offset = n2.doubleValue();
+ if (sign2.image.equals("-")) {
+ offset = -offset;
+ }
+ result = result.plus(offset);
+ }
+ {if (true) return result;}
+ throw new Error("Missing return statement in function");
+ }
+
+ final public javax.measure.unit.Unit MulExpr() throws ParseException {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ javax.measure.unit.Unit temp = javax.measure.unit.Unit.ONE;
+ result = ExponentExpr();
+ label_2:
+ while (true) {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case ASTERISK:
+ case MIDDLE_DOT:
+ case SOLIDUS:
+ ;
+ break;
+ default:
+ jj_la1[2] = jj_gen;
+ break label_2;
+ }
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case ASTERISK:
+ case MIDDLE_DOT:
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case ASTERISK:
+ jj_consume_token(ASTERISK);
+ break;
+ case MIDDLE_DOT:
+ jj_consume_token(MIDDLE_DOT);
+ break;
+ default:
+ jj_la1[3] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ temp = ExponentExpr();
+ result=result.times(temp);
+ break;
+ case SOLIDUS:
+ jj_consume_token(SOLIDUS);
+ temp = ExponentExpr();
+ result=result.divide(temp);
+ break;
+ default:
+ jj_la1[4] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ }
+ {if (true) return result;}
+ throw new Error("Missing return statement in function");
+ }
+
+ final public javax.measure.unit.Unit ExponentExpr() throws ParseException {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ javax.measure.unit.Unit temp = javax.measure.unit.Unit.ONE;
+ Exponent exponent = null;
+ Token token = null;
+ if (jj_2_2(2147483647)) {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case INTEGER:
+ token = jj_consume_token(INTEGER);
+ break;
+ case E:
+ token = jj_consume_token(E);
+ break;
+ default:
+ jj_la1[5] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ jj_consume_token(CARET);
+ result = AtomicExpr();
+ double base;
+ if (token.kind == INTEGER) {
+ base = Integer.parseInt(token.image);
+ } else {
+ base = StrictMath.E;
+ }
+ {if (true) return result.transform(new javax.measure.converter.LogConverter(base).inverse());}
+ } else {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case OPEN_PAREN:
+ case INTEGER:
+ case FLOATING_POINT:
+ case UNIT_IDENTIFIER:
+ result = AtomicExpr();
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case CARET:
+ case SUPERSCRIPT_INTEGER:
+ exponent = Exp();
+ break;
+ default:
+ jj_la1[6] = jj_gen;
+ ;
+ }
+ if (exponent != null) {
+ if (exponent.pow != 1) {
+ result = result.pow(exponent.pow);
+ }
+ if (exponent.root != 1) {
+ result = result.root(exponent.root);
+ }
+ }
+ {if (true) return result;}
+ break;
+ case LOG:
+ case NAT_LOG:
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case LOG:
+ jj_consume_token(LOG);
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case INTEGER:
+ token = jj_consume_token(INTEGER);
+ break;
+ default:
+ jj_la1[7] = jj_gen;
+ ;
+ }
+ break;
+ case NAT_LOG:
+ token = jj_consume_token(NAT_LOG);
+ break;
+ default:
+ jj_la1[8] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ jj_consume_token(OPEN_PAREN);
+ result = AddExpr();
+ jj_consume_token(CLOSE_PAREN);
+ double base = 10;
+ if (token != null) {
+ if (token.kind == INTEGER) {
+ base = Integer.parseInt(token.image);
+ } else if (token.kind == NAT_LOG) {
+ base = StrictMath.E;
+ }
+ }
+ {if (true) return result.transform(new javax.measure.converter.LogConverter(base));}
+ break;
+ default:
+ jj_la1[9] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+ final public javax.measure.unit.Unit AtomicExpr() throws ParseException {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ javax.measure.unit.Unit temp = javax.measure.unit.Unit.ONE;
+ Number n = null;
+ Token token = null;
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case INTEGER:
+ case FLOATING_POINT:
+ n = NumberExpr();
+ if (n instanceof Integer) {
+ {if (true) return result.times(n.intValue());}
+ } else {
+ {if (true) return result.times(n.doubleValue());}
+ }
+ break;
+ case UNIT_IDENTIFIER:
+ token = jj_consume_token(UNIT_IDENTIFIER);
+ javax.measure.unit.Unit unit = _symbols.getUnit(token.image);
+ if (unit == null) {
+ Prefix prefix = _symbols.getPrefix(token.image);
+ if (prefix != null) {
+ String prefixSymbol = _symbols.getSymbol(prefix);
+ unit = _symbols.getUnit(token.image.substring(prefixSymbol.length()));
+ if (unit != null) {
+ {if (true) return unit.transform(prefix.getConverter());}
+ }
+ }
+ {if (true) throw new ParseException();}
+ } else {
+ {if (true) return unit;}
+ }
+ break;
+ case OPEN_PAREN:
+ jj_consume_token(OPEN_PAREN);
+ result = AddExpr();
+ jj_consume_token(CLOSE_PAREN);
+ {if (true) return result;}
+ break;
+ default:
+ jj_la1[10] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+ final public Token Sign() throws ParseException {
+ Token result = null;
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case PLUS:
+ result = jj_consume_token(PLUS);
+ break;
+ case MINUS:
+ result = jj_consume_token(MINUS);
+ break;
+ default:
+ jj_la1[11] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ {if (true) return result;}
+ throw new Error("Missing return statement in function");
+ }
+
+ final public Number NumberExpr() throws ParseException {
+ Token token = null;
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case INTEGER:
+ token = jj_consume_token(INTEGER);
+ {if (true) return Long.valueOf(token.image);}
+ break;
+ case FLOATING_POINT:
+ token = jj_consume_token(FLOATING_POINT);
+ {if (true) return Double.valueOf(token.image);}
+ break;
+ default:
+ jj_la1[12] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+ final public Exponent Exp() throws ParseException {
+ Token powSign = null;
+ Token powToken = null;
+ Token rootSign = null;
+ Token rootToken = null;
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case CARET:
+ jj_consume_token(CARET);
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case PLUS:
+ case MINUS:
+ case INTEGER:
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case PLUS:
+ case MINUS:
+ powSign = Sign();
+ break;
+ default:
+ jj_la1[13] = jj_gen;
+ ;
+ }
+ powToken = jj_consume_token(INTEGER);
+ int pow = Integer.parseInt(powToken.image);
+ if ((powSign != null) && powSign.image.equals("-")) {
+ pow = -pow;
+ }
+ {if (true) return new Exponent(pow, 1);}
+ break;
+ case OPEN_PAREN:
+ jj_consume_token(OPEN_PAREN);
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case PLUS:
+ case MINUS:
+ powSign = Sign();
+ break;
+ default:
+ jj_la1[14] = jj_gen;
+ ;
+ }
+ powToken = jj_consume_token(INTEGER);
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case SOLIDUS:
+ jj_consume_token(SOLIDUS);
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case PLUS:
+ case MINUS:
+ rootSign = Sign();
+ break;
+ default:
+ jj_la1[15] = jj_gen;
+ ;
+ }
+ rootToken = jj_consume_token(INTEGER);
+ break;
+ default:
+ jj_la1[16] = jj_gen;
+ ;
+ }
+ jj_consume_token(CLOSE_PAREN);
+ pow = Integer.parseInt(powToken.image);
+ if ((powSign != null) && powSign.image.equals("-")) {
+ pow = -pow;
+ }
+ int root = 1;
+ if (rootToken != null) {
+ root = Integer.parseInt(rootToken.image);
+ if ((rootSign != null) && rootSign.image.equals("-")) {
+ root = -root;
+ }
+ }
+ {if (true) return new Exponent(pow, root);}
+ break;
+ default:
+ jj_la1[17] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ break;
+ case SUPERSCRIPT_INTEGER:
+ powToken = jj_consume_token(SUPERSCRIPT_INTEGER);
+ int pow = 0;
+ for (int i = 0; i < powToken.image.length(); i += 1) {
+ pow *= 10;
+ switch (powToken.image.charAt(i)) {
+ case '\u00b9': pow += 1; break;
+ case '\u00b2': pow += 2; break;
+ case '\u00b3': pow += 3; break;
+ case '\u2074': pow += 4; break;
+ case '\u2075': pow += 5; break;
+ case '\u2076': pow += 6; break;
+ case '\u2077': pow += 7; break;
+ case '\u2078': pow += 8; break;
+ case '\u2079': pow += 9; break;
+ }
+ }
+ {if (true) return new Exponent(pow, 1);}
+ break;
+ default:
+ jj_la1[18] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+ final private boolean jj_2_1(int xla) {
+ jj_la = xla; jj_lastpos = jj_scanpos = token;
+ try { return !jj_3_1(); }
+ catch(LookaheadSuccess ls) { return true; }
+ finally { jj_save(0, xla); }
+ }
+
+ final private boolean jj_2_2(int xla) {
+ jj_la = xla; jj_lastpos = jj_scanpos = token;
+ try { return !jj_3_2(); }
+ catch(LookaheadSuccess ls) { return true; }
+ finally { jj_save(1, xla); }
+ }
+
+ final private boolean jj_3R_3() {
+ Token xsp;
+ xsp = jj_scanpos;
+ if (jj_3R_5()) {
+ jj_scanpos = xsp;
+ if (jj_3R_6()) return true;
+ }
+ return false;
+ }
+
+ final private boolean jj_3R_6() {
+ if (jj_scan_token(FLOATING_POINT)) return true;
+ return false;
+ }
+
+ final private boolean jj_3_2() {
+ Token xsp;
+ xsp = jj_scanpos;
+ if (jj_scan_token(14)) {
+ jj_scanpos = xsp;
+ if (jj_scan_token(19)) return true;
+ }
+ if (jj_scan_token(CARET)) return true;
+ return false;
+ }
+
+ final private boolean jj_3_1() {
+ if (jj_3R_3()) return true;
+ if (jj_3R_4()) return true;
+ return false;
+ }
+
+ final private boolean jj_3R_4() {
+ Token xsp;
+ xsp = jj_scanpos;
+ if (jj_scan_token(5)) {
+ jj_scanpos = xsp;
+ if (jj_scan_token(6)) return true;
+ }
+ return false;
+ }
+
+ final private boolean jj_3R_5() {
+ if (jj_scan_token(INTEGER)) return true;
+ return false;
+ }
+
+ public UnitParserTokenManager token_source;
+ SimpleCharStream jj_input_stream;
+ public Token token, jj_nt;
+ private int jj_ntk;
+ private Token jj_scanpos, jj_lastpos;
+ private int jj_la;
+ public boolean lookingAhead = false;
+ private boolean jj_semLA;
+ private int jj_gen;
+ final private int[] jj_la1 = new int[19];
+ static private int[] jj_la1_0;
+ static {
+ jj_la1_0();
+ }
+ private static void jj_la1_0() {
+ jj_la1_0 = new int[] {0x800,0x60,0x380,0x180,0x380,0x84000,0x8400,0x4000,0x60000,0x175000,0x115000,0x60,0x14000,0x60,0x60,0x60,0x200,0x5060,0x8400,};
+ }
+ final private JJCalls[] jj_2_rtns = new JJCalls[2];
+ private boolean jj_rescan = false;
+ private int jj_gc = 0;
+
+ public UnitParser(java.io.InputStream stream) {
+ this(stream, null);
+ }
+ public UnitParser(java.io.InputStream stream, String encoding) {
+ try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+ token_source = new UnitParserTokenManager(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 19; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ public void ReInit(java.io.InputStream stream) {
+ ReInit(stream, null);
+ }
+ public void ReInit(java.io.InputStream stream, String encoding) {
+ try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+ token_source.ReInit(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 19; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ public UnitParser(java.io.Reader stream) {
+ jj_input_stream = new SimpleCharStream(stream, 1, 1);
+ token_source = new UnitParserTokenManager(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 19; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ public void ReInit(java.io.Reader stream) {
+ jj_input_stream.ReInit(stream, 1, 1);
+ token_source.ReInit(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 19; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ public UnitParser(UnitParserTokenManager tm) {
+ token_source = tm;
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 19; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ public void ReInit(UnitParserTokenManager tm) {
+ token_source = tm;
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 19; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ final private Token jj_consume_token(int kind) throws ParseException {
+ Token oldToken;
+ if ((oldToken = token).next != null) token = token.next;
+ else token = token.next = token_source.getNextToken();
+ jj_ntk = -1;
+ if (token.kind == kind) {
+ jj_gen++;
+ if (++jj_gc > 100) {
+ jj_gc = 0;
+ for (int i = 0; i < jj_2_rtns.length; i++) {
+ JJCalls c = jj_2_rtns[i];
+ while (c != null) {
+ if (c.gen < jj_gen) c.first = null;
+ c = c.next;
+ }
+ }
+ }
+ return token;
+ }
+ token = oldToken;
+ jj_kind = kind;
+ throw generateParseException();
+ }
+
+ static private final class LookaheadSuccess extends java.lang.Error { }
+ final private LookaheadSuccess jj_ls = new LookaheadSuccess();
+ final private boolean jj_scan_token(int kind) {
+ if (jj_scanpos == jj_lastpos) {
+ jj_la--;
+ if (jj_scanpos.next == null) {
+ jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
+ } else {
+ jj_lastpos = jj_scanpos = jj_scanpos.next;
+ }
+ } else {
+ jj_scanpos = jj_scanpos.next;
+ }
+ if (jj_rescan) {
+ int i = 0; Token tok = token;
+ while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
+ if (tok != null) jj_add_error_token(kind, i);
+ }
+ if (jj_scanpos.kind != kind) return true;
+ if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
+ return false;
+ }
+
+ final public Token getNextToken() {
+ if (token.next != null) token = token.next;
+ else token = token.next = token_source.getNextToken();
+ jj_ntk = -1;
+ jj_gen++;
+ return token;
+ }
+
+ final public Token getToken(int index) {
+ Token t = lookingAhead ? jj_scanpos : token;
+ for (int i = 0; i < index; i++) {
+ if (t.next != null) t = t.next;
+ else t = t.next = token_source.getNextToken();
+ }
+ return t;
+ }
+
+ final private int jj_ntk() {
+ if ((jj_nt=token.next) == null)
+ return (jj_ntk = (token.next=token_source.getNextToken()).kind);
+ else
+ return (jj_ntk = jj_nt.kind);
+ }
+
+ private java.util.Vector jj_expentries = new java.util.Vector();
+ private int[] jj_expentry;
+ private int jj_kind = -1;
+ private int[] jj_lasttokens = new int[100];
+ private int jj_endpos;
+
+ private void jj_add_error_token(int kind, int pos) {
+ if (pos >= 100) return;
+ if (pos == jj_endpos + 1) {
+ jj_lasttokens[jj_endpos++] = kind;
+ } else if (jj_endpos != 0) {
+ jj_expentry = new int[jj_endpos];
+ for (int i = 0; i < jj_endpos; i++) {
+ jj_expentry[i] = jj_lasttokens[i];
+ }
+ boolean exists = false;
+ for (java.util.Enumeration e = jj_expentries.elements(); e.hasMoreElements();) {
+ int[] oldentry = (int[])(e.nextElement());
+ if (oldentry.length == jj_expentry.length) {
+ exists = true;
+ for (int i = 0; i < jj_expentry.length; i++) {
+ if (oldentry[i] != jj_expentry[i]) {
+ exists = false;
+ break;
+ }
+ }
+ if (exists) break;
+ }
+ }
+ if (!exists) jj_expentries.addElement(jj_expentry);
+ if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
+ }
+ }
+
+ public ParseException generateParseException() {
+ jj_expentries.removeAllElements();
+ boolean[] la1tokens = new boolean[21];
+ for (int i = 0; i < 21; i++) {
+ la1tokens[i] = false;
+ }
+ if (jj_kind >= 0) {
+ la1tokens[jj_kind] = true;
+ jj_kind = -1;
+ }
+ for (int i = 0; i < 19; i++) {
+ if (jj_la1[i] == jj_gen) {
+ for (int j = 0; j < 32; j++) {
+ if ((jj_la1_0[i] & (1<<j)) != 0) {
+ la1tokens[j] = true;
+ }
+ }
+ }
+ }
+ for (int i = 0; i < 21; i++) {
+ if (la1tokens[i]) {
+ jj_expentry = new int[1];
+ jj_expentry[0] = i;
+ jj_expentries.addElement(jj_expentry);
+ }
+ }
+ jj_endpos = 0;
+ jj_rescan_token();
+ jj_add_error_token(0, 0);
+ int[][] exptokseq = new int[jj_expentries.size()][];
+ for (int i = 0; i < jj_expentries.size(); i++) {
+ exptokseq[i] = (int[])jj_expentries.elementAt(i);
+ }
+ return new ParseException(token, exptokseq, tokenImage);
+ }
+
+ final public void enable_tracing() {
+ }
+
+ final public void disable_tracing() {
+ }
+
+ final private void jj_rescan_token() {
+ jj_rescan = true;
+ for (int i = 0; i < 2; i++) {
+ try {
+ JJCalls p = jj_2_rtns[i];
+ do {
+ if (p.gen > jj_gen) {
+ jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
+ switch (i) {
+ case 0: jj_3_1(); break;
+ case 1: jj_3_2(); break;
+ }
+ }
+ p = p.next;
+ } while (p != null);
+ } catch(LookaheadSuccess ls) { }
+ }
+ jj_rescan = false;
+ }
+
+ final private void jj_save(int index, int xla) {
+ JJCalls p = jj_2_rtns[index];
+ while (p.gen > jj_gen) {
+ if (p.next == null) { p = p.next = new JJCalls(); break; }
+ p = p.next;
+ }
+ p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
+ }
+
+ static final class JJCalls {
+ int gen;
+ Token first;
+ int arg;
+ JJCalls next;
+ }
+
+}
diff --git a/src/main/java/javax/measure/unit/format/UnitParser.jj b/src/main/java/javax/measure/unit/format/UnitParser.jj
new file mode 100644
index 0000000..14b89f5
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/UnitParser.jj
@@ -0,0 +1,332 @@
+/*
+ * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
+ * Copyright (C) 2008 - JScience
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software is
+ * freely granted, provided that this notice is preserved.
+ */
+
+options {
+ STATIC = false;
+ UNICODE_INPUT = true;
+ DEBUG_PARSER = false;
+ DEBUG_LOOKAHEAD = false;
+ DEBUG_TOKEN_MANAGER = false;
+}
+
+PARSER_BEGIN(UnitParser)
+
+package javax.measure.unit.ucum;
+
+/** */
+class UnitParser {
+
+ private static class Exponent {
+ public final int pow;
+ public final int root;
+ public Exponent (int pow, int root) {
+ this.pow = pow;
+ this.root = root;
+ }
+ }
+
+ private SymbolMap _symbols;
+
+ public UnitParser (SymbolMap symbols, java.io.Reader in) {
+ this(in);
+ _symbols = symbols;
+ }
+}
+
+PARSER_END(UnitParser)
+
+//
+// Lexical entities
+//
+
+TOKEN: { <#DIGIT: [ "0","1","2","3","4","5","6","7","8","9" ] >
+ | <#SUPERSCRIPT_DIGIT: [ "\u2070", "\u00B9", "\u00B2", "\u00B3", "\u2074", "\u2075", "\u2076", "\u2077", "\u2078", "\u2079" ] >
+ | <#INITIAL_CHAR: ~["\u0000"-"\u0020", "(", ")", "*", "+", "-", ".", "/", "0"-"9", ":", "^", "\u00B2", "\u00B3", "\u00B7", "\u00B9", "\u2070", "\u2074", "\u2075", "\u2076", "\u2077", "\u2078", "\u2079" ] >
+ | <#EXTENDED_CHAR: ~["\u0000"-"\u0020", "(", ")", "*", "+", "-", ".", "/", ":", "^", "\u00B2", "\u00B3", "\u00B7", "\u00B9", "\u2070", "\u2074", "\u2075", "\u2076", "\u2077", "\u2078", "\u2079" ] > }
+TOKEN: { <PLUS: "+" > }
+TOKEN: { <MINUS: "-" > }
+TOKEN: { <ASTERISK: "*" > }
+TOKEN: { <MIDDLE_DOT: "\u00B7" > }
+TOKEN: { <SOLIDUS: "/" > }
+TOKEN: { <CARET: "^" > }
+TOKEN: { <COLON: ":" > }
+TOKEN: { <OPEN_PAREN: "(" > }
+TOKEN: { <CLOSE_PAREN: ")" > }
+TOKEN: { <INTEGER: (<DIGIT>)+ > }
+TOKEN: { <SUPERSCRIPT_INTEGER: (<SUPERSCRIPT_DIGIT>)+ > }
+TOKEN: { <FLOATING_POINT: (<DIGIT>)* (".")? (<DIGIT>)+ (("e" | "E") ((<PLUS>)|(<MINUS>))? (<DIGIT>)+)? > }
+TOKEN: { <LOG: "l" "o" "g" >
+ | <NAT_LOG: "l" "n" >
+ | <E: "e" > }
+TOKEN: { <UNIT_IDENTIFIER: <INITIAL_CHAR> (<EXTENDED_CHAR>)* > }
+
+//
+// Parser productions
+//
+
+javax.measure.unit.Unit parseUnit () :
+ {
+ javax.measure.unit.Unit result;
+ }
+{
+ result=CompoundExpr() <EOF>
+ {
+ return result;
+ }
+}
+
+javax.measure.unit.Unit CompoundExpr () :
+ {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ javax.measure.unit.Unit temp = javax.measure.unit.Unit.ONE;
+ }
+{
+(
+ result=AddExpr()
+ (
+ <COLON> temp=AddExpr() { result=result.compound(temp); }
+ )*
+ { return result; }
+)
+}
+
+javax.measure.unit.Unit AddExpr () :
+ {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ Number n1 = null;
+ Token sign1 = null;
+ Number n2 = null;
+ Token sign2 = null;
+ }
+{
+(
+ ( LOOKAHEAD(NumberExpr() Sign()) n1=NumberExpr() sign1=Sign() )?
+ result=MulExpr()
+ ( sign2=Sign() n2=NumberExpr() )?
+ {
+ if (n1 != null) {
+ if (sign1.image.equals("-")) {
+ result = result.times(-1);
+ }
+ result = result.plus(n1.doubleValue());
+ }
+ if (n2 != null) {
+ double offset = n2.doubleValue();
+ if (sign2.image.equals("-")) {
+ offset = -offset;
+ }
+ result = result.plus(offset);
+ }
+ return result;
+ }
+)
+}
+
+javax.measure.unit.Unit MulExpr () :
+ {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ javax.measure.unit.Unit temp = javax.measure.unit.Unit.ONE;
+ }
+{
+(
+ result=ExponentExpr()
+ (
+ ( (<ASTERISK> | <MIDDLE_DOT>) temp=ExponentExpr() { result=result.times(temp); } )
+ |
+ ( <SOLIDUS> temp=ExponentExpr() { result=result.divide(temp); } )
+ )*
+ { return result; }
+)
+}
+
+javax.measure.unit.Unit ExponentExpr () :
+ {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ javax.measure.unit.Unit temp = javax.measure.unit.Unit.ONE;
+ Exponent exponent = null;
+ Token token = null;
+ }
+{
+(
+ LOOKAHEAD((<INTEGER> | <E>) <CARET>)
+ ( ((token=<INTEGER>) | token=<E>) <CARET> result=AtomicExpr() )
+ {
+ double base;
+ if (token.kind == INTEGER) {
+ base = Integer.parseInt(token.image);
+ } else {
+ base = StrictMath.E;
+ }
+ return result.transform(new javax.measure.converter.LogConverter(base).inverse());
+ }
+|
+ ( result=AtomicExpr() ( exponent=Exp() )? )
+ {
+ if (exponent != null) {
+ if (exponent.pow != 1) {
+ result = result.pow(exponent.pow);
+ }
+ if (exponent.root != 1) {
+ result = result.root(exponent.root);
+ }
+ }
+ return result;
+ }
+|
+ ( ( ( <LOG> (token=<INTEGER>)? ) | token=<NAT_LOG> ) <OPEN_PAREN> result=AddExpr() <CLOSE_PAREN> )
+ {
+ double base = 10;
+ if (token != null) {
+ if (token.kind == INTEGER) {
+ base = Integer.parseInt(token.image);
+ } else if (token.kind == NAT_LOG) {
+ base = StrictMath.E;
+ }
+ }
+ return result.transform(new javax.measure.converter.LogConverter(base));
+ }
+)
+}
+
+javax.measure.unit.Unit AtomicExpr () :
+ {
+ javax.measure.unit.Unit result = javax.measure.unit.Unit.ONE;
+ javax.measure.unit.Unit temp = javax.measure.unit.Unit.ONE;
+ Number n = null;
+ Token token = null;
+ }
+{
+(
+ ( n=NumberExpr() )
+ {
+ if (n instanceof Integer) {
+ return result.times(n.intValue());
+ } else {
+ return result.times(n.doubleValue());
+ }
+ }
+|
+ ( token=<UNIT_IDENTIFIER> )
+ {
+ javax.measure.unit.Unit unit = _symbols.getUnit(token.image);
+ if (unit == null) {
+ Prefix prefix = _symbols.getPrefix(token.image);
+ if (prefix != null) {
+ String prefixSymbol = _symbols.getSymbol(prefix);
+ unit = _symbols.getUnit(token.image.substring(prefixSymbol.length()));
+ if (unit != null) {
+ return unit.transform(prefix.getConverter());
+ }
+ }
+ throw new ParseException();
+ } else {
+ return unit;
+ }
+ }
+|
+ ( <OPEN_PAREN> result=AddExpr() <CLOSE_PAREN> )
+ {
+ return result;
+ }
+)
+}
+
+Token Sign () :
+ {
+ Token result = null;
+ }
+{
+(
+ (result=<PLUS>)
+|
+ (result=<MINUS>)
+)
+ {
+ return result;
+ }
+}
+
+Number NumberExpr () :
+ {
+ Token token = null;
+ }
+{
+(
+ ( token=<INTEGER> )
+ {
+ return Long.valueOf(token.image);
+ }
+|
+ ( token=<FLOATING_POINT> )
+ {
+ return Double.valueOf(token.image);
+ }
+)
+}
+
+Exponent Exp () :
+ {
+ Token powSign = null;
+ Token powToken = null;
+ Token rootSign = null;
+ Token rootToken = null;
+ }
+{
+(
+ (
+ <CARET>
+ (
+ ( (powSign=Sign())? powToken=<INTEGER> )
+ {
+ int pow = Integer.parseInt(powToken.image);
+ if ((powSign != null) && powSign.image.equals("-")) {
+ pow = -pow;
+ }
+ return new Exponent(pow, 1);
+ }
+ |
+ ( <OPEN_PAREN> (powSign=Sign())? powToken=<INTEGER> ( <SOLIDUS> (rootSign=Sign())? rootToken=<INTEGER> )? <CLOSE_PAREN> )
+ {
+ pow = Integer.parseInt(powToken.image);
+ if ((powSign != null) && powSign.image.equals("-")) {
+ pow = -pow;
+ }
+ int root = 1;
+ if (rootToken != null) {
+ root = Integer.parseInt(rootToken.image);
+ if ((rootSign != null) && rootSign.image.equals("-")) {
+ root = -root;
+ }
+ }
+ return new Exponent(pow, root);
+ }
+ )
+ )
+|
+ ( powToken=<SUPERSCRIPT_INTEGER> )
+ {
+ int pow = 0;
+ for (int i = 0; i < powToken.image.length(); i += 1) {
+ pow *= 10;
+ switch (powToken.image.charAt(i)) {
+ case '\u00B9': pow += 1; break;
+ case '\u00B2': pow += 2; break;
+ case '\u00B3': pow += 3; break;
+ case '\u2074': pow += 4; break;
+ case '\u2075': pow += 5; break;
+ case '\u2076': pow += 6; break;
+ case '\u2077': pow += 7; break;
+ case '\u2078': pow += 8; break;
+ case '\u2079': pow += 9; break;
+ }
+ }
+ return new Exponent(pow, 1);
+ }
+)
+}
diff --git a/src/main/java/javax/measure/unit/format/UnitParserConstants.java b/src/main/java/javax/measure/unit/format/UnitParserConstants.java
new file mode 100644
index 0000000..06643eb
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/UnitParserConstants.java
@@ -0,0 +1,54 @@
+/* Generated By:JavaCC: Do not edit this line. UnitParserConstants.java */
+package javax.measure.unit.format;
+
+interface UnitParserConstants {
+
+ int EOF = 0;
+ int DIGIT = 1;
+ int SUPERSCRIPT_DIGIT = 2;
+ int INITIAL_CHAR = 3;
+ int EXTENDED_CHAR = 4;
+ int PLUS = 5;
+ int MINUS = 6;
+ int ASTERISK = 7;
+ int MIDDLE_DOT = 8;
+ int SOLIDUS = 9;
+ int CARET = 10;
+ int COLON = 11;
+ int OPEN_PAREN = 12;
+ int CLOSE_PAREN = 13;
+ int INTEGER = 14;
+ int SUPERSCRIPT_INTEGER = 15;
+ int FLOATING_POINT = 16;
+ int LOG = 17;
+ int NAT_LOG = 18;
+ int E = 19;
+ int UNIT_IDENTIFIER = 20;
+
+ int DEFAULT = 0;
+
+ String[] tokenImage = {
+ "<EOF>",
+ "<DIGIT>",
+ "<SUPERSCRIPT_DIGIT>",
+ "<INITIAL_CHAR>",
+ "<EXTENDED_CHAR>",
+ "\"+\"",
+ "\"-\"",
+ "\"*\"",
+ "\"\\u00b7\"",
+ "\"/\"",
+ "\"^\"",
+ "\":\"",
+ "\"(\"",
+ "\")\"",
+ "<INTEGER>",
+ "<SUPERSCRIPT_INTEGER>",
+ "<FLOATING_POINT>",
+ "<LOG>",
+ "<NAT_LOG>",
+ "\"e\"",
+ "<UNIT_IDENTIFIER>",
+ };
+
+}
diff --git a/src/main/java/javax/measure/unit/format/UnitParserTokenManager.java b/src/main/java/javax/measure/unit/format/UnitParserTokenManager.java
new file mode 100644
index 0000000..e0135b2
--- /dev/null
+++ b/src/main/java/javax/measure/unit/format/UnitParserTokenManager.java
@@ -0,0 +1,449 @@
+/* Generated By:JavaCC: Do not edit this line. UnitParserTokenManager.java */
+package javax.measure.unit.format;
+
+class UnitParserTokenManager implements UnitParserConstants
+{
+ public java.io.PrintStream debugStream = System.out;
+ public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
+private final int jjStopStringLiteralDfa_0(int pos, long active0)
+{
+ switch (pos)
+ {
+ default :
+ return -1;
+ }
+}
+private final int jjStartNfa_0(int pos, long active0)
+{
+ return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1);
+}
+private final int jjStopAtPos(int pos, int kind)
+{
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ return pos + 1;
+}
+private final int jjStartNfaWithStates_0(int pos, int kind, int state)
+{
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return pos + 1; }
+ return jjMoveNfa_0(state, pos + 1);
+}
+private final int jjMoveStringLiteralDfa0_0()
+{
+ switch(curChar)
+ {
+ case 40:
+ return jjStopAtPos(0, 12);
+ case 41:
+ return jjStopAtPos(0, 13);
+ case 42:
+ return jjStopAtPos(0, 7);
+ case 43:
+ return jjStopAtPos(0, 5);
+ case 45:
+ return jjStopAtPos(0, 6);
+ case 47:
+ return jjStopAtPos(0, 9);
+ case 58:
+ return jjStopAtPos(0, 11);
+ case 94:
+ return jjStopAtPos(0, 10);
+ case 101:
+ return jjStartNfaWithStates_0(0, 19, 7);
+ case 183:
+ return jjStopAtPos(0, 8);
+ default :
+ return jjMoveNfa_0(6, 0);
+ }
+}
+private final void jjCheckNAdd(int state)
+{
+ if (jjrounds[state] != jjround)
+ {
+ jjstateSet[jjnewStateCnt++] = state;
+ jjrounds[state] = jjround;
+ }
+}
+private final void jjAddStates(int start, int end)
+{
+ do {
+ jjstateSet[jjnewStateCnt++] = jjnextStates[start];
+ } while (start++ != end);
+}
+private final void jjCheckNAddTwoStates(int state1, int state2)
+{
+ jjCheckNAdd(state1);
+ jjCheckNAdd(state2);
+}
+private final void jjCheckNAddStates(int start, int end)
+{
+ do {
+ jjCheckNAdd(jjnextStates[start]);
+ } while (start++ != end);
+}
+private final void jjCheckNAddStates(int start)
+{
+ jjCheckNAdd(jjnextStates[start]);
+ jjCheckNAdd(jjnextStates[start + 1]);
+}
+static final long[] jjbitVec0 = {
+ 0x0L, 0x0L, 0x20c000000000000L, 0x0L
+};
+static final long[] jjbitVec1 = {
+ 0x0L, 0x3f1000000000000L, 0x0L, 0x0L
+};
+static final long[] jjbitVec2 = {
+ 0xfffffffefffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec4 = {
+ 0x0L, 0x0L, 0xfd73ffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec5 = {
+ 0xffffffffffffffffL, 0xfc0effffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+private final int jjMoveNfa_0(int startState, int curPos)
+{
+ int[] nextStates;
+ int startsAt = 0;
+ jjnewStateCnt = 15;
+ int i = 1;
+ jjstateSet[0] = startState;
+ int j, kind = 0x7fffffff;
+ for (;;)
+ {
+ if (++jjround == 0x7fffffff)
+ ReInitRounds();
+ if (curChar < 64)
+ {
+ long l = 1L << curChar;
+ MatchLoop: do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 6:
+ if ((0xf80010fe00000000L & l) != 0L)
+ {
+ if (kind > 20)
+ kind = 20;
+ jjCheckNAdd(7);
+ }
+ else if ((0x3ff000000000000L & l) != 0L)
+ {
+ if (kind > 14)
+ kind = 14;
+ jjCheckNAddStates(0, 4);
+ }
+ else if (curChar == 46)
+ jjCheckNAdd(2);
+ break;
+ case 1:
+ if (curChar == 46)
+ jjCheckNAdd(2);
+ break;
+ case 2:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 16)
+ kind = 16;
+ jjCheckNAddTwoStates(2, 3);
+ break;
+ case 4:
+ if ((0x280000000000L & l) != 0L)
+ jjCheckNAdd(5);
+ break;
+ case 5:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 16)
+ kind = 16;
+ jjCheckNAdd(5);
+ break;
+ case 7:
+ if ((0xfbff10fe00000000L & l) == 0L)
+ break;
+ if (kind > 20)
+ kind = 20;
+ jjCheckNAdd(7);
+ break;
+ case 8:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 14)
+ kind = 14;
+ jjCheckNAddStates(0, 4);
+ break;
+ case 9:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 14)
+ kind = 14;
+ jjCheckNAdd(9);
+ break;
+ case 10:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 16)
+ kind = 16;
+ jjCheckNAddStates(5, 8);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ long l = 1L << (curChar & 077);
+ MatchLoop: do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 6:
+ if ((0xffffffffbfffffffL & l) != 0L)
+ {
+ if (kind > 20)
+ kind = 20;
+ jjCheckNAdd(7);
+ }
+ if (curChar == 108)
+ jjAddStates(9, 10);
+ break;
+ case 3:
+ if ((0x2000000020L & l) != 0L)
+ jjAddStates(11, 12);
+ break;
+ case 7:
+ if ((0xffffffffbfffffffL & l) == 0L)
+ break;
+ if (kind > 20)
+ kind = 20;
+ jjCheckNAdd(7);
+ break;
+ case 11:
+ if (curChar == 108)
+ jjAddStates(9, 10);
+ break;
+ case 12:
+ if (curChar == 111)
+ jjstateSet[jjnewStateCnt++] = 13;
+ break;
+ case 13:
+ if (curChar == 103 && kind > 17)
+ kind = 17;
+ break;
+ case 14:
+ if (curChar == 110 && kind > 18)
+ kind = 18;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else
+ {
+ int hiByte = (int)(curChar >> 8);
+ int i1 = hiByte >> 6;
+ long l1 = 1L << (hiByte & 077);
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 1L << (curChar & 077);
+ MatchLoop: do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 6:
+ if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 15)
+ kind = 15;
+ jjCheckNAdd(0);
+ }
+ if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 20)
+ kind = 20;
+ jjCheckNAdd(7);
+ }
+ break;
+ case 0:
+ if (!jjCanMove_0(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 15)
+ kind = 15;
+ jjCheckNAdd(0);
+ break;
+ case 7:
+ if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 20)
+ kind = 20;
+ jjCheckNAdd(7);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 15 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return curPos; }
+ }
+}
+static final int[] jjnextStates = {
+ 9, 1, 2, 3, 10, 1, 2, 3, 10, 12, 14, 4, 5,
+};
+private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
+{
+ switch(hiByte)
+ {
+ case 0:
+ return ((jjbitVec0[i2] & l2) != 0L);
+ case 32:
+ return ((jjbitVec1[i2] & l2) != 0L);
+ default :
+ return false;
+ }
+}
+private static final boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2)
+{
+ switch(hiByte)
+ {
+ case 0:
+ return ((jjbitVec4[i2] & l2) != 0L);
+ case 32:
+ return ((jjbitVec5[i2] & l2) != 0L);
+ default :
+ if ((jjbitVec2[i1] & l1) != 0L)
+ return true;
+ return false;
+ }
+}
+public static final String[] jjstrLiteralImages = {
+"", null, null, null, null, "\53", "\55", "\52", "\267", "\57", "\136", "\72",
+"\50", "\51", null, null, null, null, null, "\145", null, };
+public static final String[] lexStateNames = {
+ "DEFAULT",
+};
+protected SimpleCharStream input_stream;
+private final int[] jjrounds = new int[15];
+private final int[] jjstateSet = new int[30];
+protected char curChar;
+public UnitParserTokenManager(SimpleCharStream stream){
+ if (SimpleCharStream.staticFlag)
+ throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+ input_stream = stream;
+}
+public UnitParserTokenManager(SimpleCharStream stream, int lexState){
+ this(stream);
+ SwitchTo(lexState);
+}
+public void ReInit(SimpleCharStream stream)
+{
+ jjmatchedPos = jjnewStateCnt = 0;
+ curLexState = defaultLexState;
+ input_stream = stream;
+ ReInitRounds();
+}
+private final void ReInitRounds()
+{
+ int i;
+ jjround = 0x80000001;
+ for (i = 15; i-- > 0;)
+ jjrounds[i] = 0x80000000;
+}
+public void ReInit(SimpleCharStream stream, int lexState)
+{
+ ReInit(stream);
+ SwitchTo(lexState);
+}
+public void SwitchTo(int lexState)
+{
+ if (lexState >= 1 || lexState < 0)
+ throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+ else
+ curLexState = lexState;
+}
+
+protected Token jjFillToken()
+{
+ Token t = Token.newToken(jjmatchedKind);
+ t.kind = jjmatchedKind;
+ String im = jjstrLiteralImages[jjmatchedKind];
+ t.image = (im == null) ? input_stream.GetImage() : im;
+ t.beginLine = input_stream.getBeginLine();
+ t.beginColumn = input_stream.getBeginColumn();
+ t.endLine = input_stream.getEndLine();
+ t.endColumn = input_stream.getEndColumn();
+ return t;
+}
+
+int curLexState = 0;
+int defaultLexState = 0;
+int jjnewStateCnt;
+int jjround;
+int jjmatchedPos;
+int jjmatchedKind;
+
+public Token getNextToken()
+{
+ int kind;
+ Token specialToken = null;
+ Token matchedToken;
+ int curPos = 0;
+
+ EOFLoop :
+ for (;;)
+ {
+ try
+ {
+ curChar = input_stream.BeginToken();
+ }
+ catch(java.io.IOException e)
+ {
+ jjmatchedKind = 0;
+ matchedToken = jjFillToken();
+ return matchedToken;
+ }
+
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_0();
+ if (jjmatchedKind != 0x7fffffff)
+ {
+ if (jjmatchedPos + 1 < curPos)
+ input_stream.backup(curPos - jjmatchedPos - 1);
+ matchedToken = jjFillToken();
+ return matchedToken;
+ }
+ int error_line = input_stream.getEndLine();
+ int error_column = input_stream.getEndColumn();
+ String error_after = null;
+ boolean EOFSeen = false;
+ try { input_stream.readChar(); input_stream.backup(1); }
+ catch (java.io.IOException e1) {
+ EOFSeen = true;
+ error_after = curPos <= 1 ? "" : input_stream.GetImage();
+ if (curChar == '\n' || curChar == '\r') {
+ error_line++;
+ error_column = 0;
+ }
+ else
+ error_column++;
+ }
+ if (!EOFSeen) {
+ input_stream.backup(1);
+ error_after = curPos <= 1 ? "" : input_stream.GetImage();
+ }
+ throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
+ }
+}
+
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/jsr-275.git
More information about the Pkg-grass-devel
mailing list