sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1766448 - in /sis/branches/JDK8/core/sis-utility/src: main/java/org/apache/sis/measure/ main/resources/org/apache/sis/measure/ test/java/org/apache/sis/measure/ test/java/org/apache/sis/test/suite/
Date Mon, 24 Oct 2016 21:07:04 GMT
Author: desruisseaux
Date: Mon Oct 24 21:07:03 2016
New Revision: 1766448

URL: http://svn.apache.org/viewvc?rev=1766448&view=rev
Log:
Add SI prefixes parsing support.

Added:
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/ConventionalUnitTest.java   (with props)
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/LinearConverterTest.java   (with props)
Modified:
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConventionalUnit.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitFormat.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitRegistry.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
    sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitAliases.properties
    sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames.properties
    sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_en_US.properties
    sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_fr.properties
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/SystemUnitTest.java
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/UnitFormatTest.java
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/AbstractUnit.java [UTF-8] Mon Oct 24 21:07:03 2016
@@ -77,6 +77,15 @@ abstract class AbstractUnit<Q extends Qu
     private final String symbol;
 
     /**
+     * A code that identifies whether this unit is part of SI system, or outside SI but accepted for use with SI.
+     * Value can be {@link UnitRegistry#SI}, {@link UnitRegistry#ACCEPTED}, other constants or 0 if unknown.
+     *
+     * <p>This information may be approximative since we can not always guess correctly whether the result of
+     * an operation is part of SI or not. Values given to the field may be adjusted in any future version.</p>
+     */
+    final byte scope;
+
+    /**
      * The EPSG code, or 0 if this unit has no EPSG code.
      */
     final short epsg;
@@ -85,10 +94,12 @@ abstract class AbstractUnit<Q extends Qu
      * Creates a new unit having the given symbol and EPSG code.
      *
      * @param  symbol  the unit symbol, or {@code null} if this unit has no specific symbol.
