sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1766508 [5/6] - in /sis/branches/JDK7: ./ application/ application/sis-console/src/main/java/org/apache/sis/console/ application/sis-openoffice/ application/sis-openoffice/src/main/java/org/apache/sis/openoffice/ core/ core/sis-metadata/sr...
Date Tue, 25 Oct 2016 10:45:15 GMT
Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java?rev=1766508&r1=1766507&r2=1766508&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] Tue Oct 25 10:45:14 2016
@@ -16,24 +16,14 @@
  */
 package org.apache.sis.measure;
 
+import javax.measure.Dimension;
 import javax.measure.Unit;
 import javax.measure.UnitConverter;
 import javax.measure.format.ParserException;
 import javax.measure.Quantity;
-import javax.measure.quantity.Angle;
-import javax.measure.quantity.Area;
-import javax.measure.quantity.Dimensionless;
-import javax.measure.quantity.Energy;
-import javax.measure.quantity.Force;
-import javax.measure.quantity.Frequency;
-import javax.measure.quantity.Length;
-import javax.measure.quantity.Mass;
-import javax.measure.quantity.Power;
-import javax.measure.quantity.Pressure;
-import javax.measure.quantity.Speed;
-import javax.measure.quantity.Temperature;
-import javax.measure.quantity.Time;
-import javax.measure.quantity.Volume;
+import javax.measure.quantity.*;
+import javax.measure.quantity.Angle;            // Because of name collision with Angle in this SIS package.
+import org.opengis.geometry.DirectPosition;     // For javadoc
 
 import org.apache.sis.util.Static;
 import org.apache.sis.util.Workaround;
