sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1737101 [3/7] - in /sis/branches/JDK6: ./ application/sis-console/src/main/artifact/conf/ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ core/sis-meta...
Date Wed, 30 Mar 2016 11:25:07 GMT
Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -243,6 +243,13 @@ public class DefaultGeodeticDatum extend
      *   </tr>
      * </table>
      *
+     * If Bursa-Wolf parameters are specified, then the prime meridian of their
+     * {@linkplain BursaWolfParameters#getTargetDatum() target datum} shall be either the same than the
+     * {@code primeMeridian} given to this constructor, or Greenwich. This restriction is for avoiding
+     * ambiguity about whether the longitude rotation shall be applied before or after the datum shift.
+     * If the target prime meridian is Greenwich, then the datum shift will be applied in a coordinate
+     * system having Greenwich as the prime meridian.
+     *
      * @param properties    The properties to be given to the identified object.
      * @param ellipsoid     The ellipsoid.
      * @param primeMeridian The prime meridian.
@@ -265,7 +272,7 @@ public class DefaultGeodeticDatum extend
                 BursaWolfParameters param = bursaWolf[i];
                 ensureNonNullElement("bursaWolf", i, param);
                 param = param.clone();
-                param.verify();
+                param.verify(primeMeridian);
                 bursaWolf[i] = param;
             }
         }
@@ -368,12 +375,21 @@ public class DefaultGeodeticDatum extend
      * 1033 – <cite>Position Vector transformation (geocentric domain)</cite>, or
      * 1053 – <cite>Time-dependent Position Vector transformation</cite>.
      *
-     * <p>If this datum and the given {@code targetDatum} do not use the same
-     * {@linkplain #getPrimeMeridian() prime meridian}, then it is caller's responsibility
-     * to apply longitude rotation before to use the matrix returned by this method.</p>
-     *
-     * <div class="section">Search order</div>
-     * This method performs the search in the following order:
+     * <p>If this datum and the given {@code targetDatum} do not use the same {@linkplain #getPrimeMeridian() prime meridian},
+     * then it is caller's responsibility to to apply longitude rotation before to use the matrix returned by this method.
+     * The target prime meridian should be Greenwich (see {@linkplain #DefaultGeodeticDatum(Map, Ellipsoid, PrimeMeridian)
+     * constructor javadoc}), in which case the datum shift should be applied in a geocentric coordinate system having
+     * Greenwich as the prime meridian.</p>
+     *
+     * <div class="note"><b>Note:</b>
+     * in EPSG dataset version 8.9, all datum shifts that can be represented by this method use Greenwich as the
+     * prime meridian, both in source and target datum.</div>
+     *
+     * <div class="section">Search criterion</div>
+     * If the given {@code areaOfInterest} is non-null and contains at least one geographic bounding box, then this
+     * method ignores any Bursa-Wolf parameters having a {@linkplain BursaWolfParameters#getDomainOfValidity() domain
+     * of validity} that does not intersect the given geographic extent.
+     * This method performs the search among the remaining parameters in the following order:
      * <ol>
      *   <li>If this {@code GeodeticDatum} contains {@code BursaWolfParameters} having the given
      *       {@linkplain BursaWolfParameters#getTargetDatum() target datum} (ignoring metadata),
@@ -449,7 +465,7 @@ public class DefaultGeodeticDatum extend
          * not a subclass of BursaWolfParameters. This optimisation covers the vast majority of cases.
          */
         return bursaWolf.getPositionVectorTransformation(bursaWolf.getClass() != BursaWolfParameters.class ?
-                Extents.getDate(areaOfInterest, 0.5) : null); // 0.5 is for choosing midway instant.
+                Extents.getDate(areaOfInterest, 0.5) : null);       // 0.5 is for choosing midway instant.
     }
 
     /**
@@ -530,7 +546,7 @@ public class DefaultGeodeticDatum extend
     @Override
     public boolean equals(final Object object, final ComparisonMode mode) {
         if (object == this) {
-            return true; // Slight optimization.
+            return true;                                // Slight optimization.
         }
         if (!super.equals(object, mode)) {
             return false;
@@ -547,14 +563,10 @@ public class DefaultGeodeticDatum extend
                 return deepEquals(getEllipsoid(),     that.getEllipsoid(),     mode) &&
                        deepEquals(getPrimeMeridian(), that.getPrimeMeridian(), mode);
                 /*
-                 * HACK: We do not consider Bursa-Wolf parameters as a non-metadata field.
-                 *       This is needed in order to get equalsIgnoreMetadata(...) to returns
-                 *       'true' when comparing the WGS84 constant in this class with a WKT
-                 *       DATUM element with a TOWGS84[0,0,0,0,0,0,0] element. Furthermore,
-                 *       the Bursa-Wolf parameters are not part of ISO 19111 specification.
-                 *       We don't want two CRS to be considered as different because one has
-                 *       more of those transformation informations (which is nice, but doesn't
-                 *       change the CRS itself).
+                 * Bursa-Wolf parameters are considered ignorable metadata. This is needed in order to get
+                 * equalsIgnoreMetadata(…) to return true when comparing WGS84 datums with and without the
+                 * WKT 1 "TOWGS84[0,0,0,0,0,0,0]" element. Furthermore those Bursa-Wolf parameters are not
+                 * part of ISO 19111 specification.
                  */
             }
         }

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -19,6 +19,7 @@ package org.apache.sis.referencing.datum
 import java.util.Date;
 import org.opengis.metadata.extent.Extent;
 import org.opengis.referencing.datum.GeodeticDatum;
+import org.opengis.referencing.datum.PrimeMeridian;
 import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.internal.util.DoubleDouble;
 
@@ -132,8 +133,8 @@ public class TimeDependentBWP extends Bu
      * Verifies parameters validity after initialization.
      */
     @Override
-    void verify() {
-        super.verify();
+    void verify(final PrimeMeridian pm) throws IllegalArgumentException {
+        super.verify(pm);
         ensureFinite("dtX", dtX);
         ensureFinite("dtY", dtY);
         ensureFinite("dtZ", dtZ);

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -40,6 +40,18 @@
  *       DefaultGeodeticDatum.getPositionVectorTransformation(GeodeticDatum, Extent)}</li>
  * </ul>
  *
+ * <div class="section">Datum shifts</div>
+ * Three classes are provided in support of coordinate transformations between different datums:
+ * <ul>
+ *   <li>{@link org.apache.sis.referencing.datum.BursaWolfParameters} performs an approximation
+ *       based on a translation, rotation and scale of geocentric coordinates.</li>
+ *   <li>{@link org.apache.sis.referencing.datum.TimeDependentBWP} is like {@code BursaWolfParameters},
+ *       but varies with time for taking in account the motion of plate tectonic.</li>
+ *   <li>{@link org.apache.sis.referencing.datum.DatumShiftGrid} is used for more accurate transformations
+ *       than what {@code BursaWolfParameters} allows, by interpolating the geographic or geocentric translations
+ *       in a grid (e.g. NADCON or NTv2) instead than apply the same transformation for every points.</li>
+ * </ul>
+ *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Cédric Briançon (Geomatys)
  * @since   0.4

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -640,6 +640,11 @@ public class CommonAuthorityFactory exte
                         return unit;
                     }
 
+                    @Override public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, Unit<?> ignored) {
+                        assert SI.METRE.equals(ignored) : ignored;
+                        return unit;
+                    }
+
                     @Override public boolean accept(CoordinateSystemAxis axis) {
                         return true;
                     }
@@ -647,6 +652,10 @@ public class CommonAuthorityFactory exte
                     @Override public AxisDirection getDirectionReplacement(AxisDirection direction) {
                         return direction;
                     }
