Author: desruisseaux
Date: Mon Oct  9 09:31:41 2017
New Revision: 1811543

URL: http://svn.apache.org/viewvc?rev=1811543&view=rev
Log:
Complete support of three-dimensional projected CRS.

Added:
    
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/EllipsoidalHeightCombiner.java
      - copied, changed from r1811538, 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CompoundCRSBuilder.java
   (with props)
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/metadata/EllipsoidalHeightCombinerTest.java
      - copied, changed from r1811538, 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ServicesForMetadataTest.java
Modified:
    
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java
    
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ServicesForMetadataTest.java
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java

Copied: 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/EllipsoidalHeightCombiner.java
 (from r1811538, 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java)
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/EllipsoidalHeightCombiner.java?p2=sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/EllipsoidalHeightCombiner.java&p1=sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java&r1=1811538&r2=1811543&rev=1811543&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/EllipsoidalHeightCombiner.java
 [UTF-8] Mon Oct  9 09:31:41 2017
@@ -17,443 +17,99 @@
 package org.apache.sis.internal.metadata;
 
 import java.util.Map;
-import java.util.Collections;
-import java.util.Locale;
-import java.util.TimeZone;
-import java.text.Format;
-import javax.measure.Unit;
-import javax.measure.quantity.Length;
-import org.opengis.geometry.Envelope;
-import org.opengis.geometry.DirectPosition;
-import org.opengis.parameter.ParameterDescriptor;
-import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.crs.CRSFactory;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.opengis.referencing.crs.SingleCRS;
-import org.opengis.referencing.crs.DerivedCRS;
 import org.opengis.referencing.crs.GeodeticCRS;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.VerticalCRS;
 import org.opengis.referencing.crs.ProjectedCRS;
-import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.cs.CSFactory;
 import org.opengis.referencing.cs.CartesianCS;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.opengis.referencing.cs.EllipsoidalCS;
-import org.opengis.referencing.datum.DatumFactory;
-import org.opengis.referencing.datum.PrimeMeridian;
 import org.opengis.referencing.datum.VerticalDatum;
-import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
+import org.opengis.referencing.operation.Conversion;
 import org.opengis.referencing.operation.CoordinateOperationFactory;
-import org.opengis.referencing.operation.OperationMethod;
-import org.opengis.referencing.operation.SingleOperation;
-import org.opengis.referencing.operation.TransformException;
 import org.opengis.util.FactoryException;
-import org.apache.sis.metadata.iso.extent.DefaultExtent;
-import org.apache.sis.metadata.iso.extent.DefaultVerticalExtent;
-import org.apache.sis.metadata.iso.extent.DefaultTemporalExtent;
-import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
-import org.apache.sis.metadata.iso.extent.DefaultSpatialTemporalExtent;
-import org.apache.sis.internal.system.DefaultFactories;
-import org.apache.sis.internal.system.OptionalDependency;
-import org.apache.sis.internal.system.Modules;
-import org.apache.sis.io.wkt.FormattableObject;
 import org.apache.sis.util.ArraysExt;
-import org.apache.sis.util.Deprecable;
 
 
 /**
- * Provides access to services defined in the {@code "sis-referencing"} module.
- * This class searches for the {@link 
org.apache.sis.internal.referencing.ServicesForMetadata}
- * implementation using Java reflection.
- *
- * <p>This class also opportunistically defines some methods and constants 
related to
- * <cite>"referencing by coordinates"</cite> but needed by metadata.</p>
+ * A class in charges of combining two-dimensional geographic or projected CRS 
with an ellipsoidal height
+ * into a three-dimensional CRS.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @version 0.8
- * @since   0.3
+ * @since   0.8
  * @module
  */
