sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1737889 - in /sis/branches/JDK8/core: sis-metadata/src/main/java/org/apache/sis/internal/metadata/ sis-metadata/src/main/java/org/apache/sis/io/wkt/ sis-referencing/src/main/java/org/apache/sis/internal/referencing/ sis-referencing/src/mai...
Date Tue, 05 Apr 2016 22:24:21 GMT
Author: desruisseaux
Date: Tue Apr  5 22:24:20 2016
New Revision: 1737889

URL: http://svn.apache.org/viewvc?rev=1737889&view=rev
Log:
Begin support of coordinate operation between CompoundCRS instances (still a work in progress).

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SourceComponent.java
  (with props)
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/ServicesForMetadata.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/Classes.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties

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=1737889&r1=1737888&r2=1737889&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] Tue Apr  5 22:24:20 2016
@@ -111,13 +111,23 @@ public class ReferencingServices extends
     public static final String OPERATION_TYPE_KEY = "operationType";
 
     /**
-     * The key for specifying a {@linkplain org.opengis.referencing.operation.MathTransformFactory}
-     * instance to use for the construction of a geodetic object. This is usually not needed
for CRS
-     * construction, except in the special case of a derived CRS created from a defining
conversion.
+     * 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 separator character between an identifier and its namespace in the argument given
to
      * {@link #getOperationMethod(String)}. For example this is the separator in {@code "EPSG:9807"}.
      *
@@ -553,11 +563,15 @@ public class ReferencingServices extends
      *
      * @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.6
+     * @since 0.7
      */
-    public CoordinateOperationFactory getCoordinateOperationFactory(Map<String,?> properties,
MathTransformFactory mtFactory) {
+    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

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=1737889&r1=1737888&r2=1737889&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] Tue Apr  5 22:24:20 2016
@@ -203,7 +203,7 @@ final class GeodeticObjectParser extends
         csFactory       = (CSFactory)    factories;
         datumFactory    = (DatumFactory) factories;
         referencing     = ReferencingServices.getInstance();
-        opFactory       = referencing.getCoordinateOperationFactory(defaultProperties, mtFactory);
+        opFactory       = referencing.getCoordinateOperationFactory(defaultProperties, mtFactory,
crsFactory, csFactory);
         transliterator  = Transliterator.DEFAULT;
         usesCommonUnits = false;
         ignoreAxes      = false;
@@ -240,7 +240,7 @@ final class GeodeticObjectParser extends
         if (f != null) {
             opFactory = (CoordinateOperationFactory) f;
         } else {
-            opFactory = referencing.getCoordinateOperationFactory(null, mtFactory);
+            opFactory = referencing.getCoordinateOperationFactory(null, mtFactory, crsFactory,
csFactory);
             factories.put(CoordinateOperationFactory.class, opFactory);
         }
     }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java?rev=1737889&r1=1737888&r2=1737889&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java
[UTF-8] Tue Apr  5 22:24:20 2016
@@ -17,8 +17,10 @@
 package org.apache.sis.internal.referencing;
 
 import java.util.Map;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Locale;
 import javax.measure.unit.Unit;
 import javax.measure.quantity.Length;
@@ -34,6 +36,8 @@ import org.opengis.referencing.crs.Tempo
 import org.opengis.referencing.crs.VerticalCRS;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.crs.CRSFactory;
+import org.opengis.referencing.cs.CSFactory;
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.cs.CartesianCS;
 import org.opengis.referencing.cs.CoordinateSystem;
@@ -623,17 +627,30 @@ public final class ServicesForMetadata e
      *
      * @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.6
+     * @since 0.7
      */
     @Override