+     * @param  scope   {@link UnitRegistry#SI}, {@link UnitRegistry#ACCEPTED}, other constants or 0 if unknown.
      * @param  epsg    the EPSG code,   or 0 if this unit has no EPSG code.
      */
-    AbstractUnit(final String symbol, final short epsg) {
+    AbstractUnit(final String symbol, final byte scope, final short epsg) {
         this.symbol = symbol;
+        this.scope  = scope;
         this.epsg   = epsg;
     }
 
@@ -226,7 +237,7 @@ abstract class AbstractUnit<Q extends Qu
     public boolean equals(final Object other) {
         if (other != null && other.getClass() == getClass()) {
             final AbstractUnit<?> that = (AbstractUnit<?>) other;
-            return epsg == that.epsg && Objects.equals(symbol, that.symbol);
+            return epsg == that.epsg && scope == that.scope && Objects.equals(symbol, that.symbol);
         }
         return false;
     }

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConventionalUnit.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConventionalUnit.java?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConventionalUnit.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/ConventionalUnit.java [UTF-8] Mon Oct 24 21:07:03 2016
@@ -59,10 +59,11 @@ final class ConventionalUnit<Q extends Q
      * @param  target     the base or derived units to which this {@code ConventionalUnit} is related.
      * @param  toTarget   the conversion from this unit to the {@code target} unit.
      * @param  symbol     the unit symbol, or {@code null} if this unit has no specific symbol.
+     * @param  scope   {@link UnitRegistry#SI}, {@link UnitRegistry#ACCEPTED}, other constants or 0 if unknown.
      * @param  epsg       the EPSG code,   or 0 if this unit has no EPSG code.
      */
-    ConventionalUnit(final SystemUnit<Q> target, final UnitConverter toTarget, final String symbol, final short epsg) {
-        super(symbol, epsg);
+    ConventionalUnit(final SystemUnit<Q> target, final UnitConverter toTarget, final String symbol, final byte scope, final short epsg) {
+        super(symbol, scope, epsg);
         this.target   = target;
         this.toTarget = toTarget;
     }
@@ -75,7 +76,7 @@ final class ConventionalUnit<Q extends Q
             return target;
         }
         // TODO: check for existing unit.
-        return new ConventionalUnit<>(target, toTarget, null, (short) 0);
+        return new ConventionalUnit<>(target, toTarget, null, (byte) 0, (short) 0);
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/LinearConverter.java [UTF-8] Mon Oct 24 21:07:03 2016
@@ -17,6 +17,7 @@
 package org.apache.sis.measure;
 
 import java.util.List;
+import java.util.Arrays;
 import java.util.Collections;
 import java.math.BigDecimal;
 import javax.measure.UnitConverter;
@@ -52,6 +53,25 @@ final class LinearConverter extends Abst
     private static final long serialVersionUID = -3759983642723729926L;
 
     /**
+     * The SI prefixes in increasing order. The only two-letters prefix – “da” – is encoded using the JCK compatibility
+     * character “㍲”. The Greek letter μ is repeated twice: the U+00B5 character for micro sign (this is the character
+     * that Apache SIS uses in unit symbols) and the U+03BC character for the Greek small letter “mu” (the later is the
+     * character that appears when decomposing JCK compatibility characters with {@link java.text.Normalizer}).
+     * Both characters have same appearance but different values.
+     *
+     * <p>For each prefix at index <var>i</var>, the multiplication factor is given by 10 raised to power {@code POWERS[i]}.</p>
+     */
+    private static final char[] PREFIXES = {'E','G','M','P','T','Y','Z','a','c','d','f','h','k','m','n','p','y','z','µ','μ','㍲'};
+    private static final byte[] POWERS   = {18,  9,  6, 15, 12, 24, 21,-18, -2, -1,-15,  2,  3, -3, -9,-12,-24,-21, -6, -6,  1};
+
+    /**
+     * The converters for SI prefixes, created when first needed.
+     *
+     * @see #forPrefix(char)
+     */
+    private static final LinearConverter[] SI = new LinearConverter[POWERS.length];
+
+    /**
      * The identity linear converter.
      */
     static final LinearConverter IDENTITY = new LinearConverter(1, 0);
@@ -101,6 +121,34 @@ final class LinearConverter extends Abst
     }
 
     /**
+     * Returns the converter for the given SI prefix, or {@code null} if none.
+     * Those converters are created when first needed and cached for reuse.
+     */
+    static LinearConverter forPrefix(final char prefix) {
+        final int i = Arrays.binarySearch(PREFIXES, prefix);
+        if (i < 0) {
+            return null;
+        }
+        synchronized (SI) {
+            LinearConverter c = SI[i];
+            if (c == null) {
+                final int p = POWERS[i];
+                final double numerator, denominator;
+                if (p >= 0) {
+                    numerator = MathFunctions.pow10(p);
+                    denominator = 1;
+                } else {
+                    numerator = 1;
+                    denominator = MathFunctions.pow10(-p);
+                }
+                c = scale(numerator, denominator);
+                SI[i] = c;
+            }
+            return c;
+        }
+    }
+
+    /**
      * Raises the given converter to the given power. This method assumes that the given converter
      * {@linkplain #isLinear() is linear} (this is not verified) and take only the scale factor;
      * the offset (if any) is ignored.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SexagesimalConverter.java [UTF-8] Mon Oct 24 21:07:03 2016
@@ -105,13 +105,13 @@ class SexagesimalConverter extends Abstr
         final SystemUnit<Angle> rad = (SystemUnit<Angle>) Units.RADIAN;
         final UnitConverter toRadian = Units.DEGREE.getConverterTo(rad);
         DM = new ConventionalUnit<>(rad, new ConcatenatedConverter(
-                new SexagesimalConverter(false, 100).inverse(), toRadian), "D.M", (short) 9111);
+                new SexagesimalConverter(false, 100).inverse(), toRadian), "D.M", UnitRegistry.OTHER, (short) 9111);
 
         DMS = new ConventionalUnit<>(rad, new ConcatenatedConverter(
-                new SexagesimalConverter(true, 10000).inverse(), toRadian), "D.MS", (short) 9110);
+                new SexagesimalConverter(true, 10000).inverse(), toRadian), "D.MS", UnitRegistry.OTHER, (short) 9110);
 
         DMS_SCALED = new ConventionalUnit<>(rad, new ConcatenatedConverter(
-                new SexagesimalConverter(true, 1).inverse(), toRadian), "DMS", (short) 9107);
+                new SexagesimalConverter(true, 1).inverse(), toRadian), "DMS", UnitRegistry.OTHER, (short) 9107);
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/SystemUnit.java [UTF-8] Mon Oct 24 21:07:03 2016
@@ -68,16 +68,18 @@ final class SystemUnit<Q extends Quantit
      * @param  quantity   the type of quantity that uses this unit, or {@code null} if unknown.
      * @param  dimension  the unit dimension.
      * @param  symbol     the unit symbol, or {@code null} if this unit has no specific symbol.
+     * @param  scope      {@link UnitRegistry#SI}, {@link UnitRegistry#ACCEPTED}, other constants or 0 if unknown.
      * @param  epsg       the EPSG code,   or 0 if this unit has no EPSG code.
      */
-    SystemUnit(final Class<Q> quantity, final UnitDimension dimension, final String symbol, final short epsg) {
-        super(symbol, epsg);
+    SystemUnit(final Class<Q> quantity, final UnitDimension dimension, final String symbol, final byte scope, final short epsg) {
+        super(symbol, scope, epsg);
         this.quantity  = quantity;
         this.dimension = dimension;
     }
 
     /**
      * Returns a unit of the given dimension with default name and symbol.
+     * This method is invoked for creating the result of arithmetic operations.
      */
     private SystemUnit<?> create(final UnitDimension dim) {
         if (dim == dimension) {
@@ -85,7 +87,7 @@ final class SystemUnit<Q extends Quantit
         }
         SystemUnit<?> result = Units.get(dim);
         if (result == null) {
-            result = new SystemUnit<>(null, dim, null, (short) 0);
+            result = new SystemUnit<>(null, dim, null, (byte) 0, (short) 0);
         }
         return result;
     }
@@ -227,7 +229,7 @@ final class SystemUnit<Q extends Quantit
          */
         SystemUnit<T> unit = Units.get(type);
         if (unit == null) {
-            unit = new SystemUnit<>(type, dimension, null, (short) 0);              // Intentionally no symbol.
+            unit = new SystemUnit<>(type, dimension, null, (byte) 0, (short) 0);       // Intentionally no symbol.
         }
         if (!dimension.equals(unit.dimension)) {
             throw new ClassCastException(Errors.format(Errors.Keys.IncompatibleUnitDimension_5, new Object[] {
@@ -336,7 +338,7 @@ final class SystemUnit<Q extends Quantit
         if (symbol.equals(getSymbol())) {
             return this;
         }
-        final SystemUnit<Q> alt = new SystemUnit<>(quantity, dimension, symbol, (short) 0);
+        final SystemUnit<Q> alt = new SystemUnit<>(quantity, dimension, symbol, (byte) 0, (short) 0);
         if (quantity != null) {
             /*
              * Use the cache only if this unit has a non-null quantity type. Do not use the cache even

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitFormat.java?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitFormat.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitFormat.java [UTF-8] Mon Oct 24 21:07:03 2016
@@ -407,7 +407,7 @@ public class UnitFormat extends Format i
                  */
                 final ResourceBundle r = ResourceBundle.getBundle("org.apache.sis.measure.UnitAliases", locale, UnitFormat.class.getClassLoader());
                 for (final String name : r.keySet()) {
-                    map.put(name, Units.get(r.getString(name)));
+                    map.put(name.intern(), Units.get(r.getString(name)));
                 }
                 map = Collections.unmodifiableMap(map);
                 /*
@@ -438,7 +438,7 @@ public class UnitFormat extends Format i
      */
     private static void copy(final Locale locale, final ResourceBundle symbolToName, final Map<String,Unit<?>> nameToUnit) {
         for (final String symbol : symbolToName.keySet()) {
-            nameToUnit.put(symbolToName.getString(symbol).toLowerCase(locale), Units.get(symbol));
+            nameToUnit.put(symbolToName.getString(symbol).toLowerCase(locale).intern(), Units.get(symbol));
         }
     }
 
@@ -733,7 +733,7 @@ public class UnitFormat extends Format i
          */
         Unit<?> unit = labelToUnit.get(uom);
         if (unit == null) {
-            unit = Units.get(uom);
+            unit = withPrefix(uom);
             if (unit == null) {
                 final int length = uom.length();
                 if (length == 0) {
@@ -774,7 +774,7 @@ public class UnitFormat extends Format i
                     }
                     if (canApply) {
                         uom = CharSequences.trimWhitespaces(uom.substring(0, i));
-                        unit = Units.get(uom);
+                        unit = withPrefix(uom);
                         if (unit != null) {
                             return unit.pow(power);
                         }
@@ -817,6 +817,38 @@ public class UnitFormat extends Format i
         }
         return unit;
     }
+
+    /**
+     * Returns the unit for the given symbol, taking the SI prefix in account.
+     * This method does not perform any arithmetic operation on {@code Unit}.
+     * Returns {@code null} if no unit is found.
+     */
+    private static Unit<?> withPrefix(final String uom) {
+        Unit<?> unit = Units.get(uom);
+        if (unit == null && uom.length() >= 2) {
+            int s = 1;
+            char prefix = uom.charAt(0);
+            if (prefix == 'd' && uom.charAt(1) == 'a') {
+                prefix = '㍲';
+                s = 2;
+            }
+            unit = Units.get(uom.substring(s));
+            if (unit instanceof SystemUnit<?> && ((SystemUnit<?>) unit).scope == UnitRegistry.SI) {
+                final LinearConverter c = LinearConverter.forPrefix(prefix);
+                if (c != null) {
+                    String symbol = unit.getSymbol();
+                    if (prefix == '㍲') {
+                        symbol = "da" + symbol;
+                    } else {
+                        symbol = prefix + symbol;
+                    }
+                    return new ConventionalUnit<>((SystemUnit<?>) unit, c, symbol.intern(), (byte) 0, (short) 0);
+                }
+            }
+            unit = null;
+        }
+        return unit;
+    }
 
     /**
      * Parses the given text as an instance of {@code Unit}.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitRegistry.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitRegistry.java?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitRegistry.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitRegistry.java [UTF-8] Mon Oct 24 21:07:03 2016
@@ -48,6 +48,30 @@ final class UnitRegistry implements Syst
     private static final long serialVersionUID = -84557361079506390L;
 
     /**
+     * Identifies units defined by the SI system.
+     * All {@link SystemUnit} instances with this code can have a SI prefix.
+     */
+    static final byte SI = 1;
+
+    /**
+     * Identifies units defined outside the SI system but accepted for use with SI.
+     * The {@link #SI} value can be used as a bitmask for identifying the SI or accepted units.
+     */
+    static final byte ACCEPTED = 3;
+
+    // All following constants shall have an even value (unless accepted for use with SI).
+
+    /**
+     * Identifies units defined for use in British imperial system.
+     */
+    static final byte IMPERIAL = 2;
+
+    /**
+     * Identifies units defined in another system than the above.
+     */
+    static final byte OTHER = 4;
+
+    /**
      * All {@link UnitDimension}, {@link SystemUnit} or {@link ConventionalUnit} that are hard-coded in Apache SIS.
      * This map is populated by {@link Units} static initializer and shall not be modified after initialization,
      * in order to avoid the need for synchronization. Key and value types are restricted to the following pairs:

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java [UTF-8] Mon Oct 24 21:07:03 2016
@@ -439,11 +439,24 @@ public final class Units extends Static
     public static final Unit<Pressure> HECTOPASCAL;
 
     /**
+     * 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<Area> HECTARE;
+
+    /**
      * The SI derived unit for area (m²).
      * The unlocalized name is “square metre”.
      *
      * @since 0.8
      *
+     * @see #HECTARE
      * @see #METRE
      * @see #CUBIC_METRE
      */
@@ -533,7 +546,8 @@ public final class Units extends Static
 
     /**
      * Unit of measurement defined as the temperature in Kelvin minus 273.15.
-     * The symbol is ℃ and the unlocalized name is “celsius”.
+     * 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
      *
@@ -646,79 +660,81 @@ public final class Units extends Static
         /*
          * 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",   Constants.EPSG_METRE);
-        final SystemUnit<Time>          s   = add(Time.class,          time,          "s",   (short) 1040);
-        final SystemUnit<Temperature>   K   = add(Temperature.class,   temperature,   "K",   (short) 0);
-        final SystemUnit<Speed>         mps = add(Speed.class,         speed,         "m∕s", (short) 1026);
-        final SystemUnit<Pressure>      Pa  = add(Pressure.class,      pressure,      "Pa",  (short) 0);
-        final SystemUnit<Angle>         rad = add(Angle.class,         dimensionless, "rad", (short) 9101);
-        final SystemUnit<Dimensionless> one = add(Dimensionless.class, dimensionless, "",    (short) 9201);
+        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.scale(1, 1000000000);
-        final LinearConverter micro = LinearConverter.scale(1,    1000000);
-        final LinearConverter milli = LinearConverter.scale(1,       1000);
-        final LinearConverter centi = LinearConverter.scale(1,        100);
-        final LinearConverter hecto = LinearConverter.scale(100,        1);
-        final LinearConverter kilo  = LinearConverter.scale(1000,       1);
+        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", (short) 9105);
-        DEGREE      = add(rad, LinearConverter.scale(Math.PI, 180),       "°", Constants.EPSG_PARAM_DEGREES);
-        ARC_MINUTE  = add(rad, LinearConverter.scale(Math.PI, 180*60),    "′", (short) 9103);
-        ARC_SECOND  = add(rad, LinearConverter.scale(Math.PI, 180*60*60), "″", (short) 9104);
-        MICRORADIAN = add(rad, micro, "µrad", (short) 9109);
+        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", (short) 0);
-        MILLIMETRE     = add(m, milli, "mm", (short) 1025);
-        CENTIMETRE     = add(m, centi, "cm", (short) 1033);
-        KILOMETRE      = add(m, kilo,  "km", (short) 9036);
-        NAUTICAL_MILE  = add(m, LinearConverter.scale(   1852,        1), "M",     (short) 9030);
-        STATUTE_MILE   = add(m, LinearConverter.scale(1609344,      100), "mi",    (short) 9093);
-        US_SURVEY_FOOT = add(m, LinearConverter.scale(   1200,     3937), "ft_US", (short) 9003);
-        FOOT           = add(m, LinearConverter.scale(   3048,    10000), "ft",    (short) 9002);
-        INCH           = add(m, LinearConverter.scale(    254,    10000), "in",    (short) 0);
-        POINT          = add(m, LinearConverter.scale( 996264, 72000000), "pt",    (short) 0);
+        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", (short) 0);
-        MINUTE         = add(s, LinearConverter.scale(         60,      1), "min", (short) 0);
-        HOUR           = add(s, LinearConverter.scale(      60*60,      1), "h",   (short) 0);
-        DAY            = add(s, LinearConverter.scale(   24*60*60,      1), "d",   (short) 0);
-        WEEK           = add(s, LinearConverter.scale( 7*24*60*60,      1), "wk",  (short) 0);
-        TROPICAL_YEAR  = add(s, LinearConverter.scale(31556925445.0, 1000), "a",   (short) 1029);
+        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",   (short) 0);
-        SQUARE_METRE        = add(Area.class,      area,                "m²",   (short) 0);
-        CUBIC_METRE         = add(Volume.class,    length.pow(3),       "m³",   (short) 0);
-        NEWTON              = add(Force.class,     force,               "N",    (short) 0);
-        JOULE               = add(Energy.class,    energy,              "J",    (short) 0);
-        WATT                = add(Power.class,     energy.divide(time), "W",    (short) 0);
-        HERTZ               = add(Frequency.class, time.pow(-1),        "Hz",   (short) 0);
-        HECTOPASCAL         = add(Pa, hecto,                            "hPa",  (short) 0);
-        KILOMETRES_PER_HOUR = add(mps, LinearConverter.scale(6, 100),   "km∕h", (short) 0);
-        CELSIUS             = add(K, LinearConverter.create(1, 273.15), "℃",    (short) 0);
+        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, "%",   (short) 0);
-        PPM     = add(one, micro, "ppm", (short) 9202);
-        PSU     = add(Dimensionless.class, dimensionless, "psu",   (short) 0);
-        SIGMA   = add(Dimensionless.class, dimensionless, "sigma", (short) 0);
-        PIXEL   = add(Dimensionless.class, dimensionless, "px",    (short) 0);
+        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));
@@ -726,7 +742,7 @@ public final class Units extends Static
         UnitRegistry.alias(ARC_MINUTE,  "'");
         UnitRegistry.alias(ARC_SECOND, "\"");
         UnitRegistry.alias(KELVIN,      "K");       // Ordinary "K" letter (not the dedicated Unicode character).
-        UnitRegistry.alias(CELSIUS,    "°C");
+        UnitRegistry.alias(CELSIUS,     "℃");
         UnitRegistry.alias(CELSIUS,   "Cel");
         UnitRegistry.alias(GRAD,      "gon");
 
@@ -737,16 +753,16 @@ public final class Units extends Static
      * 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, short epsg) {
-        return UnitRegistry.init(new SystemUnit<>(quantity, dimension, symbol, epsg));
+    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, short epsg) {
-        return UnitRegistry.init(new ConventionalUnit<>(target, toTarget, symbol, epsg));
+    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));
     }
 
     /**
@@ -774,6 +790,8 @@ public final class Units extends Static
 
     /**
      * 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>

Modified: sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitAliases.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitAliases.properties?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitAliases.properties [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitAliases.properties [UTF-8] Mon Oct 24 21:07:03 2016
@@ -3,13 +3,13 @@
 # "degrees", "metres" and "meters" are handled as special cases.
 arcsec=\u2033
 days=d
-decimal\ degree=\u00b0
-degree\ celsius=\u2103
+decimal\ degree=�
+degree\ celsius=�C
 degree\ kelvin=\u212a
-degree\ east=\u00b0
-degree\ north=\u00b0
-degree\ south=\u00b0
-degree\ west=\u00b0
+degree\ east=�
+degree\ north=�
+degree\ south=�
+degree\ west=�
 feet=ft
 grade=grad
 grades=grad
@@ -23,5 +23,5 @@ seconds=s
 weeks=wk
 
 # Common misspellings
-celcius=\u2103
-degree\ celcius=\u2103
+celcius=�C
+degree\ celcius=�C

Modified: sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames.properties?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames.properties [ISO-8859-1] Mon Oct 24 21:07:03 2016
@@ -6,6 +6,7 @@ ft=foot
 ft_US=US survey foot
 grad=grad
 h=hour
+ha=hectare
 hPa=hectopascal
 Hz=hertz
 in=inch
@@ -15,8 +16,8 @@ kg=kilogram
 km=kilometre
 M=nautical mile
 m=metre
-m\u00b2=square metre
-m\u00b3=cubic metre
+m²=square metre
+m³=cubic metre
 mi=statute mile
 min=minute
 mm=millimetre
@@ -33,7 +34,7 @@ unity=unity
 W=watt
 wk=week
 %=percentage
-\u00b0=degree
+°=degree
 \u2032=arc-minute
 \u2033=arc-second
-\u2103=Celsius
+°C=Celsius

Modified: sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_en_US.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_en_US.properties?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_en_US.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_en_US.properties [ISO-8859-1] Mon Oct 24 21:07:03 2016
@@ -2,8 +2,8 @@
 cm=centimeter
 km=kilometer
 m=meter
-m\u00b2=square meter
-m\u00b3=cubic meter
+m²=square meter
+m³=cubic meter
 mi=international mile
 mm=millimeter
 nm=nanometer

Modified: sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_fr.properties?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/resources/org/apache/sis/measure/UnitNames_fr.properties [ISO-8859-1] Mon Oct 24 21:07:03 2016
@@ -1,30 +1,30 @@
 # Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.
-a=ann\u00e9e
-cm=centim\u00e8tre
+a=année
+cm=centimètre
 d=jour
 ft=pied
 grad=grade
 h=heure
 in=pouce
 kg=kilogramme
-km=kilom\u00e8tre
+km=kilomètre
 M=mille marin international
-m=m\u00e8tre
-m\u00b2=m\u00e8tre carr\u00e9
-m\u00b3=m\u00e8tre cube
+m=mètre
+m²=mètre carré
+m³=mètre cube
 mi=mille terrestre international
 min=minute
-mm=millim\u00e8tre
+mm=millimètre
 ms=milliseconde
-nm=nanom\u00e8tre
+nm=nanomètre
 ppm=parties par million
 pt=point
 px=pixel
 rad=radian
 s=seconde
-unity=unit\u00e9
+unity=unité
 wk=semaine
 %=pourcentage
-\u00b0=degr\u00e9e
+°=degrée
 \u2032=arc-minute
 \u2033=arc-seconde

Added: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/ConventionalUnitTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/ConventionalUnitTest.java?rev=1766448&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/ConventionalUnitTest.java (added)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/ConventionalUnitTest.java [UTF-8] Mon Oct 24 21:07:03 2016
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.measure;
+
+import javax.measure.Unit;
+import org.apache.sis.test.DependsOn;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Tests the {@link ConventionalUnit} class.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.8
+ * @version 0.8
+ * @module
+ */
+@DependsOn({SystemUnitTest.class, LinearConverterTest.class})
+public final strictfp class ConventionalUnitTest extends TestCase {
+    /**
+     * Verifies the properties if the given unit.
+     *
+     * @param  system  the expected system unit.
+     * @param  unit    the conventional unit to verify.
+     * @param  symbol  the expected symbol.
+     * @param  scale   the expected scale factor.
+     */
+    static void verify(final Unit<?> system, final Unit<?> unit, final String symbol, final double scale) {
+        assertSame  ("getSystemUnit()", system, unit.getSystemUnit());
+        assertEquals("getSymbol()",     symbol, unit.getSymbol());
+        assertEquals("UnitConverter", scale, Units.toStandardUnit(unit), STRICT);
+    }
+
+    /**
+     * Verifies some of the hard-coded constants defined in the {@link Units} class.
+     */
+    @Test
+    public void verifyConstants() {
+        verify(Units.METRE,             Units.NANOMETRE,             "nm",  1E-9);
+        verify(Units.METRE,             Units.MILLIMETRE,            "mm",  1E-3);
+        verify(Units.METRE,             Units.CENTIMETRE,            "cm",  1E-2);
+        verify(Units.METRE,             Units.METRE,                  "m",  1E+0);
+        verify(Units.METRE,             Units.KILOMETRE,             "km",  1E+3);
+        verify(Units.METRE,             Units.NAUTICAL_MILE,          "M",  1852);
+        verify(Units.SECOND,            Units.SECOND,                 "s",     1);
+        verify(Units.SECOND,            Units.MINUTE,               "min",    60);
+        verify(Units.SECOND,            Units.HOUR,                   "h",  3600);
+        verify(Units.PASCAL,            Units.PASCAL,                "Pa",     1);
+        verify(Units.PASCAL,            Units.HECTOPASCAL,          "hPa",   100);
+        verify(Units.METRES_PER_SECOND, Units.KILOMETRES_PER_HOUR, "km∕h",  0.06);
+        verify(Units.KILOGRAM,          Units.KILOGRAM,              "kg",     1);
+        verify(Units.UNITY,             Units.UNITY,                   "",     1);
+        verify(Units.UNITY,             Units.PERCENT,                "%",  1E-2);
+        verify(Units.UNITY,             Units.PPM,                  "ppm",  1E-6);
+    }
+}

Propchange: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/ConventionalUnitTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/ConventionalUnitTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Added: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/LinearConverterTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/LinearConverterTest.java?rev=1766448&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/LinearConverterTest.java (added)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/LinearConverterTest.java [UTF-8] Mon Oct 24 21:07:03 2016
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.measure;
+
+import java.lang.reflect.Field;
+import org.apache.sis.test.TestCase;
+import org.apache.sis.util.ArraysExt;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Tests the {@link LinearConverter} class.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.8
+ * @version 0.8
+ * @module
+ */
+public final strictfp class LinearConverterTest extends TestCase {
+    /**
+     * Ensures that the characters in the {@link LinearConverter#PREFIXES} array are in strictly increasing order,
+     * and that {@link LinearConverter#POWERS} has the same length.
+     *
+     * @throws ReflectiveOperationException if this test can not access the private fields of {@link LinearConverter}.
+     */
+    @Test
+    public void verifyPrefixes() throws ReflectiveOperationException {
+        Field f = LinearConverter.class.getDeclaredField("PREFIXES");
+        f.setAccessible(true);
+        final char[] prefixes = (char[]) f.get(null);
+        assertTrue(ArraysExt.isSorted(prefixes, true));
+
+        f = LinearConverter.class.getDeclaredField("POWERS");
+        f.setAccessible(true);
+        assertEquals("length", prefixes.length, ((byte[]) f.get(null)).length);
+    }
+}

Propchange: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/LinearConverterTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/LinearConverterTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/SystemUnitTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/SystemUnitTest.java?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/SystemUnitTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/SystemUnitTest.java [UTF-8] Mon Oct 24 21:07:03 2016
@@ -275,8 +275,8 @@ public final strictfp class SystemUnitTe
         /*
          * Test with units outside the pre-defined constants in the Units class.
          */
-        final Unit<Length> anonymous = new SystemUnit<>(Length.class, (UnitDimension) Units.METRE.getDimension(), null,  (short) 0);
-        final Unit<Length> otherName = new SystemUnit<>(Length.class, (UnitDimension) Units.METRE.getDimension(), "Foo", (short) 0);
+        final Unit<Length> anonymous = new SystemUnit<>(Length.class, (UnitDimension) Units.METRE.getDimension(), null,  UnitRegistry.OTHER, (short) 0);
+        final Unit<Length> otherName = new SystemUnit<>(Length.class, (UnitDimension) Units.METRE.getDimension(), "Foo", UnitRegistry.OTHER, (short) 0);
         assertSame(Units.METRE, anonymous.asType(Length.class));
         assertSame(otherName,   otherName.asType(Length.class));
         /*

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/UnitFormatTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/UnitFormatTest.java?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/UnitFormatTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/measure/UnitFormatTest.java [UTF-8] Mon Oct 24 21:07:03 2016
@@ -38,7 +38,7 @@ import static org.junit.Assert.*;
  * @version 0.8
  * @module
  */
-@DependsOn(SystemUnitTest.class)
+@DependsOn({SystemUnitTest.class, ConventionalUnitTest.class})
 public final strictfp class UnitFormatTest extends TestCase {
     /**
      * Verifies all constants defined in {@link Units} class. This method verifies:
@@ -83,6 +83,7 @@ public final strictfp class UnitFormatTe
         verify(declared, "TROPICAL_YEAR",       "T",        "a",     Units.TROPICAL_YEAR);
         verify(declared, "PASCAL",              "M∕(L⋅T²)", "Pa",    Units.PASCAL);
         verify(declared, "HECTOPASCAL",         "M∕(L⋅T²)", "hPa",   Units.HECTOPASCAL);
+        verify(declared, "HECTARE",             "L²",       "ha",    Units.HECTARE);
         verify(declared, "SQUARE_METRE",        "L²",       "m²",    Units.SQUARE_METRE);
         verify(declared, "CUBIC_METRE",         "L³",       "m³",    Units.CUBIC_METRE);
         verify(declared, "METRES_PER_SECOND",   "L∕T",      "m∕s",   Units.METRES_PER_SECOND);
@@ -92,7 +93,7 @@ public final strictfp class UnitFormatTe
         verify(declared, "JOULE",               "M⋅L²∕T²",  "J",     Units.JOULE);
         verify(declared, "WATT",                "M⋅L²∕T³",  "W",     Units.WATT);
         verify(declared, "KELVIN",              "Θ",        "K",     Units.KELVIN);
-        verify(declared, "CELSIUS",             "Θ",        "℃",     Units.CELSIUS);
+        verify(declared, "CELSIUS",             "Θ",        "°C",    Units.CELSIUS);
         verify(declared, "HERTZ",               "∕T",       "Hz",    Units.HERTZ);
         verify(declared, "UNITY",               "",         "",      Units.UNITY);
         verify(declared, "PERCENT",             "",         "%",     Units.PERCENT);
@@ -254,4 +255,30 @@ public final strictfp class UnitFormatTe
         assertSame(Units.CUBIC_METRE,   f.parse("m3"));
         assertSame(Units.HERTZ,         f.parse("s-1"));
     }
+
+    /**
+     * Tests parsing of symbols with SI prefix.
+     * Note that the "da" prefix needs to be handled in a special way because it is the only two-letters long prefix.
+     */
+    @Test
+    @DependsOnMethod("testSymbolParsing")
+    public void testPrefixParsing() {
+        final UnitFormat f = new UnitFormat(Locale.UK);
+        ConventionalUnitTest.verify(Units.JOULE,  f.parse("kJ"),   "kJ",  1E+3);
+        ConventionalUnitTest.verify(Units.HERTZ,  f.parse("MHz"),  "MHz", 1E+6);
+        ConventionalUnitTest.verify(Units.PASCAL, f.parse("daPa"), "daPa",  10);
+        /*
+         * Verify that prefix are not accepted for conventional units. It would either be illegal prefix duplication
+         * (for example we should not accept "kkm" as if it was "k" + "km") or confusing (for example "a" stands for
+         * the tropical year, "ha" could be understood as 100 tropical years but is actually used for hectare).
+         */
+        assertSame(Units.TROPICAL_YEAR, f.parse("a"));
+        try {
+            f.parse("ka");
+            fail("Should not accept prefix in ConventionalUnit.");
+        } catch (ParserException e) {
+            final String message = e.getMessage();
+            assertTrue(message, message.contains("ka"));
+        }
+    }
 }

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java?rev=1766448&r1=1766447&r2=1766448&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java [UTF-8] Mon Oct 24 21:07:03 2016
@@ -103,8 +103,10 @@ import org.junit.BeforeClass;
 
     // Measurements and formatting.
     org.apache.sis.measure.SexagesimalConverterTest.class,
+    org.apache.sis.measure.LinearConverterTest.class,
     org.apache.sis.measure.UnitDimensionTest.class,
     org.apache.sis.measure.SystemUnitTest.class,
+    org.apache.sis.measure.ConventionalUnitTest.class,
     org.apache.sis.measure.UnitFormatTest.class,
     org.apache.sis.measure.UnitsTest.class,
     org.apache.sis.measure.RangeTest.class,



Mime
View raw message