-public class ReferencingServices extends OptionalDependency {
-    /**
-     * The length of one nautical mile, which is {@value} metres.
-     */
-    public static final double NAUTICAL_MILE = 1852;
-
-    /**
-     * The GRS80 {@linkplain 
org.apache.sis.referencing.datum.DefaultEllipsoid#getAuthalicRadius() authalic 
radius},
-     * which is {@value} metres.
-     */
-    public static final double AUTHALIC_RADIUS = 6371007;
-
-    /**
-     * The {@link 
org.apache.sis.referencing.datum.DefaultGeodeticDatum#BURSA_WOLF_KEY} value.
-     */
-    public static final String BURSA_WOLF_KEY = "bursaWolf";
-
-    /**
-     * The key for specifying explicitely the value to be returned by
-     * {@link 
org.apache.sis.referencing.operation.DefaultConversion#getParameterValues()}.
-     * It is usually not necessary to specify those parameters because they 
are inferred either from
-     * the {@link MathTransform}, or specified explicitely in a {@code 
DefiningConversion}. However
-     * there is a few cases, for example the Molodenski transform, where none 
of the above can apply,
-     * because SIS implements those operations as a concatenation of math 
transforms, and such
-     * concatenations do not have {@link 
org.opengis.parameter.ParameterValueGroup}.
-     */
-    public static final String PARAMETERS_KEY = "parameters";
-
-    /**
-     * The key for specifying the base type of the coordinate operation to 
create. This optional entry
-     * is used by {@code 
DefaultCoordinateOperationFactory.createSingleOperation(…)}. Apache SIS tries
-     * to infer this value automatically, but this entry may help SIS to 
perform a better choice in
-     * some cases. For example an "Affine" operation can be both a conversion 
or a transformation
-     * (the later is used in datum shift in geocentric coordinates).
-     */
-    public static final String OPERATION_TYPE_KEY = "operationType";
-
-    /**
-     * The key for specifying a {@link MathTransformFactory} instance to use 
for geodetic object constructions.
-     * This is usually not needed for CRS construction, except in the special 
case of a derived CRS created
-     * from a defining conversion.
-     */
-    public static final String MT_FACTORY = "mtFactory";
-
-    /**
-     * The key for specifying a {@link CRSFactory} instance to use for 
geodetic object constructions.
-     */
-    public static final String CRS_FACTORY = "crsFactory";
-
-    /**
-     * The key for specifying a {@link CSFactory} instance to use for geodetic 
object constructions.
-     */
-    public static final String CS_FACTORY = "csFactory";
-
-    /**
-     * The key for specifying a {@link DatumFactory} instance to use for 
geodetic object constructions.
-     */
-    public static final String DATUM_FACTORY = "datumFactory";
-
-    /**
-     * The services, fetched when first needed.
-     */
-    private static volatile ReferencingServices instance;
-
-    /**
-     * For subclass only. This constructor registers this instance as a
-     * {@link org.apache.sis.internal.system.SystemListener} in order to
-     * force a new {@code ReferencingServices} lookup if the classpath changes.
-     */
-    protected ReferencingServices() {
-        super(Modules.METADATA, "sis-referencing");
-    }
-
-    /**
-     * Invoked when the classpath changed. Resets the {@link #instance} to 
{@code null}
-     * in order to force the next call to {@link #getInstance()} to fetch a 
new one,
-     * which may be different.
-     */
-    @Override
-    protected final void classpathChanged() {
-        synchronized (ReferencingServices.class) {
-            super.classpathChanged();
-            instance = null;
-        }
-    }
-
-    /**
-     * Returns the singleton instance.
-     *
-     * @return the singleton instance.
-     */
-    @SuppressWarnings("DoubleCheckedLocking")
-    public static ReferencingServices getInstance() {
-        ReferencingServices c = instance;
-        if (c == null) {
-            synchronized (ReferencingServices.class) {
-                c = instance;
-                if (c == null) {
-                    /*
-                     * Double-checked locking: okay since Java 5 provided that 
the 'instance' field is volatile.
-                     * In the particular case of this class, the intend is to 
ensure that SystemListener.add(…)
-                     * is invoked only once.
-                     */
-                    c = getInstance(ReferencingServices.class, 
Modules.METADATA, "sis-referencing",
-                            
"org.apache.sis.internal.referencing.ServicesForMetadata");
-                    if (c == null) {
-                        c = new ReferencingServices();
-                    }
-                    instance = c;
-                }
-            }
-        }
-        return c;
-    }
-
-
-
-
-    
///////////////////////////////////////////////////////////////////////////////////////
-    ////                                                                       
        ////
-    ////                        SERVICES FOR ISO 19115 METADATA                
        ////
-    ////                                                                       
        ////
-    
///////////////////////////////////////////////////////////////////////////////////////
-
-    /**
-     * Sets a geographic bounding box from the specified envelope.
-     * If the envelope contains a CRS which is not geographic, then the 
bounding box will be transformed
-     * to a geographic CRS (without datum shift if possible). Otherwise, the 
envelope is assumed already
-     * in a geographic CRS using (<var>longitude</var>, <var>latitude</var>) 
axis order.
-     *
-     * @param  envelope  the source envelope.
-     * @param  target    the target bounding box.
-     * @throws TransformException if the given envelope can't be transformed.
-     * @throws UnsupportedOperationException if the {@code "sis-referencing"} 
module has not been found on the classpath.
-     */
-    public void setBounds(Envelope envelope, DefaultGeographicBoundingBox 
target) throws TransformException {
-        throw moduleNotFound();
-    }
-
-    /**
-     * Sets a vertical extent with the value inferred from the given envelope.
-     * Only the vertical ordinates are extracted; all other ordinates are 
ignored.
-     *
-     * @param  envelope  the source envelope.
-     * @param  target    the target vertical extent.
-     * @throws TransformException if no vertical component can be extracted 
from the given envelope.
-     * @throws UnsupportedOperationException if the {@code "sis-referencing"} 
module has not been found on the classpath.
-     */
-    public void setBounds(Envelope envelope, DefaultVerticalExtent target) 
throws TransformException {
-        throw moduleNotFound();
-    }
-
-    /**
-     * Sets a temporal extent with the value inferred from the given envelope.
-     * Only the temporal ordinates are extracted; all other ordinates are 
ignored.
-     *
-     * @param  envelope  the source envelope.
-     * @param  target    the target temporal extent.
-     * @throws TransformException if no temporal component can be extracted 
from the given envelope.
-     * @throws UnsupportedOperationException if the {@code "sis-referencing"} 
module has not been found on the classpath.
-     */
-    public void setBounds(Envelope envelope, DefaultTemporalExtent target) 
throws TransformException {
-        throw moduleNotFound();
-    }
-
-    /**
-     * Sets the geographic, vertical and temporal extents with the values 
inferred from the given envelope.
-     * If the given {@code target} has more geographic or vertical extents 
than needed (0 or 1), then the
-     * extraneous extents are removed.
-     *
-     * <p>Behavior regarding missing dimensions:</p>
-     * <ul>
-     *   <li>If the given envelope has no horizontal component, then all 
geographic extents are removed
-     *       from the given {@code target}. Non-geographic extents (e.g. 
descriptions and polygons) are
-     *       left unchanged.</li>
-     *   <li>If the given envelope has no vertical component, then the 
vertical extent is set to {@code null}.</li>
-     *   <li>If the given envelope has no temporal component, then the 
temporal extent is set to {@code null}.</li>
-     * </ul>
-     *
-     * @param  envelope  the source envelope.
-     * @param  target    the target spatio-temporal extent.
-     * @throws TransformException if no temporal component can be extracted 
from the given envelope.
-     * @throws UnsupportedOperationException if the {@code "sis-referencing"} 
module has not been found on the classpath.
-     */
-    public void setBounds(Envelope envelope, DefaultSpatialTemporalExtent 
target) throws TransformException {
-        throw moduleNotFound();
-    }
-
-    /**
-     * Initializes a horizontal, vertical and temporal extent with the values 
inferred from the given envelope.
-     *
-     * @param  envelope  the source envelope.
-     * @param  target    the target extent.
-     * @throws TransformException if a coordinate transformation was required 
and failed.
-     * @throws UnsupportedOperationException if the {@code "sis-referencing"} 
module has not been found on the classpath.
-     */
-    public void addElements(Envelope envelope, DefaultExtent target) throws 
TransformException {
-        throw moduleNotFound();
-    }
-
-    /**
-     * Creates a two-dimensional geographic position associated to the default 
geographic CRS.
-     * Axis order is (longitude, latitude).
-     *
-     * @param  λ  the longitude value.
-     * @param  φ  the latitude value.
-     * @return the direct position for the given geographic coordinate.
-     *
-     * @since 0.8
-     */
-    public DirectPosition geographic(final double λ, final double φ) {
-        throw moduleNotFound();
-    }
-
-
-
-
-    
///////////////////////////////////////////////////////////////////////////////////////
-    ////                                                                       
        ////
-    ////                          SERVICES FOR WKT FORMATTING                  
        ////
-    ////                                                                       
        ////
-    
///////////////////////////////////////////////////////////////////////////////////////
-
-    /**
-     * Returns a fully implemented parameter descriptor.
-     *
-     * @param  parameter  a partially implemented parameter descriptor, or 
{@code null}.
-     * @return a fully implemented parameter descriptor, or {@code null} if 
the given argument was null.
-     * @throws UnsupportedOperationException if the {@code "sis-referencing"} 
module has not been found on the classpath.
-     *
-     * @since 0.5
-     */
-    public ParameterDescriptor<?> toImplementation(ParameterDescriptor<?> 
parameter) {
-        throw moduleNotFound();
-    }
-
-    /**
-     * Converts the given object in a {@code FormattableObject} instance.
-     *
-     * @param  object  the object to wrap.
-     * @return the given object converted to a {@code FormattableObject} 
instance.
-     * @throws UnsupportedOperationException if the {@code "sis-referencing"} 
module has not been found on the classpath.
-     *
-     * @see 
org.apache.sis.referencing.AbstractIdentifiedObject#castOrCopy(IdentifiedObject)
-     *
-     * @since 0.4
-     */
-    public FormattableObject toFormattableObject(IdentifiedObject object) {
-        throw moduleNotFound();
-    }
-
+public class EllipsoidalHeightCombiner {
     /**
-     * Converts the given object in a {@code FormattableObject} instance. 
Callers should verify that the given
-     * object is not already an instance of {@code FormattableObject} before 
to invoke this method. This method
-     * returns {@code null} if it can not convert the object.
-     *
-     * @param  object  the object to wrap.
-     * @param  internal {@code true} if the formatting convention is {@code 
Convention.INTERNAL}.
-     * @return the given object converted to a {@code FormattableObject} 
instance, or {@code null}.
-     * @throws UnsupportedOperationException if the {@code "sis-referencing"} 
module has not been found on the classpath.
-     *
-     * @since 0.6
+     * The kind of factory initialized by {@link #initialize(int)}.
      */
-    public FormattableObject toFormattableObject(MathTransform object, boolean 
internal) {
-        throw moduleNotFound();
-    }
-
-
-
-
-    
///////////////////////////////////////////////////////////////////////////////////////
-    ////                                                                       
        ////
-    ////                           SERVICES FOR WKT PARSING                    
        ////
-    ////                                                                       
        ////
-    
///////////////////////////////////////////////////////////////////////////////////////
+    protected static final int CRS=1, CS=2, OPERATION=4;
 
     /**
-     * Returns a coordinate reference system for heights above the mean seal 
level.
-     *
-     * @return the "Mean Seal Level (MSL) height" coordinate reference system, 
or {@code null}.
-     *
-     * @since 0.6
+     * The factory to use for creating compound or three-dimensional 
geographic CRS.
      */
-    public VerticalCRS getMSLH() {
-        throw moduleNotFound();
-    }
+    protected CRSFactory crsFactory;
 
     /**
-     * Returns the Greenwich prime meridian.
-     *
-     * @return the Greenwich prime meridian.
-     *
-     * @since 0.6
+     * The factory to use for creating three-dimensional ellipsoidal CS, if 
needed.
      */
-    public PrimeMeridian getGreenwich() {
-        throw moduleNotFound();
-    }
+    protected CSFactory csFactory;
 
     /**
-     * Returns the coordinate system of a geocentric CRS using axes in the 
given unit of measurement.
-     *
-     * @param  unit  the unit of measurement for the geocentric CRS axes.
-     * @return the coordinate system for a geocentric CRS with axes using the 
given unit of measurement.
-     *
-     * @since 0.6
+     * The factory to use for creating defining conversions, if needed.
      */
-    public CartesianCS getGeocentricCS(final Unit<Length> unit) {
-        throw moduleNotFound();
-    }
+    protected CoordinateOperationFactory opFactory;
 
     /**
-     * Converts a geocentric coordinate system from the legacy WKT 1 to the 
current ISO 19111 standard.
-     * This method replaces the (Other, East, North) directions by (Geocentric 
X, Geocentric Y, Geocentric Z).
-     *
-     * @param  cs  the geocentric coordinate system to upgrade.
-     * @return the upgraded coordinate system, or {@code cs} if this method 
can not upgrade the given CS.
-     *
-     * @since 0.6
+     * Creates a new combiner with no initial factory.
+     * Subclasses must override the {@link #initialize(int)} method.
      */
-    public CartesianCS upgradeGeocentricCS(final CartesianCS cs) {
-        return cs;
+    protected EllipsoidalHeightCombiner() {
     }
 
     /**
-     * Creates a coordinate system of unknown type. This method is used during 
parsing of WKT version 1,
-     * since that legacy format did not specified any information about the 
coordinate system in use.
-     * This method should not need to be invoked for parsing WKT version 2.
-     *
-     * @param  properties  the coordinate system name, and optionally other 
properties.
-     * @param  axes        the axes of the unknown coordinate system.
-     * @return an "abstract" coordinate system using the given axes.
+     * Creates a new combiner which will use the given factories.
+     * Any factory given in argument may be {@code null} if lazy instantiation 
is desired.
      *
-     * @since 0.6
+     * @param  crsFactory  the factory to use for creating compound or 
three-dimensional geographic CRS.
+     * @param  csFactory   the factory to use for creating three-dimensional 
ellipsoidal CS, if needed.
+     * @param  opFactory   the factory to use for creating defining 
conversions, if needed.
      */
-    public CoordinateSystem createAbstractCS(final Map<String,?> properties, 
final CoordinateSystemAxis[] axes) {
-        throw moduleNotFound();
+    public EllipsoidalHeightCombiner(final CRSFactory crsFactory, final 
CSFactory csFactory,
+                                     final CoordinateOperationFactory 
opFactory)
+    {
+        this.crsFactory = crsFactory;
+        this.csFactory  = csFactory;
+        this.opFactory  = opFactory;
     }
 
     /**
-     * Creates a derived CRS from the information found in a WKT 1 {@code 
FITTED_CS} element.
-     * This coordinate system can not be easily constructed from the 
information provided by the WKT 1 format.
-     * Note that this method is needed only for WKT 1 parsing, since WKT 
provides enough information for using
-     * the standard factories.
-     *
-     * @param  properties     the properties to be given to the {@code 
DerivedCRS} and {@code Conversion} objects.
-     * @param  baseCRS        coordinate reference system to base the derived 
CRS on.
-     * @param  method         the coordinate operation method (mandatory in 
all cases).
-     * @param  baseToDerived  transform from positions in the base CRS to 
positions in this target CRS.
-     * @param  derivedCS      the coordinate system for the derived CRS.
-     * @return the newly created derived CRS, potentially implementing an 
additional CRS interface.
+     * Initializes the factory identified by the given code. This is used for 
lazy initialization if any factory given
+     * to the constructor was null. In such case, subclass must override. If 
the same {@code EllipsoidalHeightCombiner}
+     * instance is used more than once, than it is subclass responsibility to 
verify that the {@link #crsFactory},
+     * {@link #csFactory} or {@link #opFactory} field has not already been set.
      *
-     * @since 0.6
+     * @param  factoryTypes  a bitwise combination of {@link #CRS}, {@link 
#CS} and {@link #OPERATION}.
      */
-    public DerivedCRS createDerivedCRS(final Map<String,?>    properties,
-                                       final SingleCRS        baseCRS,
-                                       final OperationMethod  method,
-                                       final MathTransform    baseToDerived,
-                                       final CoordinateSystem derivedCS)
-    {
-        throw moduleNotFound();
+    protected void initialize(final int factoryTypes) {
     }
 
     /**
      * Creates a compound CRS, but we special processing for (two-dimensional 
Geographic + ellipsoidal heights) tupples.
      * If any such tupple is found, a three-dimensional geographic CRS is 
created instead than the compound CRS.
      *
-     * @param  crsFactory  the factory to use for creating compound or 
three-dimensional geographic CRS.
-     * @param  csFactory   the factory to use for creating three-dimensional 
ellipsoidal CS, if needed.
      * @param  properties  name and other properties to give to the new object.
      * @param  components  ordered array of {@code CoordinateReferenceSystem} 
objects.
      * @return the coordinate reference system for the given properties.
      * @throws FactoryException if the object creation failed.
-     *
-     * @since 0.7
      */
-    public final CoordinateReferenceSystem createCompoundCRS(final CRSFactory 
crsFactory, final CSFactory csFactory,
-            final Map<String,?> properties, CoordinateReferenceSystem... 
components) throws FactoryException
+    public final CoordinateReferenceSystem createCompoundCRS(final 
Map<String,?> properties,
+            CoordinateReferenceSystem... components) throws FactoryException
     {
         for (int i=0; i<components.length; i++) {
             final CoordinateReferenceSystem vertical = components[i];
@@ -484,19 +140,30 @@ public class ReferencingServices extends
                     axes[axisPosition++   ] = cs.getAxis(0);
                     axes[axisPosition++   ] = cs.getAxis(1);
                     axes[axisPosition %= 3] = 
vertical.getCoordinateSystem().getAxis(0);
-                    final Map<String,?> csProps = getProperties(cs, false);
-                    final Map<String,?> crsProps = (components.length == 2) ? 
properties : getProperties(crs, false);
+                    final ReferencingServices referencing = 
ReferencingServices.getInstance();
+                    final Map<String,?> csProps = 
referencing.getProperties(cs, false);
+                    final Map<String,?> crsProps = (components.length == 2) ? 
properties : referencing.getProperties(crs, false);
                     if (crs instanceof GeodeticCRS) {
+                        initialize(CS | CRS);
                         cs = csFactory.createEllipsoidalCS(csProps, axes[0], 
axes[1], axes[2]);
                         crs = crsFactory.createGeographicCRS(crsProps, 
((GeodeticCRS) crs).getDatum(), (EllipsoidalCS) cs);
                     } else {
+                        initialize(CS | CRS | OPERATION);
                         final ProjectedCRS proj = (ProjectedCRS) crs;
                         GeographicCRS base = proj.getBaseCRS();
                         if (base.getCoordinateSystem().getDimension() == 2) {
-                            base = (GeographicCRS) 
createCompoundCRS(crsFactory, csFactory, getProperties(base, false), base, 
vertical);
+                            base = (GeographicCRS) 
createCompoundCRS(referencing.getProperties(base, false), base, vertical);
                         }
+                        /*
+                         * In Apache SIS implementation, the Conversion 
contains the source and target CRS together with
+                         * a MathTransform2D. We need to recreate the same 
conversion, but without CRS and MathTransform
+                         * for letting SIS create or associate new ones, which 
will be three-dimensional now.
+                         */
+                        Conversion fromBase = proj.getConversionFromBase();
+                        fromBase = 
opFactory.createDefiningConversion(referencing.getProperties(fromBase, true),
+                                    fromBase.getMethod(), 
fromBase.getParameterValues());
                         cs = csFactory.createCartesianCS(csProps, axes[0], 
axes[1], axes[2]);
-                        crs = crsFactory.createProjectedCRS(crsProps, base, 
proj.getConversionFromBase(), (CartesianCS) cs);
+                        crs = crsFactory.createProjectedCRS(crsProps, base, 
fromBase, (CartesianCS) cs);
                     }
                     /*
                      * Remove the VerticalCRS and store the three-dimensional 
GeographicCRS in place of the previous
@@ -512,7 +179,7 @@ public class ReferencingServices extends
         switch (components.length) {
             case 0:  return null;
             case 1:  return components[0];
-            default: return crsFactory.createCompoundCRS(properties, 
components);
+            default: initialize(CRS); return 
crsFactory.createCompoundCRS(properties, components);
         }
     }
 
@@ -537,184 +204,4 @@ public class ReferencingServices extends
         }
         return null;
     }
-
-    /**
-     * Creates a format for {@link DirectPosition} instances.
-     *
-     * @param  locale    the locale for the new {@code Format}, or {@code 
null} for {@code Locale.ROOT}.
-     * @param  timezone  the timezone, or {@code null} for UTC.
-     * @return a {@link org.apache.sis.geometry.CoordinateFormat}.
-     *
-     * @since 0.8
-     */
-    public Format createCoordinateFormat(final Locale locale, final TimeZone 
timezone) {
-        throw moduleNotFound();
-    }
-
-    /**
-     * Returns an axis direction from a pole along a meridian.
-     * The given meridian is usually, but not necessarily, relative to the 
Greenwich meridian.
-     *
-     * @param  baseDirection  the base direction, which must be {@link 
AxisDirection#NORTH} or {@link AxisDirection#SOUTH}.
-     * @param  meridian       the meridian in degrees, relative to a 
unspecified (usually Greenwich) prime meridian.
-     *                        Meridians in the East hemisphere are positive 
and meridians in the West hemisphere are negative.
-     * @return the axis direction along the given meridian.
-     *
-     * @since 0.6
-     */
-    public AxisDirection directionAlongMeridian(final AxisDirection 
baseDirection, final double meridian) {
-        throw moduleNotFound();
-    }
-
-    /**
-     * Creates the {@code TOWGS84} element during parsing of a WKT version 1. 
This is an optional operation:
-     * this method is allowed to return {@code null} if the "sis-referencing" 
module is not in the classpath.
-     *
-     * @param  values  the 7 Bursa-Wolf parameter values.
-     * @return the {@link 
org.apache.sis.referencing.datum.BursaWolfParameters}, or {@code null}.
-     *
-     * @since 0.6
-     */
-    public Object createToWGS84(final double[] values) {
-        return null;
-    }
-
-    /**
-     * Creates a single operation from the given properties.
-     * This method is provided here because not yet available in GeoAPI 
interfaces.
-     *
-     * @param  properties        the properties to be given to the identified 
object.
-     * @param  sourceCRS         the source CRS.
-     * @param  targetCRS         the target CRS.
-     * @param  interpolationCRS  the CRS of additional coordinates needed for 
the operation, or {@code null} if none.
-     * @param  method            the coordinate operation method (mandatory in 
all cases).
-     * @param  factory           the factory to use.
-     * @return the coordinate operation created from the given arguments.
-     * @throws FactoryException if the object creation failed.
-     *
-     * @since 0.6
-     */
-    public SingleOperation createSingleOperation(
-            final Map<String,?>              properties,
-            final CoordinateReferenceSystem  sourceCRS,
-            final CoordinateReferenceSystem  targetCRS,
-            final CoordinateReferenceSystem  interpolationCRS,
-            final OperationMethod            method,
-            final CoordinateOperationFactory factory) throws FactoryException
-    {
-        throw moduleNotFound();
-    }
-
-    /**
-     * Returns the coordinate operation factory to use for the given 
properties and math transform factory.
-     * If the given properties are empty and the {@code mtFactory} is the 
system default, then this method
-     * returns the system default {@code CoordinateOperationFactory} instead 
of creating a new one.
-     *
-     * @param  properties  the default properties.
-     * @param  mtFactory   the math transform factory to use.
-     * @param  crsFactory  the factory to use if the operation factory needs 
to create CRS for intermediate steps.
-     * @param  csFactory   the factory to use if the operation factory needs 
to create CS for intermediate steps.
-     * @return the coordinate operation factory to use.
-     *
-     * @since 0.7
-     */
-    public CoordinateOperationFactory 
getCoordinateOperationFactory(Map<String,?> properties,
-            final MathTransformFactory mtFactory, final CRSFactory crsFactory, 
final CSFactory csFactory)
-    {
-        /*
-         * The check for 'properties' and 'mtFactory' is performed by the 
ServicesForMetadata subclass. If this code is
-         * executed, this means that the "sis-referencing" module is not on 
the classpath, in which case we do not know
-         * how to pass the 'properties' and 'mtFactory' arguments to the 
foreigner CoordinateOperationFactory anyway.
-         */
-        final CoordinateOperationFactory factory = 
DefaultFactories.forClass(CoordinateOperationFactory.class);
-        if (factory != null) {
-            return factory;
-        } else {
-            throw moduleNotFound();
-        }
-    }
-
-    /**
-     * Returns the properties of the given object.
-     *
-     * @param  object  the object from which to get the properties.
-     * @param  keepId  {@code true} for preserving the identifiers, {@code 
false} for discarding them.
-     * @return the properties of the given object.
-     *
-     * @since 0.6
-     */
-    public Map<String,?> getProperties(final IdentifiedObject object, final 
boolean keepId) {
-        return Collections.singletonMap(IdentifiedObject.NAME_KEY, 
object.getName());
-    }
-
-    /**
-     * Returns {@code true} if the {@linkplain 
org.apache.sis.referencing.AbstractIdentifiedObject#getName()
-     * primary name} or an aliases of the given object matches the given name. 
The comparison ignores case,
-     * some Latin diacritical signs and any characters that are not letters or 
digits.
-     *
-     * @param  object  the object for which to check the name or alias.
-     * @param  name    the name to compare with the object name or aliases.
-     * @return {@code true} if the primary name of at least one alias matches 
the specified {@code name}.
-     *
-     * @since 0.6
-     */
-    public boolean isHeuristicMatchForName(final IdentifiedObject object, 
final String name) {
-        return NameToIdentifier.isHeuristicMatchForName(object.getName(), 
object.getAlias(), name,
-                NameToIdentifier.Simplifier.DEFAULT);
-    }
-
-    /**
-     * Returns the operation method for the specified name or identifier. The 
given argument shall be either a
-     * method name (e.g. <cite>"Transverse Mercator"</cite>) or one of its 
identifiers (e.g. {@code "EPSG:9807"}).
-     *
-     * @param  methods     the method candidates.
-     * @param  identifier  the name or identifier of the operation method to 
search.
-     * @return the coordinate operation method for the given name or 
identifier, or {@code null} if none.
-     *
-     * @see 
org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory#getOperationMethod(String)
-     * @see 
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory#getOperationMethod(String)
-     *
-     * @since 0.6
-     */
-    public final OperationMethod getOperationMethod(final Iterable<? extends 
OperationMethod> methods, final String identifier) {
-        OperationMethod fallback = null;
-        for (final OperationMethod method : methods) {
-            if (isHeuristicMatchForName(method, identifier) ||
-                    
NameToIdentifier.isHeuristicMatchForIdentifier(method.getIdentifiers(), 
identifier))
-            {
-                /*
-                 * Stop the iteration at the first non-deprecated method.
-                 * If we find only deprecated methods, take the first one.
-                 */
-                if (!(method instanceof Deprecable) || !((Deprecable) 
method).isDeprecated()) {
-                    return method;
-                }
-                if (fallback == null) {
-                    fallback = method;
-                }
-            }
-        }
-        return fallback;
-    }
-
-    /**
-     * Returns information about the Apache SIS configuration to be reported 
in {@link org.apache.sis.setup.About}.
-     * This method is invoked only for aspects that depends on other modules 
than {@code sis-utility}.
-     *
-     * <p>Current keys are:</p>
-     * <ul>
-     *   <li>{@code "EPSG"}: version of EPSG database.</li>
-     * </ul>
-     *
-     * @param  key     a key identifying the information to return.
-     * @param  locale  language to use if possible.
-     * @return the information, or {@code null} if none.
-     *
-     * @see 
org.apache.sis.internal.util.MetadataServices#getInformation(String, Locale)
-     *
-     * @since 0.7
-     */
-    public String getInformation(String key, Locale locale) {
-        return null;
-    }
 }

Modified: 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java?rev=1811543&r1=1811542&r2=1811543&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java
 [UTF-8] Mon Oct  9 09:31:41 2017
@@ -31,19 +31,14 @@ import org.opengis.referencing.crs.CRSFa
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.SingleCRS;
 import org.opengis.referencing.crs.DerivedCRS;
-import org.opengis.referencing.crs.GeodeticCRS;
-import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.VerticalCRS;
-import org.opengis.referencing.crs.ProjectedCRS;
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.cs.CSFactory;
 import org.opengis.referencing.cs.CartesianCS;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.cs.CoordinateSystemAxis;
-import org.opengis.referencing.cs.EllipsoidalCS;
 import org.opengis.referencing.datum.DatumFactory;
 import org.opengis.referencing.datum.PrimeMeridian;
-import org.opengis.referencing.datum.VerticalDatum;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.CoordinateOperationFactory;
@@ -60,7 +55,6 @@ import org.apache.sis.internal.system.De
 import org.apache.sis.internal.system.OptionalDependency;
 import org.apache.sis.internal.system.Modules;
 import org.apache.sis.io.wkt.FormattableObject;
-import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.Deprecable;
 
 
@@ -440,105 +434,6 @@ public class ReferencingServices extends
     }
 
     /**
-     * Creates a compound CRS, but we special processing for (two-dimensional 
Geographic + ellipsoidal heights) tupples.
-     * If any such tupple is found, a three-dimensional geographic CRS is 
created instead than the compound CRS.
-     *
-     * @param  crsFactory  the factory to use for creating compound or 
three-dimensional geographic CRS.
-     * @param  csFactory   the factory to use for creating three-dimensional 
ellipsoidal CS, if needed.
-     * @param  properties  name and other properties to give to the new object.
-     * @param  components  ordered array of {@code CoordinateReferenceSystem} 
objects.
-     * @return the coordinate reference system for the given properties.
-     * @throws FactoryException if the object creation failed.
-     *
-     * @since 0.7
-     */
-    public final CoordinateReferenceSystem createCompoundCRS(final CRSFactory 
crsFactory, final CSFactory csFactory,
-            final Map<String,?> properties, CoordinateReferenceSystem... 
components) throws FactoryException
-    {
-        for (int i=0; i<components.length; i++) {
-            final CoordinateReferenceSystem vertical = components[i];
-            if (vertical instanceof VerticalCRS) {
-                final VerticalDatum datum = ((VerticalCRS) 
vertical).getDatum();
-                if (datum != null && datum.getVerticalDatumType() == 
VerticalDatumTypes.ELLIPSOIDAL) {
-                    int axisPosition = 0;
-                    CoordinateSystem cs = null;
-                    CoordinateReferenceSystem crs = null;
-                    if (i == 0 || (cs = getCsIfHorizontal2D(crs = components[i 
- 1])) == null) {
-                        /*
-                         * GeographicCRS are normally before VerticalCRS. But 
Apache SIS is tolerant to the
-                         * opposite order (note however that such ordering is 
illegal according ISO 19162).
-                         */
-                        if (i+1 >= components.length || (cs = 
getCsIfHorizontal2D(crs = components[i + 1])) == null) {
-                            continue;
-                        }
-                        axisPosition = 1;
-                    }
-                    /*
-                     * At this point we have the horizontal and vertical 
components. The horizontal component
-                     * begins at 'axisPosition', which is almost always zero. 
Create the three-dimensional CRS.
-                     * If the result is the CRS to be returned directly by 
this method (components.length == 2),
-                     * use the properties given in argument. Otherwise we need 
to use other properties; current
-                     * implementation recycles the properties of the existing 
two-dimensional CRS.
-                     */
-                    final CoordinateSystemAxis[] axes = new 
CoordinateSystemAxis[3];
-                    axes[axisPosition++   ] = cs.getAxis(0);
-                    axes[axisPosition++   ] = cs.getAxis(1);
-                    axes[axisPosition %= 3] = 
vertical.getCoordinateSystem().getAxis(0);
-                    final Map<String,?> csProps = getProperties(cs, false);
-                    final Map<String,?> crsProps = (components.length == 2) ? 
properties : getProperties(crs, false);
-                    if (crs instanceof GeodeticCRS) {
-                        cs = csFactory.createEllipsoidalCS(csProps, axes[0], 
axes[1], axes[2]);
-                        crs = crsFactory.createGeographicCRS(crsProps, 
((GeodeticCRS) crs).getDatum(), (EllipsoidalCS) cs);
-                    } else {
-                        final ProjectedCRS proj = (ProjectedCRS) crs;
-                        GeographicCRS base = proj.getBaseCRS();
-                        if (base.getCoordinateSystem().getDimension() == 2) {
-                            base = (GeographicCRS) 
createCompoundCRS(crsFactory, csFactory, getProperties(base, false), base, 
vertical);
-                        }
-                        cs = csFactory.createCartesianCS(csProps, axes[0], 
axes[1], axes[2]);
-                        crs = crsFactory.createProjectedCRS(crsProps, base, 
proj.getConversionFromBase(), (CartesianCS) cs);
-                    }
-                    /*
-                     * Remove the VerticalCRS and store the three-dimensional 
GeographicCRS in place of the previous
-                     * two-dimensional GeographicCRS. Then let the loop 
continues in case there is other CRS to merge
-                     * (should never happen, but we are paranoiac).
-                     */
-                    components = ArraysExt.remove(components, i, 1);
-                    if (axisPosition != 0) i--;             // GeographicCRS 
before VerticalCRS (usual case).
-                    components[i] = crs;
-                }
-            }
-        }
-        switch (components.length) {
-            case 0:  return null;
-            case 1:  return components[0];
-            default: return crsFactory.createCompoundCRS(properties, 
components);
-        }
-    }
-
-    /**
-     * Returns the coordinate system if the given CRS is a two-dimensional 
geographic or projected CRS,
-     * or {@code null} otherwise. The returned coordinate system is either 
ellipsoidal or Cartesian;
-     * no other type is returned.
-     */
-    private static CoordinateSystem getCsIfHorizontal2D(final 
CoordinateReferenceSystem crs) {
-        final boolean isProjected = (crs instanceof ProjectedCRS);
-        if (isProjected || crs instanceof GeodeticCRS) {
-            final CoordinateSystem cs = crs.getCoordinateSystem();
-            if (cs.getDimension() == 2 && (isProjected || cs instanceof 
EllipsoidalCS)) {
-                /*
-                 * ProjectedCRS are guaranteed to be associated to 
CartesianCS, so we do not test that.
-                 * GeodeticCRS may be associated to either CartesianCS or 
EllipsoidalCS, but this method
-                 * shall accept only EllipsoidalCS. Actually we should accept 
only GeographicCRS, but we
-                 * relax this condition by accepting GeodeticCRS with 
EllipsoidalCS.
-                 */
-                return cs;
-            }
-        }
-        return null;
-    }
-
-    /**
      * Creates a format for {@link DirectPosition} instances.
      *
      * @param  locale    the locale for the new {@code Format}, or {@code 
null} for {@code Locale.ROOT}.

Modified: 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java?rev=1811543&r1=1811542&r2=1811543&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java
 [UTF-8] Mon Oct  9 09:31:41 2017
@@ -70,6 +70,7 @@ import org.apache.sis.internal.metadata.
 import org.apache.sis.internal.metadata.VerticalDatumTypes;
 import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.metadata.TransformationAccuracy;
+import org.apache.sis.internal.metadata.EllipsoidalHeightCombiner;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.util.CharSequences;
@@ -2179,8 +2180,9 @@ class GeodeticObjectParser extends MathT
             components.add(crs);
         }
         try {
-            return referencing.createCompoundCRS(crsFactory, csFactory, 
parseMetadataAndClose(element, name, null),
-                    components.toArray(new 
CoordinateReferenceSystem[components.size()]));
+            return new EllipsoidalHeightCombiner(crsFactory, csFactory, 
opFactory).createCompoundCRS(
+                            parseMetadataAndClose(element, name, null),
+                            components.toArray(new 
CoordinateReferenceSystem[components.size()]));
         } catch (FactoryException exception) {
             throw element.parseFailed(exception);
         }

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java?rev=1811543&r1=1811542&r2=1811543&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
 [UTF-8] Mon Oct  9 09:31:41 2017
@@ -40,10 +40,10 @@ import org.opengis.referencing.datum.Tem
 import org.opengis.referencing.operation.CoordinateOperationFactory;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.Conversion;
-import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.system.DefaultFactories;
+import org.apache.sis.internal.metadata.EllipsoidalHeightCombiner;
 import org.apache.sis.internal.referencing.provider.TransverseMercator;
 import org.apache.sis.internal.referencing.provider.PolarStereographicA;
 import org.apache.sis.measure.Latitude;
@@ -424,7 +424,13 @@ public class GeodeticObjectBuilder exten
      * @throws FactoryException if the object creation failed.
      */
     public CoordinateReferenceSystem createCompoundCRS(final 
CoordinateReferenceSystem... components) throws FactoryException {
-        return 
ReferencingServices.getInstance().createCompoundCRS(getCRSFactory(), 
getCSFactory(), properties, components);
+        return new EllipsoidalHeightCombiner() {
+            @Override public void initialize(final int factoryTypes) {
+                if ((factoryTypes & CRS)       != 0) crsFactory = 
getCRSFactory();
+                if ((factoryTypes & CS)        != 0)  csFactory = 
getCSFactory();
+                if ((factoryTypes & OPERATION) != 0)  opFactory = 
getCoordinateOperationFactory();
+            }
+        }.createCompoundCRS(properties, components);
     }
 
     /**

Added: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CompoundCRSBuilder.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CompoundCRSBuilder.java?rev=1811543&view=auto
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CompoundCRSBuilder.java
 (added)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CompoundCRSBuilder.java
 [UTF-8] Mon Oct  9 09:31:41 2017
@@ -0,0 +1,57 @@
+/*
+ * 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.referencing.operation;
+
+import org.apache.sis.internal.metadata.EllipsoidalHeightCombiner;
+import org.opengis.referencing.operation.CoordinateOperationFactory;
+
+
+/**
+ * Helper class for combining two-dimensional geographic or projected CRS with 
an ellipsoidal height
+ * into a three-dimensional CRS.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 0.8
+ * @since   0.8
+ * @module
+ */
+final class CompoundCRSBuilder extends EllipsoidalHeightCombiner {
+    /**
+     * The Apache SIS implementation of {@link CoordinateOperationFactory}.
+     */
+    private final DefaultCoordinateOperationFactory factorySIS;
+
+    /**
+     * Creates a new builder for the given coordinate operation factory.
+     *
+     * @param factory     the factory to use for creating coordinate 
operations.
+     * @param factorySIS  used only when we need a SIS-specific method.
+     */
+    CompoundCRSBuilder(final CoordinateOperationFactory factory, final 
DefaultCoordinateOperationFactory factorySIS) {
+        super(null, null, factory);
+        this.factorySIS = factorySIS;
+    }
+
+    /**
+     * Invoked when the builder needs a CRS or CS factory.
+     */
+    @Override
+    public void initialize(final int factoryTypes) {
+        if ((factoryTypes & CRS) != 0) crsFactory = factorySIS.getCRSFactory();
+        if ((factoryTypes & CS)  != 0)  csFactory = factorySIS.getCSFactory();
+    }
+}

Propchange: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CompoundCRSBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

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=1811543&r1=1811542&r2=1811543&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] Mon Oct  9 09:31:41 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.ReferencingServices;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.referencing.provider.Geographic2Dto3D;
 import org.apache.sis.internal.referencing.provider.Geographic3Dto2D;
@@ -839,8 +838,8 @@ public class CoordinateOperationFinder e
             } else if (stepComponents.length == 1) {
                 stepTargetCRS = target;                 // Slight optimization 
of the next block.
             } else {
-                stepTargetCRS = 
toAuthorityDefinition(CoordinateReferenceSystem.class, 
ReferencingServices.getInstance()
-                        .createCompoundCRS(factorySIS.getCRSFactory(), 
factorySIS.getCSFactory(), derivedFrom(target), stepComponents));
+                stepTargetCRS = 
toAuthorityDefinition(CoordinateReferenceSystem.class,
+                        new CompoundCRSBuilder(factory, 
factorySIS).createCompoundCRS(derivedFrom(target), stepComponents));
             }
             int delta = source.getCoordinateSystem().getDimension();
             final int startAtDimension = endAtDimension;

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java?rev=1811543&r1=1811542&r2=1811543&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
 [UTF-8] Mon Oct  9 09:31:41 2017
@@ -1044,10 +1044,7 @@ class CoordinateOperationRegistry {
             }
         }
         return toAuthorityDefinition(CoordinateReferenceSystem.class,
-                ReferencingServices.getInstance().createCompoundCRS(
-                        factorySIS.getCRSFactory(),
-                        factorySIS.getCSFactory(),
-                        derivedFrom(crs), crs, 
CommonCRS.Vertical.ELLIPSOIDAL.crs()));
+                new CompoundCRSBuilder(factory, 
factorySIS).createCompoundCRS(derivedFrom(crs), crs, 
CommonCRS.Vertical.ELLIPSOIDAL.crs()));
     }
 
     /**

Copied: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/metadata/EllipsoidalHeightCombinerTest.java
 (from r1811538, 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ServicesForMetadataTest.java)
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/metadata/EllipsoidalHeightCombinerTest.java?p2=sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/metadata/EllipsoidalHeightCombinerTest.java&p1=sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ServicesForMetadataTest.java&r1=1811538&r2=1811543&rev=1811543&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ServicesForMetadataTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/metadata/EllipsoidalHeightCombinerTest.java
 [UTF-8] Mon Oct  9 09:31:41 2017
@@ -14,13 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.referencing;
+package org.apache.sis.internal.metadata;
 
 import java.util.Map;
 import java.util.Collections;
-import org.opengis.geometry.Envelope;
-import org.opengis.metadata.extent.GeographicBoundingBox;
-import org.opengis.metadata.extent.VerticalExtent;
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.SingleCRS;
@@ -28,18 +25,12 @@ import org.opengis.referencing.crs.Geogr
 import org.opengis.referencing.crs.ProjectedCRS;
 import org.opengis.referencing.crs.VerticalCRS;
 import org.opengis.referencing.crs.TemporalCRS;
-import org.opengis.referencing.operation.TransformException;
 import org.opengis.util.FactoryException;
-import org.apache.sis.internal.metadata.ReferencingServices;
-import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
-import org.apache.sis.metadata.iso.extent.DefaultVerticalExtent;
-import org.apache.sis.metadata.iso.extent.DefaultSpatialTemporalExtent;
-import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.referencing.CRS;
-import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.cs.HardCodedCS;
 import org.apache.sis.referencing.crs.HardCodedCRS;
 import org.apache.sis.referencing.factory.GeodeticObjectFactory;
+import org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory;
 import org.apache.sis.referencing.operation.HardCodedConversions;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
@@ -47,151 +38,48 @@ import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
 import static org.apache.sis.test.Assert.*;
-import static org.apache.sis.test.TestUtilities.getSingleton;
 
 
 /**
- * Tests {@link ServicesForMetadata}.
+ * Tests {@link EllipsoidalHeightCombiner}. This class is defined in {@code 
sis-metadata} module
+ * but tested here because the tests use CRS instances defined in {@code 
sis-referencing}.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @version 0.8
- * @since   0.5
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/SIS-303";>SIS-303</a>
+ *
+ * @since 0.8
  * @module
  */
 @DependsOn({
     org.apache.sis.referencing.CRSTest.class,
-    org.apache.sis.referencing.CommonCRSTest.class
+    org.apache.sis.internal.referencing.ServicesForMetadataTest.class
 })
