sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1812190 - in /sis/branches/JDK8/core: sis-metadata/src/test/java/org/apache/sis/internal/metadata/ sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/ sis-referencing/src/main/java/org/apache/sis/internal/referencing/ s...
Date Sat, 14 Oct 2017 15:24:11 GMT
Author: desruisseaux
Date: Sat Oct 14 15:24:11 2017
New Revision: 1812190

URL: http://svn.apache.org/viewvc?rev=1812190&view=rev
Log:
Complete implementation combined URI for multi-dimensional CRS.
https://issues.apache.org/jira/browse/SIS-341

Added:
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateReferenceSystemTest.java   (with props)
Modified:
    sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/NameMeaningTest.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java

Modified: sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/NameMeaningTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/NameMeaningTest.java?rev=1812190&r1=1812189&r2=1812190&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/NameMeaningTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/internal/metadata/NameMeaningTest.java [UTF-8] Sat Oct 14 15:24:11 2017
@@ -16,10 +16,14 @@
  */
 package org.apache.sis.internal.metadata;
 
+import javax.measure.Unit;
 import org.opengis.referencing.cs.*;
 import org.opengis.referencing.crs.*;
 import org.opengis.referencing.datum.*;
 import org.opengis.referencing.ReferenceSystem;
+import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.referencing.operation.CoordinateOperation;
+import org.opengis.parameter.ParameterDescriptor;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
@@ -41,19 +45,23 @@ public final strictfp class NameMeaningT
      */
     @Test
     public void testToObjectType() {
-        assertEquals("crs",             NameMeaning.toObjectType(GeographicCRS       .class));
-        assertEquals("crs",             NameMeaning.toObjectType(ProjectedCRS        .class));
-        assertEquals("crs",             NameMeaning.toObjectType(VerticalCRS         .class));
-        assertEquals("crs",             NameMeaning.toObjectType(TemporalCRS         .class));
-        assertEquals("datum",           NameMeaning.toObjectType(GeodeticDatum       .class));
-        assertEquals("datum",           NameMeaning.toObjectType(VerticalDatum       .class));
-        assertEquals("datum",           NameMeaning.toObjectType(TemporalDatum       .class));
-        assertEquals("ellipsoid",       NameMeaning.toObjectType(Ellipsoid           .class));
-        assertEquals("meridian",        NameMeaning.toObjectType(PrimeMeridian       .class));
-        assertEquals("cs",              NameMeaning.toObjectType(EllipsoidalCS       .class));
-        assertEquals("cs",              NameMeaning.toObjectType(CartesianCS         .class));
-        assertEquals("axis",            NameMeaning.toObjectType(CoordinateSystemAxis.class));
-        assertEquals("referenceSystem", NameMeaning.toObjectType(ReferenceSystem     .class));
+        assertEquals("crs",                 NameMeaning.toObjectType(GeographicCRS       .class));
+        assertEquals("crs",                 NameMeaning.toObjectType(ProjectedCRS        .class));
+        assertEquals("crs",                 NameMeaning.toObjectType(VerticalCRS         .class));
+        assertEquals("crs",                 NameMeaning.toObjectType(TemporalCRS         .class));
+        assertEquals("datum",               NameMeaning.toObjectType(GeodeticDatum       .class));
+        assertEquals("datum",               NameMeaning.toObjectType(VerticalDatum       .class));
+        assertEquals("datum",               NameMeaning.toObjectType(TemporalDatum       .class));
+        assertEquals("ellipsoid",           NameMeaning.toObjectType(Ellipsoid           .class));
+        assertEquals("meridian",            NameMeaning.toObjectType(PrimeMeridian       .class));
+        assertEquals("cs",                  NameMeaning.toObjectType(EllipsoidalCS       .class));
+        assertEquals("cs",                  NameMeaning.toObjectType(CartesianCS         .class));
+        assertEquals("axis",                NameMeaning.toObjectType(CoordinateSystemAxis.class));
+        assertEquals("referenceSystem",     NameMeaning.toObjectType(ReferenceSystem     .class));
+        assertEquals("coordinateOperation", NameMeaning.toObjectType(CoordinateOperation .class));
+        assertEquals("method",              NameMeaning.toObjectType(OperationMethod     .class));
+        assertEquals("parameter",           NameMeaning.toObjectType(ParameterDescriptor .class));
+        assertEquals("uom",                 NameMeaning.toObjectType(Unit                .class));
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java?rev=1812190&r1=1812189&r2=1812190&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java [UTF-8] Sat Oct 14 15:24:11 2017
@@ -170,7 +170,7 @@ public final class Code {
             Identifier fallback = null;
             for (final Identifier identifier : identifiers) {
                 final String code = identifier.getCode();
-                if (code == null) continue; // Paranoiac check.
+                if (code == null) continue;                                                 // Paranoiac check.
                 if (code.regionMatches(true, 0, "urn:", 0, 4)) {
                     return new Code(identifier);
                 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java?rev=1812190&r1=1812189&r2=1812190&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java [UTF-8] Sat Oct 14 15:24:11 2017
@@ -68,6 +68,11 @@ public final class Resources extends Ind
         public static final short AmbiguousEllipsoid_1 = 1;
 
         /**
+         * Can not create objects of type ‘{0}’ from combined URI.
+         */
+        public static final short CanNotCombineUriAsType_1 = 79;
+
+        /**
          * Can not compute the coordinate operation derivative.
          */
         public static final short CanNotComputeDerivative = 2;
@@ -78,7 +83,7 @@ public final class Resources extends Ind
         public static final short CanNotConcatenateTransforms_2 = 3;
 
         /**
-         * Can not create an object of group “{1}” as an instance of class ‘{0}’.
+         * Can not create an object of type “{1}” as an instance of class ‘{0}’.
          */
         public static final short CanNotCreateObjectAsInstanceOf_2 = 4;
 
@@ -98,6 +103,11 @@ public final class Resources extends Ind
         public static final short CanNotMapAxisToDirection_1 = 6;
 
         /**
+         * Can not parse component {1} in the combined {0,choice,0#URN|1#URL}.
+         */
+        public static final short CanNotParseCombinedReference_2 = 78;
+
+        /**
          * Target dimension {0} depends on excluded source dimensions.
          */
         public static final short CanNotSeparateTargetDimension_1 = 7;
@@ -427,6 +437,11 @@ public final class Resources extends Ind
         public static final short SingularMatrix = 63;
 
         /**
+         * Combined URI contains unexpected components.
+         */
+        public static final short UnexpectedComponentInURI = 80;
+
+        /**
          * Unexpected dimension for a coordinate system of type ‘{0}’.
          */
         public static final short UnexpectedDimensionForCS_1 = 64;

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties?rev=1812190&r1=1812189&r2=1812190&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties [ISO-8859-1] Sat Oct 14 15:24:11 2017
@@ -42,12 +42,14 @@ NonConformCRS_3                   = The
 #
 # Error messages (to be used in exceptions)
 #
-CanNotConcatenateTransforms_2     = Can not concatenate transforms \u201c{0}\u201d and \u201c{1}\u201d.
+CanNotCombineUriAsType_1          = Can not create objects of type \u2018{0}\u2019 from combined URI.
 CanNotComputeDerivative           = Can not compute the coordinate operation derivative.
-CanNotCreateObjectAsInstanceOf_2  = Can not create an object of group \u201c{1}\u201d as an instance of class \u2018{0}\u2019.
+CanNotConcatenateTransforms_2     = Can not concatenate transforms \u201c{0}\u201d and \u201c{1}\u201d.
+CanNotCreateObjectAsInstanceOf_2  = Can not create an object of type \u201c{1}\u201d as an instance of class \u2018{0}\u2019.
 CanNotInferGridSizeFromValues_1   = Can not infer a grid size from the given values in {0} range.
 CanNotInstantiateGeodeticObject_1 = Can not instantiate geodetic object for \u201c{0}\u201d.
 CanNotMapAxisToDirection_1        = Can not map an axis from the specified coordinate system to the \u201c{0}\u201d direction.
+CanNotParseCombinedReference_2    = Can not parse component {1} in the combined {0,choice,0#URN|1#URL}.
 CanNotSeparateTargetDimension_1   = Target dimension {0} depends on excluded source dimensions.
 CanNotTransformEnvelopeToGeodetic = Can not transform envelope to a geodetic reference system.
 CanNotUseGeodeticParameters_2     = Can not use the {0} geodetic parameters: {1}
@@ -96,6 +98,7 @@ NoSuchOperationMethod_1           = No o
 ParameterNotFound_2               = No parameter named \u201c{1}\u201d has been found in \u201c{0}\u201d.
 RecursiveCreateCallForCode_2      = Recursive call while creating an object of type \u2018{0}\u2019 for code \u201c{1}\u201d.
 SingularMatrix                    = Matrix is singular.
+UnexpectedComponentInURI          = Combined URI contains unexpected components.
 UnexpectedDimensionForCS_1        = Unexpected dimension for a coordinate system of type \u2018{0}\u2019.
 UnitlessParameter_1               = Parameter \u201c{0}\u201d does not expect unit.
 UnknownAuthority_1                = Authority \u201c{0}\u201d is unknown.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties?rev=1812190&r1=1812189&r2=1812190&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties [ISO-8859-1] Sat Oct 14 15:24:11 2017
@@ -47,13 +47,15 @@ NonConformCRS_3                   = La d
 #
 # Error messages (to be used in exceptions)
 #
-CanNotConcatenateTransforms_2     = Les transformations \u00ab\u202f{0}\u202f\u00bb et \u00ab\u202f{1}\u202f\u00bb ne peuvent pas \u00eatre combin\u00e9es.
+CanNotCombineUriAsType_1          = Ne peut pas cr\u00e9er d\u2019objets de type \u2018{0}\u2019 \u00e0 partir d\u2019un URI combin\u00e9.
 CanNotComputeDerivative           = La d\u00e9riv\u00e9 de l\u2019op\u00e9ration sur les coordonn\u00e9es ne peut pas \u00eatre calcul\u00e9e.
-CanNotCreateObjectAsInstanceOf_2  = Ne peut pas cr\u00e9er un objet du groupe \u00ab\u202f{1}\u202f\u00bb comme une instance de la classe \u2018{0}\u2019.
+CanNotConcatenateTransforms_2     = Les transformations \u00ab\u202f{0}\u202f\u00bb et \u00ab\u202f{1}\u202f\u00bb ne peuvent pas \u00eatre combin\u00e9es.
+CanNotCreateObjectAsInstanceOf_2  = Ne peut pas cr\u00e9er un objet du type \u00ab\u202f{1}\u202f\u00bb comme une instance de la classe \u2018{0}\u2019.
 CanNotInferGridSizeFromValues_1   = Ne peut pas inf\u00e9rer une taille de grille \u00e0 partir des valeurs donn\u00e9es dans la plage {0}.
 CanNotInstantiateGeodeticObject_1 = Ne peut pas cr\u00e9er l\u2019objet g\u00e9od\u00e9tique pour \u00ab\u202f{0}\u202f\u00bb.
 CanNotMapAxisToDirection_1        = Aucun axe du syst\u00e8me de coordonn\u00e9es sp\u00e9cifi\u00e9 n\u2019a pu \u00eatre associ\u00e9 \u00e0 la direction \u00ab\u202f{0}\u202f\u00bb.
 CanNotSeparateTargetDimension_1   = La dimension de destination {0} d\u00e9pend de dimensions sources qui ont \u00e9t\u00e9 exclues.
+CanNotParseCombinedReference_2    = Ne peut pas d\u00e9coder la composante {1} dans l\u2019{0,choice,0#URN|1#URL} combin\u00e9.
 CanNotTransformEnvelopeToGeodetic = Ne peut pas transformer l\u2019enveloppe vers un r\u00e9f\u00e9rentiel g\u00e9od\u00e9sique.
 CanNotUseGeodeticParameters_2     = Ne peut pas utiliser les param\u00e8tres g\u00e9od\u00e9siques {0}\u202f: {1}
 ColinearAxisDirections_2          = Les directions d\u2019axes {0} et {1} sont colin\u00e9aires.
@@ -101,6 +103,7 @@ NoSuchOperationMethod_1           = Aucu
 ParameterNotFound_2               = Aucun param\u00e8tre nomm\u00e9 \u00ab\u202f{1}\u202f\u00bb n\u2019a \u00e9t\u00e9 trouv\u00e9 dans \u00ab\u202f{0}\u202f\u00bb.
 RecursiveCreateCallForCode_2      = Appels r\u00e9cursifs lors de la cr\u00e9ation d\u2019un objet de type \u2018{0}\u2019 pour le code \u00ab\u202f{1}\u202f\u00bb.
 SingularMatrix                    = La matrice est singuli\u00e8re.
+UnexpectedComponentInURI          = L\u2019URI combin\u00e9 contient des composantes qui n\u2019\u00e9taient pas attendues.
 UnexpectedDimensionForCS_1        = Dimension inattendue pour un syst\u00e8me de coordonn\u00e9es de type \u2018{0}\u2019.
 UnitlessParameter_1               = Le param\u00e8tre \u00ab\u202f{0}\u202f\u00bb n\u2019attend pas d\u2019unit\u00e9.
 UnknownAuthority_1                = L\u2019autorit\u00e9 \u00ab\u202f{0}\u202f\u00bb n\u2019est pas reconnue.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java?rev=1812190&r1=1812189&r2=1812190&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java [UTF-8] Sat Oct 14 15:24:11 2017
@@ -569,8 +569,9 @@ abstract class AuthorityFactoryProxy<T>
      */
     private static final Map<String, AuthorityFactoryProxy<?>> BY_URN_TYPE;
     static {
-        final Map<String, AuthorityFactoryProxy<?>> map = new HashMap<>(14);
+        final Map<String, AuthorityFactoryProxy<?>> map = new HashMap<>(16);
         map.put("crs",                  CRS);
+        map.put("crs-compound",         CRS);
         map.put("datum",                DATUM);
         map.put("ellipsoid",            ELLIPSOID);
         map.put("meridian",             PRIME_MERIDIAN);
@@ -610,7 +611,7 @@ abstract class AuthorityFactoryProxy<T>
      * The proxy to use for a given type declared in a URN.
      * For example in the {@code "urn:ogc:def:crs:EPSG::4326"} URN, the proxy to use is {@link #CRS}.
      *
-     * @param  typeName  the URN type.
+     * @param  typeName  the name of URN type.
      * @return the proxy for the given type, or {@code null} if the given type is illegal.
      */
     @SuppressWarnings("unchecked")

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java?rev=1812190&r1=1812189&r2=1812190&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] Sat Oct 14 15:24:11 2017
@@ -20,6 +20,7 @@ import java.util.ServiceLoader;
 import java.util.Collections;
 import java.util.Collection;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.Set;
 import java.util.Map;
@@ -49,9 +50,13 @@ import org.apache.sis.internal.util.Abst
 import org.apache.sis.internal.util.DefinitionURI;
 import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.internal.util.SetOfUnknownSize;
+import org.apache.sis.internal.metadata.NameMeaning;
 import org.apache.sis.internal.referencing.LazySet;
 import org.apache.sis.internal.referencing.Resources;
+import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
@@ -117,7 +122,7 @@ import org.apache.sis.util.collection.Ba
  * do not need to be thread-safe. See constructor Javadoc for more information.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.7
+ * @version 0.8
  *
  * @see org.apache.sis.referencing.CRS#getAuthorityFactory(String)
  *
@@ -727,21 +732,47 @@ public class MultiAuthoritiesFactory ext
      * @return the object from one of the authority factory specified at construction time.
      * @throws FactoryException if an error occurred while creating the object.
      */
-    final <T> T create(AuthorityFactoryProxy<? extends T> proxy, String code) throws FactoryException {
+    private <T> T create(AuthorityFactoryProxy<? extends T> proxy, String code) throws FactoryException {
         ArgumentChecks.ensureNonNull("code", code);
         final String authority, version;
         final String[] parameters;
         final DefinitionURI uri = DefinitionURI.parse(code);
         if (uri != null) {
+            Class<? extends T> type = proxy.type;
+            proxy = proxy.specialize(uri.type);
+            /*
+             * If the URN or URL contains combined references for compound coordinate reference systems,
+             * create the components. First we verify that all component references have been parsed
+             * before to start creating any object.
+             */
+            if (uri.code == null) {
+                final DefinitionURI[] components = uri.components;
+                if (components != null) {
+                    for (int i=0; i < components.length; i++) {
+                        if (components[i] == null) {
+                            throw new NoSuchAuthorityCodeException(Resources.format(
+                                    Resources.Keys.CanNotParseCombinedReference_2, i+1, uri.isHTTP ? 1 : 0),
+                                    uri.authority, null, uri.toString());
+                        }
+                    }
+                    if (proxy != null) type = proxy.type;       // Use the more specific type declared in the URN.
+                    return combine(type, components, uri.isHTTP);
+                }
+            }
+            /*
+             * At this point we determined that the URN or URL references a single instance (not combined references).
+             * Example: "urn:ogc:def:crs:EPSG:9.1:4326". Verifies that the object type is recognized and that a code
+             * is present. The remainder steps are the same as if the user gave a simple code (e.g. "EPSG:4326").
+             */
             if (uri.authority == null) {
-                throw new NoSuchAuthorityCodeException(Resources.format(Resources.Keys.MissingAuthority_1, code), null, uri.code, code);
+                // We want this check before the 'code' value is modified below.
+                throw new NoSuchAuthorityCodeException(
+                        Resources.format(Resources.Keys.MissingAuthority_1, code), null, uri.code, code);
             }
-            final Class<? extends T> type = proxy.type;
             authority  = uri.authority;
             version    = uri.version;
             code       = uri.code;
             parameters = uri.parameters;
-            proxy      = proxy.specialize(uri.type);
             if (code == null || proxy == null) {
                 final String s = uri.toString();
                 final String message;
@@ -1486,6 +1517,195 @@ public class MultiAuthoritiesFactory ext
     }
 
     /**
+     * Invoked when a {@code createFoo(…)} method is given a combined URI.
+     * A combined URI is a URN or URL referencing other components. For example if the given URI
+     * is {@code "urn:ogc:def:crs, crs:EPSG::27700, crs:EPSG::5701"}, then the components are:
+     * <ol>
+     *   <li>{@code "urn:ogc:def:crs:EPSG:9.1:27700"}</li>
+     *   <li>{@code "urn:ogc:def:crs:EPSG:9.1:5701"}</li>
+     * </ol>
+     *
+     * We do not require the components to be instance of CRS, since the "Definition identifier URNs in
+     * OGC namespace" best practice paper allows other kinds of combination (e.g. of coordinate operations).
+     *
+     * @param  <T>         compile-time value of {@code type} argument.
+     * @param  type        type of object to create.
+     * @param  references  parsed URI of the components.
+     * @param  isHTTP      whether the user URI is an URL (i.e. {@code "http://something"}) instead than a URN.
+     * @return the combined object.
+     * @throws FactoryException if an error occurred while creating the combined object.
+     */
+    private <T> T combine(final Class<T> type, final DefinitionURI[] references, final boolean isHTTP) throws FactoryException {
+        /*
+         * Identify the type requested by the user and create all components with the assumption that they will
+         * be of that type. This is the most common case. If during iteration we find an object of another kind,
+         * then the array type will be downgraded to IdentifiedObject[]. The 'componentType' variable will keep
+         * its non-null value only if the array stay of the expected sub-type.
+         */
+        final byte requestedType;
+        IdentifiedObject[] components;
+        Class<? extends IdentifiedObject> componentType;
+        if (CoordinateReferenceSystem.class.isAssignableFrom(type)) {
+            requestedType = AuthorityFactoryIdentifier.CRS;
+            componentType = CoordinateReferenceSystem.class;
+            components    = new CoordinateReferenceSystem[references.length];       // Intentional covariance.
+        } else if (CoordinateOperation.class.isAssignableFrom(type)) {
+            requestedType = AuthorityFactoryIdentifier.OPERATION;
+            componentType = CoordinateOperation.class;
+            components    = new CoordinateOperation[references.length];             // Intentional covariance.
+        } else {
+            throw new FactoryException(Resources.format(Resources.Keys.CanNotCombineUriAsType_1, type));
+        }
+        final String expected = NameMeaning.toObjectType(componentType);    // Note: "compound-crs" ⟶ "crs".
+        for (int i=0; i<references.length; i++) {
+            final DefinitionURI ref = references[i];
+            final IdentifiedObject component = createObject(ref.toString());
+            if (componentType != null && (!componentType.isInstance(component) || !expected.equalsIgnoreCase(ref.type))) {
+                componentType = null;
+                components = Arrays.copyOf(components, components.length, IdentifiedObject[].class);
+            }
+            components[i] = component;
+        }
+        /*
+         * At this point we have successfully created all components. The way to interpret those components
+         * depends mostly on the type of object requested by the user. For a given requested type, different
+         * rules apply depending on the type of components. Those rules are described in OGC 07-092r1 (2007):
+         * "Definition identifier URNs in OGC namespace".
+         */
+        IdentifiedObject combined = null;
+        switch (requestedType) {
+            case AuthorityFactoryIdentifier.OPERATION: {
+                if (componentType != null) {
+                    /*
+                     * URN combined references for concatenated operations. We build an operation name from
+                     * the operation identifiers (rather than CRS identifiers) because this is what the user
+                     * gave to us, and because source/target CRS are not guaranteed to be defined. We do not
+                     * yet support swapping roles of source and target CRS if an implied-reverse coordinate
+                     * operation is included.
+                     */
+                    final CoordinateOperation[] ops = (CoordinateOperation[]) components;
+                    String name = IdentifiedObjects.getIdentifierOrName(ops[0]) + " ⟶ "
+                                + IdentifiedObjects.getIdentifierOrName(ops[ops.length - 1]);
+                    combined = DefaultFactories.forBuildin(CoordinateOperationFactory.class)
+                            .createConcatenatedOperation(Collections.singletonMap(CoordinateOperation.NAME_KEY, name), ops);
+                }
+                break;
+            }
+            case AuthorityFactoryIdentifier.CRS: {
+                if (componentType != null) {
+                    /*
+                     * URN combined references for compound coordinate reference systems.
+                     * The URNs of the individual well-known CRSs are listed in the same order in which the
+                     * individual coordinate tuples are combined to form the CompoundCRS coordinate tuple.
+                     */
+                    combined = CRS.compound((CoordinateReferenceSystem[]) components);
+                } else if (!isHTTP) {
+                    final CoordinateSystem cs = remove(references, components, CoordinateSystem.class);
+                    if (cs != null) {
+                        final Datum datum = remove(references, components, Datum.class);
+                        if (datum != null) {
+                            /*
+                             * URN combined references for datum and coordinate system. In this case, the URN shall
+                             * concatenate the URNs of one well-known datum and one well-known coordinate system.
+                             */
+                            if (ArraysExt.allEquals(references, null)) {
+                                combined = combine((GeodeticDatum) datum, cs);
+                            }
+                        } else {
+                            /*
+                             * URN combined references for projected or derived CRSs. In this case, the URN shall
+                             * concatenate the URNs of the one well-known CRS, one well-known Conversion, and one
+                             * well-known CartesianCS. Similar action can be taken for derived CRS.
+                             */
+                            CoordinateReferenceSystem baseCRS = remove(references, components, CoordinateReferenceSystem.class);
+                            CoordinateOperation op = remove(references, components, CoordinateOperation.class);
+                            if (ArraysExt.allEquals(references, null) && op instanceof Conversion) {
+                                combined = combine(baseCRS, (Conversion) op, cs);
+                            }
+                        }
+                    }
+                }
+                break;
+            }
+        }
+        /*
+         * At this point the combined object has been created if we know how to create it.
+         * Maybe the result matches the definition of an existing object in the database,
+         * in which case we will use the existing definition for better metadata.
+         */
+        if (combined == null) {
+            throw new FactoryException(Resources.format(Resources.Keys.UnexpectedComponentInURI));
+        }
+        final IdentifiedObject existing = newIdentifiedObjectFinder().findSingleton(combined);
+        return type.cast(existing != null ? existing : combined);
+    }
+
+    /**
+     * If the given {@code type} is found in the given {@code references}, sets that reference element to {@code null}
+     * and returns the corresponding {@code components} element. Otherwise returns {@code null}. This is equivalent to
+     * {@link Map#remove(Object, Object)} where {@code references} are the keys and {@code components} are the values.
+     * We do not bother building that map because the arrays are very short (2 or 3 elements).
+     */
+    private static <T> T remove(final DefinitionURI[] references, final IdentifiedObject[] components, final Class<T> type) {
+        final String expected = NameMeaning.toObjectType(type);
+        for (int i=0; i<references.length; i++) {
+            final DefinitionURI ref = references[i];
+            if (ref != null && expected.equalsIgnoreCase(ref.type)) {
+                references[i] = null;
+                return type.cast(components[i]);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Invoked when a {@code createFoo(…)} method is given a combined URI containing a datum and a coordinate system.
+     * If the given information are not sufficient or not applicable, then this method returns {@code null}.
+     *
+     * @param  datum  the datum, or {@code null} if missing.
+     * @param  cs     the coordinate system (never null).
+     * @return the combined CRS, or {@code null} if the given information are not sufficient.
+     * @throws FactoryException if an error occurred while creating the combined CRS.
+     */
+    private static GeodeticCRS combine(final GeodeticDatum datum, final CoordinateSystem cs) throws FactoryException {
+        final Map<String,?> properties = IdentifiedObjects.getProperties(datum, Datum.IDENTIFIERS_KEY);
+        final CRSFactory factory = DefaultFactories.forBuildin(CRSFactory.class);
+        if (datum instanceof GeodeticDatum) {
+            if (cs instanceof EllipsoidalCS) {
+                return factory.createGeographicCRS(properties, datum, (EllipsoidalCS) cs);
+            } else if (cs instanceof SphericalCS) {
+                return factory.createGeocentricCRS(properties, datum, (SphericalCS) cs);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Invoked when a {@code createFoo(…)} method is given a combined URI containing a conversion and a coordinate
+     * system. If the given information are not sufficient or not applicable, then this method returns {@code null}.
+     *
+     * @param  baseCRS   the CRS on which the derived CRS will be based on, or {@code null} if missing.
+     * @param  fromBase  the conversion from {@code baseCRS} to the CRS to be created by this method.
+     * @param  cs        the coordinate system (never null).
+     * @return the combined CRS, or {@code null} if the given information are not sufficient.
+     * @throws FactoryException if an error occurred while creating the combined CRS.
+     */
+    private static GeneralDerivedCRS combine(final CoordinateReferenceSystem baseCRS, final Conversion fromBase,
+            final CoordinateSystem cs) throws FactoryException
+    {
+        if (baseCRS != null && fromBase.getSourceCRS() == null && fromBase.getTargetCRS() == null) {
+            final Map<String,?> properties = IdentifiedObjects.getProperties(fromBase, Datum.IDENTIFIERS_KEY);
+            final CRSFactory factory = DefaultFactories.forBuildin(CRSFactory.class);
+            if (baseCRS instanceof GeographicCRS && cs instanceof CartesianCS) {
+                return factory.createProjectedCRS(properties, (GeographicCRS) baseCRS, fromBase, (CartesianCS) cs);
+            } else {
+                return factory.createDerivedCRS(properties, baseCRS, fromBase, cs);
+            }
+        }
+        return null;
+    }
+
+    /**
      * Creates a finder which can be used for looking up unidentified objects.
      * The default implementation delegates the lookups to the underlying factories.
      *

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java?rev=1812190&r1=1812189&r2=1812190&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java [UTF-8] Sat Oct 14 15:24:11 2017
@@ -122,10 +122,10 @@ final class CRSPair {
     }
 
     /**
-     * Return a string representation of this key.
+     * Returns a string representation of this key.
      */
     @Override
     public String toString() {
-        return label(sourceCRS) + " → " + label(targetCRS);
+        return label(sourceCRS) + " ⟶ " + label(targetCRS);
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java?rev=1812190&r1=1812189&r2=1812190&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java [UTF-8] Sat Oct 14 15:24:11 2017
@@ -27,6 +27,7 @@ import org.opengis.referencing.crs.CRSAu
 import org.opengis.referencing.crs.GeocentricCRS;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.VerticalCRS;
+import org.opengis.referencing.cs.EllipsoidalCS;
 import org.opengis.referencing.cs.CSAuthorityFactory;
 import org.opengis.referencing.datum.DatumAuthorityFactory;
 import org.opengis.referencing.datum.GeodeticDatum;
@@ -40,6 +41,7 @@ import org.apache.sis.measure.Units;
 import org.apache.sis.metadata.iso.extent.Extents;
 import org.apache.sis.referencing.datum.HardCodedDatum;
 import org.apache.sis.referencing.crs.HardCodedCRS;
+import org.apache.sis.referencing.cs.HardCodedCS;
 
 import static org.junit.Assert.*;
 
@@ -48,7 +50,7 @@ import static org.junit.Assert.*;
  * A pseudo-authority factory with hard-coded objects.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 0.8
  * @since   0.7
  * @module
  */
@@ -114,6 +116,7 @@ public final strictfp class AuthorityFac
         if (type.isAssignableFrom(GeodeticDatum.class)) add(codes, 6326, 6322, 6807, 6301, 6612, 6047);
         if (type.isAssignableFrom(VerticalDatum.class)) add(codes, 5100);
         if (type.isAssignableFrom(VerticalCRS.class))   add(codes, 5714, 9905);
+        if (type.isAssignableFrom(EllipsoidalCS.class)) add(codes, 6422, 6424);
         return codes;
     }
 
@@ -147,6 +150,8 @@ public final strictfp class AuthorityFac
             case 6612: return HardCodedDatum.JGD2000;
             case 6047: return HardCodedDatum.SPHERE;
             case 5100: return HardCodedDatum.MEAN_SEA_LEVEL;
+            case 6422: return HardCodedCS.GEODETIC_φλ;
+            case 6424: return HardCodedCS.GEODETIC_2D;
             default: throw new NoSuchAuthorityCodeException(code, authority.getTitle().toString(), code);
         }
     }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java?rev=1812190&r1=1812189&r2=1812190&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactoryTest.java [UTF-8] Sat Oct 14 15:24:11 2017
@@ -28,6 +28,8 @@ import org.opengis.referencing.crs.Geoce
 import org.opengis.referencing.crs.GeodeticCRS;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.VerticalCRS;
+import org.opengis.referencing.crs.CompoundCRS;
+import org.opengis.referencing.crs.SingleCRS;
 import org.opengis.referencing.datum.Datum;
 import org.opengis.referencing.datum.DatumAuthorityFactory;
 import org.opengis.referencing.datum.GeodeticDatum;
@@ -36,6 +38,7 @@ import org.opengis.referencing.datum.Ver
 import org.opengis.util.FactoryException;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.metadata.iso.extent.Extents;
+import org.apache.sis.referencing.cs.HardCodedCS;
 import org.apache.sis.referencing.crs.HardCodedCRS;
 import org.apache.sis.referencing.datum.HardCodedDatum;
 import org.apache.sis.measure.Units;
@@ -274,6 +277,89 @@ public final strictfp class MultiAuthori
     }
 
     /**
+     * Tests {@code MultiAuthoritiesFactory.createFoo(String)} from codes in the
+     * {@code "urn:ogc:def:type, type₁:authority₁:version₁:code₁, type₂:authority₂:version₂:code₂"} form.
+     *
+     * @throws FactoryException if an authority or a code is not recognized.
+     *
+     * @since 0.8
+     */
+    @Test
+    @DependsOnMethod("testCreateFromURNs")
+    public void testCreateFromCombinedURNs() throws FactoryException {
+        final Set<AuthorityFactoryMock> mock = Collections.singleton(new AuthorityFactoryMock("MOCK", "2.3"));
+        final MultiAuthoritiesFactory factory = new MultiAuthoritiesFactory(mock, mock, mock, null);
+        testCreateFromCombinedURIs(factory, "urn:ogc:def:crs, crs:MOCK::4326, crs:MOCK::5714");
+        /*
+         * Following are more unusual combinations described in OGC 07-092r1 (2007)
+         * "Definition identifier URNs in OGC namespace".
+         */
+        SingleCRS crs = factory.createGeographicCRS("urn:ogc:def:crs, datum:MOCK::6326, cs:MOCK::6424");
+        assertSame("datum", HardCodedDatum.WGS84, crs.getDatum());
+        assertSame("cs", HardCodedCS.GEODETIC_2D, crs.getCoordinateSystem());
+        /*
+         * Verify that invalid combined URIs are rejected.
+         */
+        try {
+            factory.createObject("urn:ogc:def:cs, crs:MOCK::4326, crs:MOCK::5714");
+            fail("Shall not accept to create CoordinateSystem from combined URI.");
+        } catch (FactoryException e) {
+            String message = e.getMessage();
+            assertTrue(message, message.contains("CoordinateSystem"));
+        }
+        try {
+            factory.createObject("urn:ogc:def:crs, datum:MOCK::6326, cs:MOCK::6424, cs:MOCK::6422");
+            fail("Shall not accept to create combined URI with unexpected objects.");
+        } catch (FactoryException e) {
+            assertNotNull(e.getMessage());
+        }
+    }
+
+    /**
+     * Tests {@code MultiAuthoritiesFactory.createFoo(String)} from codes in the
+     * {@code "http://www.opengis.net/def/crs-compound?1=(…)/code₁&2=(…)/code₂"} form.
+     *
+     * @throws FactoryException if an authority or a code is not recognized.
+     *
+     * @since 0.8
+     */
+    @Test
+    @DependsOnMethod("testCreateFromHTTPs")
+    public void testCreateFromCombinedHTTPs() throws FactoryException {
+        final Set<AuthorityFactoryMock> mock = Collections.singleton(new AuthorityFactoryMock("MOCK", "2.3"));
+        final MultiAuthoritiesFactory factory = new MultiAuthoritiesFactory(mock, mock, mock, null);
+        testCreateFromCombinedURIs(factory, "http://www.opengis.net/def/crs-compound?"
+                                        + "1=http://www.opengis.net/def/crs/MOCK/0/4326&"
+                                        + "2=http://www.opengis.net/def/crs/MOCK/0/5714");
+        testCreateFromCombinedURIs(factory, "http://www.opengis.net/def/crs-compound?"
+                                        + "2=http://www.opengis.net/def/crs/MOCK/0/5714&"
+                                        + "1=http://www.opengis.net/def/crs/MOCK/0/4326");
+        /*
+         * Contrarily to URN, the HTTP form shall not accept Datum + CoordinateSystem combination.
+         */
+        try {
+            factory.createObject("http://www.opengis.net/def/crs-compound?"
+                             + "1=http://www.opengis.net/def/datum/MOCK/0/6326&"
+                             + "2=http://www.opengis.net/def/cs/MOCK/0/6424");
+            fail("Shall not accept Datum + CoordinateSystem combination.");
+        } catch (FactoryException e) {
+            assertNotNull(e.getMessage());
+        }
+    }
+
+    /**
+     * Implementation of {@link #testCreateFromCombinedURNs()} and {@link #testCreateFromCombinedHTTPs()}.
+     */
+    private static void testCreateFromCombinedURIs(final MultiAuthoritiesFactory factory, final String heightOnWGS84)
+            throws FactoryException
+    {
+        CompoundCRS crs = factory.createCompoundCRS(heightOnWGS84);
+        assertArrayEquals("WGS 84 + MSL height", new SingleCRS[] {
+            HardCodedCRS.WGS84_φλ, HardCodedCRS.GRAVITY_RELATED_HEIGHT
+        }, crs.getComponents().toArray());
+    }
+
+    /**
      * Tests {@link MultiAuthoritiesFactory#getAuthorityCodes(Class)}.
      *
      * @throws FactoryException if an error occurred while fetching the set of codes.

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java?rev=1812190&r1=1812189&r2=1812190&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java [UTF-8] Sat Oct 14 15:24:11 2017
@@ -864,7 +864,7 @@ public final strictfp class CoordinateOp
         assertSame      ("sourceCRS", sourceCRS, operation.getSourceCRS());
         assertSame      ("targetCRS", targetCRS, operation.getTargetCRS());
         assertInstanceOf("operation", ConcatenatedOperation.class, operation);
-        assertEquals    ("name", "CompoundCRS[“Test3D”] → CompoundCRS[“Test4D”]", operation.getName().getCode());
+        assertEquals    ("name", "CompoundCRS[“Test3D”] ⟶ CompoundCRS[“Test4D”]", operation.getName().getCode());
 
         transform = operation.getMathTransform();
         assertInstanceOf("transform", LinearTransform.class, transform);

Added: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateReferenceSystemTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateReferenceSystemTest.java?rev=1812190&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateReferenceSystemTest.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateReferenceSystemTest.java [UTF-8] Sat Oct 14 15:24:11 2017
@@ -0,0 +1,56 @@
+/*
+ * 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.test.integration;
+
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.test.DependsOn;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Advances CRS constructions requiring the EPSG geodetic dataset.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 0.8
+ * @since   0.8
+ * @module
+ */
+@DependsOn({
+    org.apache.sis.referencing.CRSTest.class,
+    org.apache.sis.referencing.CommonCRSTest.class,
+    org.apache.sis.referencing.factory.sql.EPSGFactoryTest.class,
+    org.apache.sis.referencing.factory.MultiAuthoritiesFactoryTest.class
+})
+public final strictfp class CoordinateReferenceSystemTest extends TestCase {
+    /**
+     * Tests creation from codes in the
+     * {@code "urn:ogc:def:type, type₁:authority₁:version₁:code₁, type₂:authority₂:version₂:code₂"} form.
+     *
+     * @throws FactoryException if an authority or a code is not recognized.
+     */
+    @Test
+    @org.junit.Ignore("Pending a mechanism for detecting if EPSG dataset is present.")
+    public void testCreateFromCombinedURN() throws FactoryException {
+        CoordinateReferenceSystem crs = CRS.forCode("urn:ogc:def:crs, crs:EPSG::27700, crs:EPSG::5701");
+        assertSame("OSGB 1936 / British National Grid + ODN height", CRS.forCode("EPSG:7405"), crs);
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateReferenceSystemTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1812190&r1=1812189&r2=1812190&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] Sat Oct 14 15:24:11 2017
@@ -249,6 +249,7 @@ import org.junit.BeforeClass;
 
     org.apache.sis.distance.LatLonPointRadiusTest.class,        // Pending refactoring in a geometry package.
 
+    org.apache.sis.test.integration.CoordinateReferenceSystemTest.class,
     org.apache.sis.test.integration.CoordinateOperationTest.class,
     org.apache.sis.test.integration.DatumShiftTest.class,
     org.apache.sis.test.integration.MetadataTest.class,

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java?rev=1812190&r1=1812189&r2=1812190&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java [UTF-8] Sat Oct 14 15:24:11 2017
@@ -67,7 +67,7 @@ import java.lang.reflect.Array;
  * objects.
  *
  * @author Martin Desruisseaux (IRD, Geomatys)
- * @version 0.4
+ * @version 0.8
  *
  * @see Arrays
  *
@@ -1684,6 +1684,33 @@ public final class ArraysExt extends Sta
     }
 
     /**
+     * Returns {@code true} if all values in the specified array are equal to the specified value,
+     * which may be {@code null}.
+     *
+     * @param  array  the array to check.
+     * @param  value  the expected value.
+     * @return {@code true} if all elements in the given array are equal to the given value.
+     *
+     * @since 0.8
+     */
+    public static boolean allEquals(final Object[] array, final Object value) {
+        if (value == null) {
+            for (int i=0; i<array.length; i++) {
+                if (array[i] != null) {
+                    return false;
+                }
+            }
+        } else {
+            for (int i=0; i<array.length; i++) {
+                if (!value.equals(array[i])) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
      * Returns {@code true} if all values in the specified array are equal to the specified value,
      * which may be {@link Double#NaN}.
      *



Mime
View raw message