+
+                    @Override public AxisDirection getDirectionReplacement(CoordinateSystemAxis axis, AxisDirection direction) {
+                        return direction;
+                    }
                 });
             }
             /*

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -26,6 +26,8 @@ import java.util.logging.Logger;
 import java.util.logging.LogRecord;
 import java.util.concurrent.atomic.AtomicReference;
 import java.lang.reflect.Constructor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import javax.measure.unit.Unit;
 import javax.measure.quantity.Angle;
 import javax.measure.quantity.Length;
@@ -186,8 +188,9 @@ import org.apache.sis.xml.XML;
  * since localizations are applied by the {@link InternationalString#toString(Locale)} method.</p>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @author  Guilhem Legal (Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  */
 public class GeodeticObjectFactory extends AbstractFactory implements CRSFactory, CSFactory, DatumFactory, Parser {
@@ -1524,7 +1527,13 @@ public class GeodeticObjectFactory exten
             if (c == null) {
                 c = Class.forName("org.apache.sis.io.wkt.GeodeticObjectParser").asSubclass(Parser.class)
                          .getConstructor(Map.class, ObjectFactory.class, MathTransformFactory.class);
-                c.setAccessible(true);
+                final Constructor<?> cp = c;     // For allowing use in inner class or lambda expression.
+                AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                    @Override public Void run() {
+                        cp.setAccessible(true);
+                        return null;
+                    }
+                });
                 parserConstructor = c;
             }
             p = c.newInstance(defaultProperties, this, getMathTransformFactory());

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -751,7 +751,7 @@ public class MultiAuthoritiesFactory ext
                 if (code == null) {
                     message = Errors.format(Errors.Keys.MissingComponentInElement_2, s, "code");
                 } else {
-                    message = Errors.format(Errors.Keys.CanNotCreateObjectOfType_2, type, uri.type);
+                    message = Errors.format(Errors.Keys.CanNotCreateObjectAsInstanceOf_2, type, uri.type);
                 }
                 throw new NoSuchAuthorityCodeException(message, authority, code, s);
             }

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -17,14 +17,21 @@
 package org.apache.sis.referencing.factory.sql;
 
 import java.util.Locale;
+import java.util.List;
+import java.util.Map;
+import java.util.LinkedHashMap;
 import java.sql.ResultSet;
 import javax.measure.unit.Unit;
 import javax.measure.unit.NonSI;
 import javax.measure.unit.SI;
 import javax.measure.converter.ConversionException;
+import org.opengis.util.FactoryException;
+import org.opengis.metadata.extent.Extent;
+import org.apache.sis.internal.referencing.ExtentSelector;
 import org.apache.sis.referencing.datum.BursaWolfParameters;
 import org.apache.sis.referencing.datum.TimeDependentBWP;
 import org.apache.sis.referencing.factory.FactoryDataException;
+import org.apache.sis.referencing.factory.GeodeticAuthorityFactory;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.measure.Units;
 
