sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1724442 - in /sis/branches/JDK8/core: sis-referencing/src/main/java/org/apache/sis/referencing/factory/ sis-utility/src/main/java/org/apache/sis/internal/util/ sis-utility/src/main/java/org/apache/sis/measure/
Date Wed, 13 Jan 2016 15:44:58 GMT
Author: desruisseaux
Date: Wed Jan 13 15:44:57 2016
New Revision: 1724442

URL: http://svn.apache.org/viewvc?rev=1724442&view=rev
Log:
Support the way units were specified in the legacy "AUTO" namespace (by EPSG codes instead
than multiplication factor).

Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/Units.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitsMap.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java?rev=1724442&r1=1724441&r2=1724442&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
[UTF-8] Wed Jan 13 15:44:57 2016
@@ -24,7 +24,6 @@ import java.util.Collections;
 import javax.measure.unit.SI;
 import javax.measure.unit.NonSI;
 import javax.measure.unit.Unit;
-import javax.measure.quantity.Length;
 import org.opengis.util.FactoryException;
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.citation.Citation;
@@ -201,6 +200,11 @@ public class CommonAuthorityFactory exte
     private static final String AUTO2 = "AUTO2";
 
     /**
+     * The bit for saying that a namespace is the legacy {@code "AUTO"} namespace.
+     */
+    private static final int LEGACY_MASK = 0x80000000;
+
+    /**
      * First code in the AUTO(2) namespace.
      */
     private static final int FIRST_PROJECTION_CODE = 42001;
@@ -263,55 +267,67 @@ public class CommonAuthorityFactory exte
     }
 
     /**
-     * Returns {@code true} if the given string if one of the namespaces recognized by this
factory.
+     * Returns {@code true} if the given portion of the code is equal, ignoring case, to
the given namespace.
      */