@@ -47,6 +37,31 @@ import static org.apache.sis.measure.Sex
 
 /**
  * Provides constants for various Units of Measurement together with static methods working on {@link Unit} instances.
+ * This class focuses on the most commonly used units in the geospatial domain:
+ * angular units ({@linkplain #DEGREE degree}, {@linkplain #ARC_SECOND arc-second}, …),
+ * linear units ({@linkplain #KILOMETRE kilometre}, {@linkplain #NAUTICAL_MILE nautical mile}, …) and
+ * temporal units ({@linkplain #DAY day}, {@linkplain #TROPICAL_YEAR year}, …).
+ * But some other kind of units are also provided for completeness.
+ *
+ * <p>All Units of Measurement are based on units from the International System (SI).
+ * The fundamental units are listed below, together with some dimensionless units:</p>
+ *
+ * <table class="sis">
+ *   <caption>SI fundamental units and dimensionless units</caption>
+ *   <tr><th>Quantity type</th>       <th>Dimension symbol</th> <th>Base unit</th></tr>
+ *   <tr><td>{@link Length}</td>            <td>L</td>          <td>{@link #METRE}</td></tr>
+ *   <tr><td>{@link Mass}</td>              <td>M</td>          <td>{@link #KILOGRAM}</td></tr>
+ *   <tr><td>{@link Time}</td>              <td>T</td>          <td>{@link #SECOND}</td></tr>
+ *   <tr><td>{@link ElectricCurrent}</td>   <td>I</td>          <td>{@link #AMPERE}</td></tr>
+ *   <tr><td>{@link Temperature}</td>       <td>Θ</td>          <td>{@link #KELVIN}</td></tr>
+ *   <tr><td>{@link AmountOfSubstance}</td> <td>N</td>          <td>{@link #MOLE}</td></tr>
+ *   <tr><td>{@link LuminousIntensity}</td> <td>J</td>          <td>{@link #CANDELA}</td></tr>
+ *   <tr><td>{@link Angle}</td>             <td></td>           <td>{@link #RADIAN}</td></tr>
+ * </table>
+ *
+ * Unit names and definitions in this class follow the definitions provided in the EPSG geodetic dataset
+ * (when the unit exists in that dataset),
+ * except “year” which has been renamed “{@linkplain #TROPICAL_YEAR tropical year}”.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3
@@ -55,427 +70,735 @@ import static org.apache.sis.measure.Sex
  */
 public final class Units extends Static {
     /**
-     * The SI base unit for distances (symbol “m”).
+     * Unit of measurement defined as 10<sup>-9</sup> metres (1 nm). This unit is often used in
+     * {@linkplain org.apache.sis.metadata.iso.content.DefaultBand#getBoundUnits() wavelength measurements}.
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #METRE}
+     * and the unlocalized name is "nanometre".
      *
-     * @see #NANOMETRE
-     * @see #MILLIMETRE
      * @see #CENTIMETRE
-     * @see #KILOMETRE
-     * @see #NAUTICAL_MILE
-     * @see #MILE
-     * @see #FOOT
-     * @see #FOOT_SURVEY_US
-     * @see #INCH
-     * @see #PIXEL
+     * @see #MILLIMETRE
      *
      * @since 0.8
      */
-    public static final Unit<Length> METRE = tec.units.ri.unit.Units.METRE;
+    public static final Unit<Length> NANOMETRE;
 
     /**
-     * Unit of measurement defined as 10<sup>-9</sup> metres.
-     * This unit is often used in wavelength measurements.
+     * Unit of measurement defined as 0.001 metres (1 mm).
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #METRE},
+     * the unlocalized name is “millimetre” and the identifier is EPSG:1025.
      *
-     * @see #METRE
+     * @see #NANOMETRE
      * @see #CENTIMETRE
-     * @see #MILLIMETRE
+     * @see #KILOMETRE
      *
      * @since 0.8
      */
-    public static final Unit<Length> NANOMETRE = METRE.divide(1E9);
+    public static final Unit<Length> MILLIMETRE;
 
     /**
-     * Unit of measurement defined as 0.001 metres.
+     * Unit of measurement defined as 0.01 metres (1 cm).
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #METRE},
+     * the unlocalized name is “centimetre” and the identifier is EPSG:1033.
      *
-     * @see #METRE
      * @see #NANOMETRE
-     * @see #CENTIMETRE
+     * @see #MILLIMETRE
      * @see #KILOMETRE
      *
      * @since 0.8
      */
-    public static final Unit<Length> MILLIMETRE = METRE.divide(1000);
+    public static final Unit<Length> CENTIMETRE;
 
     /**
-     * Unit of measurement defined as 0.01 metres.
+     * The SI base unit for distances (m).
+     * The unlocalized name is “metre” and the identifier is EPSG:9001.
+     * This is the base of all other {@linkplain #isLinear(Unit) linear} units:
      *
-     * @see #METRE
-     * @see #NANOMETRE
-     * @see #MILLIMETRE
-     * @see #KILOMETRE
+     * {@link #NANOMETRE} (nm),
+     * {@link #MILLIMETRE} (mm),
+     * {@link #CENTIMETRE} (cm),
+     * {@link #KILOMETRE} (km),
+     * {@link #NAUTICAL_MILE} (M),
+     * {@link #STATUTE_MILE} (mi),
+     * {@link #US_SURVEY_FOOT},
+     * {@link #FOOT} (ft),
+     * {@link #INCH} (in) and
+     * {@link #POINT} (pt)
+     * among others.
+     *
+     * @see #SQUARE_METRE
+     * @see #CUBIC_METRE
      *
      * @since 0.8
      */
-    public static final Unit<Length> CENTIMETRE = METRE.divide(100);
+    public static final Unit<Length> METRE;
 
     /**
-     * Unit of measurement defined as 1000 metres.
+     * Unit of measurement defined as 1000 metres (1 km).
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #METRE},
+     * the unlocalized name is “kilometre” and the identifier is EPSG:9036.
      *
-     * @see #METRE
+     * @see #STATUTE_MILE
      * @see #NAUTICAL_MILE
      *
      * @since 0.8
      */
-    public static final Unit<Length> KILOMETRE = METRE.multiply(1000);
+    public static final Unit<Length> KILOMETRE;
 
     /**
-     * Unit of measurement defined as 1852 metres.
-     * This is approximatively the distance between two parallels of latitude separated by one arc-minute.
+     * Unit of measurement defined as exactly 1852 metres (1 M).
+     * This is approximatively the distance between two parallels of latitude
+     * separated by one {@linkplain #ARC_MINUTE arc-minute}.
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #METRE},
+     * the unlocalized name is “nautical mile” and the identifier is EPSG:9030.
      *
-     * @see #METRE
+     * <p>There is no internationally agreed symbol for nautical mile. Apache SIS uses “M” in agreement with the
+     * International Hydrographic Organization (IHO) and the International Bureau of Weights and Measures (BIPM).
+     * But “NM” and “nmi” are also in use.</p>
+     *
+     * @see #STATUTE_MILE
      * @see #KILOMETRE
-     * @see #MILE
+     * @see #ARC_MINUTE
      *
      * @since 0.8
      */
-    public static final Unit<Length> NAUTICAL_MILE = METRE.multiply(1852);
+    public static final Unit<Length> NAUTICAL_MILE;
 
     /**
-     * Unit of measurement defined as 1609.344 metres.
+     * Unit of measurement defined as exactly 1609.344 metres (1 mi).
+     * This unit is often named “mile” without qualifier, but Apache SIS uses “statute mile”
+     * for emphasing the difference with {@linkplain #NAUTICAL_MILE nautical mile}.
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #METRE}.
+     * The unlocalized name is “statute mile” but is localized as "international mile" in the US
+     * for avoiding confusion with the US survey mile.
+     * The identifier is EPSG:9093.
      *
-     * @see #METRE
      * @see #KILOMETRE
      * @see #NAUTICAL_MILE
+     * @see #FOOT
      *
      * @since 0.8
      */
-    public static final Unit<Length> MILE = METRE.multiply(1609.344);
+    public static final Unit<Length> STATUTE_MILE;
 
     /**
-     * Unit of measurement defined as 0.3048 metres.
+     * Unit of measurement approximatively equals to 0.3048006096… metres.
+     * The legal definition is exactly 12/39.37 metres.
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #METRE},
+     * the unlocalized name is “US survey foot” and the identifier is EPSG:9003.
      *
-     * @see #METRE
-     * @see #FOOT_SURVEY_US
+     * @see #FOOT
      *
      * @since 0.8
      */
-    public static final Unit<Length> FOOT = METRE.multiply(0.3048);
+    public static final Unit<Length> US_SURVEY_FOOT;
 
     /**
-     * Unit of measurement defined as 12/39.37 metres.
-     * This is approximatively 0.3048006096… metres.
+     * Unit of measurement defined as exactly 0.3048 metres (1 ft).
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #METRE},
+     * the unlocalized name is “foot” and the identifier is EPSG:9002.
      *
-     * @see #METRE
-     * @see #FOOT
+     * @see #US_SURVEY_FOOT
+     * @see #STATUTE_MILE
+     * @see #INCH
      *
      * @since 0.8
      */
-    public static final Unit<Length> FOOT_SURVEY_US = METRE.multiply(12 / 39.37);
+    public static final Unit<Length> FOOT;
 
     /**
-     * Unit of measurement defined as 2.54 centimetres.
+     * Unit of measurement defined as 2.54 centimetres (1 in).
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #METRE}
+     * and the unlocalized name is “inch”.
+     *
+     * @see #CENTIMETRE
+     * @see #POINT
+     * @see #FOOT
      *
      * @since 0.8
      */
-    public static final Unit<Length> INCH = METRE.multiply(2.54 / 100);
+    public static final Unit<Length> INCH;
 
     /**
-     * Unit of measurement defined as 0.013837 inch.
+     * Unit of measurement defined as 0.013837 inch (1 pt).
      * This is commonly used to measure the height of a font.
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #METRE}
+     * and the unlocalized name is “point”.
+     *
+     * @see #INCH
+     * @see #MILLIMETRE
+     * @see #PIXEL
      *
      * @since 0.8
      */
-    public static final Unit<Length> POINT = METRE.multiply(0.996264 / 72);
+    public static final Unit<Length> POINT;
 
     /**
-     * The SI unit for plane angles.
+     * The SI unit for plane angles (rad).
      * There is 2π radians in a circle.
+     * The unlocalized name is “radian” and the identifier is EPSG:9101.
+     * This is the base of all other {@linkplain #isAngular(Unit) angular} units:
      *
-     * @see #DEGREE
-     * @see #GRAD
-     * @see #ARC_MINUTE
-     * @see #ARC_SECOND
-     * @see #MICRORADIAN
+     * {@link #GRAD} (grad),
+     * {@link #DEGREE} (°),
+     * {@link #ARC_MINUTE} (′),
+     * {@link #ARC_SECOND} (″) and
+     * {@link #MICRORADIAN} (µrad)
+     * among others.
      *
      * @since 0.8
      */
-    public static final Unit<Angle> RADIAN = tec.units.ri.unit.Units.RADIAN;
+    public static final Unit<Angle> RADIAN;
 
     /**
-     * Unit of measurement defined as π/180 radians.
-     * There is 360° in a circle.
+     * Unit of measurement defined as π/200 radians (1 grad).
+     * There is 400 grads in a circle.
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #RADIAN},
+     * the unlocalized name is “grad” and the identifier is EPSG:9105.
      *
-     * @see #RADIAN
-     * @see #ARC_MINUTE
-     * @see #ARC_SECOND
+     * @see #DEGREE
      *
      * @since 0.8
      */
-    public static final Unit<Angle> DEGREE = RADIAN.multiply(Math.PI/180);
+    public static final Unit<Angle> GRAD;
 
     /**
-     * Unit of measurement defined as π/200 radians.
-     * There is 400 grads in a circle.
+     * Unit of measurement defined as π/180 radians (1°).
+     * There is 360° in a circle.
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #RADIAN},
+     * the unlocalized name is “degree” and the identifier is EPSG:9102.
      *
-     * @see #RADIAN
-     * @see #DEGREE
+     * @see #ARC_MINUTE
+     * @see #ARC_SECOND
      *
      * @since 0.8
      */
-    public static final Unit<Angle> GRAD = RADIAN.multiply(Math.PI/200);
+    public static final Unit<Angle> DEGREE;
 
     /**
-     * Unit of measurement defined as 1/60 degree.
+     * Unit of measurement defined as 1/60 degree (1′).
+     * The distance of one arc-minute of latitude on Earth is approximatively 1852 metres
+     * (one {@linkplain #NAUTICAL_MILE nautical mile}).
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #RADIAN},
+     * the unlocalized name is “arc-minute” and the identifier is EPSG:9103.
      *
-     * @see #RADIAN
      * @see #DEGREE
+     * @see #ARC_SECOND
+     * @see #NAUTICAL_MILE
      *
      * @since 0.8
      */
-    public static final Unit<Angle> ARC_MINUTE = RADIAN.multiply(Math.PI / (180*60));
+    public static final Unit<Angle> ARC_MINUTE;
 
     /**
-     * Unit of measurement defined as 1/(60×60) degree.
+     * Unit of measurement defined as 1/(60×60) degree (1″).
+     * The distance of one arc-second of latitude on Earth is approximatively 31 metres.
+     * This unit of measurement is used for rotation terms in
+     * {@linkplain org.apache.sis.referencing.datum.BursaWolfParameters Bursa-Wolf parameters}.
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #RADIAN},
+     * the unlocalized name is “arc-second” and the identifier is EPSG:9104.
      *
-     * @see #RADIAN
      * @see #DEGREE
+     * @see #ARC_MINUTE
      *
      * @since 0.8
      */
-    public static final Unit<Angle> ARC_SECOND = RADIAN.multiply(Math.PI / (180*60*60));
+    public static final Unit<Angle> ARC_SECOND;
 
     /**
-     * Unit of measurement defined as 10<sup>-6</sup> radians.
+     * Unit of measurement defined as 10<sup>-6</sup> radians (1 µrad).
+     * The distance of one microradian of latitude on Earth is approximatively 2 millimetres.
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #RADIAN},
+     * the unlocalized name is “microradian” and the identifier is EPSG:9109.
      *
-     * @see #RADIAN
+     * @see #ARC_MINUTE
+     * @see #ARC_SECOND
      *
      * @since 0.8
      */
-    public static final Unit<Angle> MICRORADIAN = RADIAN.divide(1E+6);
+    public static final Unit<Angle> MICRORADIAN;
 
     /**
-     * The SI base unit for durations (symbol “s”).
+     * Unit of measurement defined as 10<sup>-3</sup> seconds (1 ms).
+     * This unit is useful for inter-operability with various methods from the standard Java library.
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #SECOND}
+     * and the unlocalized name is “millisecond”.
      *
-     * @see #MILLISECOND
-     * @see #MINUTE
-     * @see #HOUR
-     * @see #DAY
-     * @see #WEEK
-     * @see #YEAR
-     *
-     * @since 0.8
+     * @see java.util.concurrent.TimeUnit#MILLISECONDS
      */
-    public static final Unit<Time> SECOND = tec.units.ri.unit.Units.SECOND;
+    public static final Unit<Time> MILLISECOND;
 
     /**
-     * Unit of measurement defined as 10<sup>-3</sup> seconds.
-     * Useful for conversions from and to {@link java.util.Date} objects.
+     * The SI base unit for durations (s).
+     * The unlocalized name is “second” and the identifier is EPSG:1040.
+     * This is the base of all other {@linkplain #isTemporal(Unit) temporal} units:
      *
-     * @see #SECOND
+     * {@link #MILLISECOND} (ms),
+     * {@link #MINUTE} (min),
+     * {@link #HOUR} (h),
+     * {@link #DAY} (d),
+     * {@link #WEEK} (wk) and
+     * {@link #TROPICAL_YEAR} (a)
+     * among others.
+     *
+     * @see #HERTZ
+     *
+     * @since 0.8
      */
-    public static final Unit<Time> MILLISECOND = SECOND.divide(1000);
+    public static final Unit<Time> SECOND;
 
     /**
-     * Unit of measurement defined as 60 seconds.
+     * Unit of measurement defined as 60 seconds (1 min).
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #SECOND}
+     * and the unlocalized name is “minute”.
      *
      * @see #SECOND
      * @see #HOUR
+     * @see #DAY
      *
      * @since 0.8
      */
-    public static final Unit<Time> MINUTE = tec.units.ri.unit.Units.MINUTE;
+    public static final Unit<Time> MINUTE;
 
     /**
-     * Unit of measurement defined as 60×60 seconds.
+     * Unit of measurement defined as 60×60 seconds (1 h).
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #SECOND}
+     * and the unlocalized name is “hour”.
      *
      * @see #SECOND
      * @see #MINUTE
+     * @see #DAY
      *
      * @since 0.8
      */
-    public static final Unit<Time> HOUR = tec.units.ri.unit.Units.HOUR;
+    public static final Unit<Time> HOUR;
 
     /**
-     * Unit of measurement defined as 24×60×60 seconds.
+     * Unit of measurement defined as 24×60×60 seconds (1 d).
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #SECOND}
+     * and the unlocalized name is “day”.
      *
-     * @see #SECOND
+     * @see #HOUR
      * @see #WEEK
+     * @see #TROPICAL_YEAR
      *
      * @since 0.8
      */
-    public static final Unit<Time> DAY = tec.units.ri.unit.Units.DAY;
+    public static final Unit<Time> DAY;
 
     /**
-     * Unit of measurement defined as 7 days.
+     * Unit of measurement defined as 7 days (1 wk).
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #SECOND}
+     * and the unlocalized name is “week”.
      *
-     * @see #SECOND
      * @see #DAY
-     * @see #YEAR
+     * @see #TROPICAL_YEAR
      *
      * @since 0.8
      */
-    public static final Unit<Time> WEEK = tec.units.ri.unit.Units.WEEK;
+    public static final Unit<Time> WEEK;
 
     /**
-     * The EPSG:1029 definition of year.
+     * Unit of measurement approximatively equals to 365.24219 days (1 a).
+     * This is defined by the International Union of Geological Sciences (IUGS) as exactly 31556925.445 seconds,
+     * taken as the length of the tropical year in the the year 2000.
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #SECOND},
+     * the unlocalized name is “year” and the identifier is EPSG:1029.
      *
-     * @see #SECOND
-     * @see #WEEK
      * @see #DAY
+     * @see #WEEK
      *
      * @since 0.8
      */
-    private static final Unit<Time> YEAR = SECOND.divide(31556925.445);
-
-    /**
-     * The SI unit for frequency (symbol “Hz”).
-     * A unit of frequency equal to one cycle per second.
-     *
-     * @since 0.8
-     */
-    public static final Unit<Frequency> HERTZ = tec.units.ri.unit.Units.HERTZ;
+    public static final Unit<Time> TROPICAL_YEAR;
 
     /**
-     * The SI unit for pressure (symbol “Pa”).
+     * The SI derived unit for pressure (Pa).
      * One pascal is equal to 1 N/m².
      * Pressures are often used in {@linkplain org.apache.sis.referencing.crs.DefaultParametricCRS parametric CRS}
-     * for height measurements.
+     * for height measurements on a vertical axis.
+     * The unlocalized name is “pascal”.
      *
+     * @see #NEWTON
+     * @see #SQUARE_METRE
      * @see #HECTOPASCAL
      *
      * @since 0.8
      */
-    public static final Unit<Pressure> PASCAL = tec.units.ri.unit.Units.PASCAL;
+    public static final Unit<Pressure> PASCAL;
 
     /**
-     * Unit of measurement defined as 100 pascals.
+     * Unit of measurement defined as 100 pascals (1 hPa).
+     * The hectopascal is the international unit for measuring atmospheric or barometric pressure.
+     * One hectopascal is exactly equal to one millibar.
+     * The unlocalized name is “hectopascal”.
      *
      * @see #PASCAL
      *
      * @since 0.8
      */
-    public static final Unit<Pressure> HECTOPASCAL = PASCAL.multiply(100);
+    public static final Unit<Pressure> HECTOPASCAL;
 
     /**
-     * The SI base unit for mass (symbol “kg”).
+     * Unit of measurement defined as 10,000 square metres (1 ha).
+     * One hectare is exactly equals to one hectometre (1 hm²).
+     * While not an SI unit, the hectare is often used in the measurement of land.
+     * The unlocalized name is “hectare”.
      *
      * @since 0.8
+     *
+     * @see #SQUARE_METRE
      */
-    public static final Unit<Mass> KILOGRAM = tec.units.ri.unit.Units.KILOGRAM;
+    public static final Unit<Area> HECTARE;
 
     /**
-     * The SI unit for force (symbol “N”).
-     * One newton is the force required to give a mass of 1 kg an acceleration of 1 m/s².
+     * The SI derived unit for area (m²).
+     * The unlocalized name is “square metre”.
      *
      * @since 0.8
+     *
+     * @see #HECTARE
+     * @see #METRE
+     * @see #CUBIC_METRE
      */
-    public static final Unit<Force> NEWTON = tec.units.ri.unit.Units.NEWTON;
+    public static final Unit<Area> SQUARE_METRE;
 
     /**
-     * The SI unit for energy (symbol “J”).
+     * The SI derived unit for volume (m³).
+     * The unlocalized name is “cubic metre”.
      *
      * @since 0.8
+     *
+     * @see #METRE
+     * @see #SQUARE_METRE
      */
-    public static final Unit<Energy> JOULE = tec.units.ri.unit.Units.JOULE;
+    public static final Unit<Volume> CUBIC_METRE;
 
     /**
-     * The SI unit for power (symbol “W”).
-     * One watt is equal to one joule per second.
+     * The SI derived unit for speed (m/s).
+     * The unlocalized name is “metres per second” and the identifier is EPSG:1026.
+     *
+     * @see #METRE
+     * @see #SECOND
+     * @see #KILOMETRES_PER_HOUR
      *
      * @since 0.8
      */
-    public static final Unit<Power> WATT = tec.units.ri.unit.Units.WATT;
+    public static final Unit<Speed> METRES_PER_SECOND;
 
     /**
-     * The SI base unit for thermodynamic temperature (symbol “K”).
+     * Unit of measurement defined as 60/1000 metres per second (1 km/h).
+     * The unlocalized name is “kilometres per hour”.
      *
-     * @see #CELSIUS
+     * @see #KILOMETRE
+     * @see #HOUR
+     * @see #METRES_PER_SECOND
      *
      * @since 0.8
      */
-    public static final Unit<Temperature> KELVIN = tec.units.ri.unit.Units.KELVIN;
+    public static final Unit<Speed> KILOMETRES_PER_HOUR;
 
     /**
-     * Unit of measurement defined as the temperature in Kelvin minus 273.15.
+     * The SI base unit for mass (kg).
+     * The unlocalized name is “kilogram”.
      *
-     * @see #KELVIN
+     * @since 0.8
+     */
+    public static final Unit<Mass> KILOGRAM;
+
+    /**
+     * The SI derived unit for force (N).
+     * One newton is the force required to give a mass of 1 kg an acceleration of 1 m/s².
+     * The unlocalized name is “newton”.
      *
      * @since 0.8
+     *
+     * @see #KILOGRAM
+     * @see #METRES_PER_SECOND
      */
-    public static final Unit<Temperature> CELSIUS = tec.units.ri.unit.Units.CELSIUS;
+    public static final Unit<Force> NEWTON;
 
     /**
-     * Derived unit of measurement for speed (symbol “m/s”).
+     * The SI derived unit for energy (J).
+     * The unlocalized name is “joule”.
      *
-     * @see #KILOMETRES_PER_HOUR
+     * @since 0.8
+     */
+    public static final Unit<Energy> JOULE;
+
+    /**
+     * The SI derived unit for power (W).
+     * One watt is equal to one joule per second.
+     * The unlocalized name is “watt”.
      *
      * @since 0.8
      */
-    public static final Unit<Speed> METRES_PER_SECOND = tec.units.ri.unit.Units.METRES_PER_SECOND;
+    public static final Unit<Power> WATT;
 
     /**
-     * Derived unit of measurement for speed (symbol “km/h”).
+     * The SI base unit for thermodynamic temperature (K).
+     * The unlocalized name is “kelvin”.
      *
-     * @see #METRES_PER_SECOND
+     * @see #CELSIUS
      *
      * @since 0.8
      */
-    public static final Unit<Speed> KILOMETRES_PER_HOUR = tec.units.ri.unit.Units.KILOMETRES_PER_HOUR;
+    public static final Unit<Temperature> KELVIN;
 
     /**
-     * Derived unit of measurement for area (symbol “m²”).
+     * Unit of measurement defined as the temperature in Kelvin minus 273.15.
+     * The symbol is °C and the unlocalized name is “Celsius”.
+     * Note that this is the only SI unit with an upper-case letter in its name.
+     *
+     * @see #KELVIN
      *
      * @since 0.8
      */
-    public static final Unit<Area> SQUARE_METRE = tec.units.ri.unit.Units.SQUARE_METRE;
+    public static final Unit<Temperature> CELSIUS;
 
     /**
-     * Derived unit of measurement for area (symbol “m²”).
+     * The SI derived unit for frequency (Hz).
+     * One hertz is equal to one cycle per second.
+     * The unlocalized name is “hertz”.
      *
      * @since 0.8
+     *
+     * @see #SECOND
      */
-    public static final Unit<Volume> CUBIC_METRE = tec.units.ri.unit.Units.CUBIC_METRE;
+    public static final Unit<Frequency> HERTZ;
 
     /**
-     * Dimensionless unit for scale measurements.
+     * The base dimensionless unit for scale measurements.
+     * The unlocalized name is “unity” and the identifier is EPSG:9201.
+     * This is the base of all other {@linkplain #isScale(Unit) scale} units:
      *
-     * @see #PERCENT
-     * @see #PPM
+     * {@link #PERCENT} (%),
+     * {@link #PPM} (ppm) and
+     * {@link #PIXEL} (px)
+     * among others.
      *
      * @since 0.8
      */
-    public static final Unit<Dimensionless> ONE = tec.units.ri.AbstractUnit.ONE;
+    public static final Unit<Dimensionless> UNITY;
 
     /**
-     * Dimensionless unit for percentages.
+     * Dimensionless unit for percentages (%).
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #UNITY}
+     * and the unlocalized name is “percentage”.
      *
-     * @see #ONE
+     * @see #UNITY
      * @see #PPM
      *
      * @since 0.8
      */
-    public static final Unit<Dimensionless> PERCENT = tec.units.ri.unit.Units.PERCENT;
+    public static final Unit<Dimensionless> PERCENT;
 
     /**
-     * Dimensionless unit for parts per million.
+     * Dimensionless unit for parts per million (ppm).
+     * The {@linkplain ConventionalUnit#getSystemUnit() system unit} is {@link #UNITY},
+     * the unlocalized name is “parts per million” and the identifier is EPSG:9202.
      *
-     * @see #ONE
+     * @see #UNITY
      * @see #PERCENT
      */
-    public static final Unit<Dimensionless> PPM = ONE.divide(1E+6);
+    public static final Unit<Dimensionless> PPM;
 
     /**
      * Salinity measured using PSS-78. While this is a dimensionless measurement, the {@code "psu"} symbol
      * is sometime added to PSS-78 measurement. However this is officially discouraged.
+     *
+     * <p>If we make this field public in a future SIS version, we should consider introducing a
+     * {@code Salinity} quantity type.</p>
      */
-    static final Unit<Dimensionless> PSU = ONE.alternate("psu");
+    static final Unit<Dimensionless> PSU;
 
     /**
      * Sigma-level, used in oceanography. This is a way to measure a depth as a fraction of the sea floor depth.
+     *
+     * <p>If we make this field public in a future SIS version, we should consider introducing a new quantity type.
+     * The type to introduce has not yet been determined.</p>
      */
-    static final Unit<Dimensionless> SIGMA = ONE.alternate("sigma");
+    static final Unit<Dimensionless> SIGMA;
 
     /**
-     * Dimensionless unit for pixels.
+     * Dimensionless unit for pixels (px).
+     * The unlocalized name is “pixel”.
+     *
+     * @see #POINT
      */
-    public static final Unit<Dimensionless> PIXEL = ONE.alternate("pixel");
+    public static final Unit<Dimensionless> PIXEL;
 
+    /**
+     * Sets to {@code true} by the static initializer after the initialization has been completed.
+     * This is a safety against unexpected changes in the {@link UnitRegistry#HARD_CODED} map.
+     *
+     * <p>We use here a "lazy final initialization" pattern. We rely on the fact that this field is
+     * initialized to {@code true} only at the end of the following static initializer. All methods
+     * invoked in the static initializer will see the default value, which is {@code false}, until
+     * the initializer fully completed. While apparently dangerous, this behavior is actually documented
+     * in <a href="http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.4.1">section 12.4.1
+     * of Java language specification</a>:</p>
+     *
+     * <blockquote>The fact that initialization code is unrestricted allows examples to be constructed where
+     * the value of a class variable can be observed when it still has its initial default value, before its
+     * initializing expression is evaluated, but such examples are rare in practice. (…snip…) The full power
+     * of the Java programming language is available in these initializers; programmers must exercise some care.
+     * This power places an extra burden on code generators, but this burden would arise in any case because
+     * the Java programming language is concurrent.</blockquote>
+     */
+    static final boolean initialized;
     static {
-        final javax.measure.format.UnitFormat format = tec.units.ri.format.SimpleUnitFormat.getInstance();
-        format.label(METRE,  "m");
-        format.label(FOOT,  "ft");
-        format.label(DEGREE, "°");
-        format.label(GRAD, "grad");
+        final UnitDimension length        = new UnitDimension('L');
+        final UnitDimension mass          = new UnitDimension('M');
+        final UnitDimension time          = new UnitDimension('T');
+        final UnitDimension temperature   = new UnitDimension('Θ');
+        final UnitDimension area          = length.pow(2);
+        final UnitDimension speed         = length.divide(time);
+        final UnitDimension force         = mass.multiply(speed).divide(time);
+        final UnitDimension energy        = force.multiply(length);
+        final UnitDimension pressure      = force.divide(area);
+        final UnitDimension dimensionless = UnitDimension.NONE;
+        /*
+         * Base, derived or alternate units that we need to reuse more than once in this static initializer.
+         */
+        final SystemUnit<Length>        m   = add(Length.class,        length,        "m",   UnitRegistry.SI, Constants.EPSG_METRE);
+        final SystemUnit<Area>          m2  = add(Area.class,          area,          "m²",  UnitRegistry.SI, (short) 0);
+        final SystemUnit<Time>          s   = add(Time.class,          time,          "s",   UnitRegistry.SI, (short) 1040);
+        final SystemUnit<Temperature>   K   = add(Temperature.class,   temperature,   "K",   UnitRegistry.SI, (short) 0);
+        final SystemUnit<Speed>         mps = add(Speed.class,         speed,         "m∕s", UnitRegistry.SI, (short) 1026);
+        final SystemUnit<Pressure>      Pa  = add(Pressure.class,      pressure,      "Pa",  UnitRegistry.SI, (short) 0);
+        final SystemUnit<Angle>         rad = add(Angle.class,         dimensionless, "rad", UnitRegistry.SI, (short) 9101);
+        final SystemUnit<Dimensionless> one = add(Dimensionless.class, dimensionless, "",    UnitRegistry.SI, (short) 9201);
+        /*
+         * All SI prefix to be used below.
+         */
+        final LinearConverter nano  = LinearConverter.forPrefix('n');
+        final LinearConverter micro = LinearConverter.forPrefix('µ');
+        final LinearConverter milli = LinearConverter.forPrefix('m');
+        final LinearConverter centi = LinearConverter.forPrefix('c');
+        final LinearConverter hecto = LinearConverter.forPrefix('h');
+        final LinearConverter kilo  = LinearConverter.forPrefix('k');
+        /*
+         * All Unit<Angle>
+         */
+        RADIAN      = rad;
+        GRAD        = add(rad, LinearConverter.scale(Math.PI, 200),    "grad", UnitRegistry.OTHER,    (short) 9105);
+        DEGREE      = add(rad, LinearConverter.scale(Math.PI, 180),       "°", UnitRegistry.ACCEPTED, Constants.EPSG_PARAM_DEGREES);
+        ARC_MINUTE  = add(rad, LinearConverter.scale(Math.PI, 180*60),    "′", UnitRegistry.ACCEPTED, (short) 9103);
+        ARC_SECOND  = add(rad, LinearConverter.scale(Math.PI, 180*60*60), "″", UnitRegistry.ACCEPTED, (short) 9104);
+        MICRORADIAN = add(rad, micro,                                  "µrad", UnitRegistry.SI,       (short) 9109);
+        /*
+         * All Unit<Length>
+         */
+        METRE          = m;
+        NANOMETRE      = add(m, nano,                                     "nm",    UnitRegistry.SI,       (short) 0);
+        MILLIMETRE     = add(m, milli,                                    "mm",    UnitRegistry.SI,       (short) 1025);
+        CENTIMETRE     = add(m, centi,                                    "cm",    UnitRegistry.SI,       (short) 1033);
+        KILOMETRE      = add(m, kilo,                                     "km",    UnitRegistry.SI,       (short) 9036);
+        NAUTICAL_MILE  = add(m, LinearConverter.scale(   1852,        1), "M",     UnitRegistry.OTHER,    (short) 9030);
+        STATUTE_MILE   = add(m, LinearConverter.scale(1609344,      100), "mi",    UnitRegistry.IMPERIAL, (short) 9093);
+        US_SURVEY_FOOT = add(m, LinearConverter.scale(   1200,     3937), "ft_US", UnitRegistry.OTHER,    (short) 9003);
+        FOOT           = add(m, LinearConverter.scale(   3048,    10000), "ft",    UnitRegistry.IMPERIAL, (short) 9002);
+        INCH           = add(m, LinearConverter.scale(    254,    10000), "in",    UnitRegistry.IMPERIAL, (short) 0);
+        POINT          = add(m, LinearConverter.scale( 996264, 72000000), "pt",    UnitRegistry.OTHER,    (short) 0);
+        /*
+         * All Unit<Time>
+         */
+        SECOND         = s;
+        MILLISECOND    = add(s, milli, "ms", UnitRegistry.SI, (short) 0);
+        MINUTE         = add(s, LinearConverter.scale(         60,      1), "min", UnitRegistry.ACCEPTED, (short) 0);
+        HOUR           = add(s, LinearConverter.scale(      60*60,      1), "h",   UnitRegistry.ACCEPTED, (short) 0);
+        DAY            = add(s, LinearConverter.scale(   24*60*60,      1), "d",   UnitRegistry.ACCEPTED, (short) 0);
+        WEEK           = add(s, LinearConverter.scale( 7*24*60*60,      1), "wk",  UnitRegistry.OTHER,    (short) 0);
+        TROPICAL_YEAR  = add(s, LinearConverter.scale(31556925445.0, 1000), "a",   UnitRegistry.OTHER,    (short) 1029);
+        /*
+         * Other units.
+         */
+        KELVIN              = K;
+        PASCAL              = Pa;
+        SQUARE_METRE        = m2;
+        METRES_PER_SECOND   = mps;
+        KILOGRAM            = add(Mass.class,      mass,                  "kg",   UnitRegistry.SI,       (short) 0);
+        CUBIC_METRE         = add(Volume.class,    length.pow(3),         "m³",   UnitRegistry.SI,       (short) 0);
+        NEWTON              = add(Force.class,     force,                 "N",    UnitRegistry.SI,       (short) 0);
+        JOULE               = add(Energy.class,    energy,                "J",    UnitRegistry.SI,       (short) 0);
+        WATT                = add(Power.class,     energy.divide(time),   "W",    UnitRegistry.SI,       (short) 0);
+        HERTZ               = add(Frequency.class, time.pow(-1),          "Hz",   UnitRegistry.SI,       (short) 0);
+        HECTOPASCAL         = add(Pa, hecto,                              "hPa",  UnitRegistry.SI,       (short) 0);
+        HECTARE             = add(m2,  LinearConverter.scale(10000, 1),   "ha",   UnitRegistry.ACCEPTED, (short) 0);
+        KILOMETRES_PER_HOUR = add(mps, LinearConverter.scale(6, 100),     "km∕h", UnitRegistry.ACCEPTED, (short) 0);
+        CELSIUS             = add(K,   LinearConverter.create(1, 273.15), "°C",   UnitRegistry.SI,       (short) 0);
+        /*
+         * All Unit<Dimensionless>
+         */
+        PERCENT = add(one, centi,                         "%",     UnitRegistry.OTHER, (short) 0);
+        PPM     = add(one, micro,                         "ppm",   UnitRegistry.OTHER, (short) 9202);
+        PSU     = add(Dimensionless.class, dimensionless, "psu",   UnitRegistry.OTHER, (short) 0);
+        SIGMA   = add(Dimensionless.class, dimensionless, "sigma", UnitRegistry.OTHER, (short) 0);
+        PIXEL   = add(Dimensionless.class, dimensionless, "px",    UnitRegistry.OTHER, (short) 0);
+        UNITY   = UnitRegistry.init(one);  // Must be last in order to take precedence over all other units associated to UnitDimension.NONE.
+
+        UnitRegistry.alias(UNITY,       Short.valueOf((short) 9203));
+        UnitRegistry.alias(DEGREE,      Short.valueOf(Constants.EPSG_AXIS_DEGREES));
+        UnitRegistry.alias(ARC_MINUTE,  "'");
+        UnitRegistry.alias(ARC_SECOND, "\"");
+        UnitRegistry.alias(KELVIN,      "K");       // Ordinary "K" letter (not the dedicated Unicode character).
+        UnitRegistry.alias(CELSIUS,     "℃");
+        UnitRegistry.alias(CELSIUS,   "Cel");
+        UnitRegistry.alias(GRAD,      "gon");
+
+        initialized = true;
+    }
+
+    /**
+     * Invoked by {@code Units} static class initializer for registering SI base and derived units.
+     * This method shall be invoked in a single thread by the {@code Units} class initializer only.
+     */
+    private static <Q extends Quantity<Q>> SystemUnit<Q> add(Class<Q> quantity, UnitDimension dimension, String symbol, byte scope, short epsg) {
+        return UnitRegistry.init(new SystemUnit<>(quantity, dimension, symbol, scope, epsg));
+    }
+
+    /**
+     * Invoked by {@code Units} static class initializer for registering SI conventional units.
+     * This method shall be invoked in a single thread by the {@code Units} class initializer only.
+     */
+    private static <Q extends Quantity<Q>> ConventionalUnit<Q> add(SystemUnit<Q> target, UnitConverter toTarget, String symbol, byte scope, short epsg) {
+        return UnitRegistry.init(new ConventionalUnit<>(target, toTarget, symbol, scope, epsg));
+    }
+
+    /**
+     * Returns the system unit for the given dimension, or {@code null} if none.
+     * Note that this method can not distinguish the different kinds of dimensionless units.
+     * If the symbol or the quantity type is known, use {@link #get(String)} or {@link #get(Class)} instead.
+     *
+     * <p><b>Implementation note:</b> this method must be defined in this {@code Units} class
+     * in order to force a class initialization before use.</p>
+     */
+    static SystemUnit<?> get(final Dimension dim) {
+        return (SystemUnit<?>) UnitRegistry.get(dim);
+    }
+
+    /**
+     * Returns the system unit for the given quantity, or {@code null} if none.
+     *
+     * <p><b>Implementation note:</b> this method must be defined in this {@code Units} class
+     * in order to force a class initialization before use.</p>
+     */
+    @SuppressWarnings("unchecked")
+    static <Q extends Quantity<Q>> SystemUnit<Q> get(final Class<Q> type) {
+        return (SystemUnit<Q>) UnitRegistry.get(type);
+    }
+
+    /**
+     * Returns the system unit for the given symbol, or {@code null} if none.
+     * This method does not perform any parsing (prefix, exponents, <i>etc</i>).
+     * It is only for getting one of the pre-defined constants, for example after deserialization.
+     *
+     * <p><b>Implementation note:</b> this method must be defined in this {@code Units} class
+     * in order to force a class initialization before use.</p>
+     */
+    @SuppressWarnings("unchecked")
+    static Unit<?> get(final String symbol) {
+        return (Unit<?>) UnitRegistry.get(symbol);
     }
 
     /**
@@ -489,7 +812,7 @@ public final class Units extends Static
      * Linear units are convertible to {@link #DEGREE}.
      *
      * <p>Angular units are dimensionless, which may be a cause of confusion with other
-     * dimensionless units like {@link #ONE} or {@link #PPM}. This method take care
+     * dimensionless units like {@link #UNITY} or {@link #PPM}. This method take care
      * of differentiating angular units from other dimensionless units.</p>
      *
      * @param  unit  the unit to check (may be {@code null}).
@@ -508,6 +831,7 @@ public final class Units extends Static
      * @param  unit  the unit to check (may be {@code null}).
      * @return {@code true} if the given unit is non-null and linear.
      *
+     * @see #METRE
      * @see #ensureLinear(Unit)
      */
     public static boolean isLinear(final Unit<?> unit) {
@@ -541,15 +865,16 @@ public final class Units extends Static
 
     /**
      * Returns {@code true} if the given unit is a dimensionless scale unit.
-     * This include {@link Unit#ONE} and {@link #PPM}.
+     * This include {@link #UNITY} and {@link #PPM}.
      *
      * @param  unit  the unit to check (may be {@code null}).
      * @return {@code true} if the given unit is non-null and a dimensionless scale.
      *
+     * @see #UNITY
      * @see #ensureScale(Unit)
      */
     public static boolean isScale(final Unit<?> unit) {
-        return (unit != null) && unit.getSystemUnit().equals(ONE);
+        return (unit != null) && unit.getSystemUnit().equals(UNITY);
     }
 
     /**
@@ -657,54 +982,101 @@ public final class Units extends Static
                 return (Unit<Q>) FOOT;
             }
             if (abs(factor - (1200.0/3937)) <= (EPS * (1200.0/3937))) {
-                return (Unit<Q>) FOOT_SURVEY_US;
+                return (Unit<Q>) US_SURVEY_FOOT;
             }
         }
         if (abs(factor - 1) > EPS) {
             unit = unit.multiply(factor);
         }
-        return UnitsMap.canonicalize(unit);
+        return unit;
     }
 
     /**
      * Returns the factor by which to multiply the standard unit in order to get the given unit.
-     * The "standard" unit is usually the SI unit on which the given unit is based.
+     * The "standard" unit is usually the SI unit on which the given unit is based, as given by
+     * {@link Unit#getSystemUnit()}.
      *
-     * <p><b>Example:</b> if the given unit is <var>kilometre</var>, then this method returns 1000
-     * since a measurement in kilometres must be multiplied by 1000 in order to give the equivalent
-     * measurement in the "standard" units (here <var>metres</var>).</p>
-     *
-     * @param  <Q>   the quantity measured by the unit.
-     * @param  unit  the unit for which we want the multiplication factor to standard unit.
-     * @return the factor by which to multiply a measurement in the given unit in order to
-     *         get an equivalent measurement in the standard unit.
+     * <div class="note"><b>Example:</b>
+     * if the given unit is {@link #KILOMETRE}, then this method returns 1000 since a measurement in kilometres
+     * must be multiplied by 1000 in order to give the equivalent measurement in the "standard" units
+     * (here {@link #METRE}).</div>
+     *
+     * If the given unit is {@code null} or if the conversion to the "standard" unit can not be expressed
+     * by a single multiplication factor, then this method returns {@link Double#NaN}.
+     *
+     * @param  <Q>   the quantity measured by the unit, or {@code null}.
+     * @param  unit  the unit for which we want the multiplication factor to standard unit, or {@code null}.
+     * @return the factor by which to multiply a measurement in the given unit in order to get an equivalent
+     *         measurement in the standard unit, or NaN if the conversion can not be expressed by a scale factor.
      */
-    @Workaround(library="JSR-275", version="0.9.3")
     public static <Q extends Quantity<Q>> double toStandardUnit(final Unit<Q> unit) {
-        return derivative(unit.getConverterTo(unit.getSystemUnit()), 0);
+        if (unit != null) {
+            final UnitConverter converter = unit.getConverterTo(unit.getSystemUnit());
+            if (converter.isLinear() && converter.convert(0) == 0) {
+                // Above check for converter(0) is a paranoiac check since
+                // JSR-363 said that a "linear" converter has no offset.
+                return converter.convert(1);
+            }
+        }
+        return Double.NaN;
     }
 
     /**
-     * Returns an estimation of the derivative of the given converter at the given value.
-     * This method is a workaround for a method which existed in previous JSR-275 API but
-     * have been removed in more recent releases.
+     * Returns the coefficients of the given converter expressed as a polynomial equation.
+     * This method returns the first of the following choices that apply:
      *
-     * <p>Current implementation computes the derivative as below:</p>
+     * <ul>
+     *   <li>If the given converter {@linkplain UnitConverter#isIdentity() is identity}, returns an empty array.</li>
+     *   <li>If the given converter shifts the values without scaling them (for example the conversion from Kelvin to
+     *       Celsius degrees), returns an array of length 1 containing only the offset.</li>
+     *   <li>If the given converter scales the values (optionally in addition to shifting them), returns an array of
+     *       length 2 containing the offset and scale factor, in that order.</li>
+     * </ul>
      *
-     * {@preformat java
-     *     return converter.convert(value + 1) - converter.convert(value);
-     * }
+     * This method returns {@code null} if it can not get the polynomial equation coefficients from the given converter.
      *
-     * The above is exact for linear converters, which is the case of the vast majority of unit converters in use.
-     * It may not be exact for a few unusual converter like the one from sexagesimal degrees to decimal degrees.
+     * @param  converter  the converter from which to get the coefficients of the polynomial equation, or {@code null}.
+     * @return the polynomial equation coefficients (may be any length, including zero), or {@code null} if the given
+     *         converter is {@code null} or if this method can not get the coefficients.
      *
-     * @param  converter  the converter for which we want the derivative at a given point.
+     * @since 0.8
+     */
+    @SuppressWarnings("fallthrough")
+    public static Number[] coefficients(final UnitConverter converter) {
+        if (converter != null) {
+            if (converter instanceof AbstractConverter) {
+                return ((AbstractConverter) converter).coefficients();
+            }
+            if (converter.isIdentity()) {
+                return new Number[0];
+            }
+            if (converter.isLinear()) {
+                final double offset = converter.convert(0);  // Should be zero as per JSR-363 specification, but we are paranoiac.
+                final double scale  = converter.convert(1) - offset;
+                final Number[] c = new Number[(scale != 1) ? 2 : (offset != 0) ? 1 : 0];
+                switch (c.length) {
+                    case 2: c[1] = scale;       // Fall through
+                    case 1: c[0] = offset;
+                    case 0: break;
+                }
+                return c;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the derivative of the given converter at the given value,
+     * or {@code NaN} if this method can not compute it.
+     *
+     * @param  converter  the converter for which we want the derivative at a given point, or {@code null}.
      * @param  value      the point at which to compute the derivative.
-     * @return the derivative at the given point.
+     * @return the derivative at the given point, or {@code NaN} if unknown.
+     *
+     * @see org.apache.sis.referencing.operation.transform.AbstractMathTransform#derivative(DirectPosition)
      */
-    @Workaround(library="JSR-275", version="0.9.3")
     public static double derivative(final UnitConverter converter, final double value) {
-        return converter.convert(value + 1) - converter.convert(value);
+        return AbstractConverter.derivative(converter, value);
     }
 
     /**
@@ -778,11 +1150,14 @@ public final class Units extends Static
      *     </table></td>
      *     <td class="sep"><table class="compact" summary="Linear units">
      *       <tr><td style="width: 40px"><b>Code</b></td><td><b>Unit</b></td></tr>
+     *       <tr><td>1025</td><td>millimetre</td></tr>
+     *       <tr><td>1033</td><td>centimetre</td></tr>
      *       <tr><td>9001</td><td>metre</td></tr>
      *       <tr><td>9002</td><td>foot</td></tr>
      *       <tr><td>9003</td><td>US survey foot</td></tr>
      *       <tr><td>9030</td><td>nautical mile</td></tr>
      *       <tr><td>9036</td><td>kilometre</td></tr>
+     *       <tr><td>9093</td><td>statute mile</td></tr>
      *     </table></td>
      *     <td class="sep"><table class="compact" summary="Time units">
      *       <tr><td style="width: 40px"><b>Code</b></td><td><b>Unit</b></td></tr>
@@ -791,9 +1166,9 @@ public final class Units extends Static
      *     </table></td>
      *     <td class="sep"><table class="compact" summary="Scale units">
      *       <tr><td style="width: 40px"><b>Code</b></td><td><b>Unit</b></td></tr>
-     *       <tr><td>9201</td><td>one</td></tr>
-     *       <tr><td>9202</td><td>part per million</td></tr>
-     *       <tr><td>9203</td><td>one</td></tr>
+     *       <tr><td>9201</td><td>unity</td></tr>
+     *       <tr><td>9202</td><td>parts per million</td></tr>
+     *       <tr><td>9203</td><td>unity</td></tr>
      *     </table></td>
      *   </tr>
      * </table>
@@ -809,30 +1184,26 @@ public final class Units extends Static
      * @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createUnit(String)
      */
     public static Unit<?> valueOfEPSG(final int code) {
+        /*
+         * The switch for the SexagesimalConverter cases are needed since we did not put those units
+         * in the UnitRegistry map for reducing a little bit class loading in the common cases where
+         * those units are not needed. Other cases are redundant with the UnitRegistry check, but we
+         * add them opportunistically as a shortcut since those units are frequently used.
+         */
         switch (code) {
             case Constants.EPSG_PARAM_DEGREES:  // Fall through
             case Constants.EPSG_AXIS_DEGREES:   return DEGREE;
             case Constants.EPSG_METRE:          return METRE;
 
-            case 1029: return YEAR;
-            case 1040: return SECOND;
-            case 9002: return FOOT;
-            case 9003: return FOOT_SURVEY_US;
-            case 9030: return NAUTICAL_MILE;
-            case 9036: return KILOMETRE;
-            case 9101: return RADIAN;
-            case 9103: return ARC_MINUTE;
-            case 9104: return ARC_SECOND;
-            case 9105: return GRAD;
-            case 9109: return MICRORADIAN;
             case 9107: // Fall through
             case 9108: return SexagesimalConverter.DMS_SCALED;
             case 9110: return SexagesimalConverter.DMS;
             case 9111: return SexagesimalConverter.DM;
             case 9203: // Fall through
-            case 9201: return ONE;
-            case 9202: return PPM;
-            default:   return null;
+            case 9201: return UNITY;
+            default: {
+                return (code > 0 && code <= Short.MAX_VALUE) ? (Unit<?>) UnitRegistry.get((short) code) : null;
+            }
         }
     }
 
@@ -855,11 +1226,22 @@ public final class Units extends Static
      *
      * @since 0.4
      */
-    public static Integer getEpsgCode(final Unit<?> unit, final boolean inAxis) {
-        Integer code = UnitsMap.EPSG_CODES.get(unit);
-        if (inAxis && code != null && code == Constants.EPSG_PARAM_DEGREES) {
-            code = UnitsMap.EPSG_AXIS_DEGREES;
+    public static Integer getEpsgCode(Unit<?> unit, final boolean inAxis) {
+        if (unit != null) {
+            if (!(unit instanceof AbstractUnit<?>)) {
+                unit = get(unit.getSymbol());
+                if (!(unit instanceof AbstractUnit<?>)) {
+                    return null;
+                }
+            }
+            short code = ((AbstractUnit<?>) unit).epsg;
+            if (code != 0) {
+                if (inAxis && code == Constants.EPSG_PARAM_DEGREES) {
+                    code = Constants.EPSG_AXIS_DEGREES;
+                }
+                return Integer.valueOf(code);
+            }
         }
-        return code;
+        return null;
     }
 }

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java?rev=1766508&r1=1766507&r2=1766508&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java [UTF-8] Tue Oct 25 10:45:14 2016
@@ -921,10 +921,10 @@ search:     for (; fromIndex <= toIndex;
 
     /**
      * Replaces some Unicode characters by ASCII characters on a "best effort basis".
-     * For example the {@code 'é'} character is replaced by {@code 'e'} (without accent).
-     *
-     * <p>The current implementation replaces the characters in the range {@code 00C0}
-     * to {@code 00FF} (inclusive) and some space and punctuation characters.</p>
+     * For example the “ é ” character is replaced by  “ e ” (without accent),
+     * the  “ ″ ” symbol for minutes of angle is replaced by straight double quotes “ " ”,
+     * and combined characters like ㎏, ㎎, ㎝, ㎞, ㎢, ㎦, ㎖, ㎧, ㎩, ㎐, <i>etc.</i> are replaced
+     * by the corresponding sequences of characters.
      *
      * <div class="note"><b>Note:</b>
      * the replacement of Greek letters is a more complex task than what this method can do,
@@ -938,6 +938,7 @@ search:     for (; fromIndex <= toIndex;
      *
      * @see StringBuilders#toASCII(StringBuilder)
      * @see org.apache.sis.io.wkt.Transliterator#filter(String)
+     * @see java.text.Normalizer
      */
     public static CharSequence toASCII(final CharSequence text) {
         return StringBuilders.toASCII(text, null);

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/Characters.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/Characters.java?rev=1766508&r1=1766507&r2=1766508&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/Characters.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/Characters.java [UTF-8] Tue Oct 25 10:45:14 2016
@@ -86,7 +86,7 @@ public final class Characters extends St
      * They are ASCII codes 32 to 125 inclusive except ! (33), # (35), $ (36), @ (64) and ` (96),
      * plus the addition of ° (176) despite being formally outside the ASCII character set.
      *
-     * @param  c The code point to test.
+     * @param  c  the code point to test.
      * @return {@code true} if the given code point is a valid WKT character.
      *
      * @see org.apache.sis.io.wkt.Transliterator
@@ -110,7 +110,7 @@ public final class Characters extends St
      * line separator}, a {@linkplain Character#PARAGRAPH_SEPARATOR paragraph separator} or one
      * of the {@code '\r'} or {@code '\n'} control characters.
      *
-     * @param  c The code point to test.
+     * @param  c  the code point to test.
      * @return {@code true} if the given code point is a line or paragraph separator.
      *
      * @see #LINE_SEPARATOR
@@ -130,7 +130,7 @@ public final class Characters extends St
      * This method returns {@code true} if {@code c} is between {@code '0'} and {@code '9'} inclusive,
      * or between {@code 'A'} and {@code 'F'} inclusive, or between {@code 'a'} and {@code 'f'} inclusive.
      *
-     * @param  c The character to test.
+     * @param  c  the character to test.
      * @return {@code true} if the given character is an hexadecimal digit.
      *
      * @since 0.5
@@ -152,16 +152,16 @@ public final class Characters extends St
      *   ⁰ ¹ ² ³ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹ ⁺ ⁻ ⁼ ⁽ ⁾ ⁿ
      * }
      *
-     * @param  c The character to test.
+     * @param  c  the character to test.
      * @return {@code true} if the given character is a superscript.
      */
     public static boolean isSuperScript(final int c) {
         switch (c) {
             case '¹':      // Legacy values in "Latin-1 supplement" space: 00B9, 00B2 and 00B3.
-            case '²':      // Those values are outside the normal [2070 … 207F] range.
+            case '²':      // Those values are outside the usual [2070 … 207F] range.
             case '³':      return true;
-            case '\u2071': // Would be the '¹', '²' and '³' values if they were declared in the
-            case '\u2072': // normal range. Since they are not, those values are unassigned.
+            case '\u2071': // Would be the '¹', '²' and '³' values if they were declared in the usual range.
+            case '\u2072': // Since they are not, those values are unassigned.
             case '\u2073': return false;
             default:       return (c >= '⁰' && c <= 'ⁿ');
         }
@@ -175,7 +175,7 @@ public final class Characters extends St
      *   ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ₊ ₋ ₌ ₍ ₎
      * }
      *
-     * @param  c The character to test.
+     * @param  c  the character to test.
      * @return {@code true} if the given character is a subscript.
      */
     public static boolean isSubScript(final int c) {
@@ -190,9 +190,8 @@ public final class Characters extends St
      *     0 1 2 3 4 5 6 7 8 9 + - = ( ) n
      * }
      *
-     * @param  c The character to convert.
-     * @return The given character as a superscript, or {@code c}
-     *         if the given character can not be converted.
+     * @param  c  the character to convert.
+     * @return the given character as a superscript, or {@code c} if the given character can not be converted.
      */
     public static char toSuperScript(char c) {
         switch (c) {
@@ -223,9 +222,8 @@ public final class Characters extends St
      *     0 1 2 3 4 5 6 7 8 9 + - = ( )
      * }
      *
-     * @param  c The character to convert.
-     * @return The given character as a subscript, or {@code c}
-     *         if the given character can not be converted.
+     * @param  c  the character to convert.
+     * @return the given character as a subscript, or {@code c} if the given character can not be converted.
      */
     public static char toSubScript(char c) {
         switch (c) {
@@ -247,8 +245,8 @@ public final class Characters extends St
     /**
      * Converts the given character argument to normal script.
      *
-     * @param  c The character to convert.
-     * @return The given character as a normal script, or {@code c} if the
+     * @param  c  the character to convert.
+     * @return the given character as a normal script, or {@code c} if the
      *         given character was not a superscript or a subscript.
      */
     public static char toNormalScript(char c) {
@@ -369,8 +367,8 @@ public final class Characters extends St
         /**
          * Creates a new subset of the given name.
          *
-         * @param name  The subset name.
-         * @param types A bitmask of character types.
+         * @param  name   the subset name.
+         * @param  types  a bitmask of character types.
          */
         Filter(final String name, final long types) {
             super(name);
@@ -380,7 +378,7 @@ public final class Characters extends St
         /**
          * Returns {@code true} if this subset contains the given Unicode character.
          *
-         * @param  codePoint The Unicode character, as a code point value.
+         * @param  codePoint  the Unicode character, as a code point value.
          * @return {@code true} if this subset contains the given character.
          */
         public boolean contains(final int codePoint) {
@@ -395,7 +393,7 @@ public final class Characters extends St
          * {@link Character#DECIMAL_DIGIT_NUMBER DECIMAL_DIGIT_NUMBER} or
          * {@link Character#SPACE_SEPARATOR      SPACE_SEPARATOR}.
          *
-         * @param  type One of the {@link Character} constants.
+         * @param  type  one of the {@link Character} constants.
          * @return {@code true} if this subset contains the characters of the given type.
          *
          * @see Character#getType(int)
@@ -407,8 +405,8 @@ public final class Characters extends St
         /**
          * Returns a subset representing the union of all Unicode characters of the given types.
          *
-         * @param  types The character types, as {@link Character} constants.
-         * @return The subset of Unicode characters of the given type.
+         * @param  types  the character types, as {@link Character} constants.
+         * @return the subset of Unicode characters of the given type.
          *
          * @see Character#LOWERCASE_LETTER
          * @see Character#UPPERCASE_LETTER

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/StringBuilders.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/StringBuilders.java?rev=1766508&r1=1766507&r2=1766508&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/StringBuilders.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/StringBuilders.java [UTF-8] Tue Oct 25 10:45:14 2016
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.util;
 
+import java.text.Normalizer;
 import org.apache.sis.util.resources.Errors;
 
 import static java.lang.Character.*;
@@ -34,7 +35,7 @@ import static java.lang.Character.*;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.8
  * @module
  *
  * @see CharSequences
@@ -42,6 +43,9 @@ import static java.lang.Character.*;
 public final class StringBuilders extends Static {
     /**
      * Letters in the range 00C0 (192) to 00FF (255) inclusive with their accent removed, when possible.
+     * This string partially duplicates the work done by {@link Normalizer} with additional replacements.
+     * We use it for more direct character replacements (compared to using {@code Normalizer} than removing
+     * combining marks) for those common and easy cases.
      */
     private static final String ASCII = "AAAAAAÆCEEEEIIIIDNOOOOO*OUUUUYÞsaaaaaaæceeeeiiiionooooo/ouuuuyþy";
     // Original letters (with accent) = "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ";
@@ -55,10 +59,10 @@ public final class StringBuilders extend
     /**
      * Replaces every occurrences of the given character in the given buffer.
      *
-     * @param  buffer    The string in which to perform the replacements.
-     * @param  toSearch  The character to replace.
-     * @param  replaceBy The replacement for the searched character.
-     * @throws NullArgumentException If the {@code buffer} arguments is null.
+     * @param  buffer     the string in which to perform the replacements.
+     * @param  toSearch   the character to replace.
+     * @param  replaceBy  the replacement for the searched character.
+     * @throws NullArgumentException if the {@code buffer} arguments is null.
      *
      * @see String#replace(char, char)
      */
@@ -78,11 +82,11 @@ public final class StringBuilders extend
      * This method invokes {@link StringBuilder#replace(int, int, String)}
      * for each occurrence of {@code search} found in the buffer.
      *
-     * @param  buffer    The string in which to perform the replacements.
-     * @param  toSearch  The string to replace.
-     * @param  replaceBy The replacement for the searched string.
-     * @throws NullArgumentException If any of the arguments is null.
-     * @throws IllegalArgumentException If the {@code toSearch} argument is empty.
+     * @param  buffer     the string in which to perform the replacements.
+     * @param  toSearch   the string to replace.
+     * @param  replaceBy  the replacement for the searched string.
+     * @throws NullArgumentException if any of the arguments is null.
+     * @throws IllegalArgumentException if the {@code toSearch} argument is empty.
      *
      * @see String#replace(char, char)
      * @see CharSequences#replace(CharSequence, CharSequence, CharSequence)
@@ -107,10 +111,10 @@ public final class StringBuilders extend
      * The substring to be replaced begins at the specified {@code start} and extends to the
      * character at index {@code end - 1}.
      *
-     * @param  buffer The buffer in which to perform the replacement.
-     * @param  start  The beginning index in the {@code buffer}, inclusive.
-     * @param  end    The ending index in the {@code buffer}, exclusive.
-     * @param  chars  The array that will replace previous contents.
+     * @param  buffer  the buffer in which to perform the replacement.
+     * @param  start   the beginning index in the {@code buffer}, inclusive.
+     * @param  end     the ending index in the {@code buffer}, exclusive.
+     * @param  chars   the array that will replace previous contents.
      * @throws NullArgumentException if the {@code buffer} or {@code chars} argument is null.
      *
      * @see StringBuilder#replace(int, int, String)
@@ -140,10 +144,10 @@ public final class StringBuilders extend
      * {@link StringBuilder#delete(int, int)} for each occurrence of {@code search} found in
      * the buffer.
      *
-     * @param  buffer   The string in which to perform the removals.
-     * @param  toSearch The string to remove.
-     * @throws NullPointerException If any of the arguments is null.
-     * @throws IllegalArgumentException If the {@code toSearch} argument is empty.
+     * @param  buffer    the string in which to perform the removals.
+     * @param  toSearch  the string to remove.
+     * @throws NullPointerException if any of the arguments is null.
+     * @throws IllegalArgumentException if the {@code toSearch} argument is empty.
      *
      * @see StringBuilder#delete(int, int)
      */
@@ -170,8 +174,8 @@ public final class StringBuilders extend
      * This method is useful after a {@linkplain StringBuilder#append(double) double value has
      * been appended to the buffer}, in order to make it appears like an integer when possible.
      *
-     * @param buffer The buffer to trim if possible.
-     * @throws NullArgumentException If the given {@code buffer} is null.
+     * @param  buffer  the buffer to trim if possible.
+     * @throws NullArgumentException if the given {@code buffer} is null.
      *
      * @see CharSequences#trimFractionalPart(CharSequence)
      */
@@ -191,15 +195,16 @@ public final class StringBuilders extend
 
     /**
      * Replaces some Unicode characters by ASCII characters on a "best effort basis".
-     * For example the {@code 'é'} character is replaced by {@code 'e'} (without accent).
+     * For example the “ é ” character is replaced by  “ e ” (without accent),
+     * the  “ ″ ” symbol for minutes of angle is replaced by straight double quotes “ " ”,
+     * and combined characters like ㎏, ㎎, ㎝, ㎞, ㎢, ㎦, ㎖, ㎧, ㎩, ㎐, <i>etc.</i> are replaced
+     * by the corresponding sequences of characters.
      *
-     * <p>The current implementation replaces the characters in the range {@code 00C0}
-     * to {@code 00FF} (inclusive) and some space and punctuation characters.</p>
-     *
-     * @param  buffer The text to scan for Unicode characters to replace by ASCII characters.
-     * @throws NullArgumentException If the given {@code buffer} is null.
+     * @param  buffer  the text to scan for Unicode characters to replace by ASCII characters.
+     * @throws NullArgumentException if the given {@code buffer} is null.
      *
      * @see CharSequences#toASCII(CharSequence)
+     * @see Normalizer#normalize(CharSequence, Normalizer.Form)
      */
     public static void toASCII(final StringBuilder buffer) {
         ArgumentChecks.ensureNonNull("buffer", buffer);
@@ -211,6 +216,7 @@ public final class StringBuilders extend
      */
     static CharSequence toASCII(CharSequence text, StringBuilder buffer) {
         if (text != null) {
+            boolean doneNFKD = false;
             /*
              * Scan the buffer in reverse order because we may suppress some characters.
              */
@@ -219,41 +225,68 @@ public final class StringBuilders extend
                 final int c = codePointBefore(text, i);
                 final int n = charCount(c);
                 final int r = c - 0xC0;
-                i -= n; // After this line, 'i' is the index of character 'c'.
+                i -= n;                                     // After this line, 'i' is the index of character 'c'.
                 if (r >= 0) {
-                    final char cr; // The character replacement.
+                    final char cr;                          // The character replacement.
                     if (r < ASCII.length()) {
                         cr = ASCII.charAt(r);
                     } else {
                         switch (getType(c)) {
                             case FORMAT:
-                            case CONTROL: buffer.delete(i, i + n); continue;  // Character.isIdentifierIgnorable
+                            case CONTROL:                   // Character.isIdentifierIgnorable
+                            case NON_SPACING_MARK:          cr = 0; break;
                             case PARAGRAPH_SEPARATOR:       // Fall through
                             case LINE_SEPARATOR:            cr = '\n'; break;
                             case SPACE_SEPARATOR:           cr = ' '; break;
                             case INITIAL_QUOTE_PUNCTUATION: cr = (c == '‘') ? '\'' : '"'; break;
                             case FINAL_QUOTE_PUNCTUATION:   cr = (c == '’') ? '\'' : '"'; break;
-                            case OTHER_PUNCTUATION: {
+                            case OTHER_PUNCTUATION:
+                            case MATH_SYMBOL: {
                                 switch (c) {
+                                    case '⋅': cr = '*';  break;
+                                    case '∕': cr = '/';  break;
                                     case '′': cr = '\''; break;
                                     case '″': cr = '"';  break;
                                     default:  continue;
                                 }
                                 break;
                             }
-                            default: continue;
+                            default: {
+                                /*
+                                 * For any unknown character, try to decompose the string in a sequence of simpler
+                                 * letters with their modifiers and restart the whole process from the beginning.
+                                 * If the character is still unknown after decomposition, leave it unchanged.
+                                 */
+                                if (!doneNFKD) {
+                                    doneNFKD = true;
+                                    final String decomposed = Normalizer.normalize(text, Normalizer.Form.NFKD);
+                                    if (!decomposed.contentEquals(text)) {
+                                        if (buffer == null) {
+                                            text = buffer = new StringBuilder(decomposed.length());
+                                        } else {
+                                            buffer.setLength(0);
+                                        }
+                                        i = buffer.append(decomposed).length();
+                                    }
+                                }
+                                continue;
+                            }
                         }
                     }
                     if (buffer == null) {
                         buffer = new StringBuilder(text.length()).append(text);
                         text = buffer;
                     }
-                    if (n == 2) {
-                        buffer.deleteCharAt(i + 1); // Remove the low surrogate of a surrogate pair.
+                    if (cr == 0) {
+                        buffer.delete(i, i + n);
+                    } else {
+                        if (n == 2) {
+                            buffer.deleteCharAt(i + 1);         // Remove the low surrogate of a surrogate pair.
+                        }
+                        // Nothing special to do about codepoint here, since 'c' is in
+                        // the basic plane (verified by the r < ASCII.length() check).
+                        buffer.setCharAt(i, cr);
                     }
-                    // Nothing special to do about codepoint here, since 'c' is in
-                    // the basic plane (verified by the r < ASCII.length() check).
-                    buffer.setCharAt(i, cr);
                 }
             }
         }

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1766508&r1=1766507&r2=1766508&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Tue Oct 25 10:45:14 2016
@@ -388,6 +388,12 @@ public final class Errors extends Indexe
         public static final short IncompatiblePropertyValue_1 = 63;
 
         /**
+         * The “{0}” unit of measurement has dimension of ‘{1}’ ({2}). It is incompatible with
+         * dimension of ‘{3}’ ({4}).
+         */
+        public static final short IncompatibleUnitDimension_5 = 163;
+
+        /**
          * Unit “{0}” is incompatible with current value.
          */
         public static final short IncompatibleUnit_1 = 64;
@@ -574,11 +580,21 @@ public final class Errors extends Indexe
         public static final short NonLinearUnit_1 = 100;
 
         /**
+         * The scale of measurement for “{0}” unit is not a ratio scale.
+         */
+        public static final short NonRatioUnit_1 = 162;
+
+        /**
          * “{0}” is not a scale unit.
          */
         public static final short NonScaleUnit_1 = 101;
 
         /**
+         * “{0}” is not a fundamental or derived unit.
+         */
+        public static final short NonSystemUnit_1 = 161;
+
+        /**
          * “{0}” is not a time unit.
          */
         public static final short NonTemporalUnit_1 = 102;

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1766508&r1=1766507&r2=1766508&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Tue Oct 25 10:45:14 2016
@@ -90,6 +90,7 @@ IncompatibleFormat_2              = Can
 IncompatiblePropertyValue_1       = Property \u201c{0}\u201d has an incompatible value.
 IncompatibleUnit_1                = Unit \u201c{0}\u201d is incompatible with current value.
 IncompatibleUnits_2               = Units \u201c{0}\u201d and \u201c{1}\u201d are incompatible.
+IncompatibleUnitDimension_5       = The \u201c{0}\u201d unit of measurement has dimension of \u2018{1}\u2019 ({2}). It is incompatible with dimension of \u2018{3}\u2019 ({4}).
 InconsistentAttribute_2           = Value \u201c{1}\u201d of attribute \u2018{0}\u2019 is inconsistent with other attributes.
 InconsistentNamespace_2           = Expected \u201c{0}\u201d namespace for \u201c{1}\u201d.
 InconsistentTableColumns          = Inconsistent table columns.
@@ -126,6 +127,8 @@ NonAngularUnit_1                  = \u20
 NonLinearUnit_1                   = \u201c{0}\u201d is not a linear unit.
 NonScaleUnit_1                    = \u201c{0}\u201d is not a scale unit.
 NonTemporalUnit_1                 = \u201c{0}\u201d is not a time unit.
+NonSystemUnit_1                   = \u201c{0}\u201d is not a fundamental or derived unit.
+NonRatioUnit_1                    = The scale of measurement for \u201c{0}\u201d unit is not a ratio scale.
 NotABackwardReference_1           = No element for the \u201c{0}\u201d identifier, or the identifier is a forward reference.
 NotAKeyValuePair_1                = \u201c{0}\u201d is not a key-value pair.
 NotANumber_1                      = Argument \u2018{0}\u2019 shall not be NaN (Not-a-Number).

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1766508&r1=1766507&r2=1766508&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] Tue Oct 25 10:45:14 2016
@@ -87,6 +87,7 @@ IncompatibleFormat_2              = Le f
 IncompatiblePropertyValue_1       = La valeur de la propri\u00e9t\u00e9 \u00ab\u202f{0}\u202f\u00bb n\u2019est pas compatible.
 IncompatibleUnit_1                = L\u2019unit\u00e9 \u00ab\u202f{0}\u202f\u00bb n\u2019est pas compatible avec la valeur actuelle.
 IncompatibleUnits_2               = Les unit\u00e9s \u00ab\u202f{0}\u202f\u00bb et \u00ab\u202f{1}\u202f\u00bb ne sont pas compatibles.
+IncompatibleUnitDimension_5       = L\u2019unit\u00e9 de mesure \u00ab\u202f{0}\u202f\u00bb a la dimension de \u2018{1}\u2019 ({2}). Elle est incompatible avec la dimension de \u2018{3}\u2019 ({4}).
 InconsistentAttribute_2           = La valeur \u00ab\u202f{1}\u202f\u00bb de l\u2019attribut \u2018{0}\u2019 n\u2019est pas coh\u00e9rente avec celles des autres attributs.
 InconsistentNamespace_2           = L\u2019espace de nom \u201c{0}\u201d \u00e9tait attendu pour \u201c{1}\u201d.
 InconsistentTableColumns          = Les colonnes des tables ne sont pas coh\u00e9rentes.
@@ -123,6 +124,8 @@ NonAngularUnit_1                  = \u00
 NonLinearUnit_1                   = \u00ab\u202f{0}\u202f\u00bb n\u2019est pas une unit\u00e9 de longueurs.
 NonScaleUnit_1                    = \u00ab\u202f{0}\u202f\u00bb n\u2019est pas une unit\u00e9 d\u2019\u00e9chelles.
 NonTemporalUnit_1                 = \u00ab\u202f{0}\u202f\u00bb n\u2019est pas une unit\u00e9 de temps.
+NonSystemUnit_1                   = \u00ab\u202f{0}\u202f\u00bb n\u2019est pas une unit\u00e9 fondamentale ou d\u00e9riv\u00e9e.
+NonRatioUnit_1                    = L\u2019\u00e9chelle de mesure de l\u2019unit\u00e9 \u00ab\u202f{0}\u202f\u00bb n\u2019est pas une \u00e9chelle de rapports.
 NotABackwardReference_1           = Il n\u2019y a pas d\u2019\u00e9l\u00e9ment pour l\u2019identifiant \u201c{0}\u201d, ou l\u2019identifiant est une r\u00e9f\u00e9rence vers l\u2019avant.
 NotAKeyValuePair_1                = \u00ab\u202f{0}\u202f\u00bb n\u2019est pas une paire cl\u00e9-valeur.
 NotANumber_1                      = L\u2019argument \u2018{0}\u2019 ne doit pas \u00eatre NaN (Not-a-Number).

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/IndexedResourceBundle.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/IndexedResourceBundle.java?rev=1766508&r1=1766507&r2=1766508&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/IndexedResourceBundle.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/IndexedResourceBundle.java [UTF-8] Tue Oct 25 10:45:14 2016
@@ -30,7 +30,6 @@ import java.util.ResourceBundle;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
 import java.lang.reflect.Modifier;
-import javax.measure.Unit;
 import org.opengis.util.CodeList;
 import org.opengis.util.ControlledVocabulary;
 import org.opengis.util.InternationalString;
@@ -42,7 +41,6 @@ import org.apache.sis.util.CharSequences
 import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.internal.system.Loggers;
-import org.apache.sis.internal.util.PatchedUnitFormat;
 
 
 /**
@@ -411,8 +409,6 @@ public class IndexedResourceBundle exten
                 replacement = Classes.getShortName(getPublicType((Class<?>) element));
             } else if (element instanceof ControlledVocabulary) {
                 replacement = Types.getCodeTitle((ControlledVocabulary) element).toString(getLocale());
-            } else if (element instanceof Unit<?>) {
-                replacement = PatchedUnitFormat.toString((Unit<?>) element);
             }
             // No need to check for Numbers or Dates instances, since they are
             // properly formatted in the ResourceBundle locale by MessageFormat.

Modified: sis/branches/JDK7/core/sis-utility/src/main/resources/META-INF/services/org.apache.sis.util.ObjectConverter
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/resources/META-INF/services/org.apache.sis.util.ObjectConverter?rev=1766508&r1=1766507&r2=1766508&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/resources/META-INF/services/org.apache.sis.util.ObjectConverter [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/resources/META-INF/services/org.apache.sis.util.ObjectConverter [UTF-8] Tue Oct 25 10:45:14 2016
@@ -38,3 +38,5 @@ org.apache.sis.internal.converter.DateCo
 org.apache.sis.internal.converter.DateConverter$Timestamp
 org.apache.sis.internal.converter.CollectionConverter$List
 org.apache.sis.internal.converter.CollectionConverter$Set
+org.apache.sis.internal.converter.FractionConverter
+org.apache.sis.internal.converter.FractionConverter$FromInteger

Modified: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gml/MeasureTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gml/MeasureTest.java?rev=1766508&r1=1766507&r2=1766508&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gml/MeasureTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gml/MeasureTest.java [UTF-8] Tue Oct 25 10:45:14 2016
@@ -44,7 +44,7 @@ public final strictfp class MeasureTest
         assertEquals("urn:ogc:def:uom:EPSG::9001", measure.getUOM());
         measure.unit = Units.DEGREE;
         assertEquals("urn:ogc:def:uom:EPSG::9102", measure.getUOM());
-        measure.unit = Units.ONE;
+        measure.unit = Units.UNITY;
         assertEquals("urn:ogc:def:uom:EPSG::9201", measure.getUOM());
     }
 

Modified: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/SexagesimalConverterTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/SexagesimalConverterTest.java?rev=1766508&r1=1766507&r2=1766508&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/SexagesimalConverterTest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/measure/SexagesimalConverterTest.java [UTF-8] Tue Oct 25 10:45:14 2016
@@ -19,7 +19,6 @@ package org.apache.sis.measure;
 import javax.measure.Unit;
 import javax.measure.Quantity;
 import javax.measure.UnitConverter;
-import org.apache.sis.internal.util.PatchedUnitFormat;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
@@ -94,13 +93,12 @@ public final strictfp class SexagesimalC
     }
 
     /**
-     * Tests {@link PatchedUnitFormat#toString(Unit)}.
-     * Tested here because it can be tested only after {@link SexagesimalConverter} initialization.
+     * Verifies the unit symbols.
      */
     @Test
-    public void testPatchedUnitFormat() {
-        assertEquals("D.M",  PatchedUnitFormat.toString(DM));
-        assertEquals("D.MS", PatchedUnitFormat.toString(DMS));
-        assertEquals("DMS",  PatchedUnitFormat.toString(DMS_SCALED));
+    public void testToString() {
+        assertEquals("D.M",  DM.toString());
+        assertEquals("D.MS", DMS.toString());
+        assertEquals("DMS",  DMS_SCALED.toString());
     }
 }



Mime
View raw message