-    public CoordinateOperationFactory getCoordinateOperationFactory(Map<String,?> properties,
MathTransformFactory mtFactory) {
-        if (Containers.isNullOrEmpty(properties) && DefaultFactories.isDefaultInstance(MathTransformFactory.class,
mtFactory)) {
-            return CoordinateOperations.factory();
-        } else {
-            return new DefaultCoordinateOperationFactory(properties, mtFactory);
+    public CoordinateOperationFactory getCoordinateOperationFactory(Map<String,?> properties,
+            final MathTransformFactory mtFactory, final CRSFactory crsFactory, final CSFactory
csFactory)
+    {
+        if (Containers.isNullOrEmpty(properties)) {
+            if (DefaultFactories.isDefaultInstance(MathTransformFactory.class, mtFactory)
&&
+                DefaultFactories.isDefaultInstance(CRSFactory.class, crsFactory) &&
+                DefaultFactories.isDefaultInstance(CSFactory.class, csFactory))
+            {
+                return CoordinateOperations.factory();
+            }
+            properties = Collections.emptyMap();
         }
+        final HashMap<String,Object> p = new HashMap<>(properties);
+        p.putIfAbsent(CRS_FACTORY, crsFactory);
+        p.putIfAbsent(CS_FACTORY,  csFactory);
+        properties = p;
+        return new DefaultCoordinateOperationFactory(properties, mtFactory);
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java?rev=1737889&r1=1737888&r2=1737889&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
[UTF-8] Tue Apr  5 22:24:20 2016
@@ -18,6 +18,7 @@ package org.apache.sis.referencing.opera
 
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.IdentifiedObject;
+import org.apache.sis.referencing.AbstractIdentifiedObject;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.Classes;
@@ -78,24 +79,36 @@ final class CRSPair {
     }
 
     /**
-     * Returns a name for the given object, truncating it if needed.
+     * Returns the name of the GeoAPI interface implemented by the specified object,
+     * followed by the name between brackets.
      */
-    static String shortName(final IdentifiedObject object) {
-        String name = IdentifiedObjects.getName(object, null);
-        if (name == null) {
-            name = Classes.getShortClassName(object);
+    static String label(final IdentifiedObject object) {
+        if (object == null) {
+            return null;
+        }
+        Class<?> type;
+        if (object instanceof AbstractIdentifiedObject) {
+            type = ((AbstractIdentifiedObject) object).getInterface();
         } else {
-            int i = 30;                 // Arbitrary length threshold.
+            type = object.getClass();
+            final Class<?>[] c = Classes.getLeafInterfaces(type, IdentifiedObject.class);
+            if (c.length != 0) type = c[0];
+        }
+        String label = Classes.getShortName(type);
+        String name = IdentifiedObjects.getName(object, null);
+        if (name != null) {
+            int i = 30;                                         // Arbitrary length threshold.
             if (name.length() >= i) {
-                while (i > 15) {        // Arbitrary minimal length.
+                while (i > 15) {                                // Arbitrary minimal length.
                     final int c = name.codePointBefore(i);
                     if (Character.isSpaceChar(c)) break;
                     i -= Character.charCount(c);
                 }
                 name = CharSequences.trimWhitespaces(name, 0, i).toString() + '…';
             }
+            label = label + "[“" + name + "”]";
         }
-        return name;
+        return label;
     }
 
     /**
@@ -103,6 +116,6 @@ final class CRSPair {
      */
     @Override
     public String toString() {
-        return shortName(sourceCRS) + " → " + shortName(targetCRS);
+        return label(sourceCRS) + " → " + label(targetCRS);
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java?rev=1737889&r1=1737888&r2=1737889&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
[UTF-8] Tue Apr  5 22:24:20 2016
@@ -18,6 +18,7 @@ package org.apache.sis.referencing.opera
 
 import java.util.Map;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Collections;
 import javax.measure.unit.Unit;
 import javax.measure.quantity.Duration;
@@ -56,9 +57,6 @@ import org.apache.sis.referencing.Common
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.referencing.cs.CoordinateSystems;
-import org.apache.sis.referencing.cs.DefaultVerticalCS;
-import org.apache.sis.referencing.crs.DefaultVerticalCRS;
-import org.apache.sis.referencing.crs.DefaultGeographicCRS;
 import org.apache.sis.referencing.datum.BursaWolfParameters;
 import org.apache.sis.referencing.datum.DefaultGeodeticDatum;
 import org.apache.sis.referencing.operation.matrix.Matrices;
@@ -177,6 +175,21 @@ public class CoordinateOperationInferenc
     private double desiredAccuracy;
 
     /**
+     * Identifiers used as the basis for identifier of CRS used as an intermediate step.
+     * The values can be of two kinds:
+     *
+     * <ul>
+     *   <li>If the value is an instance of {@link Integer}, then this is the number
+     *       of identifiers derived from the identifier associated to the key.</li>
+     *   <li>Otherwise the key is itself an {@link Indentifier} derived from another
+     *       identifier, and the value is that identifier.</li>
+     * </ul>
+     *
+     * @see #derivedFrom(IdentifiedObject)
+     */
+    private final Map<Identifier,Object> identifierOfStepCRS;
+
+    /**
      * The pair of source and target CRS for which we already searched a coordinate operation.
      * This is used as a safety against infinite recursivity.
      */
@@ -200,7 +213,8 @@ public class CoordinateOperationInferenc
             desiredAccuracy = context.getDesiredAccuracy();
             bbox            = context.getGeographicBoundingBox();
         }
-        previousSearches = new HashMap<>(4);
+        identifierOfStepCRS = new HashMap<>(8);
+        previousSearches    = new HashMap<>(8);
     }
 
     /**
@@ -235,29 +249,6 @@ public class CoordinateOperationInferenc
         }
         ////////////////////////////////////////////////////////////////////////////////
         ////                                                                        ////
-        ////                        Compound  →  various CRS                        ////
-        ////                                                                        ////
-        ////  We check CompoundCRS first because experience shows that it produces  ////
-        ////  simpler transformation chains than if we check them last.             ////
-        ////                                                                        ////
-        ////////////////////////////////////////////////////////////////////////////////
-        if (sourceCRS instanceof CompoundCRS) {
-            final CompoundCRS source = (CompoundCRS) sourceCRS;
-            if (targetCRS instanceof CompoundCRS) {
-//              return createOperationStep(source, (CompoundCRS) targetCRS);
-            }
-            if (targetCRS instanceof SingleCRS) {
-//              return createOperationStep(source, (SingleCRS) targetCRS);
-            }
-        }
-        if (targetCRS instanceof CompoundCRS) {
-            final CompoundCRS target = (CompoundCRS) targetCRS;
-            if (sourceCRS instanceof SingleCRS) {
-//              return createOperationStep((SingleCRS) sourceCRS, target);
-            }
-        }
-        ////////////////////////////////////////////////////////////////////////////////
-        ////                                                                        ////
         ////                       Derived  →  any Single CRS                       ////
         ////                                                                        ////
         ////////////////////////////////////////////////////////////////////////////////
@@ -317,6 +308,14 @@ public class CoordinateOperationInferenc
                 return createOperationStep(source, (TemporalCRS) targetCRS);
             }
         }
+        ////////////////////////////////////////////////////////////////////////////////
+        ////                                                                        ////
+        ////                        Compound  ↔  various CRS                        ////
+        ////                                                                        ////
+        ////////////////////////////////////////////////////////////////////////////////
+        if (sourceCRS instanceof CompoundCRS || targetCRS instanceof CompoundCRS) {
+            return decompose(sourceCRS, targetCRS);
+        }
         throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS));
     }
 
@@ -585,7 +584,8 @@ public class CoordinateOperationInferenc
         if (!(interpolationCS instanceof EllipsoidalCS)) {
             final EllipsoidalCS cs = CommonCRS.WGS84.geographic3D().getCoordinateSystem();
             if (!equalsIgnoreMetadata(interpolationCS, cs)) {
-                step1 = createOperation(sourceCRS, new DefaultGeographicCRS(sameNameAs(sourceCRS),
sourceCRS.getDatum(), cs));
+                step1 = createOperation(sourceCRS, factorySIS.getCRSFactory()
+                        .createGeographicCRS(derivedFrom(sourceCRS), sourceCRS.getDatum(),
cs));
                 interpolationCRS = step1.getTargetCRS();
                 interpolationCS  = interpolationCRS.getCoordinateSystem();
             }
@@ -614,11 +614,12 @@ public class CoordinateOperationInferenc
             heightCS  = heightCRS.getCoordinateSystem();
             isEllipsoidalHeight = equalsIgnoreMetadata(heightCS.getAxis(0), expectedAxis);
             if (!isEllipsoidalHeight) {
-                heightCS = new DefaultVerticalCS(sameNameAs(heightCS), expectedAxis);
+                heightCS = factorySIS.getCSFactory().createVerticalCS(derivedFrom(heightCS),
expectedAxis);
             }
         }
         if (!isEllipsoidalHeight) {                     // 'false' if we need to change datum,
unit or axis direction.
-            heightCRS = new DefaultVerticalCRS(sameNameAs(heightCRS), CommonCRS.Vertical.ELLIPSOIDAL.datum(),
heightCS);
+            heightCRS = factorySIS.getCRSFactory()
+                    .createVerticalCRS(derivedFrom(heightCRS), CommonCRS.Vertical.ELLIPSOIDAL.datum(),
heightCS);
         }
         if (heightCRS != targetCRS) {
             step3     = createOperation(heightCRS, targetCRS);  // May need interpolationCRS
for performing datum change.
@@ -726,6 +727,55 @@ public class CoordinateOperationInferenc
     }
 
     /**
+     * Creates an operation between at least one {@code CompoundCRS} (usually the source)
and an arbitrary CRS.
+     * The default implementation tries to invoke the {@link #createOperation createOperation(…)}
method with
+     * various combinations of source and target components. A preference is given for components
of the same
+     * type (e.g. source {@link GeodeticCRS} with target {@code GeodeticCRS}, <i>etc.</i>).
+     *
+     * @param  sourceCRS  input coordinate reference system.
+     * @param  targetCRS  output coordinate reference system.
+     * @return a coordinate operation from {@code sourceCRS} to {@code targetCRS}.
+     * @throws FactoryException if the operation can not be constructed.
+     */
+    private CoordinateOperation decompose(final CoordinateReferenceSystem sourceCRS,
+                                          final CoordinateReferenceSystem targetCRS)
+            throws FactoryException
+    {
+        final List<SingleCRS> sources = CRS.getSingleComponents(sourceCRS);
+        final List<SingleCRS> targets = CRS.getSingleComponents(targetCRS);
+        final SourceComponent[] infos = new SourceComponent[targets.size()];
+        final boolean[]  sourceIsUsed = new boolean[sources.size()];
+        /*
+         * Operations found are stored in 'infos', but are not yet wrapped in PassThroughOperations.
+         * We need to know first if some ordinate values need reordering for matching the
target CRS
+         * order. We also need to know if any source ordinates should be dropped.
+         */
+        for (int i=0; i<infos.length; i++) {
+            if ((infos[i] = SourceComponent.create(this, sourceIsUsed, sources, targets.get(i)))
== null) {
+                throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS));
+            }
+        }
+        /*
+         * A coordinate operation has been found for every target component CRS.
+         * Some reordering of ordinate values may be needed, and some coordinates may need
to be dropped.
+         */
+        final Matrix select = SourceComponent.sourceToSelected(sourceCRS.getCoordinateSystem().getDimension(),
infos);
+        throw new UnsupportedOperationException();      // TODO continue work from here.
+    }
+
+
+
+
+
+    /////////////////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////////////////
+    ////////////                                                         ////////////
+    ////////////                M I S C E L L A N E O U S                ////////////
+    ////////////                                                         ////////////
+    /////////////////////////////////////////////////////////////////////////////////
+    /////////////////////////////////////////////////////////////////////////////////
+
+    /**
      * Creates a coordinate operation from a matrix, which usually describes an affine transform.
      * A default {@link OperationMethod} object is given to this transform. In the special
case
      * where the {@code name} identifier is {@link #DATUM_SHIFT} or {@link #ELLIPSOID_CHANGE},
@@ -996,28 +1046,46 @@ public class CoordinateOperationInferenc
     }
 
     /**
-     * Returns the name of the given object in a singleton map.
-     */
-    private static Map<String,?> sameNameAs(final IdentifiedObject object) {
-        return Collections.singletonMap(IdentifiedObject.NAME_KEY, object.getName());
+     * Returns a name for an object derived from the specified one.
+     * This method builds a name of the form "{@literal <original identifier>} (step
1)"
+     * where "(step 1)" may be replaced by "(step 2)", "(step 3)", <i>etc.</i>
if this
+     * method has already been invoked for the same identifier (directly or indirectly).
+     */
+    private Map<String,?> derivedFrom(final IdentifiedObject object) {
+        Identifier oldID = object.getName();
+        Object p = identifierOfStepCRS.get(oldID);
+        if (p instanceof Identifier) {
+            oldID = (Identifier) p;
+            p = identifierOfStepCRS.get(oldID);
+        }
+        final int count = (p != null) ? (Integer) p + 1 : 1;
+        final Identifier newID = new NamedIdentifier(Citations.SIS, oldID.getCode() + " (step
" + count + ')');
+        identifierOfStepCRS.put(newID, oldID);
+        identifierOfStepCRS.put(oldID, count);
+
+        final Map<String,Object> properties = new HashMap<>(4);
+        properties.put(IdentifiedObject.NAME_KEY, newID);
+        properties.put(IdentifiedObject.REMARKS_KEY, Vocabulary.formatInternational(
+                            Vocabulary.Keys.DerivedFrom_1, CRSPair.label(object)));
+        return properties;
     }
 
     /**
      * Returns a name for a transformation between two CRS.
      */
     private static Map<String,?> defaultName(CoordinateReferenceSystem source, CoordinateReferenceSystem
target) {
-        return properties(CRSPair.shortName(source) + " → " + CRSPair.shortName(target));
+        return properties(CRSPair.label(source) + " → " + CRSPair.label(target));
     }
 
     /**
      * Returns an error message for "No path found from sourceCRS to targetCRS".
      * This is used for the construction of {@link OperationNotFoundException}.
      *
-     * @param  source The source CRS.
-     * @param  target The target CRS.
+     * @param  source the source CRS.
+     * @param  target the target CRS.
      * @return A default error message.
      */
     private static String notFoundMessage(final IdentifiedObject source, final IdentifiedObject
target) {
-        return Errors.format(Errors.Keys.CoordinateOperationNotFound_2, CRSPair.shortName(source),
CRSPair.shortName(target));
+        return Errors.format(Errors.Keys.CoordinateOperationNotFound_2, CRSPair.label(source),
CRSPair.label(target));
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java?rev=1737889&r1=1737888&r2=1737889&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
[UTF-8] Tue Apr  5 22:24:20 2016
@@ -30,6 +30,8 @@ import org.opengis.referencing.crs.Coord
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.ProjectedCRS;
 import org.opengis.referencing.crs.SingleCRS;
+import org.opengis.referencing.crs.CRSFactory;
+import org.opengis.referencing.cs.CSFactory;
 import org.opengis.referencing.datum.Datum;
 import org.apache.sis.internal.referencing.MergedProperties;
 import org.apache.sis.internal.metadata.ReferencingServices;
@@ -44,6 +46,7 @@ import org.apache.sis.util.iso.AbstractF
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.Classes;
 import org.apache.sis.util.NullArgumentException;
 import org.apache.sis.util.Utilities;
 
@@ -85,6 +88,22 @@ public class DefaultCoordinateOperationF
     private final Map<String,?> defaultProperties;
 
     /**
+     * The factory to use if {@link CoordinateOperationInference} needs to create CRS for
intermediate steps.
+     * Will be created only when first needed.
+     *
+     * @see #getCRSFactory()
+     */
+    private volatile CRSFactory crsFactory;
+
+    /**
+     * The factory to use if {@link CoordinateOperationInference} needs to create CS for
intermediate steps.
+     * Will be created only when first needed.
+     *
+     * @see #getCSFactory()
+     */
+    private volatile CSFactory csFactory;
+
+    /**
      * The math transform factory. Will be created only when first needed.
      *
      * @see #getMathTransformFactory()
@@ -101,8 +120,7 @@ public class DefaultCoordinateOperationF
      * Constructs a factory with no default properties.
      */
     public DefaultCoordinateOperationFactory() {
-        defaultProperties = Collections.emptyMap();
-        pool = new WeakHashSet<>(IdentifiedObject.class);
+        this(null, null);
     }
 
     /**
@@ -110,19 +128,36 @@ public class DefaultCoordinateOperationF
      * {@code DefaultCoordinateOperationFactory} will fallback on the map given to this constructor
      * for any property not present in the map provided to a {@code createFoo(Map<String,?>,
…)} method.
      *
-     * @param properties The default properties, or {@code null} if none.
-     * @param mtFactory The factory to use for creating
+     * @param properties the default properties, or {@code null} if none.
+     * @param factory the factory to use for creating
      *        {@linkplain org.apache.sis.referencing.operation.transform.AbstractMathTransform
math transforms},
      *        or {@code null} for the default factory.
      */
-    public DefaultCoordinateOperationFactory(Map<String,?> properties, final MathTransformFactory
mtFactory) {
+    public DefaultCoordinateOperationFactory(Map<String,?> properties, final MathTransformFactory
factory) {
         if (properties == null || properties.isEmpty()) {
             properties = Collections.emptyMap();
         } else {
-            properties = CollectionsExt.compact(new HashMap<String,Object>(properties));
+            String key   = null;
+            Object value = null;
+            properties   = new HashMap<>(properties);
+            /*
+             * Following use of properties is an undocumented feature for now. Current version
documents only
+             * MathTransformFactory because math transforms are intimately related to coordinate
operations.
+             */
+            try {
+                crsFactory = (CRSFactory)           (value = properties.remove(key = ReferencingServices.CRS_FACTORY));
+                csFactory  = (CSFactory)            (value = properties.remove(key = ReferencingServices.CS_FACTORY));
+                mtFactory  = (MathTransformFactory) (value = properties.remove(key = ReferencingServices.MT_FACTORY));
+            } catch (ClassCastException e) {
+                throw new IllegalArgumentException(Errors.getResources(properties)
+                        .getString(Errors.Keys.IllegalPropertyClass_2, key, Classes.getClass(value)));
+            }
+            properties = CollectionsExt.compact(properties);
         }
         defaultProperties = properties;
-        this.mtFactory = mtFactory;
+        if (factory != null) {
+            mtFactory = factory;
+        }
         pool = new WeakHashSet<>(IdentifiedObject.class);
     }
 
@@ -148,6 +183,28 @@ public class DefaultCoordinateOperationF
     }
 
     /**
+     * Returns the factory to use if {@link CoordinateOperationInference} needs to create
CRS for intermediate steps.
+     */
+    final CRSFactory getCRSFactory() {
+        CRSFactory factory = crsFactory;
+        if (factory == null) {
+            crsFactory = factory = DefaultFactories.forBuildin(CRSFactory.class);
+        }
+        return factory;
+    }
+
+    /**
+     * Returns the factory to use if {@link CoordinateOperationInference} needs to create
CS for intermediate steps.
+     */
+    final CSFactory getCSFactory() {
+        CSFactory factory = csFactory;
+        if (factory == null) {
+            csFactory = factory = DefaultFactories.forBuildin(CSFactory.class);
+        }
+        return factory;
+    }
+
+    /**
      * Returns the underlying math transform factory. This factory is used for constructing
{@link MathTransform}
      * dependencies for all {@linkplain AbstractCoordinateOperation coordinate operations}
instances.
      *

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SourceComponent.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SourceComponent.java?rev=1737889&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SourceComponent.java
(added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/SourceComponent.java
[UTF-8] Tue Apr  5 22:24:20 2016
@@ -0,0 +1,188 @@
+/*
+ * 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 java.util.List;
+import org.opengis.referencing.crs.*;
+import org.opengis.referencing.operation.CoordinateOperation;
+import org.opengis.referencing.operation.Matrix;
+import org.opengis.referencing.operation.OperationNotFoundException;
+import org.opengis.util.FactoryException;
+import org.apache.sis.util.logging.Logging;
+import org.apache.sis.internal.system.Loggers;
+import org.apache.sis.referencing.operation.matrix.Matrices;
+
+
+/**
+ * Information about the relationship between a source component and a target component
+ * in {@code CompoundCRS} instances.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.7
+ * @version 0.7
+ * @module
+ */
+final class SourceComponent {
+    /**
+     * Types of target CRS, together with the type of CRS that may be used as the source
for that target.
+     * For each array {@code COMPATIBLE_TYPES[i]}, the first element (i.e. {@code COMPATIBLE_TYPES[i][0]})
+     * is the target CRS and the whole array (including the first element) gives the valid
source CRS type,
+     * if preference order.
+     *
+     * <div class="note"><b>Example:</b>
+     * if a target CRS is of type {@link VerticalCRS}, then the source CRS may be another
{@code VerticalCRS}
+     * or a {@link GeodeticCRS}. The geodetic CRS is possible because it may be three-dimensional.</div>
+     *
+     * {@link ProjectedCRS} and {@link DerivedCRS} are not in this list because we rather
use their base CRS
+     * as the criterion for determining their type.
+     */
+    private static final Class<?>[][] COMPATIBLE_TYPES = {
+        {GeodeticCRS.class},
+        {VerticalCRS.class, GeodeticCRS.class},
+        {TemporalCRS.class},
+        {ParametricCRS.class},
+        {EngineeringCRS.class},
+        {ImageCRS.class}
+    };
+
+    /**
+     * Returns the class of the given CRS after unwrapping derived and projected CRS.
+     * The returned type is for use with {@link #COMPATIBLE_TYPES}.
+     */
+    private static Class<?> type(SingleCRS crs) {
+        while (crs instanceof GeneralDerivedCRS) {
+            crs = ((GeneralDerivedCRS) crs).getBaseCRS();
+        }
+        return crs.getClass();
+    }
+
+    /**
+     * The coordinate operation between a source component and a target component.
+     */
+    final CoordinateOperation operation;
+
+    /**
+     * Returns the first dimension (inclusive) where the source component CRS begins in the
source compound CRS.
+     */
+    private final int startAtDimension;
+
+    /**
+     * Returns the last dimension (exclusive) where the source component CRS ends in the
source compound CRS.
+     */
+    private final int endAtDimension;
+
+    /**
+     * Creates a new instance containing the given information.
+     */
+    private SourceComponent(final CoordinateOperation operation, final int startAtDimension,
final int endAtDimension) {
+        this.operation        = operation;
+        this.startAtDimension = startAtDimension;
+        this.endAtDimension   = endAtDimension;
+    }
+
+    /**
+     * Searches in given list of source components for an operation capable to convert or
transform coordinates
+     * to the given target CRS. If no such operation can be found, then this method returns
{@code null}.
+     *
+     * @param  caller       the object which is inferring a coordinate operation.
+     * @param  sourceIsUsed flags for keeping trace of which source has been used.
+     * @param  sources      all components of the source CRS.
+     * @param  target       one component of the target CRS.
+     * @return information about a coordinate operation from a source CRS to the given target
CRS, or {@code null}.
+     * @throws FactoryException if an error occurred while grabbing a coordinate operation.
+     */
+    static SourceComponent create(final CoordinateOperationInference caller, final boolean[]
sourceIsUsed,
+            final List<SingleCRS> sources, final SingleCRS target) throws FactoryException
+    {
+        OperationNotFoundException failure = null;
+        final Class<?> targetType = type(target);
+        for (final Class<?>[] sourceTypes : COMPATIBLE_TYPES) {
+            if (sourceTypes[0].isAssignableFrom(targetType)) {
+                int startAtDimension;
+                int endAtDimension = 0;
+                for (final Class<?> sourceType : sourceTypes) {
+                    for (int i=0; i<sourceIsUsed.length; i++) {
+                        final SingleCRS source = sources.get(i);
+                        startAtDimension = endAtDimension;
+                        endAtDimension += source.getCoordinateSystem().getDimension();
+                        if (!sourceIsUsed[i] && sourceType.isInstance(source)) {
+                            final CoordinateOperation operation;
+                            try {
+                                operation = caller.createOperation(source, target);
+                            } catch (OperationNotFoundException exception) {
+                                if (failure == null) {
+                                    failure = exception;
+                                } else {
+                                    failure.addSuppressed(exception);
+                                }
+                                continue;
+                            }
+                            /*
+                             * Found an operation. Remove the source component from the list
because each source
+                             * should be used at most once by SourceComponent. Note that
the same source may still
+                             * be used again in another context if that source is also an
interpolation CRS.
+                             *
+                             * EXAMPLE: consider a coordinate operation from (GeodeticCRS₁,
VerticalCRS₁) source
+                             * to (GeodeticCRS₂, VerticalCRS₂) target.  The source GeodeticCRS₁
should be mapped
+                             * to exactly one target component (which is GeodeticCRS₂)
 and  VerticalCRS₁ mapped
+                             * to VerticalCRS₂.  But the operation on vertical coordinates
may need GeodeticCRS₁
+                             * for doing its work, so GeodeticCRS₁ is needed twice.  However
when needed for the
+                             * vertical coordinate operation, the GeodeticCRS₁ is used
as an "interpolation CRS".
+                             * Interpolation CRS are handled in other code paths; it is not
the business of this
+                             * SourceComponent class to care about them. From the point of
view of this class,
+                             * GeodeticCRS₁ is used only once.
+                             */
+                            sourceIsUsed[i] = true;
+                            if (failure != null) {
+                                Logging.recoverableException(Logging.getLogger(Loggers.COORDINATE_OPERATION),
+                                        CoordinateOperationInference.class, "decompose",
failure);
+                            }
+                            return new SourceComponent(operation, startAtDimension, endAtDimension);
+                        }
+                    }
+                }
+            }
+        }
+        if (failure != null) {
+            throw failure;
+        }
+        return null;
+    }
+
+    /**
+     * Returns a matrix for an affine transform from all source coordinates to the coordinates
of the
+     * source components selected for participating in the coordinate operation.
+     *
+     * @param sourceDimensions number of dimension of the source {@code CompoundCRS}.
+     * @param selected all {@code SourceComponent} instances needed for the target {@code
CompoundCRS}.
+     */
+    static Matrix sourceToSelected(final int sourceDimensions, final SourceComponent[] selected)
{
+        int selectedDimensions = 0;
+        for (final SourceComponent component : selected) {
+            selectedDimensions += component.endAtDimension - component.startAtDimension;
+        }
+        final Matrix select = Matrices.createZero(selectedDimensions + 1, sourceDimensions
+ 1);
+        select.setElement(selectedDimensions, sourceDimensions, 1);
+        int j = 0;
+        for (final SourceComponent component : selected) {
+            for (int i=component.startAtDimension; i<component.endAtDimension; i++) {
+                select.setElement(j++, i, 1);
+            }
+        }
+        return select;
+    }
+}

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

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

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/Classes.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/Classes.java?rev=1737889&r1=1737888&r2=1737889&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/Classes.java [UTF-8]
(original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/Classes.java [UTF-8]
Tue Apr  5 22:24:20 2016
@@ -370,10 +370,10 @@ next:       for (final Class<?> candidat
                     for (int i=0; i<count; i++) {
                         final Class<?> old = types[i];
                         if (candidate.isAssignableFrom(old)) {
-                            continue next; // A more specialized interface already exists.
+                            continue next;                      // A more specialized interface
already exists.
                         }
                         if (old.isAssignableFrom(candidate)) {
-                            types[i] = candidate; // This interface specializes a previous
interface.
+                            types[i] = candidate;               // This interface specializes
a previous interface.
                             continue next;
                         }
                     }
@@ -501,14 +501,14 @@ next:       for (final Class<?> candidat
      */
     public static Set<Class<?>> findCommonInterfaces(final Class<?> c1,
final Class<?> c2) {
         final Set<Class<?>> interfaces = getInterfaceSet(c1);
-        final Set<Class<?>> buffer     = getInterfaceSet(c2); // To be recycled.
+        final Set<Class<?>> buffer     = getInterfaceSet(c2);               //
To be recycled.
         if (interfaces == null || buffer == null) {
             return Collections.emptySet();
         }
         interfaces.retainAll(buffer);
         for (Iterator<Class<?>> it=interfaces.iterator(); it.hasNext();) {
             final Class<?> candidate = it.next();
-            buffer.clear(); // Safe because the buffer can not be Collections.EMPTY_SET at
this point.
+            buffer.clear();     // Safe because the buffer can not be Collections.EMPTY_SET
at this point.
             getInterfaceSet(candidate, buffer);
             if (interfaces.removeAll(buffer)) {
                 it = interfaces.iterator();

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java?rev=1737889&r1=1737888&r2=1737889&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
[UTF-8] Tue Apr  5 22:24:20 2016
@@ -191,6 +191,11 @@ public final class Vocabulary extends In
         public static final short DefaultValue = 71;
 
         /**
+         * Derived from {0}
+         */
+        public static final short DerivedFrom_1 = 108;
+
+        /**
          * Description
          */
         public static final short Description = 75;

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties?rev=1737889&r1=1737888&r2=1737889&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
[ISO-8859-1] Tue Apr  5 22:24:20 2016
@@ -41,6 +41,7 @@ Datum                   = Datum
 DatumShift              = Datum shift
 DaylightTime            = Daylight time
 DefaultValue            = Default value
+DerivedFrom_1           = Derived from {0}
 Description             = Description
 Destination             = Destination
 Dimensions              = Dimensions

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties?rev=1737889&r1=1737888&r2=1737889&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
[ISO-8859-1] Tue Apr  5 22:24:20 2016
@@ -48,6 +48,7 @@ Datum                   = R\u00e9f\u00e9
 DatumShift              = Changement de r\u00e9f\u00e9rentiel
 DaylightTime            = Heure normale
 DefaultValue            = Valeur par d\u00e9faut
+DerivedFrom_1           = D\u00e9riv\u00e9 de {0}
 Description             = Description
 Destination             = Destination
 Dimensions              = Dimensions




Mime
View raw message