@@ -123,11 +130,22 @@ final class BursaWolfInfo {
     final int target;
 
     /**
+     * The value of {@code AREA_OF_USE_CODE}.
+     */
+    private final int domainOfValidity;
+
+    /**
+     * The domain of validity as an {@code Extent} object.
+     */
+    private Extent extent;
+
+    /**
      * Fills a structure with the specified values.
      */
-    BursaWolfInfo(final int operation, final int method, final int targetCRS) {
-        this.operation = operation;
-        this.method    = method;
+    BursaWolfInfo(final int operation, final int method, final int targetCRS, final int domainOfValidity) {
+        this.operation        = operation;
+        this.method           = method;
+        this.domainOfValidity = domainOfValidity;
         switch (targetCRS) {
             case TARGET_CRS: target = TARGET_DATUM; break;
             // More codes may be added in future SIS version.
@@ -155,4 +173,44 @@ final class BursaWolfInfo {
     public String toString() {
         return String.valueOf(operation);
     }
+
+    /**
+     * Gets the domain of validity. The result is cached.
+     *
+     * @param factory The factory to use for creating {@code Extent} instances.
+     */
+    Extent getDomainOfValidity(final GeodeticAuthorityFactory factory) throws FactoryException {
+        if (extent == null && domainOfValidity != 0) {
+            extent = factory.createExtent(String.valueOf(domainOfValidity));
+        }
+        return extent;
+    }
+
+    /**
+     * Given an array of {@code BursaWolfInfo} instances, retains only the instances having the largest
+     * domain of validity for each target datum. If two instances have the same domain of validity, the
+     * first one is retained. This presume that the instances have already been sorted for preference order
+     * before to invoke this method.
+     *
+     * @param factory     The factory to use for creating {@code Extent} instances.
+     * @param candidates  The Bursa-Wolf parameters candidates.
+     * @param addTo       Where to add the instances retained by this method.
+     */
+    static void filter(final GeodeticAuthorityFactory factory, final BursaWolfInfo[] candidates,
+            final List<BursaWolfInfo> addTo) throws FactoryException
+    {
+        final Map<Integer,ExtentSelector<BursaWolfInfo>> added = new LinkedHashMap<Integer,ExtentSelector<BursaWolfInfo>>();
+        for (BursaWolfInfo candidate : candidates) {
+            final Integer target = candidate.target;
+            ExtentSelector<BursaWolfInfo> selector = added.get(target);
+            if (selector == null) {
+                selector = new ExtentSelector<BursaWolfInfo>(null);
+                added.put(target, selector);
+            }
+            selector.evaluate(candidate.getDomainOfValidity(factory), candidate);
+        }
+        for (final ExtentSelector<BursaWolfInfo> select : added.values()) {
+            addTo.add(select.best());
+        }
+    }
 }

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -19,7 +19,6 @@ package org.apache.sis.referencing.facto
 import java.util.Set;
 import java.util.Map;
 import java.util.List;
-import java.util.HashSet;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedHashMap;
@@ -40,7 +39,6 @@ import java.sql.ResultSetMetaData;
 import java.sql.Statement;
 import java.sql.SQLException;
 import java.text.DateFormat;
-import java.text.SimpleDateFormat;
 import java.text.ParseException;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -72,6 +70,7 @@ import org.apache.sis.internal.metadata.
 import org.apache.sis.internal.metadata.sql.SQLUtilities;
 import org.apache.sis.internal.referencing.DeprecatedCode;
 import org.apache.sis.internal.referencing.EPSGParameterDomain;
+import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.referencing.Formulas;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.system.Semaphores;
@@ -107,17 +106,21 @@ import org.apache.sis.util.ArgumentCheck
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.Localized;
 import org.apache.sis.util.Version;
+import org.apache.sis.util.Workaround;
+import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.collection.Containers;
 import org.apache.sis.measure.MeasurementRange;
 import org.apache.sis.measure.NumberRange;
 import org.apache.sis.measure.Units;
 
+import static org.apache.sis.util.Utilities.equalsIgnoreMetadata;
 import static org.apache.sis.internal.referencing.ServicesForMetadata.CONNECTION;
 
 // Branch-dependent imports
 import org.apache.sis.internal.jdk7.JDK7;
 import org.apache.sis.internal.jdk8.JDK8;
 import org.apache.sis.internal.jdk7.AutoCloseable;
+import org.apache.sis.internal.util.StandardDateFormat;
 
 
 /**
@@ -176,6 +179,7 @@ public class EPSGDataAccess extends Geod
      *
      * @see #replaceDeprecatedCS
      */
+    @Workaround(library = "EPSG:6401-6420", version = "8.9")        // Deprecated in 2002 but still present in 2016.
     private static final Map<Integer,Integer> DEPRECATED_CS = deprecatedCS();
     static Map<Integer,Integer> deprecatedCS() {
         final Map<Integer,Integer> m = new HashMap<Integer,Integer>(24);
@@ -1640,7 +1644,7 @@ addURIs:    for (int i=0; ; i++) {
                         properties = new HashMap<String,Object>(properties);         // Protect from changes
                         final Ellipsoid ellipsoid    = owner.createEllipsoid    (getString(code, result, 10));
                         final PrimeMeridian meridian = owner.createPrimeMeridian(getString(code, result, 11));
-                        final BursaWolfParameters[] param = createBursaWolfParameters(epsg);
+                        final BursaWolfParameters[] param = createBursaWolfParameters(meridian, epsg);
                         if (param != null) {
                             properties.put(DefaultGeodeticDatum.BURSA_WOLF_KEY, param);
                         }
@@ -1665,7 +1669,7 @@ addURIs:    for (int i=0; ; i++) {
                             throw new FactoryDataException(error().getString(Errors.Keys.DatumOriginShallBeDate));
                         }
                         if (dateFormat == null) {
-                            dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.CANADA);
+                            dateFormat = new StandardDateFormat();
                             dateFormat.setCalendar(getCalendar());          // Use UTC timezone.
                         }
                         try {
@@ -1713,10 +1717,13 @@ addURIs:    for (int i=0; ; i++) {
      * That legacy format had a {@code TOWGS84} element which needs the information provided by this method.
      * Note that {@code TOWGS84} is a deprecated element as of WKT 2 (ISO 19162).</p>
      *
-     * @param  code The EPSG code of the {@link GeodeticDatum}.
+     * @param  meridian The source datum prime meridian, used for discarding any target datum using a different meridian.
+     * @param  code The EPSG code of the source {@link GeodeticDatum}.
      * @return an array of Bursa-Wolf parameters, or {@code null}.
      */
-    private BursaWolfParameters[] createBursaWolfParameters(final Integer code) throws SQLException, FactoryException {
+    private BursaWolfParameters[] createBursaWolfParameters(final PrimeMeridian meridian, final Integer code)
+            throws SQLException, FactoryException
+    {
         /*
          * We do not provide TOWGS84 information for WGS84 itself or for any other datum on our list of target datum,
          * in order to avoid infinite recursivity. The 'ensureNonRecursive' call is an extra safety check which should
@@ -1729,7 +1736,8 @@ addURIs:    for (int i=0; ; i++) {
         ResultSet result = executeQuery("BursaWolfParametersSet",
                 "SELECT COORD_OP_CODE," +
                       " COORD_OP_METHOD_CODE," +
-                      " TARGET_CRS_CODE" +
+                      " TARGET_CRS_CODE," +
+                      " AREA_OF_USE_CODE"+
                 " FROM [Coordinate_Operation]" +
                " WHERE DEPRECATED=0" +           // Do not put spaces around "=" - SQLTranslator searches for this exact match.
                  " AND TARGET_CRS_CODE = "       + BursaWolfInfo.TARGET_CRS +
@@ -1743,7 +1751,8 @@ addURIs:    for (int i=0; ; i++) {
                 final BursaWolfInfo info = new BursaWolfInfo(
                         getInteger(code, result, 1),                // Operation
                         getInteger(code, result, 2),                // Method
-                        getInteger(code, result, 3));               // Target datum
+                        getInteger(code, result, 3),                // Target datum
+                        getInteger(code, result, 4));               // Domain of validity
                 if (info.target != code) {                          // Paranoiac check.
                     bwInfos.add(info);
                 }
@@ -1764,12 +1773,7 @@ addURIs:    for (int i=0; ; i++) {
             final BursaWolfInfo[] codes = bwInfos.toArray(new BursaWolfInfo[size]);
             sort("Coordinate_Operation", codes);
             bwInfos.clear();
-            final Set<Integer> added = new HashSet<Integer>();
-            for (BursaWolfInfo candidate : codes) {
-                if (added.add(candidate.target)) {
-                    bwInfos.add(candidate);
-                }
-            }
+            BursaWolfInfo.filter(owner, codes, bwInfos);
             size = bwInfos.size();
         }
         /*
@@ -1777,6 +1781,7 @@ addURIs:    for (int i=0; ; i++) {
          */
         final BursaWolfParameters[] parameters = new BursaWolfParameters[size];
         final Locale locale = getLocale();
+        int count = 0;
         for (int i=0; i<size; i++) {
             final BursaWolfInfo info = bwInfos.get(i);
             final GeodeticDatum datum;
@@ -1786,7 +1791,17 @@ addURIs:    for (int i=0; ; i++) {
             } finally {
                 endOfRecursivity(BursaWolfParameters.class, code);
             }
-            final BursaWolfParameters bwp = new BursaWolfParameters(datum, null);
+            /*
+             * Accept only Bursa-Wolf parameters between datum that use the same prime meridian.
+             * This is for avoiding ambiguity about whether longitude rotation should be applied
+             * before or after the datum change. This check is useless for EPSG dataset 8.9 since
+             * all datum seen by this method use Greenwich. But we nevertheless perform this check
+             * as a safety for future evolution or customized EPSG dataset.
+             */
+            if (!equalsIgnoreMetadata(meridian, datum.getPrimeMeridian())) {
+                continue;
+            }
+            final BursaWolfParameters bwp = new BursaWolfParameters(datum, info.getDomainOfValidity(owner));
             result = executeQuery("BursaWolfParameters",
                 "SELECT PARAMETER_CODE," +
                       " PARAMETER_VALUE," +
@@ -1809,9 +1824,9 @@ addURIs:    for (int i=0; ; i++) {
                 // except for the sign of rotation parameters.
                 bwp.reverseRotation();
             }
-            parameters[i] = bwp;
+            parameters[count++] = bwp;
         }
-        return parameters;
+        return ArraysExt.resize(parameters, count);
     }
 
     /**
@@ -2313,7 +2328,8 @@ addURIs:    for (int i=0; ; i++) {
                     throw new FactoryDataException(exception.getLocalizedMessage(), exception);
                 }
                 final AxisName an = getAxisName(nameCode);
-                final CoordinateSystemAxis axis = owner.csFactory.createCoordinateSystemAxis(createProperties("Coordinate Axis", an.name, epsg, an.description, false),
+                final CoordinateSystemAxis axis = owner.csFactory.createCoordinateSystemAxis(
+                        createProperties("Coordinate Axis", an.name, epsg, an.description, false),
                         abbreviation, direction, owner.createUnit(unit));
                 returnValue = ensureSingleton(axis, returnValue, code);
             }
@@ -2832,7 +2848,7 @@ next:               while (r.next()) {
                         sourceDimensions = sourceCRS.getCoordinateSystem().getDimension();
                     } else {
                         sourceCRS = null;
-                        sourceDimensions = 2;       // Acceptable default for projections only.
+                        sourceDimensions = 2;           // Acceptable default for projections only.
                         isDimensionKnown = false;
                     }
                     if (targetCode != null) {
@@ -2840,7 +2856,7 @@ next:               while (r.next()) {
                         targetDimensions = targetCRS.getCoordinateSystem().getDimension();
                     } else {
                         targetCRS = null;
-                        targetDimensions = 2;       // Acceptable default for projections only.
+                        targetDimensions = 2;           // Acceptable default for projections only.
                         isDimensionKnown = false;
                     }
                     /*
@@ -2930,10 +2946,8 @@ next:               while (r.next()) {
                         final MathTransform mt;
                         final MathTransformFactory mtFactory = owner.mtFactory;
                         if (mtFactory instanceof DefaultMathTransformFactory) {
-                            DefaultMathTransformFactory.Context context = new DefaultMathTransformFactory.Context();
-                            context.setSource(sourceCRS);
-                            context.setTarget(targetCRS);
-                            mt = ((DefaultMathTransformFactory) mtFactory).createParameterizedTransform(parameters, context);
+                            mt = ((DefaultMathTransformFactory) mtFactory).createParameterizedTransform(parameters,
+                                    ReferencingUtilities.createTransformContext(sourceCRS, targetCRS, null));
                         } else {
                             // Fallback for non-SIS implementations. Work for map projections but not for Molodensky.
                             mt = mtFactory.createBaseToDerived(sourceCRS, parameters, targetCRS.getCoordinateSystem());

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -350,8 +350,9 @@ public class EPSGFactory extends Concurr
      *     If no provider is specified, then this method will search on the classpath (with {@link java.util.ServiceLoader})
      *     for user-provided implementations of {@code InstallationScriptProvider}.
      *     If no user-specified provider is found, then this method will search for
-     *     {@code "EPSG_Tables.sql"}, {@code "EPSG_Data.sql"} and {@code "EPSG_FKeys.sql"} files in the
-     *     {@code $SIS_DATA/Databases/ExternalSources} directory.</li>
+     *     {@code "EPSG_*Tables.sql"}, {@code "EPSG_*Data.sql"} and {@code "EPSG_*FKeys.sql"} files in the
+     *     {@code $SIS_DATA/Databases/ExternalSources} directory where {@code *} stands for any characters
+     *     provided that there is no ambiguity.</li>
      * </ul>
      *
      * <p><b>Legal constraint:</b>
@@ -374,28 +375,33 @@ public class EPSGFactory extends Concurr
             if (ac) {
                 connection.setAutoCommit(false);
             }
-            boolean success = false;
             try {
-                if (!"".equals(schema)) {                                               // Schema may be null.
-                    installer.setSchema(schema != null ? schema : Constants.EPSG);
-                    if (catalog != null && !catalog.isEmpty()) {
-                        installer.prependNamespace(catalog);
+                boolean success = false;
+                try {
+                    if (!"".equals(schema)) {                                           // Schema may be null.
+                        installer.setSchema(schema != null ? schema : Constants.EPSG);
+                        if (catalog != null && !catalog.isEmpty()) {
+                            installer.prependNamespace(catalog);
+                        }
                     }
-                }
-                installer.run(scriptProvider);
-                success = true;
-            } finally {
-                if (ac) {
-                    if (success) {
-                        connection.commit();
-                    } else {
-                        connection.rollback();
+                    installer.run(scriptProvider, locale);
+                    success = true;
+                } finally {
+                    if (ac) {
+                        if (success) {
+                            connection.commit();
+                        } else {
+                            connection.rollback();
+                        }
+                        connection.setAutoCommit(true);
                     }
-                    connection.setAutoCommit(true);
-                }
-                if (!success) {
-                    installer.logFailure(locale);
                 }
+            } catch (IOException e) {
+                installer.logFailure(locale, e);
+                throw e;
+            } catch (SQLException e) {
+                installer.logFailure(locale, e);
+                throw e;
             }
         } finally {
             installer.close();

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -32,11 +32,10 @@ import java.io.BufferedReader;
 import org.apache.sis.util.StringBuilders;
 import org.apache.sis.internal.metadata.sql.ScriptRunner;
 import org.apache.sis.internal.metadata.sql.SQLUtilities;
-import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.util.Fallback;
 import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.Exceptions;
 import org.apache.sis.util.resources.Messages;
-import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.logging.PerformanceLevel;
 import org.apache.sis.setup.InstallationResources;
 
@@ -251,12 +250,12 @@ final class EPSGInstaller extends Script
      * @throws IOException if an error occurred while reading an input.
      * @throws SQLException if an error occurred while executing a SQL statement.
      */
-    public void run(InstallationResources scriptProvider) throws SQLException, IOException {
+    public void run(InstallationResources scriptProvider, final Locale locale) throws SQLException, IOException {
         long time = System.nanoTime();
-        log(Messages.getResources(null).getLogRecord(Level.INFO, Messages.Keys.CreatingSchema_2, EPSG,
-                SQLUtilities.getSimplifiedURL(getConnection().getMetaData())));
+        InstallationScriptProvider.log(Messages.getResources(locale).getLogRecord(Level.INFO,
+                Messages.Keys.CreatingSchema_2, EPSG, SQLUtilities.getSimplifiedURL(getConnection().getMetaData())));
         if (scriptProvider == null) {
-            scriptProvider = lookupProvider();
+            scriptProvider = lookupProvider(locale);
         }
         final String[] scripts = scriptProvider.getResourceNames(EPSG);
         int numRows = 0;
@@ -269,7 +268,7 @@ final class EPSGInstaller extends Script
             }
         }
         time = System.nanoTime() - time;
-        log(Messages.getResources(null).getLogRecord(
+        InstallationScriptProvider.log(Messages.getResources(locale).getLogRecord(
                 PerformanceLevel.forDuration(time, TimeUnit.NANOSECONDS),
                 Messages.Keys.InsertDuration_2, numRows, time / 1E9f));
     }
@@ -277,7 +276,7 @@ final class EPSGInstaller extends Script
     /**
      * Searches for a SQL script provider on the classpath before to fallback on the default provider.
      */
-    private static InstallationResources lookupProvider() {
+    private static InstallationResources lookupProvider(final Locale locale) throws IOException {
         InstallationResources fallback = null;
         for (final InstallationResources provider : ServiceLoader.load(InstallationResources.class)) {
             if (provider.getAuthorities().contains(EPSG)) {
@@ -287,7 +286,7 @@ final class EPSGInstaller extends Script
                 fallback = provider;
             }
         }
-        return (fallback != null) ? fallback : new InstallationScriptProvider.Default();
+        return (fallback != null) ? fallback : new InstallationScriptProvider.Default(locale);
     }
 
     /**
@@ -296,21 +295,13 @@ final class EPSGInstaller extends Script
      * lets the exception propagate. Another code (for example {@link org.apache.sis.referencing.CRS#forCode(String)})
      * may catch that exception and log another record with the exception message.
      */
-    final void logFailure(final Locale locale) {
+    final void logFailure(final Locale locale, final Exception cause) {
         String message = Messages.getResources(locale).getString(Messages.Keys.CanNotCreateSchema_1, EPSG);
         String status = status(locale);
         if (status != null) {
             message = message + ' ' + status;
         }
-        log(new LogRecord(Level.WARNING, message));
-    }
-
-    /**
-     * Logs the given record. This method pretend that the record has been logged by
-     * {@code EPSGFactory.install(…)} because it is the public API using this class.
-     */
-    private static void log(final LogRecord record) {
-        record.setLoggerName(Loggers.CRS_FACTORY);
-        Logging.log(EPSGFactory.class, "install", record);
+        message = Exceptions.formatChainedMessages(locale, message, cause);
+        InstallationScriptProvider.log(new LogRecord(Level.WARNING, message));
     }
 }

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -19,6 +19,8 @@ package org.apache.sis.referencing.facto
 import java.util.Set;
 import java.util.Locale;
 import java.util.Collections;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
 import java.sql.Connection;
 import java.io.BufferedReader;
 import java.io.LineNumberReader;
@@ -28,14 +30,17 @@ import java.io.IOException;
 import java.io.FileNotFoundException;
 import java.nio.charset.Charset;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.setup.InstallationResources;
 import org.apache.sis.internal.system.DataDirectory;
+import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.internal.util.Constants;
 
 // Branch-dependent imports
 import org.apache.sis.internal.jdk7.StandardCharsets;
+import org.apache.sis.internal.jdk7.DirectoryStream;
 import org.apache.sis.internal.jdk7.Files;
 import org.apache.sis.internal.jdk7.Path;
 
@@ -261,17 +266,27 @@ public abstract class InstallationScript
      */
     protected abstract InputStream openStream(final String name) throws IOException;
 
+    /**
+     * Logs the given record. This method pretend that the record has been logged by
+     * {@code EPSGFactory.install(…)} because it is the public API using this class.
+     */
+    static void log(final LogRecord record) {
+        record.setLoggerName(Loggers.CRS_FACTORY);
+        Logging.log(EPSGFactory.class, "install", record);
+    }
+
 
 
 
     /**
      * The default implementation which use the scripts in the {@code $SIS_DATA/Databases/ExternalSources}
-     * directory, if present. This class expects the files to have those exact names:
+     * directory, if present. This class expects the files to have those exact names where {@code *} stands
+     * for any characters provided that there is no ambiguity:
      *
      * <ul>
-     *   <li>{@code EPSG_Tables.sql}</li>
-     *   <li>{@code EPSG_Data.sql}</li>
-     *   <li>{@code EPSG_FKeys.sql}</li>
+     *   <li>{@code EPSG_*Tables.sql}</li>
+     *   <li>{@code EPSG_*Data.sql}</li>
+     *   <li>{@code EPSG_*FKeys.sql}</li>
      * </ul>
      *
      * @author  Martin Desruisseaux (Geomatys)
@@ -283,27 +298,61 @@ public abstract class InstallationScript
         /**
          * The directory containing the scripts, or {@code null} if it does not exist.
          */
-        private final Path directory;
+        private Path directory;
+
+        /**
+         * Index of the first real file in the array given to the constructor.
+         * We set the value to 1 for skipping the {@code PREPARE} pseudo-file.
+         */
+        private static final int FIRST_FILE = 1;
 
         /**
          * Creates a default provider.
          */
-        Default() {
+        Default(final Locale locale) throws IOException {
             super(Constants.EPSG,
                     PREPARE,
-                    "EPSG_Tables.sql",
-                    "EPSG_Data.sql",
-                    "EPSG_FKeys.sql",
+                    "Tables",
+                    "Data",
+                    "FKeys",
                     FINISH);
 
             Path dir = DataDirectory.DATABASES.getDirectory();
             if (dir != null) {
                 dir = dir.resolve("ExternalSources");
-                if (!Files.isRegularFile(dir.resolve("EPSG_Tables.sql"))) {
-                    dir = null;
+                if (Files.isDirectory(dir)) {
+                    final String[] resources = super.resources;
+                    final String[] found = new String[resources.length - FIRST_FILE - 1];
+                    DirectoryStream stream = Files.newDirectoryStream(dir, "EPSG_*.sql");
+                    try {
+                        for (final Path path : stream) {
+                            final String name = path.getFileName().toString();
+                            for (int i=0; i<found.length; i++) {
+                                final String part = resources[FIRST_FILE + i];
+                                if (name.contains(part)) {
+                                    if (found[i] != null) {
+                                        log(Errors.getResources(locale)
+                                                  .getLogRecord(Level.WARNING, Errors.Keys.DuplicatedElement_1, part));
+                                        return;                         // Stop the search because of duplicated file.
+                                    }
+                                    found[i] = name;
+                                }
+                            }
+                        }
+                    } finally {
+                        stream.close();
+                    }
+                    for (int i=0; i<found.length; i++) {
+                        final String file = found[i];
+                        if (file != null) {
+                            resources[FIRST_FILE + i] = file;
+                        } else {
+                            dir = null;
+                        }
+                    }
+                    directory = dir;
                 }
             }
-            directory = dir;
         }
 
         /**
@@ -337,7 +386,7 @@ public abstract class InstallationScript
          */
         @Override
         protected InputStream openStream(final String name) throws IOException {
-            return Files.newInputStream(directory.resolve(name));
+            return (directory != null) ? Files.newInputStream(directory.resolve(name)) : null;
         }
     }
 }

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -31,6 +31,7 @@ import org.opengis.metadata.quality.Posi
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.crs.GeneralDerivedCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.ConcatenatedOperation;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.MathTransform;
@@ -650,16 +651,29 @@ check:      for (int isTarget=0; ; isTar
      * {@linkplain #transform}, if possible. If no descriptor can be inferred from the math transform,
      * then this method fallback on the {@link OperationMethod} parameters.
      */
-    ParameterDescriptorGroup getParameterDescriptors() throws UnsupportedOperationException {
-        MathTransform mt = transform;
-        while (mt != null) {
-            if (mt instanceof Parameterized) {
+    ParameterDescriptorGroup getParameterDescriptors() {
+        ParameterDescriptorGroup descriptor = getParameterDescriptors(transform);
+        if (descriptor == null) {
+            final OperationMethod method = getMethod();
+            if (method != null) {
+                descriptor = method.getParameters();
+            }
+        }
+        return descriptor;
+    }
+
+    /**
+     * Returns the parameter descriptors for the given transform, or {@code null} if unknown.
+     */
+    static ParameterDescriptorGroup getParameterDescriptors(MathTransform transform) {
+        while (transform != null) {
+            if (transform instanceof Parameterized) {
                 final ParameterDescriptorGroup param;
                 if (Semaphores.queryAndSet(Semaphores.ENCLOSED_IN_OPERATION)) {
-                    throw new AssertionError(); // Should never happen.
+                    throw new AssertionError();                                     // Should never happen.
                 }
                 try {
-                    param = ((Parameterized) mt).getParameterDescriptors();
+                    param = ((Parameterized) transform).getParameterDescriptors();
                 } finally {
                     Semaphores.clear(Semaphores.ENCLOSED_IN_OPERATION);
                 }
@@ -667,14 +681,13 @@ check:      for (int isTarget=0; ; isTar
                     return param;
                 }
             }
-            if (mt instanceof PassThroughTransform) {
-                mt = ((PassThroughTransform) mt).getSubTransform();
+            if (transform instanceof PassThroughTransform) {
+                transform = ((PassThroughTransform) transform).getSubTransform();
             } else {
                 break;
             }
         }
-        final OperationMethod method = getMethod();
-        return (method != null) ? method.getParameters() : null;
+        return null;
     }
 
     /**
@@ -685,13 +698,13 @@ check:      for (int isTarget=0; ; isTar
      * @throws UnsupportedOperationException if the parameter values can not
      *         be determined for the current math transform implementation.
      */
-    ParameterValueGroup getParameterValues() {
+    ParameterValueGroup getParameterValues() throws UnsupportedOperationException {
         MathTransform mt = transform;
         while (mt != null) {
             if (mt instanceof Parameterized) {
                 final ParameterValueGroup param;
                 if (Semaphores.queryAndSet(Semaphores.ENCLOSED_IN_OPERATION)) {
-                    throw new AssertionError(); // Should never happen.
+                    throw new AssertionError();                                     // Should never happen.
                 }
                 try {
                     param = ((Parameterized) mt).getParameterValues();
@@ -844,32 +857,45 @@ check:      for (int isTarget=0; ; isTar
     protected String formatTo(final Formatter formatter) {
         super.formatTo(formatter);
         formatter.newLine();
-        append(formatter, getSourceCRS(), WKTKeywords.SourceCRS);
-        append(formatter, getTargetCRS(), WKTKeywords.TargetCRS);
-        formatter.append(DefaultOperationMethod.castOrCopy(getMethod()));
-        ParameterValueGroup parameters;
-        try {
-            parameters = getParameterValues();
-        } catch (UnsupportedOperationException e) {
-            final IdentifiedObject c = getParameterDescriptors();
-            formatter.setInvalidWKT(c != null ? c : this, e);
-            parameters = null;
+        /*
+         * If the WKT is a component of a ConcatenatedOperation, do not format the source and target CRS.
+         * This decision SIS-specific since the WKT 2 specification does not define concatenated operations.
+         * The choice of content to omit may change in any future version.
+         */
+        final boolean isComponent = (formatter.getEnclosingElement(1) instanceof ConcatenatedOperation);
+        if (!isComponent) {
+            append(formatter, getSourceCRS(), WKTKeywords.SourceCRS);
+            append(formatter, getTargetCRS(), WKTKeywords.TargetCRS);
         }
-        if (parameters != null) {
-            formatter.newLine();
-            for (final GeneralParameterValue param : parameters.values()) {
-                WKTUtilities.append(param, formatter);
+        final OperationMethod method = getMethod();
+        if (method != null) {
+            formatter.append(DefaultOperationMethod.castOrCopy(method));
+            ParameterValueGroup parameters;
+            try {
+                parameters = getParameterValues();
+            } catch (UnsupportedOperationException e) {
+                final IdentifiedObject c = getParameterDescriptors();
+                formatter.setInvalidWKT(c != null ? c : this, e);
+                parameters = null;
             }
-        }
-        append(formatter, getInterpolationCRS(), WKTKeywords.InterpolationCRS);
-        final double accuracy = getLinearAccuracy();
-        if (accuracy > 0) {
-            formatter.append(new FormattableObject() {
-                @Override protected String formatTo(final Formatter formatter) {
-                    formatter.append(accuracy);
-                    return WKTKeywords.OperationAccuracy;
+            if (parameters != null) {
+                formatter.newLine();
+                for (final GeneralParameterValue param : parameters.values()) {
+                    WKTUtilities.append(param, formatter);
                 }
-            });
+            }
+        }
+        if (!isComponent) {
+            append(formatter, getInterpolationCRS(), WKTKeywords.InterpolationCRS);
+            final double accuracy = getLinearAccuracy();
+            if (accuracy > 0) {
+                formatter.append(new FormattableObject() {
+                    @Override protected String formatTo(final Formatter formatter) {
+                        formatter.append(accuracy);
+                        return WKTKeywords.OperationAccuracy;
+                    }
+                });
+            }
         }
         if (formatter.getConvention().majorVersion() == 1) {
             formatter.setInvalidWKT(this, null);

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -225,14 +225,14 @@ class AbstractSingleOperation extends Ab
          * ignoring null java.lang.Integer instances.  We do not specify whether the method
          * dimensions should include the interpolation dimensions or not, so we accept both.
          */
-        int isTarget = 0;   // 0 == false: the wrong dimension is the source one.
+        int isTarget = 0;               // 0 == false: the wrong dimension is the source one.
         if (expected == null || (actual == expected) || (actual == expected + interpDim)) {
             actual = transform.getTargetDimensions();
             expected = method.getTargetDimensions();
             if (expected == null || (actual == expected) || (actual == expected + interpDim)) {
                 return;
             }
-            isTarget = 1;   // 1 == true: the wrong dimension is the target one.
+            isTarget = 1;               // 1 == true: the wrong dimension is the target one.
         }
         /*
          * At least one dimension does not match.  In principle this is an error, but we make an exception for the

Copied: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java (from r1737089, sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java?p2=sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java&p1=sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java&r1=1737089&r2=1737101&rev=1737101&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -23,7 +23,7 @@ import org.apache.sis.util.CharSequences
 import org.apache.sis.util.Classes;
 
 // Branch-dependent imports
-import java.util.Objects;
+import org.apache.sis.internal.jdk7.Objects;
 
 
 /**

Copied: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java (from r1737089, sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java?p2=sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java&p1=sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java&r1=1737089&r2=1737101&rev=1737101&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -64,7 +64,7 @@ import org.apache.sis.util.resources.Voc
 import static org.apache.sis.util.Utilities.equalsIgnoreMetadata;
 
 // Branch-dependent imports
-import java.util.Objects;
+import org.apache.sis.internal.jdk7.Objects;
 import org.apache.sis.internal.jdk8.JDK8;
 
 
@@ -194,7 +194,7 @@ public class CoordinateOperationInferenc
             desiredAccuracy = context.getDesiredAccuracy();
             bbox            = context.getGeographicBoundingBox();
         }
-        previousSearches = new HashMap<>(4);
+        previousSearches = new HashMap<CRSPair,Boolean>(4);
     }
 
     /**
@@ -558,7 +558,9 @@ public class CoordinateOperationInferenc
         final Matrix matrix;
         try {
             matrix = CoordinateSystems.swapAndScaleAxes(sourceCS, targetCS);
-        } catch (IllegalArgumentException | ConversionException exception) {
+        } catch (IllegalArgumentException exception) {
+            throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS), exception);
+        } catch (ConversionException exception) {
             throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS), exception);
         }
         return createFromAffineTransform(AXIS_CHANGES, sourceCRS, targetCRS, matrix);
@@ -604,7 +606,9 @@ public class CoordinateOperationInferenc
         final Matrix matrix;
         try {
             matrix = CoordinateSystems.swapAndScaleAxes(sourceCS, targetCS);
-        } catch (IllegalArgumentException | ConversionException exception) {
+        } catch (IllegalArgumentException exception) {
+            throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS), exception);
+        } catch (ConversionException exception) {
             throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS), exception);
         }
         final int translationColumn = matrix.getNumCol() - 1;           // Paranoiac check: should always be 1.
@@ -784,7 +788,7 @@ public class CoordinateOperationInferenc
         if (step2.getName() == AXIS_CHANGES && mt2.getSourceDimensions() == mt2.getTargetDimensions()) main = step1;
         if (main instanceof SingleOperation) {
             final MathTransform mt = factorySIS.getMathTransformFactory().createConcatenatedTransform(mt1, mt2);
-            main = createFromMathTransform(new HashMap<>(IdentifiedObjects.getProperties(main)),
+            main = createFromMathTransform(new HashMap<String,Object>(IdentifiedObjects.getProperties(main)),
                    sourceCRS, targetCRS, mt, ((SingleOperation) main).getMethod(),
                    (main instanceof Transformation) ? Transformation.class : SingleOperation.class);
         } else {
@@ -803,7 +807,7 @@ public class CoordinateOperationInferenc
                     break;
                 }
             }
-            main = createFromMathTransform(new HashMap<>(IdentifiedObjects.getProperties(main)),
+            main = createFromMathTransform(new HashMap<String,Object>(IdentifiedObjects.getProperties(main)),
                     main.getSourceCRS(), main.getTargetCRS(), main.getMathTransform(), null, type);
         }
         return main;
@@ -859,7 +863,7 @@ public class CoordinateOperationInferenc
      * @return a modifiable map containing the given name. Callers can put other entries in this map.
      */
     private static Map<String,Object> properties(final Identifier name) {
-        final Map<String,Object> properties = new HashMap<>(4);
+        final Map<String,Object> properties = new HashMap<String,Object>(4);
         properties.put(CoordinateOperation.NAME_KEY, name);
         if ((name == DATUM_SHIFT) || (name == ELLIPSOID_CHANGE)) {
             properties.put(CoordinateOperation.COORDINATE_OPERATION_ACCURACY_KEY, new PositionalAccuracy[] {

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -46,6 +46,7 @@ import static org.apache.sis.util.Utilit
 
 // Branch-dependent imports
 import org.apache.sis.internal.jdk7.Objects;
+import org.apache.sis.io.wkt.Formatter;
 
 
 /**
@@ -325,6 +326,23 @@ final class DefaultConcatenatedOperation
         return super.computeHashCode() + 37 * Objects.hashCode(operations);
     }
 
+    /**
+     * Formats this coordinate operation in pseudo-WKT. This is specific to Apache SIS since
+     * there is no concatenated operation in the Well Known Text (WKT) version 2 format.
+     *
+     * @param  formatter The formatter to use.
+     * @return {@code "ConcatenatedOperation"}.
+     */
+    @Override
+    protected String formatTo(final Formatter formatter) {
+        super.formatTo(formatter);
+        for (final CoordinateOperation component : operations) {
+            formatter.append(castOrCopy(component));
+        }
+        formatter.setInvalidWKT(this, null);
+        return "ConcatenatedOperation";
+    }
+
 
 
 

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -254,12 +254,12 @@ public class DefaultConversion extends A
                  * CoordinateReferenceSystem because the targetCRS is typically under construction when this
                  * method in invoked, and attempts to use it can cause NullPointerException.
                  */
-                final DefaultMathTransformFactory.Context context = new DefaultMathTransformFactory.Context();
-                context.setSource(source);
+                final DefaultMathTransformFactory.Context context;
                 if (target instanceof GeneralDerivedCRS) {
+                    context = ReferencingUtilities.createTransformContext(source, null, null);
                     context.setTarget(target.getCoordinateSystem());    // Using 'target' would be unsafe here.
                 } else {
-                    context.setTarget(target);
+                    context = ReferencingUtilities.createTransformContext(source, target, null);
                 }
                 transform = ((DefaultMathTransformFactory) factory).createParameterizedTransform(parameters, context);
                 parameters = Parameters.unmodifiable(context.getCompletedParameters());

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -19,6 +19,7 @@ package org.apache.sis.referencing.opera
 import java.util.Map;
 import java.util.HashMap;
 import java.util.Collections;
+import java.util.List;
 import org.opengis.util.FactoryException;
 import org.opengis.util.NoSuchIdentifierException;
 import org.opengis.parameter.ParameterValueGroup;
@@ -28,11 +29,13 @@ import org.opengis.referencing.Identifie
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.ProjectedCRS;
+import org.opengis.referencing.crs.SingleCRS;
+import org.opengis.referencing.datum.Datum;
 import org.apache.sis.internal.referencing.MergedProperties;
 import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.util.CollectionsExt;
-import org.apache.sis.internal.util.Utilities;
+import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
 import org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.apache.sis.util.collection.WeakHashSet;
@@ -42,6 +45,7 @@ import org.apache.sis.util.resources.Err
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.NullArgumentException;
+import org.apache.sis.util.Utilities;
 
 
 /**
@@ -68,7 +72,7 @@ import org.apache.sis.util.NullArgumentE
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  */
 public class DefaultCoordinateOperationFactory extends AbstractFactory implements CoordinateOperationFactory {
@@ -149,7 +153,7 @@ public class DefaultCoordinateOperationF
      *
      * @return The underlying math transform factory.
      */
-    private MathTransformFactory getMathTransformFactory() {
+    final MathTransformFactory getMathTransformFactory() {
         MathTransformFactory factory = mtFactory;
         if (factory == null) {
             mtFactory = factory = DefaultFactories.forBuildin(MathTransformFactory.class);
@@ -158,6 +162,18 @@ public class DefaultCoordinateOperationF
     }
 
     /**
+     * Returns the Apache SIS implementation of math transform factory.
+     * This method is used only when we need SIS-specific methods.
+     */
+    final DefaultMathTransformFactory getDefaultMathTransformFactory() {
+        MathTransformFactory factory = getMathTransformFactory();
+        if (factory instanceof DefaultMathTransformFactory) {
+            return (DefaultMathTransformFactory) factory;
+        }
+        return DefaultFactories.forBuildin(MathTransformFactory.class, DefaultMathTransformFactory.class);
+    }
+
+    /**
      * Returns the operation method of the given name. The given argument shall be either a method
      * {@linkplain DefaultOperationMethod#getName() name} (e.g. <cite>"Transverse Mercator"</cite>)
      * or one of its {@linkplain DefaultOperationMethod#getIdentifiers() identifiers} (e.g. {@code "EPSG:9807"}).
@@ -314,6 +330,39 @@ public class DefaultCoordinateOperationF
     }
 
     /**
+     * Returns {@code true} if the given CRS are using equivalent (ignoring metadata) datum.
+     * If the CRS are {@link CompoundCRS}, then this method verifies that all datum in the
+     * target CRS exists in the source CRS, but not necessarily in the same order.
+     * The target CRS may have less datum than the source CRS.
+     *
+     * @param sourceCRS The target CRS.
+     * @param targetCRS The source CRS.
+     * @return {@code true} if all datum in the {@code targetCRS} exists in the {@code sourceCRS}.
+     */
+    private static boolean isConversion(final CoordinateReferenceSystem sourceCRS,
+                                        final CoordinateReferenceSystem targetCRS)
+    {
+        List<SingleCRS> components = CRS.getSingleComponents(sourceCRS);
+        int n = components.size();                      // Number of remaining datum from sourceCRS to verify.
+        final Datum[] datum = new Datum[n];
+        for (int i=0; i<n; i++) {
+            datum[i] = components.get(i).getDatum();
+        }
+        components = CRS.getSingleComponents(targetCRS);
+next:   for (int i=components.size(); --i >= 0;) {
+            final Datum d = components.get(i).getDatum();
+            for (int j=n; --j >= 0;) {
+                if (Utilities.equalsIgnoreMetadata(d, datum[j])) {
+                    System.arraycopy(datum, j+1, datum, j, --n - j);  // Remove the datum from the list.
+                    continue next;
+                }
+            }
+            return false;                               // Datum from 'targetCRS' not found in 'sourceCRS'.
+        }
+        return true;
+    }
+
+    /**
      * Creates a transformation or conversion from the given properties.
      * This method infers by itself if the operation to create is a
      * {@link Transformation}, a {@link Conversion} or a {@link Projection} sub-type
@@ -401,7 +450,7 @@ public class DefaultCoordinateOperationF
         }
         if (method instanceof DefaultOperationMethod) {
             final Class<? extends SingleOperation> c = ((DefaultOperationMethod) method).getOperationType();
-            if (c != null) {  // Paranoiac check (above method should not return null).
+            if (c != null) {                        // Paranoiac check (above method should not return null).
                 if (baseType.isAssignableFrom(c)) {
                     baseType = c;
                 } else if (!c.isAssignableFrom(baseType)) {
@@ -424,7 +473,7 @@ public class DefaultCoordinateOperationF
          * could be different, which we want to allow.
          */
         if (baseType == SingleOperation.class) {
-            if (OperationPathFinder.isConversion(sourceCRS, targetCRS)) {
+            if (isConversion(sourceCRS, targetCRS)) {
                 if (interpolationCRS == null && sourceCRS instanceof GeographicCRS
                                              && targetCRS instanceof ProjectedCRS)
                 {
@@ -473,7 +522,7 @@ public class DefaultCoordinateOperationF
             op = new AbstractSingleOperation(properties, sourceCRS, targetCRS, interpolationCRS, method, transform);
         }
         if (!baseType.isInstance(op)) {
-            throw new FactoryException(Errors.format(Errors.Keys.CanNotInstantiate_1, baseType));
+            throw new FactoryException(Errors.format(Errors.Keys.CanNotCreateObjectAsInstanceOf_2, baseType, op.getName()));
         }
         return pool.unique(op);
     }
@@ -528,57 +577,87 @@ public class DefaultCoordinateOperationF
     }
 
     /**
-     * Not yet implemented.
-     *
-     * @param  sourceCRS Input coordinate reference system.
-     * @param  targetCRS Output coordinate reference system.
-     * @param  method the algorithmic method for conversion or transformation.
-     * @return A coordinate operation from {@code sourceCRS} to {@code targetCRS}.
-     * @throws FactoryException if the operation creation failed.
+     * Finds or creates an operation for conversion or transformation between two coordinate reference systems.
+     * If an operation exists, it is returned. If more than one operation exists, the operation having the widest
+     * domain of validity is returned. If no operation exists, then an exception is thrown.
+     *
+     * <p>The default implementation delegates to <code>{@linkplain #createOperation(CoordinateReferenceSystem,
+     * CoordinateReferenceSystem, CoordinateOperationContext) createOperation}(sourceCRS, targetCRS, null)}</code>.</p>
+     *
+     * @param  sourceCRS  input coordinate reference system.
+     * @param  targetCRS  output coordinate reference system.
+     * @return a coordinate operation from {@code sourceCRS} to {@code targetCRS}.
+     * @throws OperationNotFoundException if no operation path was found from {@code sourceCRS} to {@code targetCRS}.
+     * @throws FactoryException if the operation creation failed for some other reason.
      */
     @Override
     public CoordinateOperation createOperation(final CoordinateReferenceSystem sourceCRS,
-                                               final CoordinateReferenceSystem targetCRS,
-                                               final OperationMethod method)
-            throws FactoryException
+                                               final CoordinateReferenceSystem targetCRS)
+            throws OperationNotFoundException, FactoryException
     {
-        return delegate().createOperation(sourceCRS, targetCRS, method);
+        return createOperation(sourceCRS, targetCRS, (CoordinateOperationContext) null);
     }
 
     /**
-     * Not yet implemented.
+     * Finds or creates an operation for conversion or transformation between two coordinate reference systems.
+     * If an operation exists, it is returned. If more than one operation exists, then the operation having the
+     * widest intersection between its {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of
+     * validity} and the {@linkplain CoordinateOperationContext#getAreaOfInterest() area of interest} is returned.
+     *
+     * <p>The default implementation is as below:</p>
      *
-     * @param  sourceCRS Input coordinate reference system.
-     * @param  targetCRS Output coordinate reference system.
-     * @return A coordinate operation from {@code sourceCRS} to {@code targetCRS}.
+     * {@preformat java
+     *   return new CoordinateOperationInference(this, context).createOperation(sourceCRS, targetCRS);
+     * }
+     *
+     * Subclasses can override this method if they need, for example, to use a custom
+     * {@link CoordinateOperationInference} implementation.
+     *
+     * @param  sourceCRS  input coordinate reference system.
+     * @param  targetCRS  output coordinate reference system.
+     * @param  context    area of interest and desired accuracy, or {@code null}.
+     * @return a coordinate operation from {@code sourceCRS} to {@code targetCRS}.
      * @throws OperationNotFoundException if no operation path was found from {@code sourceCRS} to {@code targetCRS}.
      * @throws FactoryException if the operation creation failed for some other reason.
+     *
+     * @see CoordinateOperationInference
+     *
+     * @since 0.7
      */
-    @Override
     public CoordinateOperation createOperation(final CoordinateReferenceSystem sourceCRS,
-                                               final CoordinateReferenceSystem targetCRS)
+                                               final CoordinateReferenceSystem targetCRS,
+                                               final CoordinateOperationContext context)
             throws OperationNotFoundException, FactoryException
     {
-        return delegate().createOperation(sourceCRS, targetCRS);
+        return new CoordinateOperationInference(this, context).createOperation(sourceCRS, targetCRS);
     }
 
     /**
-     * Temporarily returns a third-party factory for operation not yet implemented by this class.
-     * This method will be removed when the missing implementation will have been ported to SIS.
+     * Returns an operation using a particular method for conversion or transformation between
+     * two coordinate reference systems. If an operation exists using the given method, then it
+     * is returned. If no operation using the given method is found, then the implementation has
+     * the option of inferring the operation from the argument objects.
+     *
+     * <p>Current implementation ignores the {@code method} argument.
+     * This behavior may change in a future Apache SIS version.</p>
+     *
+     * @param  sourceCRS  input coordinate reference system.
+     * @param  targetCRS  output coordinate reference system.
+     * @param  method     the algorithmic method for conversion or transformation.
+     * @return a coordinate operation from {@code sourceCRS} to {@code targetCRS}.
+     * @throws OperationNotFoundException if no operation path was found from {@code sourceCRS} to {@code targetCRS}.
+     * @throws FactoryException if the operation creation failed for some other reason.
+     *
+     * @deprecated Replaced by {@link #createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, CoordinateOperationContext)}.
      */
-    private synchronized CoordinateOperationFactory delegate() throws FactoryException {
-        if (delegate != null) {
-            return delegate;
-        }
-        for (final CoordinateOperationFactory factory : java.util.ServiceLoader.load(CoordinateOperationFactory.class)) {
-            if (!Utilities.isSIS(factory.getClass())) {
-                delegate = factory;
-                return factory;
-            }
-        }
-        throw new FactoryException(Errors.format(Errors.Keys.MissingRequiredModule_1, "geotk-referencing")); // This is temporary.
+    @Override
+    @Deprecated
+    public CoordinateOperation createOperation(final CoordinateReferenceSystem sourceCRS,
+                                               final CoordinateReferenceSystem targetCRS,
+                                               final OperationMethod method)
+            throws FactoryException
+    {
+        ArgumentChecks.ensureNonNull("method", method);     // As a matter of principle.
+        return createOperation(sourceCRS, targetCRS, (CoordinateOperationContext) null);
     }
-
-    /** Temporary, to be deleted in a future SIS version. */
-    private transient CoordinateOperationFactory delegate;
 }

Copied: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java (from r1737089, sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java?p2=sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java&p1=sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java&r1=1737089&r2=1737101&rev=1737101&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/InverseOperationMethod.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -67,7 +67,7 @@ final class InverseOperationMethod exten
         }
         Identifier name = method.getName();
         name = new ImmutableIdentifier(null, name.getCodeSpace(), "Inverse " + name.getCode());
-        final Map<String,Object> properties = new HashMap<>(6);
+        final Map<String,Object> properties = new HashMap<String,Object>(6);
         properties.put(NAME_KEY,    name);
         properties.put(FORMULA_KEY, method.getFormula());
         properties.put(REMARKS_KEY, method.getRemarks());

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java?rev=1737101&r1=1737100&r2=1737101&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java [UTF-8] Wed Mar 30 11:25:06 2016
@@ -191,7 +191,7 @@ class GeneralMatrix extends MatrixSIS im
      */
     static int indexOfErrors(final int numRow, final int numCol, final double[] elements) {
         assert elements.length % (numRow * numCol) == 0;
-        return (numRow * numCol) % elements.length; // A % B is for getting 0 without branching if A == B.
+        return (numRow * numCol) % elements.length;         // A % B is for getting 0 without branching if A == B.
     }
 
     /**
@@ -337,7 +337,7 @@ class GeneralMatrix extends MatrixSIS im
                 if (copy) {
                     elements = elements.clone();
                 }
-                return elements; // Internal array already uses extended precision.
+                return elements;                                // Internal array already uses extended precision.
             } else {
                 elements = Arrays.copyOf(elements, length);
             }
@@ -415,7 +415,7 @@ class GeneralMatrix extends MatrixSIS im
      * @see Matrices#create(int, int, Number[])
      */
     final boolean setElements(final Number[] newValues) {
-        final int numRow = this.numRow; // Protection against accidental changes.
+        final int numRow = this.numRow;                         // Protection against accidental changes.
         final int numCol = this.numCol;
         final int length = numRow * numCol;
         if (newValues.length != length) {
@@ -494,9 +494,18 @@ class GeneralMatrix extends MatrixSIS im
      */
     @Override
     public final boolean isAffine() {
-        final int numRow = this.numRow; // Protection against accidental changes.
+        return isAffine(true);
+    }
+
+    /**
+     * Implementation of {@link #isAffine()} with control on whether we require the matrix to be square.
+     *
+     * @param square {@code true} if the matrix must be square, or {@code false} for allowing non-square matrices.
+     */
+    final boolean isAffine(final boolean square) {
+        final int numRow = this.numRow;                     // Protection against accidental changes.
         final int numCol = this.numCol;
-        if (numRow == numCol) {
+        if (numRow == numCol || !square) {
             int i = numRow * numCol;
             if (elements[--i] == 1) {
                 final int base = (numRow - 1) * numCol;
@@ -526,7 +535,7 @@ class GeneralMatrix extends MatrixSIS im
      */
     @Override
     public final boolean isIdentity() {
-        final int numRow = this.numRow; // Protection against accidental changes.
+        final int numRow = this.numRow;                     // Protection against accidental changes.
         final int numCol = this.numCol;
         if (numRow != numCol) {
             return false;
@@ -553,9 +562,9 @@ class GeneralMatrix extends MatrixSIS im
      */
     @Override
     public void transpose() {
-        final int numRow = this.numRow; // Protection against accidental changes.
+        final int numRow = this.numRow;                                 // Protection against accidental changes.
         final int numCol = this.numCol;
-        final int errors = indexOfErrors(numRow, numCol, elements); // Where error values start, or 0 if none.
+        final int errors = indexOfErrors(numRow, numCol, elements);     // Where error values start, or 0 if none.
         for (int j=0; j<numRow; j++) {
             for (int i=0; i<j; i++) {
                 final int lo = j*numCol + i;
@@ -574,7 +583,7 @@ class GeneralMatrix extends MatrixSIS im
      * The matrix sizes much match - this is not verified unless assertions are enabled.
      */
     final void setToProduct(final Matrix A, final Matrix B) {
-        final int numRow = this.numRow; // Protection against accidental changes.
+        final int numRow = this.numRow;         // Protection against accidental changes.
         final int numCol = this.numCol;
         final int nc = A.getNumCol();
         assert B.getNumRow() == nc;
@@ -585,7 +594,7 @@ class GeneralMatrix extends MatrixSIS im
          */
         final double[] eltA   = getExtendedElements(A, numRow, nc, false);
         final double[] eltB   = getExtendedElements(B, nc, numCol, false);
-        final int errorOffset = numRow * numCol; // Where error terms start.
+        final int errorOffset = numRow * numCol;            // Where error terms start.
         final int errA        = numRow * nc;
         final int errB        = nc * numCol;
         /*
@@ -597,20 +606,20 @@ class GeneralMatrix extends MatrixSIS im
             for (int i=0; i<numCol; i++) {
                 sum.clear();
                 double max = 0;
-                int iB = i;       // Index of values in a single column of B.
-                int iA = j * nc;  // Index of values in a single row of A.
+                int iB = i;                                 // Index of values in a single column of B.
+                int iA = j * nc;                            // Index of values in a single row of A.
                 final int nextRow = iA + nc;
                 while (iA < nextRow) {
                     dot.setFrom (eltA, iA, errA);
                     dot.multiply(eltB, iB, errB);
                     sum.add(dot);
-                    iB += numCol; // Move to next row of B.
-                    iA++;         // Move to next column of A.
+                    iB += numCol;                           // Move to next row of B.
+                    iA++;                                   // Move to next column of A.
                     final double value = Math.abs(dot.value);
                     if (value > max) max = value;
                 }
                 if (Math.abs(sum.value) < Math.ulp(max) * ZERO_THRESHOLD) {
-                    sum.clear(); // Sum is not significant according double arithmetic.
+                    sum.clear();                            // Sum is not significant according double arithmetic.
                 }
                 sum.storeTo(elements, k++, errorOffset);
             }



Mime
View raw message