Author: desruisseaux
Date: Sat Oct  7 15:13:52 2017
New Revision: 1811436

URL: http://svn.apache.org/viewvc?rev=1811436&view=rev
Log:
Do not allow creation of CompoundCRS made of horizontal CRS + vertical height.
https://issues.apache.org/jira/browse/SIS-303

Modified:
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.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/crs/DefaultCompoundCRS.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.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/referencing/operation/DefaultCoordinateOperationFactoryTest.java

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java?rev=1811436&r1=1811435&r2=1811436&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
 [UTF-8] Sat Oct  7 15:13:52 2017
@@ -33,6 +33,8 @@ import org.opengis.referencing.crs.*;
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.datum.Ellipsoid;
 import org.opengis.referencing.datum.PrimeMeridian;
+import org.opengis.referencing.datum.VerticalDatum;
+import org.opengis.referencing.datum.VerticalDatumType;
 import org.opengis.referencing.operation.CoordinateOperationFactory;
 import org.opengis.util.FactoryException;
 import org.apache.sis.internal.system.DefaultFactories;
@@ -173,6 +175,30 @@ public final class ReferencingUtilities
     }
 
     /**
+     * Returns {@code true} if the type of the given datum is ellipsoidal. A 
vertical datum is not allowed
+     * to be ellipsoidal according ISO 19111, but Apache SIS relaxes this 
restriction in some limited cases,
+     * for example when parsing a string in the legacy WKT 1 format. Apache 
SIS should not expose those
+     * vertical heights as much as possible, and instead try to combine them 
with three-dimensional
+     * geographic or projected CRS as soon as it can.
+     *
+     * @param  datum  the datum to test, or {@code null} if none.
+     * @return {@code true} if the given datum is non null and of ellipsoidal 
type.
+     *
+     * @see org.apache.sis.internal.metadata.VerticalDatumTypes#ELLIPSOIDAL
+     *
+     * @since 0.8
+     */
+    public static boolean isEllipsoidalHeight(final VerticalDatum datum) {
+        if (datum != null) {
+            final VerticalDatumType type = datum.getVerticalDatumType();
+            if (type != null) {
+                return "ELLIPSOIDAL".equalsIgnoreCase(type.name());
+            }
+        }
+        return false;
+    }
+
+    /**
      * Returns the ellipsoid used by the specified coordinate reference 
system, provided that the two first dimensions
      * use an instance of {@link GeographicCRS}. Otherwise (i.e. if the two 
first dimensions are not geographic),
      * returns {@code null}.
@@ -327,13 +353,16 @@ public final class ReferencingUtilities
      */
     public static StringBuilder toPropertyName(final Class<?> base, final 
Class<?> type) {
         final UML uml = type.getAnnotation(UML.class);
-        if (uml != null && uml.specification() == Specification.ISO_19111) {
-            final String name = uml.identifier();
-            final int length = name.length();
-            final StringBuilder buffer = new 
StringBuilder(length).append(name, name.indexOf('_') + 1, length);
-            if (buffer.length() != 0) {
-                buffer.setCharAt(0, Character.toLowerCase(buffer.charAt(0)));
-                return buffer;
+        if (uml != null) {
+            final Specification spec = uml.specification();
+            if (spec == Specification.ISO_19111 || spec == 
Specification.ISO_19111_2) {
+                final String name = uml.identifier();
+                final int length = name.length();
+                final StringBuilder buffer = new 
StringBuilder(length).append(name, name.indexOf('_') + 1, length);
+                if (buffer.length() != 0) {
+                    buffer.setCharAt(0, 
Character.toLowerCase(buffer.charAt(0)));
+                    return buffer;
+                }
             }
         }
         for (final Class<?> c : type.getInterfaces()) {

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=1811436&r1=1811435&r2=1811436&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  7 15:13:52 2017
@@ -149,6 +149,18 @@ public final class Resources extends Ind
         public static final short DuplicatedParameterName_4 = 16;
 
         /**
+         * Compound coordinate reference systems can not contain two 
{0,choice,1#horizontal|2#vertical}
+         * components.
+         */
+        public static final short DuplicatedSpatialComponents_1 = 76;
+
+        /**
+         * Compound coordinate reference systems should not contain 
ellipsoidal height. Use a
+         * three-dimensional {0,choice,0#geographic|1#projected} system 
instead.
+         */
+        public static final short EllipsoidalHeightNotAllowed_1 = 77;
+
+        /**
          * There is no factory for version {1} of “{0}” authority. Fallback on 
default version for
          * objects creation.
          */

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=1811436&r1=1811435&r2=1811436&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  7 15:13:52 2017
@@ -55,6 +55,8 @@ ColinearAxisDirections_2          = Axis
 CoordinateOperationNotFound_2     = Coordinate conversion of transformation 
from system \u201c{0}\u201d to \u201c{1}\u201d has not been found.
 DatumOriginShallBeDate            = Origin of temporal datum shall be a date.
 DuplicatedParameterName_4         = Name or alias for parameter 
\u201c{0}\u201d at index {1} conflict with name \u201c{2}\u201d at index {3}.
+DuplicatedSpatialComponents_1     = Compound coordinate reference systems can 
not contain two {0,choice,1#horizontal|2#vertical} components.
+EllipsoidalHeightNotAllowed_1     = Compound coordinate reference systems 
should not contain ellipsoidal height. Use a three-dimensional 
{0,choice,0#geographic|1#projected} system instead.
 IllegalAxisDirection_2            = Coordinate system of class \u2018{0}\u2019 
can not have axis in the {1} direction.
 IllegalOperationDimension_3       = Dimensions of \u201c{0}\u201d operation 
can not be ({1} \u2192 {2}).
 IllegalOperationForValueClass_1   = This operation can not be applied to 
values of class \u2018{0}\u2019.

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=1811436&r1=1811435&r2=1811436&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  7 15:13:52 2017
@@ -60,6 +60,8 @@ ColinearAxisDirections_2          = Les
 CoordinateOperationNotFound_2     = La conversion ou transformation des 
coordonn\u00e9es du syst\u00e8me \u00ab\u202f{0}\u202f\u00bb vers 
\u00ab\u202f{1}\u202f\u00bb n\u2019a pas \u00e9t\u00e9 trouv\u00e9e.
 DatumOriginShallBeDate            = L\u2019origine d\u2019un 
r\u00e9f\u00e9rentiel temporel doit \u00eatre une date.
 DuplicatedParameterName_4         = Le nom ou un alias pour le param\u00e8tre 
\u00ab\u202f{0}\u202f\u00bb \u00e0 l\u2019index {1} duplique le nom 
\u00ab\u202f{2}\u202f\u00bb \u00e0 l\u2019index {3}.
+DuplicatedSpatialComponents_1     = Un syst\u00e8me de r\u00e9f\u00e9rence des 
coordonn\u00e9es ne peut pas contenir deux composantes 
{0,choice,1#horizontales|2#verticales}.
+EllipsoidalHeightNotAllowed_1     = Un syst\u00e8me de r\u00e9f\u00e9rence des 
coordonn\u00e9es ne devrait pas contenir une hauteur ellipso\u00efdale. 
Utilisez plut\u00f4t un syst\u00e8me 
{0,choice,0#g\u00e9ographique|1#projet\u00e9} \u00e0 trois dimensions.
 IllegalAxisDirection_2            = Les syst\u00e8mes de coordonn\u00e9es de 
classe \u2018{0}\u2019 ne peuvent pas avoir d\u2019axe dans la direction 
\u00ab\u202f{1}\u202f\u00bb.
 IllegalOperationDimension_3       = Les dimensions de l\u2019op\u00e9ration 
\u00ab\u202f{0}\u202f\u00bb ne peuvent pas \u00eatre ({1} \u2192 {2}).
 IllegalOperationForValueClass_1   = Cette op\u00e9ration ne peut pas 
s\u2019appliquer aux valeurs de classe \u2018{0}\u2019.

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java?rev=1811436&r1=1811435&r2=1811436&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
 [UTF-8] Sat Oct  7 15:13:52 2017
@@ -35,6 +35,7 @@ import org.opengis.referencing.crs.Proje
 import org.opengis.referencing.crs.EngineeringCRS;
 import org.opengis.referencing.crs.VerticalCRS;
 import org.opengis.referencing.crs.TemporalCRS;
+import org.opengis.referencing.crs.ParametricCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.apache.sis.referencing.cs.AxesConvention;
@@ -42,6 +43,7 @@ import org.apache.sis.referencing.cs.Def
 import org.apache.sis.referencing.AbstractReferenceSystem;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.internal.metadata.WKTKeywords;
+import org.apache.sis.internal.referencing.Resources;
 import org.apache.sis.internal.referencing.WKTUtilities;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.util.UnmodifiableArrayList;
@@ -107,7 +109,7 @@ import org.apache.sis.io.wkt.Convention;
  * SIS factories and static constants.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.7
+ * @version 0.8
  *
  * @see 
org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createCompoundCRS(String)
  *
@@ -184,13 +186,58 @@ public class DefaultCompoundCRS extends
      *
      * @param  properties  the properties to be given to the coordinate 
reference system.
      * @param  components  the sequence of coordinate reference systems making 
this compound CRS.
+     * @throws IllegalArgumentException if the given array does not contain at 
least two components,
+     *         or if two consecutive components are a geographic CRS with an 
ellipsoidal height.
      *
      * @see 
org.apache.sis.referencing.factory.GeodeticObjectFactory#createCompoundCRS(Map, 
CoordinateReferenceSystem...)
      */
     public DefaultCompoundCRS(final Map<String,?> properties, final 
CoordinateReferenceSystem... components) {
         super(properties, createCoordinateSystem(properties, components));
         setComponents(Arrays.asList(components));
-        // 'singles' is computed by the above method call.
+        /*
+         * 'singles' is computed by the above method call. Now verify that we 
do not have an ellipsoidal
+         * height with a geographic or projected CRS (see 
https://issues.apache.org/jira/browse/SIS-303).
+         * Note that this is already be done if the given array does not 
contain nested CompoundCRS.
+         */
+        if (singles != this.components) {
+            verify(properties, singles.toArray(new SingleCRS[singles.size()]));
+        }
+    }
+
+    /**
+     * Verifies that the given array does not contain duplicated horizontal or 
vertical components.
+     * Verifies also that if there is an horizontal component, then there is 
no ellipsoidal height
+     * defined separately.
+     *
+     * @param  properties  the user-specified properties, for determining the 
locale of error messages.
+     * @param  components  the components to verify.
+     */
+    private static void verify(final Map<String,?> properties, final 
CoordinateReferenceSystem[] components) {
+        int allTypes = 0;
+        int isProjected = 0;                            // 0 for false, 1 for 
true.
+        boolean isEllipsoidalHeight = false;
+        for (final CoordinateReferenceSystem component : components) {
+            final int type;
+            if (component instanceof GeodeticCRS) {
+                type = 1;   // Must match the number used in 
Resources.Keys.DuplicatedSpatialComponents_1.
+            } else if (component instanceof ProjectedCRS) {
+                isProjected = 1;
+                type = 1;   // Intentionally same number than for 
GeographicCRS case.
+            } else if (component instanceof VerticalCRS) {
+                isEllipsoidalHeight = 
ReferencingUtilities.isEllipsoidalHeight(((VerticalCRS) component).getDatum());
+                type = 2;   // Must match the number used in 
Resources.Keys.DuplicatedSpatialComponents_1.
+            } else {
+                continue;   // Skip other types. In particular, we allow 2 
temporal CRS (used in meteorology).
+            }
+            if (allTypes == (allTypes |= type)) {
+                throw new 
IllegalArgumentException(Resources.forProperties(properties)
+                        
.getString(Resources.Keys.DuplicatedSpatialComponents_1, type));
+            }
+        }
+        if (isEllipsoidalHeight && ((allTypes & 1) != 0)) {
+            throw new 
IllegalArgumentException(Resources.forProperties(properties)
+                    .getString(Resources.Keys.EllipsoidalHeightNotAllowed_1, 
isProjected));
+        }
     }
 
     /**
@@ -204,6 +251,7 @@ public class DefaultCompoundCRS extends
             final CoordinateReferenceSystem[] components)
     {
         ArgumentChecks.ensureNonNull("components", components);
+        verify(properties, components);
         if (components.length < 2) {
             throw new 
IllegalArgumentException(Errors.getResources(properties).getString(
                     Errors.Keys.TooFewArguments_2, 2, components.length));
@@ -296,7 +344,6 @@ public class DefaultCompoundCRS extends
      *
      * @see #getComponents()
      */
-    @SuppressWarnings("SuspiciousToArrayCall")
     private void setComponents(final List<? extends CoordinateReferenceSystem> 
crs) {
         if (setSingleComponents(crs)) {
             components = singles;                           // Shares the same 
list.
@@ -407,7 +454,7 @@ public class DefaultCompoundCRS extends
                     return false;
                 }
                 case 1: {
-                    if (crs instanceof VerticalCRS) {   // TODO: accept also 
ParametricCRS here.
+                    if (crs instanceof VerticalCRS || crs instanceof 
ParametricCRS) {
                         state = 2; continue;    // Next CRS can only be 
temporal.
                     }
                     // Fallthrough (the current CRS may be temporal)

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java?rev=1811436&r1=1811435&r2=1811436&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
 [UTF-8] Sat Oct  7 15:13:52 2017
@@ -33,7 +33,6 @@ import org.opengis.metadata.Identifier;
 import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.parameter.ParameterValueGroup;
 import org.apache.sis.internal.metadata.AxisDirections;
-import org.apache.sis.internal.metadata.VerticalDatumTypes;
 import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.referencing.provider.Geographic2Dto3D;
@@ -629,7 +628,7 @@ public class CoordinateOperationFinder e
         VerticalCRS heightCRS = targetCRS;      // First candidate, will be 
replaced if it doesn't fit.
         VerticalCS  heightCS  = heightCRS.getCoordinateSystem();
         if (equalsIgnoreMetadata(heightCS.getAxis(0), expectedAxis)) {
-            isEllipsoidalHeight = 
VerticalDatumTypes.ELLIPSOIDAL.equals(heightCRS.getDatum().getVerticalDatumType());
+            isEllipsoidalHeight = 
ReferencingUtilities.isEllipsoidalHeight(heightCRS.getDatum());
         } else {
             heightCRS = CommonCRS.Vertical.ELLIPSOIDAL.crs();
             heightCS  = heightCRS.getCoordinateSystem();

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java?rev=1811436&r1=1811435&r2=1811436&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ReferencingUtilitiesTest.java
 [UTF-8] Sat Oct  7 15:13:52 2017
@@ -21,6 +21,7 @@ import org.opengis.referencing.cs.*;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.datum.PrimeMeridian;
+import org.opengis.referencing.datum.VerticalDatum;
 import org.opengis.referencing.IdentifiedObject;
 import org.apache.sis.referencing.datum.HardCodedDatum;
 import org.apache.sis.referencing.crs.HardCodedCRS;
@@ -56,6 +57,14 @@ public final strictfp class ReferencingU
     }
 
     /**
+     * Tests {@link ReferencingUtilities#isEllipsoidalHeight(VerticalDatum)}.
+     */
+    @Test
+    public void testEllipsoidalHeight() {
+        assertTrue(isEllipsoidalHeight(HardCodedDatum.ELLIPSOID));
+    }
+
+    /**
      * Asserts that normalization of the given CRS produces {@link 
HardCodedCRS#WGS84} (ignoring metadata).
      *
      * @param  message         the message to show in case of failure.
@@ -110,7 +119,7 @@ public final strictfp class ReferencingU
         assertEquals("cylindricalCS",    
toPropertyName(CoordinateSystem.class, CylindricalCS   .class).toString());
         assertEquals("ellipsoidalCS",    
toPropertyName(CoordinateSystem.class, EllipsoidalCS   .class).toString());
         assertEquals("linearCS",         
toPropertyName(CoordinateSystem.class, LinearCS        .class).toString());
-//      assertEquals("parametricCS",     
toPropertyName(CoordinateSystem.class, ParametricCS    .class).toString());
+        assertEquals("parametricCS",     
toPropertyName(CoordinateSystem.class, ParametricCS    .class).toString());
         assertEquals("polarCS",          
toPropertyName(CoordinateSystem.class, PolarCS         .class).toString());
         assertEquals("sphericalCS",      
toPropertyName(CoordinateSystem.class, SphericalCS     .class).toString());
         assertEquals("timeCS",           
toPropertyName(CoordinateSystem.class, TimeCS          .class).toString());

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.java?rev=1811436&r1=1811435&r2=1811436&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.java
 [UTF-8] Sat Oct  7 15:13:52 2017
@@ -17,6 +17,9 @@
 package org.apache.sis.referencing.crs;
 
 import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Locale;
 import javax.xml.bind.JAXBException;
 import org.opengis.test.Validators;
 import org.opengis.referencing.cs.AxisDirection;
@@ -33,7 +36,7 @@ import org.apache.sis.test.XMLTestCase;
 import org.junit.Test;
 
 import static java.util.Collections.singletonMap;
-import static org.opengis.referencing.cs.CoordinateSystem.NAME_KEY;
+import static org.opengis.referencing.crs.CompoundCRS.NAME_KEY;
 import static org.apache.sis.test.ReferencingAssert.*;
 
 
@@ -41,7 +44,7 @@ import static org.apache.sis.test.Refere
  * Tests the {@link DefaultCompoundCRS} class.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 0.8
  * @since   0.4
  * @module
  */
@@ -67,6 +70,64 @@ public final strictfp class DefaultCompo
     private static final String XML_FILE = "CompoundCRS.xml";
 
     /**
+     * Verifies that we do not allow construction with a duplicated horizontal 
or vertical component.
+     *
+     * @since 0.8
+     */
+    @Test
+    @SuppressWarnings("ResultOfObjectAllocationIgnored")
+    public void testDuplicatedComponent() {
+        final Map<String,Object> properties = new HashMap<>(4);
+        assertNull(properties.put(DefaultCompoundCRS.LOCALE_KEY, 
Locale.ENGLISH));
+        assertNull(properties.put(DefaultCompoundCRS.NAME_KEY,   "3D + 
illegal"));
+        try {
+            new DefaultCompoundCRS(properties, HardCodedCRS.WGS84, HEIGHT, 
HardCodedCRS.SPHERE);
+            fail("Should not allow construction with two horizontal 
components.");
+        } catch (IllegalArgumentException e) {
+            assertEquals("Compound coordinate reference systems can not 
contain two horizontal components.", e.getMessage());
+        }
+        /*
+         * Try again with duplicated vertical components, opportunistically
+         * testing localization in a different language.
+         */
+        properties.put(DefaultCompoundCRS.LOCALE_KEY, Locale.FRENCH);
+        try {
+            new DefaultCompoundCRS(properties, HardCodedCRS.WGS84, HEIGHT, 
HardCodedCRS.ELLIPSOIDAL_HEIGHT);
+            fail("Should not allow construction with two vertical 
components.");
+        } catch (IllegalArgumentException e) {
+            assertEquals("Un système de référence des coordonnées ne peut pas 
contenir deux composantes verticales.", e.getMessage());
+        }
+    }
+
+    /**
+     * Verifies that horizontal CRS + ellipsoidal height is disallowed.
+     *
+     * @see <a href="https://issues.apache.org/jira/browse/SIS-303";>SIS-303</a>
+     *
+     * @since 0.8
+     */
+    @Test
+    @SuppressWarnings("ResultOfObjectAllocationIgnored")
+    public void testEllipsoidalHeight() {
+        final Map<String,Object> properties = new HashMap<>(4);
+        assertNull(properties.put(DefaultCompoundCRS.LOCALE_KEY, 
Locale.ENGLISH));
+        assertNull(properties.put(DefaultCompoundCRS.NAME_KEY,   "3D"));
+        try {
+            new DefaultCompoundCRS(properties, HardCodedCRS.WGS84, 
HardCodedCRS.ELLIPSOIDAL_HEIGHT);
+            fail("Should not allow construction with ellipsoidal height.");
+        } catch (IllegalArgumentException e) {
+            assertEquals("Compound coordinate reference systems should not 
contain ellipsoidal height. "
+                    + "Use a three-dimensional geographic system instead.", 
e.getMessage());
+        }
+        /*
+         * We allow an ellipsoidal height if there is no horizontal CRS.
+         * This is a departure from ISO 19111.
+         */
+        final DefaultCompoundCRS crs = new DefaultCompoundCRS(properties, 
HardCodedCRS.ELLIPSOIDAL_HEIGHT, TIME);
+        assertAxisDirectionsEqual("CompoundCRS", crs.getCoordinateSystem(), 
AxisDirection.UP, AxisDirection.FUTURE);
+    }
+
+    /**
      * Tests construction and serialization of a {@link DefaultCompoundCRS}.
      */
     @Test

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=1811436&r1=1811435&r2=1811436&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  7 15:13:52 2017
@@ -814,7 +814,7 @@ public final strictfp class CoordinateOp
                 "  Id[“EPSG”, “3395”]]");
 
         CoordinateReferenceSystem sourceCRS = targetCRS;
-        sourceCRS = compound("Mercator 3D", sourceCRS, 
CommonCRS.Vertical.ELLIPSOIDAL.crs());
+        sourceCRS = compound("Mercator 3D", sourceCRS, 
CommonCRS.Vertical.MEAN_SEA_LEVEL.crs());
         sourceCRS = compound("Mercator 4D", sourceCRS, 
CommonCRS.Temporal.MODIFIED_JULIAN.crs());
 
         final CoordinateOperation operation = 
finder.createOperation(sourceCRS, targetCRS);

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactoryTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactoryTest.java?rev=1811436&r1=1811435&r2=1811436&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactoryTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactoryTest.java
 [UTF-8] Sat Oct  7 15:13:52 2017
@@ -215,7 +215,7 @@ public final strictfp class DefaultCoord
                 "  VerticalCRS[“Ellipsoidal height”,\n" +
                 "    VerticalDatum[“Ellipsoid”],\n" +
                 "    CS[vertical, 1],\n" +
-                "      Axis[“Ellipsoidal height (h)”, up],\n" +
+                "      Axis[“Geoidal height (H)”, up],\n" +
                 "      Unit[“metre”, 1]],\n" +
                 "  TimeCRS[“Modified Julian”,\n" +
                 "    TimeDatum[“Modified Julian”, 
TimeOrigin[1858-11-17T00:00:00.0Z]],\n" +


Reply via email to