-public final strictfp class ServicesForMetadataTest extends TestCase {
-    /**
-     * Tests {@link 
org.apache.sis.metadata.iso.extent.Extents#centroid(GeographicBoundingBox)}.
-     *
-     * @since 0.8
-     */
-    @Test
-    public void testGeographicBoundingBoxCentroid() {
-        org.apache.sis.metadata.iso.extent.ExtentsTest.testCentroid();
-    }
-
+public final strictfp class EllipsoidalHeightCombinerTest extends TestCase {
     /**
-     * Creates a test envelope with the given CRS and initialized with
-     * [-10 … 70]° of longitude, [-20 … 30]° of latitude, [-40 … 60] metres of 
elevation
-     * and [51000 … 52000] modified Julian days.
+     * Creates an instance to be tested.
      */
-    @SuppressWarnings("fallthrough")
-    private static Envelope createEnvelope(final CoordinateReferenceSystem 
crs) {
-        final GeneralEnvelope envelope = new GeneralEnvelope(crs);
-        switch (crs.getCoordinateSystem().getDimension()) {
-            default: throw new AssertionError();
-            case 4: envelope.setRange(3, 51000, 52000);                 // 
Fall through
-            case 3: envelope.setRange(2, -10, 70);                      // 
Fall through
-            case 2: envelope.setRange(1, -20, 30);                      // 
Fall through
-            case 1: envelope.setRange(0, -40, 60);
-            case 0: break;
-        }
-        return envelope;
-    }
-
-    /**
-     * Verifies the values of the given geographic bounding box.
-     */
-    private static void verifySpatialExtent(final GeographicBoundingBox box) {
-        assertEquals(-40, box.getWestBoundLongitude(), STRICT);
-        assertEquals( 60, box.getEastBoundLongitude(), STRICT);
-        assertEquals(-20, box.getSouthBoundLatitude(), STRICT);
-        assertEquals( 30, box.getNorthBoundLatitude(), STRICT);
-        assertEquals(Boolean.TRUE, box.getInclusion());
-    }
-
-    /**
-     * Verifies the values of the given vertical extent.
-     */
-    private static void verifyVerticalExtent(final CommonCRS.Vertical 
expectedCRS, final VerticalExtent extent) {
-        assertEquals(-10, extent.getMinimumValue(), STRICT);
-        assertEquals( 70, extent.getMaximumValue(), STRICT);
-        assertEqualsIgnoreMetadata(expectedCRS.crs(), extent.getVerticalCRS());
-    }
-
-    /**
-     * Tests (indirectly) {@link ServicesForMetadata#setBounds(Envelope, 
DefaultGeographicBoundingBox)}
-     * from a three-dimensional envelope.
-     *
-     * @throws TransformException should never happen.
-     */
-    @Test
-    public void testSetGeographicBoundsFrom3D() throws TransformException {
-        final DefaultGeographicBoundingBox box = new 
DefaultGeographicBoundingBox();
-        box.setBounds(createEnvelope(HardCodedCRS.WGS84_3D));
-        verifySpatialExtent(box);
-    }
-
-    /**
-     * Tests (indirectly) {@link ServicesForMetadata#setBounds(Envelope, 
DefaultGeographicBoundingBox)}
-     * from a for-dimensional envelope.
-     *
-     * @throws TransformException should never happen.
-     */
-    @Test
-    public void testSetGeographicBoundsFrom4D() throws TransformException {
-        final DefaultGeographicBoundingBox box = new 
DefaultGeographicBoundingBox();
-        box.setBounds(createEnvelope(HardCodedCRS.GEOID_4D));
-        verifySpatialExtent(box);
-    }
-
-    /**
-     * Tests (indirectly) {@link ServicesForMetadata#setBounds(Envelope, 
DefaultVerticalExtent)}
-     * from an ellipsoidal height
-     *
-     * @throws TransformException should never happen.
-     */
-    @Test
-    public void testSetVerticalBoundsFromEllipsoid() throws TransformException 
{
-        final DefaultVerticalExtent extent = new DefaultVerticalExtent();
-        extent.setBounds(createEnvelope(HardCodedCRS.WGS84_3D));
-        verifyVerticalExtent(CommonCRS.Vertical.ELLIPSOIDAL, extent);
-    }
-
-    /**
-     * Tests (indirectly) {@link ServicesForMetadata#setBounds(Envelope, 
DefaultVerticalExtent)}
-     * from a geoidal height
-     *
-     * @throws TransformException should never happen.
-     */
-    @Test
-    public void testSetVerticalBoundsFromGeoid() throws TransformException {
-        final DefaultVerticalExtent extent = new DefaultVerticalExtent();
-        extent.setBounds(createEnvelope(HardCodedCRS.GEOID_4D));
-        verifyVerticalExtent(CommonCRS.Vertical.MEAN_SEA_LEVEL, extent);
-    }
-
-    /**
-     * Tests (indirectly) {@link ServicesForMetadata#setBounds(Envelope, 
DefaultSpatialTemporalExtent)}.
-     *
-     * @throws TransformException should never happen.
-     */
-    @Test
-    @DependsOnMethod({"testSetGeographicBoundsFrom4D", 
"testSetVerticalBoundsFromGeoid"})
-    public void testSetSpatialTemporalBounds() throws TransformException {
-        final DefaultSpatialTemporalExtent extent = new 
DefaultSpatialTemporalExtent();
-        extent.setBounds(createEnvelope(HardCodedCRS.GEOID_3D));
-        verifySpatialExtent((GeographicBoundingBox) 
getSingleton(extent.getSpatialExtent()));
-        verifyVerticalExtent(CommonCRS.Vertical.MEAN_SEA_LEVEL, 
extent.getVerticalExtent());
+    private static EllipsoidalHeightCombiner create() {
+        final GeodeticObjectFactory factory = new GeodeticObjectFactory();
+        return new EllipsoidalHeightCombiner(factory, factory, null) {
+            @Override protected void initialize(final int factoryTypes) {
+                if ((factoryTypes & OPERATION) != 0) {
+                    opFactory = new DefaultCoordinateOperationFactory();
+                }
+            }
+        };
     }
 
     /**
-     * Tests {@link ServicesForMetadata#createCompoundCRS 
ReferencingUtilities.createCompoundCRS(…)}
+     * Tests {@link EllipsoidalHeightCombiner#createCompoundCRS 
EllipsoidalHeightCombiner.createCompoundCRS(…)}
      * with a geographic CRS.
      *
      * @throws FactoryException if a CRS can not be created.
-     *
-     * @see <a href="https://issues.apache.org/jira/browse/SIS-303";>SIS-303</a>
-     *
-     * @since 0.7
      */
     @Test
-    public void testCreateCompoundGeographicCRS() throws FactoryException {
-        final ReferencingServices  services = 
ServicesForMetadata.getInstance();
-        final GeodeticObjectFactory factory = new GeodeticObjectFactory();
+    public void testGeographicCRS() throws FactoryException {
+        final EllipsoidalHeightCombiner services = create();
         final Map<String,String> properties = 
Collections.singletonMap(CoordinateReferenceSystem.NAME_KEY, "WGS 84 (4D)");
         final GeographicCRS horizontal   = HardCodedCRS.WGS84;
         final GeographicCRS horizontal3D = HardCodedCRS.WGS84_3D;
@@ -201,23 +89,23 @@ public final strictfp class ServicesForM
         /*
          * createCompoundCRS(…) should not combine GeographicCRS with 
non-ellipsoidal height.
          */
-        CoordinateReferenceSystem compound = 
services.createCompoundCRS(factory, factory, properties, horizontal, geoidal, 
temporal);
+        CoordinateReferenceSystem compound = 
services.createCompoundCRS(properties, horizontal, geoidal, temporal);
         assertArrayEqualsIgnoreMetadata(new SingleCRS[] {horizontal, geoidal, 
temporal}, CRS.getSingleComponents(compound).toArray());
         /*
          * createCompoundCRS(…) should combine GeographicCRS with ellipsoidal 
height.
          */
-        compound = services.createCompoundCRS(factory, factory, properties, 
horizontal, vertical);
+        compound = services.createCompoundCRS(properties, horizontal, 
vertical);
         assertArrayEqualsIgnoreMetadata(new SingleCRS[] {horizontal3D}, 
CRS.getSingleComponents(compound).toArray());
         /*
          * createCompoundCRS(…) should combine GeographicCRS with ellipsoidal 
height and keep time.
          */
-        compound = services.createCompoundCRS(factory, factory, properties, 
horizontal, vertical, temporal);
+        compound = services.createCompoundCRS(properties, horizontal, 
vertical, temporal);
         assertArrayEqualsIgnoreMetadata(new SingleCRS[] {horizontal3D, 
temporal}, CRS.getSingleComponents(compound).toArray());
         /*
          * Non-standard feature: accept (VerticalCRS + GeodeticCRS) order.
          * The test below use the reverse order for all axes compared to the 
previous test.
          */
-        compound = services.createCompoundCRS(factory, factory, properties, 
temporal, vertical, HardCodedCRS.WGS84_φλ);
+        compound = services.createCompoundCRS(properties, temporal, vertical, 
HardCodedCRS.WGS84_φλ);
         final Object[] components = 
CRS.getSingleComponents(compound).toArray();
         assertEquals(2, components.length);
         assertEqualsIgnoreMetadata(temporal, components[0]);
@@ -228,17 +116,15 @@ public final strictfp class ServicesForM
     }
 
     /**
-     * Tests {@link ServicesForMetadata#createCompoundCRS 
ReferencingUtilities.createCompoundCRS(…)}
+     * Tests {@link EllipsoidalHeightCombiner#createCompoundCRS 
EllipsoidalHeightCombiner.createCompoundCRS(…)}
      * with a projected CRS.
      *
      * @throws FactoryException if a CRS can not be created.
-     *
-     * @since 0.8
      */
     @Test
-    @DependsOnMethod("testCreateCompoundGeographicCRS")
-    public void testCreateCompoundProjectedCRS() throws FactoryException {
-        final ReferencingServices  services = 
ServicesForMetadata.getInstance();
+    @DependsOnMethod("testGeographicCRS")
+    public void testProjectedCRS() throws FactoryException {
+        final EllipsoidalHeightCombiner services = create();
         final GeodeticObjectFactory factory = new GeodeticObjectFactory();
         final Map<String,String> properties = 
Collections.singletonMap(CoordinateReferenceSystem.NAME_KEY, "World Mercator 
(4D)");
         final ProjectedCRS horizontal   = 
factory.createProjectedCRS(properties, HardCodedCRS.WGS84,    
HardCodedConversions.MERCATOR, HardCodedCS.PROJECTED);
@@ -249,31 +135,28 @@ public final strictfp class ServicesForM
         /*
          * createCompoundCRS(…) should not combine ProjectedCRS with 
non-ellipsoidal height.
          */
-        CoordinateReferenceSystem compound = 
services.createCompoundCRS(factory, factory, properties, horizontal, geoidal, 
temporal);
+        CoordinateReferenceSystem compound = 
services.createCompoundCRS(properties, horizontal, geoidal, temporal);
         assertArrayEqualsIgnoreMetadata(new SingleCRS[] {horizontal, geoidal, 
temporal}, CRS.getSingleComponents(compound).toArray());
         /*
          * createCompoundCRS(…) should combine ProjectedCRS with ellipsoidal 
height.
          */
-        if (true) return;       // TODO - debug after this point.
-        compound = services.createCompoundCRS(factory, factory, properties, 
horizontal, vertical);
+        compound = services.createCompoundCRS(properties, horizontal, 
vertical);
         assertArrayEqualsIgnoreMetadata(new SingleCRS[] {horizontal3D}, 
CRS.getSingleComponents(compound).toArray());
         /*
-         * createCompoundCRS(…) should combine GeographicCRS with ellipsoidal 
height and keep time.
+         * createCompoundCRS(…) should combine ProjectedCRS with ellipsoidal 
height and keep time.
          */
-        compound = services.createCompoundCRS(factory, factory, properties, 
horizontal, vertical, temporal);
+        compound = services.createCompoundCRS(properties, horizontal, 
vertical, temporal);
         assertArrayEqualsIgnoreMetadata(new SingleCRS[] {horizontal3D, 
temporal}, CRS.getSingleComponents(compound).toArray());
         /*
-         * Non-standard feature: accept (VerticalCRS + GeodeticCRS) order.
-         * The test below use the reverse order for all axes compared to the 
previous test.
+         * Non-standard feature: accept (VerticalCRS + ProjectedCRS) order.
          */
-        compound = services.createCompoundCRS(factory, factory, properties,
-                temporal, vertical, HardCodedCRS.WGS84_φλ);
+        compound = services.createCompoundCRS(properties, temporal, vertical, 
horizontal);
         final Object[] components = 
CRS.getSingleComponents(compound).toArray();
         assertEquals(2, components.length);
         assertEqualsIgnoreMetadata(temporal, components[0]);
-        assertInstanceOf("Shall be a three-dimensional geographic CRS.", 
GeographicCRS.class, components[1]);
-        assertAxisDirectionsEqual("Shall be a three-dimensional geographic 
CRS.",
+        assertInstanceOf("Shall be a three-dimensional projected CRS.", 
ProjectedCRS.class, components[1]);
+        assertAxisDirectionsEqual("Shall be a three-dimensional projected 
CRS.",
                 ((CoordinateReferenceSystem) 
components[1]).getCoordinateSystem(),
-                AxisDirection.UP, AxisDirection.NORTH, AxisDirection.EAST);
+                AxisDirection.UP, AxisDirection.EAST, AxisDirection.NORTH);
     }
 }

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ServicesForMetadataTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ServicesForMetadataTest.java?rev=1811543&r1=1811542&r2=1811543&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ServicesForMetadataTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/ServicesForMetadataTest.java
 [UTF-8] Mon Oct  9 09:31:41 2017
@@ -16,31 +16,17 @@
  */
 package org.apache.sis.internal.referencing;
 
-import java.util.Map;
-import java.util.Collections;
 import org.opengis.geometry.Envelope;
 import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.metadata.extent.VerticalExtent;
-import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.opengis.referencing.crs.SingleCRS;
-import org.opengis.referencing.crs.GeographicCRS;
-import org.opengis.referencing.crs.ProjectedCRS;
-import org.opengis.referencing.crs.VerticalCRS;
-import org.opengis.referencing.crs.TemporalCRS;
 import org.opengis.referencing.operation.TransformException;
-import org.opengis.util.FactoryException;
-import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
 import org.apache.sis.metadata.iso.extent.DefaultVerticalExtent;
 import org.apache.sis.metadata.iso.extent.DefaultSpatialTemporalExtent;
 import org.apache.sis.geometry.GeneralEnvelope;
-import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.CommonCRS;
-import org.apache.sis.referencing.cs.HardCodedCS;
 import org.apache.sis.referencing.crs.HardCodedCRS;
-import org.apache.sis.referencing.factory.GeodeticObjectFactory;
-import org.apache.sis.referencing.operation.HardCodedConversions;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
@@ -59,7 +45,6 @@ import static org.apache.sis.test.TestUt
  * @module
  */
 @DependsOn({
-    org.apache.sis.referencing.CRSTest.class,
     org.apache.sis.referencing.CommonCRSTest.class
 })
 public final strictfp class ServicesForMetadataTest extends TestCase {
@@ -177,103 +162,4 @@ public final strictfp class ServicesForM
         verifySpatialExtent((GeographicBoundingBox) 
getSingleton(extent.getSpatialExtent()));
         verifyVerticalExtent(CommonCRS.Vertical.MEAN_SEA_LEVEL, 
extent.getVerticalExtent());
     }
-
-    /**
-     * Tests {@link ServicesForMetadata#createCompoundCRS 
ReferencingUtilities.createCompoundCRS(…)}
-     * with a geographic CRS.
-     *
-     * @throws FactoryException if a CRS can not be created.
-     *
-     * @see <a href="https://issues.apache.org/jira/browse/SIS-303";>SIS-303</a>
-     *
-     * @since 0.7
-     */
-    @Test
-    public void testCreateCompoundGeographicCRS() throws FactoryException {
-        final ReferencingServices  services = 
ServicesForMetadata.getInstance();
-        final GeodeticObjectFactory factory = new GeodeticObjectFactory();
-        final Map<String,String> properties = 
Collections.singletonMap(CoordinateReferenceSystem.NAME_KEY, "WGS 84 (4D)");
-        final GeographicCRS horizontal   = HardCodedCRS.WGS84;
-        final GeographicCRS horizontal3D = HardCodedCRS.WGS84_3D;
-        final VerticalCRS   vertical     = HardCodedCRS.ELLIPSOIDAL_HEIGHT;
-        final TemporalCRS   temporal     = HardCodedCRS.TIME;
-        final VerticalCRS   geoidal      = HardCodedCRS.GRAVITY_RELATED_HEIGHT;
-        /*
-         * createCompoundCRS(…) should not combine GeographicCRS with 
non-ellipsoidal height.
-         */
-        CoordinateReferenceSystem compound = 
services.createCompoundCRS(factory, factory, properties, horizontal, geoidal, 
temporal);
-        assertArrayEqualsIgnoreMetadata(new SingleCRS[] {horizontal, geoidal, 
temporal}, CRS.getSingleComponents(compound).toArray());
-        /*
-         * createCompoundCRS(…) should combine GeographicCRS with ellipsoidal 
height.
-         */
-        compound = services.createCompoundCRS(factory, factory, properties, 
horizontal, vertical);
-        assertArrayEqualsIgnoreMetadata(new SingleCRS[] {horizontal3D}, 
CRS.getSingleComponents(compound).toArray());
-        /*
-         * createCompoundCRS(…) should combine GeographicCRS with ellipsoidal 
height and keep time.
-         */
-        compound = services.createCompoundCRS(factory, factory, properties, 
horizontal, vertical, temporal);
-        assertArrayEqualsIgnoreMetadata(new SingleCRS[] {horizontal3D, 
temporal}, CRS.getSingleComponents(compound).toArray());
-        /*
-         * Non-standard feature: accept (VerticalCRS + GeodeticCRS) order.
-         * The test below use the reverse order for all axes compared to the 
previous test.
-         */
-        compound = services.createCompoundCRS(factory, factory, properties, 
temporal, vertical, HardCodedCRS.WGS84_φλ);
-        final Object[] components = 
CRS.getSingleComponents(compound).toArray();
-        assertEquals(2, components.length);
-        assertEqualsIgnoreMetadata(temporal, components[0]);
-        assertInstanceOf("Shall be a three-dimensional geographic CRS.", 
GeographicCRS.class, components[1]);
-        assertAxisDirectionsEqual("Shall be a three-dimensional geographic 
CRS.",
-                ((CoordinateReferenceSystem) 
components[1]).getCoordinateSystem(),
-                AxisDirection.UP, AxisDirection.NORTH, AxisDirection.EAST);
-    }
-
-    /**
-     * Tests {@link ServicesForMetadata#createCompoundCRS 
ReferencingUtilities.createCompoundCRS(…)}
-     * with a projected CRS.
-     *
-     * @throws FactoryException if a CRS can not be created.
-     *
-     * @since 0.8
-     */
-    @Test
-    @DependsOnMethod("testCreateCompoundGeographicCRS")
-    public void testCreateCompoundProjectedCRS() throws FactoryException {
-        final ReferencingServices  services = 
ServicesForMetadata.getInstance();
-        final GeodeticObjectFactory factory = new GeodeticObjectFactory();
-        final Map<String,String> properties = 
Collections.singletonMap(CoordinateReferenceSystem.NAME_KEY, "World Mercator 
(4D)");
-        final ProjectedCRS horizontal   = 
factory.createProjectedCRS(properties, HardCodedCRS.WGS84,    
HardCodedConversions.MERCATOR, HardCodedCS.PROJECTED);
-        final ProjectedCRS horizontal3D = 
factory.createProjectedCRS(properties, HardCodedCRS.WGS84_3D, 
HardCodedConversions.MERCATOR, HardCodedCS.PROJECTED_3D);
-        final VerticalCRS  vertical     = HardCodedCRS.ELLIPSOIDAL_HEIGHT;
-        final TemporalCRS  temporal     = HardCodedCRS.TIME;
-        final VerticalCRS  geoidal      = HardCodedCRS.GRAVITY_RELATED_HEIGHT;
-        /*
-         * createCompoundCRS(…) should not combine ProjectedCRS with 
non-ellipsoidal height.
-         */
-        CoordinateReferenceSystem compound = 
services.createCompoundCRS(factory, factory, properties, horizontal, geoidal, 
temporal);
-        assertArrayEqualsIgnoreMetadata(new SingleCRS[] {horizontal, geoidal, 
temporal}, CRS.getSingleComponents(compound).toArray());
-        /*
-         * createCompoundCRS(…) should combine ProjectedCRS with ellipsoidal 
height.
-         */
-        if (true) return;       // TODO - debug after this point.
-        compound = services.createCompoundCRS(factory, factory, properties, 
horizontal, vertical);
-        assertArrayEqualsIgnoreMetadata(new SingleCRS[] {horizontal3D}, 
CRS.getSingleComponents(compound).toArray());
-        /*
-         * createCompoundCRS(…) should combine GeographicCRS with ellipsoidal 
height and keep time.
-         */
-        compound = services.createCompoundCRS(factory, factory, properties, 
horizontal, vertical, temporal);
-        assertArrayEqualsIgnoreMetadata(new SingleCRS[] {horizontal3D, 
temporal}, CRS.getSingleComponents(compound).toArray());
-        /*
-         * Non-standard feature: accept (VerticalCRS + GeodeticCRS) order.
-         * The test below use the reverse order for all axes compared to the 
previous test.
-         */
-        compound = services.createCompoundCRS(factory, factory, properties,
-                temporal, vertical, HardCodedCRS.WGS84_φλ);
-        final Object[] components = 
CRS.getSingleComponents(compound).toArray();
-        assertEquals(2, components.length);
-        assertEqualsIgnoreMetadata(temporal, components[0]);
-        assertInstanceOf("Shall be a three-dimensional geographic CRS.", 
GeographicCRS.class, components[1]);
-        assertAxisDirectionsEqual("Shall be a three-dimensional geographic 
CRS.",
-                ((CoordinateReferenceSystem) 
components[1]).getCoordinateSystem(),
-                AxisDirection.UP, AxisDirection.NORTH, AxisDirection.EAST);
-    }
 }

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=1811543&r1=1811542&r2=1811543&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] Mon Oct  9 09:31:41 2017
@@ -229,7 +229,7 @@ import org.junit.BeforeClass;
     
org.apache.sis.referencing.operation.builder.LinearTransformBuilderTest.class,
     
org.apache.sis.referencing.operation.builder.LocalizationGridBuilderTest.class,
 
-    // Geometry
+    // Geometry and miscellaneous
     org.apache.sis.geometry.AbstractDirectPositionTest.class,
     org.apache.sis.geometry.GeneralDirectPositionTest.class,
     org.apache.sis.geometry.DirectPosition1DTest.class,
@@ -244,6 +244,7 @@ import org.junit.BeforeClass;
     org.apache.sis.geometry.Shapes2DTest.class,                 // Simpler 
than EnvelopesTest.
     org.apache.sis.geometry.EnvelopesTest.class,
     org.apache.sis.internal.referencing.ServicesForMetadataTest.class,
+    org.apache.sis.internal.metadata.EllipsoidalHeightCombinerTest.class,
     org.apache.sis.geometry.CoordinateFormatTest.class,
 
     org.apache.sis.distance.LatLonPointRadiusTest.class,        // Pending 
refactoring in a geometry package.


Reply via email to