-    private static boolean isCodeSpace(final String namespace) {
-        if (!namespace.equalsIgnoreCase(Constants.CRS) && !namespace.equalsIgnoreCase(Constants.OGC))
{
-            final int s = AUTO2.length() - 1;
-            if (!namespace.regionMatches(true, 0, AUTO2, 0, s)) {
-                return false;
-            }
-            switch (namespace.length() - s) {
-                case 0:  break;                                 // Namespace is exactly "AUTO"
(ignoring case).
-                case 1:  final char c = namespace.charAt(s);    // Namespace has one more
character than "AUTO".
-                         return (c >= '1' && c <= '2');         // Namespace
has more than one more character.
-                default: return false;
-            }
-        }
-        return true;
+    private static boolean regionMatches(final String namespace, final String code, final
int start, final int end) {
+        return (namespace.length() == end - start) && code.regionMatches(true, start,
namespace, 0, namespace.length());
     }
 
     /**
-     * If the given code begins with {@code "OGC"}, {@code "CRS"}, {@code "AUTO"}, {@code
"AUTO1"} or {@code "AUTO2"}
-     * authority (ignoring spaces), returns the code without the authority part. Otherwise
if the code starts with any
-     * other authority, throw an exception. Otherwise if the code has no authority, returns
the code as-is.
+     * Returns the index where the code begins, ignoring spaces and the {@code "OGC"}, {@code
"CRS"}, {@code "AUTO"},
+     * {@code "AUTO1"} or {@code "AUTO2"} namespaces if present. If a namespace is found
and is a legacy one, then
+     * this {@link #LEGACY_MASK} bit will be set.
+     *
+     * @return Index where the code begin, possibly with the {@link #LEGACY_MASK} bit set.
+     * @throws NoSuchAuthorityCodeException if an authority is present but is not one of
the recognized authorities.
      */
-    private String trimAuthority(String code) throws NoSuchAuthorityCodeException {
+    private static int skipNamespace(final String code) throws NoSuchAuthorityCodeException
{
+        int isLegacy = 0;
         int s = code.indexOf(DefaultNameSpace.DEFAULT_SEPARATOR);
         if (s >= 0) {
-            final String scope = code.substring(0, s);
-            if (!isCodeSpace(CharSequences.trimWhitespaces(scope))) {
-                throw new NoSuchAuthorityCodeException(Errors.format(Errors.Keys.UnknownAuthority_1,
scope), Constants.OGC, code);
-            }
-            final int length = code.length();
-            s = CharSequences.skipLeadingWhitespaces(code, s+1, length);
-            code = code.substring(s, CharSequences.skipTrailingWhitespaces(code, s, length));
+            final int end   = CharSequences.skipTrailingWhitespaces(code, 0, s);
+            final int start = CharSequences.skipLeadingWhitespaces (code, 0, end);
+            if (!regionMatches(Constants.CRS, code, start, end) &&
+                !regionMatches(Constants.OGC, code, start, end))
+            {
+                boolean isRecognized = false;
+                final int length = AUTO2.length() - 1;
+                if (code.regionMatches(true, start, AUTO2, 0, length)) {
+                    switch (end - start - length) {         // Number of extra characters
after "AUTO".
+                        case 0: {                           // Namespace is exactly "AUTO"
(ignoring case).
+                            isRecognized = true;
+                            isLegacy = LEGACY_MASK;
+                            break;
+                        }
+                        case 1: {                           // Namespace has one more character
than "AUTO".
+                            final char c = code.charAt(end - 1);
+                            isRecognized = (c >= '1' && c <= '2');
+                            if (c == '1') {
+                                isLegacy = LEGACY_MASK;
+                            }
+                        }
+                    }
+                }
+                if (!isRecognized) {
+                    throw new NoSuchAuthorityCodeException(Errors.format(Errors.Keys.UnknownAuthority_1,
+                            CharSequences.trimWhitespaces(code.substring(0, s))), Constants.OGC,
code);
+                }
+            }
         }
+        s = CharSequences.skipLeadingWhitespaces(code, s+1, code.length());
         /*
          * Above code removed the "CRS" part when it is used as a namespace, as in "CRS:84".
          * The code below removes the "CRS" prefix when it is concatenated within the code,
          * as in "CRS84". Together, those two checks handle redundant codes like "CRS:CRS84"
          * (malformed code, but seen in practice).
          */
-        int start = CharSequences.skipLeadingWhitespaces(code, 0, code.length());
-        if (code.regionMatches(true, start, Constants.CRS, 0, Constants.CRS.length())) {
-            start = CharSequences.skipLeadingWhitespaces(code, start + Constants.CRS.length(),
code.length());
+        if (code.regionMatches(true, s, Constants.CRS, 0, Constants.CRS.length())) {
+            s = CharSequences.skipLeadingWhitespaces(code, s + Constants.CRS.length(), code.length());
         }
-        code = code.substring(start, CharSequences.skipTrailingWhitespaces(code, start, code.length()));
-        if (code.isEmpty()) {
+        if (s >= code.length()) {
             throw new NoSuchAuthorityCodeException(Errors.format(Errors.Keys.EmptyArgument_1,
"code"), Constants.OGC, code);
         }
-        return code;
+        return s | isLegacy;
     }
 
     /**
@@ -377,7 +393,8 @@ public class CommonAuthorityFactory exte
      */
     @Override
     public InternationalString getDescriptionText(final String code) throws FactoryException
{
-        final String localCode = trimAuthority(code);
+        final int s = skipNamespace(code) & ~LEGACY_MASK;
+        final String localCode = code.substring(s, CharSequences.skipTrailingWhitespaces(code,
s, code.length()));
         if (localCode.indexOf(SEPARATOR) < 0) {
             /*
              * For codes in the "AUTO(2)" namespace without parameters, we can not rely on
the default implementation
@@ -430,12 +447,20 @@ public class CommonAuthorityFactory exte
     @Override
     public CoordinateReferenceSystem createCoordinateReferenceSystem(final String code) throws
FactoryException {
         ArgumentChecks.ensureNonNull("code", code);
-        String localCode  = trimAuthority(code);
+        final String localCode;
+        final boolean isLegacy;
         String complement = null;
-        final int startOfParameters = localCode.indexOf(SEPARATOR);
-        if (startOfParameters >= 0) {
-            complement = localCode.substring(startOfParameters + 1);
-            localCode = localCode.substring(0, CharSequences.skipTrailingWhitespaces(localCode,
0, startOfParameters));
+        { // Block for keeping 'start' and 'end' variables locale.
+            int start = skipNamespace(code);
+            isLegacy = (start & LEGACY_MASK) != 0;
+            start &= ~LEGACY_MASK;
+            final int startOfParameters = code.indexOf(SEPARATOR, start);
+            int end = CharSequences.skipTrailingWhitespaces(code, start, code.length());
+            if (startOfParameters >= 0) {
+                complement = code.substring(startOfParameters + 1);
+                end = CharSequences.skipTrailingWhitespaces(code, start, startOfParameters);
+            }
+            localCode = code.substring(start, end);
         }
         int codeValue = 0;
         double[] parameters = ArraysExt.EMPTY_DOUBLE;
@@ -462,9 +487,10 @@ public class CommonAuthorityFactory exte
                 errorKey = Errors.Keys.TooManyArguments_2;
             }
             if (errorKey == 0) {
-                return createAuto(code, codeValue, (count > 2) ? parameters[0] : 1,
-                                                                 parameters[count - 2],
-                                                                 parameters[count - 1]);
+                return createAuto(code, codeValue, isLegacy,
+                        (count > 2) ? parameters[0] : isLegacy ? Constants.EPSG_METRE
: 1,
+                                      parameters[count - 2],
+                                      parameters[count - 1]);
             }
             throw new NoSuchAuthorityCodeException(Errors.format(errorKey, expected, count),
AUTO2, localCode, code);
         }
@@ -489,13 +515,14 @@ public class CommonAuthorityFactory exte
      *
      * @param  code        The user-specified code, used only for error reporting.
      * @param  projection  The projection code (e.g. 42001).
+     * @param  isLegacy    {@code true} if the code was found in {@code "AUTO"} or {@code
"AUTO1"} namespace.
      * @param  factor      The multiplication factor for the unit of measurement.
      * @param  longitude   A longitude in the desired projection zone.
      * @param  latitude    A latitude in the desired projection zone.
      * @return The projected CRS for the given projection and parameters.
      */
     @SuppressWarnings("null")
-    private ProjectedCRS createAuto(final String code, final int projection,
+    private ProjectedCRS createAuto(final String code, final int projection, final boolean
isLegacy,
             final double factor, final double longitude, final double latitude) throws FactoryException
     {
         Boolean isUTM = null;
@@ -527,7 +554,7 @@ public class CommonAuthorityFactory exte
         try {
             if (isUTM != null && isUTM) {
                 crs = datum.UTM(latitude, longitude);
-                if (factor == 1) {
+                if (factor == (isLegacy ? Constants.EPSG_METRE : 1)) {
                     return crs;
                 }
                 baseCRS = crs.getBaseCRS();
@@ -547,8 +574,13 @@ public class CommonAuthorityFactory exte
              * At this point we got a coordinate system with axes in metres.
              * If the user asked for another unit of measurement, change the axes now.
              */
-            if (factor != 1) {
-                final Unit<Length> unit = Units.multiply(SI.METRE, factor);
+            final Unit<?> unit;
+            if (isLegacy) {
+                unit = createUnitFromEPSG(factor);
+            } else {
+                unit = (factor != 1) ? Units.multiply(SI.METRE, factor) : SI.METRE;
+            }
+            if (!SI.METRE.equals(unit)) {
                 cs = (CartesianCS) CoordinateSystems.replaceAxes(cs, new AxisFilter() {
                     @Override public Unit<?> getUnitReplacement(Unit<?> ignored)
{
                         assert SI.METRE.equals(ignored) : ignored;
@@ -581,6 +613,31 @@ public class CommonAuthorityFactory exte
     }
 
     /**
+     * Returns the unit of measurement for the given EPSG code.
+     * This is used only for codes in the legacy {@code "AUTO"} namespace.
+     */
+    private static Unit<?> createUnitFromEPSG(final double code) throws NoSuchAuthorityCodeException
{
+        String message = null;      // Error message to be used only in case of failure.
+        final String s;             // The string representation of the code, to be used
only in case of failure.
+        final int c = (int) code;
+        if (c == code) {
+            final Unit<?> unit = Units.valueOfEPSG(c);
+            if (Units.isLinear(unit)) {
+                return unit;
+            } else if (unit != null) {
+                message = Errors.format(Errors.Keys.NonLinearUnit_1, unit);
+            }
+            s = String.valueOf(c);
+        } else {
+            s = String.valueOf(code);
+        }
+        if (message == null) {
+            message = Errors.format(Errors.Keys.NoSuchAuthorityCode_3, Constants.EPSG, Unit.class,
s);
+        }
+        throw new NoSuchAuthorityCodeException(message, Constants.EPSG, s);
+    }
+
+    /**
      * Returns the "Computer display" reference system (CRS:1). This is rarely used.
      */
     private synchronized CoordinateReferenceSystem displayCRS() throws FactoryException {

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java?rev=1724442&r1=1724441&r2=1724442&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Constants.java
[UTF-8] Wed Jan 13 15:44:57 2016
@@ -184,6 +184,21 @@ public final class Constants extends Sta
     public static final short EPSG_B0 = 8639;
 
     /**
+     * The EPSG code for metres.
+     */
+    public static final short EPSG_METRE = 9001;
+
+    /**
+     * The EPSG code for degrees when used in parameters.
+     */
+    public static final short EPSG_PARAM_DEGREES = 9102;
+
+    /**
+     * The EPSG code for degrees when used in axes.
+     */
+    public static final short EPSG_AXIS_DEGREES = 9122;
+
+    /**
      * Do not allow instantiation of this class.
      */
     private Constants() {

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=1724442&r1=1724441&r2=1724442&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]
Wed Jan 13 15:44:57 2016
@@ -561,16 +561,17 @@ public final class Units extends Static
      */
     public static Unit<?> valueOfEPSG(final int code) {
         switch (code) {
+            case Constants.EPSG_PARAM_DEGREES:  // Fall through
+            case Constants.EPSG_AXIS_DEGREES:   return NonSI.DEGREE_ANGLE;
+            case Constants.EPSG_METRE:          return SI.METRE;
+
             case 1029: return       YEAR;
             case 1040: return SI   .SECOND;
-            case 9001: return SI   .METRE;
             case 9002: return NonSI.FOOT;
             case 9003: return NonSI.FOOT_SURVEY_US;
             case 9030: return NonSI.NAUTICAL_MILE;
             case 9036: return SI   .KILOMETRE;
             case 9101: return SI   .RADIAN;
-            case 9122: // Fall through
-            case 9102: return NonSI.DEGREE_ANGLE;
             case 9103: return NonSI.MINUTE_ANGLE;
             case 9104: return NonSI.SECOND_ANGLE;
             case 9105: return NonSI.GRADE;
@@ -607,8 +608,8 @@ public final class Units extends Static
      */
     public static Integer getEpsgCode(final Unit<?> unit, final boolean inAxis) {
         Integer code = UnitsMap.EPSG_CODES.get(unit);
-        if (inAxis && code != null && code == 9102) {
-            code = UnitsMap.I9122;
+        if (inAxis && code != null && code == Constants.EPSG_PARAM_DEGREES)
{
+            code = UnitsMap.EPSG_AXIS_DEGREES;
         }
         return code;
     }

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitsMap.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitsMap.java?rev=1724442&r1=1724441&r2=1724442&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitsMap.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/measure/UnitsMap.java
[UTF-8] Wed Jan 13 15:44:57 2016
@@ -24,6 +24,7 @@ import javax.measure.unit.SI;
 import javax.measure.unit.NonSI;
 import javax.measure.unit.Unit;
 import javax.measure.quantity.Quantity;
+import org.apache.sis.internal.util.Constants;
 import org.apache.sis.util.Static;
 
 import static org.apache.sis.measure.Units.*;
@@ -49,7 +50,7 @@ final class UnitsMap extends Static {
      * The 9122 integer, used as an alternative code for the degrees unit.
      * See {@link Units#getEpsgCode(Unit, boolean)} for more information.
      */
-    static final Integer I9122 = 9122;
+    static final Integer EPSG_AXIS_DEGREES = (int) Constants.EPSG_AXIS_DEGREES;
 
     /**
      * EPSG codes of some units. This map is the reverse of {@link Units#valueOfEPSG(int)}.



Mime
View raw message