sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1735974 - in /sis/branches/JDK8/core: sis-referencing/src/main/java/org/apache/sis/internal/referencing/ sis-referencing/src/main/java/org/apache/sis/referencing/datum/ sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/ ...
Date Mon, 21 Mar 2016 13:49:08 GMT
Author: desruisseaux
Date: Mon Mar 21 13:49:07 2016
New Revision: 1735974

URL: http://svn.apache.org/viewvc?rev=1735974&view=rev
Log:
Complete CoordinateOperationInference.createOperationStep(GeocentricCRS, GeocentricCRS)
including longitude rotation and change of coordinate system (Cartesian <-> Spherical).
This work required a clarification of the condition for using the Bursa-Wolf parameters.
In order to avoid ambiguities, we use those parameters only if there is no longitude rotation,
or if the target datum use the Greenwich prime meridian. Otherwise the parameters are ignored
and the transformation will be reported to have a lower accuracy.

Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtentSelector.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.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-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/LoggingWatcher.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtentSelector.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtentSelector.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtentSelector.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ExtentSelector.java [UTF-8] Mon Mar 21 13:49:07 2016
@@ -72,7 +72,7 @@ public final class ExtentSelector<T> {
      */
     public boolean evaluate(final Extent extent, final T object) {
         final double area = Extents.area(Extents.intersection(Extents.getGeographicBoundingBox(extent), areaOfInterest));
-        if (best != null && !(area > largestArea)) { // Use '!' for catching NaN.
+        if (best != null && !(area > largestArea)) {    // Use '!' for catching NaN.
             /*
              * At this point, the given extent is not greater than the previous one.
              * However if the previous object had no extent information at all (i.e.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java [UTF-8] Mon Mar 21 13:49:07 2016
@@ -65,14 +65,16 @@ public final class ReferencingUtilities
      * This method provides the same functionality than {@link DefaultPrimeMeridian#getGreenwichLongitude(Unit)},
      * but on arbitrary implementation.
      *
-     * @param  primeMeridian The prime meridian from which to get the Greenwich longitude.
+     * @param  primeMeridian The prime meridian from which to get the Greenwich longitude, or {@code null}.
      * @param  unit The unit for the prime meridian to return.
-     * @return The prime meridian in the given units.
+     * @return The prime meridian in the given units, or {@code 0} if the given prime meridian was null.
      *
      * @see DefaultPrimeMeridian#getGreenwichLongitude(Unit)
      */
     public static double getGreenwichLongitude(final PrimeMeridian primeMeridian, final Unit<Angle> unit) {
-        if (primeMeridian instanceof DefaultPrimeMeridian) { // Maybe the user overrode some methods.
+        if (primeMeridian == null) {
+            return 0;
+        } else if (primeMeridian instanceof DefaultPrimeMeridian) {         // Maybe the user overrode some methods.
             return ((DefaultPrimeMeridian) primeMeridian).getGreenwichLongitude(unit);
         } else {
             return primeMeridian.getAngularUnit().getConverterTo(unit).convert(primeMeridian.getGreenwichLongitude());

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java [UTF-8] Mon Mar 21 13:49:07 2016
@@ -21,11 +21,13 @@ import java.util.Arrays;
 import java.io.Serializable;
 import org.opengis.metadata.extent.Extent;
 import org.opengis.referencing.datum.GeodeticDatum;
+import org.opengis.referencing.datum.PrimeMeridian;
 import org.opengis.referencing.operation.Matrix;
 import org.apache.sis.referencing.operation.matrix.Matrix4;
 import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.io.wkt.FormattableObject;
 import org.apache.sis.io.wkt.Formatter;
+import org.apache.sis.util.Utilities;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.util.DoubleDouble;
 import org.apache.sis.internal.metadata.WKTKeywords;
@@ -123,7 +125,7 @@ import java.util.Objects;
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  *
  * @see DefaultGeodeticDatum#getBursaWolfParameters()
@@ -226,15 +228,37 @@ public class BursaWolfParameters extends
 
     /**
      * Verifies parameters validity after initialization of {@link DefaultGeodeticDatum}.
-     */
-    void verify() {
+     * This method requires that the prime meridian of the target datum is either the same
+     * than the enclosing {@code GeodeticDatum}, or Greenwich. We put this restriction for
+     * avoiding ambiguity about whether the longitude rotation should be applied before or
+     * after the datum shift.
+     *
+     * <p>If the target prime meridian is Greenwich, then SIS will assume that the datum shift
+     * needs to be applied in a coordinate system having Greenwich as the prime meridian.</p>
+     *
+     * <p><b>Maintenance note:</b>
+     * if the above policy regarding prime meridians is modified, then some {@code createOperationStep(…)} method
+     * implementations in {@link org.apache.sis.referencing.operation.CoordinateOperationInference} may need to be
+     * revisited. See especially the methods creating a transformation between a pair of {@code GeocentricCRS} or
+     * between a pair of {@code GeographicCRS} (tip: search for {@code DefaultGeodeticDatum}).</p>
+     *
+     * @param pm The prime meridian of the enclosing {@code GeodeticDatum}.
+     */
+    void verify(final PrimeMeridian pm) throws IllegalArgumentException {
+        if (targetDatum != null) {
+            final PrimeMeridian actual = targetDatum.getPrimeMeridian();
+            if (actual.getGreenwichLongitude() != 0 && !Utilities.equalsIgnoreMetadata(pm, actual)) {
+                throw new IllegalArgumentException(Errors.format(Errors.Keys.MismatchedPrimeMeridian_2,
+                        IdentifiedObjects.getName(pm, null), IdentifiedObjects.getName(actual, null)));
+            }
+        }
         ensureFinite("tX", tX);
         ensureFinite("tY", tY);
         ensureFinite("tZ", tZ);
         ensureFinite("rX", rX);
         ensureFinite("rY", rY);
         ensureFinite("rZ", rZ);
-        ensureBetween("dS", -PPM, PPM, dS); // For preventing zero or negative value on the matrix diagonal.
+        ensureBetween("dS", -PPM, PPM, dS);     // For preventing zero or negative value on the matrix diagonal.
     }
 
     /**
@@ -276,7 +300,7 @@ public class BursaWolfParameters extends
     public double[] getValues() {
         final double[] elements = new double[(dS != 0) ? 7 : (rZ != 0 || rY != 0 || rX != 0) ? 6 : 3];
         switch (elements.length) {
-            default: elements[6] = dS;  // Fallthrough everywhere.
+            default: elements[6] = dS;      // Fallthrough everywhere.
             case 6:  elements[5] = rZ;
                      elements[4] = rY;
                      elements[3] = rX;
@@ -307,7 +331,7 @@ public class BursaWolfParameters extends
     @SuppressWarnings("fallthrough")
     public void setValues(final double... elements) {
         switch (elements.length) {
-            default: dS = elements[6];  // Fallthrough everywhere.
+            default: dS = elements[6];      // Fallthrough everywhere.
             case 6:  rZ = elements[5];
             case 5:  rY = elements[4];
             case 4:  rX = elements[3];
@@ -543,17 +567,17 @@ public class BursaWolfParameters extends
             }
             for (int i = j+1; i < SIZE-1; i++) {
                 S.setFrom(RS);
-                S.inverseDivide(getNumber(matrix, j,i)); // Negative rotation term.
+                S.inverseDivide(getNumber(matrix, j,i));        // Negative rotation term.
                 double value = S.value;
                 double error = S.error;
                 S.setFrom(RS);
-                S.inverseDivide(getNumber(matrix, i,j)); // Positive rotation term.
-                if (!(abs(value + S.value) <= tolerance)) { // We expect r1 ≈ -r2
+                S.inverseDivide(getNumber(matrix, i,j));        // Positive rotation term.
+                if (!(abs(value + S.value) <= tolerance)) {     // We expect r1 ≈ -r2
                     throw new IllegalArgumentException(Errors.format(Errors.Keys.NotASkewSymmetricMatrix));
                 }
                 S.subtract(value, error);
                 S.multiply(0.5, 0);
-                value = S.value; // Average of the two rotation terms.
+                value = S.value;                                // Average of the two rotation terms.
                 switch (j*SIZE + i) {
                     case 1: rZ =  value; break;
                     case 2: rY = -value; break;

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java [UTF-8] Mon Mar 21 13:49:07 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.
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/TimeDependentBWP.java [UTF-8] Mon Mar 21 13:49:07 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/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java [UTF-8] Mon Mar 21 13:49:07 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/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/BursaWolfInfo.java [UTF-8] Mon Mar 21 13:49:07 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<>();
+        for (BursaWolfInfo candidate : candidates) {
+            final Integer target = candidate.target;
+            ExtentSelector<BursaWolfInfo> selector = added.get(target);
+            if (selector == null) {
+                selector = new ExtentSelector<>(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/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java [UTF-8] Mon Mar 21 13:49:07 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;
@@ -107,11 +106,13 @@ 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
@@ -1619,7 +1620,7 @@ addURIs:    for (int i=0; ; i++) {
                         properties = new HashMap<>(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);
                         }
@@ -1690,10 +1691,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
@@ -1706,7 +1710,8 @@ addURIs:    for (int i=0; ; i++) {
         try (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 +
@@ -1720,7 +1725,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);
                 }
@@ -1739,12 +1745,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<>();
-            for (BursaWolfInfo candidate : codes) {
-                if (added.add(candidate.target)) {
-                    bwInfos.add(candidate);
-                }
-            }
+            BursaWolfInfo.filter(owner, codes, bwInfos);
             size = bwInfos.size();
         }
         /*
@@ -1752,6 +1753,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;
@@ -1761,7 +1763,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));
             try (ResultSet result = executeQuery("BursaWolfParameters",
                 "SELECT PARAMETER_CODE," +
                       " PARAMETER_VALUE," +
@@ -1782,9 +1794,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);
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java [UTF-8] Mon Mar 21 13:49:07 2016
@@ -17,7 +17,11 @@
 package org.apache.sis.referencing.operation;
 
 import java.io.Serializable;
+import org.opengis.metadata.extent.Extent;
 import org.opengis.metadata.extent.GeographicBoundingBox;
+import org.apache.sis.metadata.iso.extent.DefaultExtent;
+import org.apache.sis.metadata.iso.extent.Extents;
+import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.util.ArgumentChecks;
 
 
@@ -57,9 +61,14 @@ public class CoordinateOperationContext
     private static final long serialVersionUID = -6944460471653277973L;
 
     /**
-     * The area of interest, or {@code null} if none.
+     * The spatio-temporal area of interest, or {@code null} if none.
      */
-    private GeographicBoundingBox areaOfInterest;
+    private Extent areaOfInterest;
+
+    /**
+     * The geographic component of the area of interest, computed when first needed.
+     */
+    private transient GeographicBoundingBox bbox;
 
     /**
      * The desired accuracy in metres, or 0 for the best accuracy available.
@@ -80,31 +89,69 @@ public class CoordinateOperationContext
      * @param accuracy The desired accuracy in metres, or 0 for the best accuracy available.
      * See {@link #getDesiredAccuracy()} for more details about what we mean by <cite>"best accuracy"</cite>.
      */
-    public CoordinateOperationContext(final GeographicBoundingBox area, final double accuracy) {
+    public CoordinateOperationContext(final Extent area, final double accuracy) {
         ArgumentChecks.ensurePositive("accuracy", accuracy);
         areaOfInterest  = area;
         desiredAccuracy = accuracy;
     }
 
     /**
-     * Returns the geographic area of interest, or {@code null} if none.
+     * Returns the spatio-temporal area of interest, or {@code null} if none.
      *
-     * @return The area of interest, or {@code null} if none.
+     * @return The spatio-temporal area of interest, or {@code null} if none.
      */
-    public GeographicBoundingBox getAreaOfInterest() {
+    public Extent getAreaOfInterest() {
         return areaOfInterest;
     }
 
     /**
-     * Sets the geographic area of interest, or {@code null} if none.
+     * Sets the spatio-temporal area of interest, or {@code null} if none.
      *
-     * @param area The area of interest, or {@code null} if none.
+     * @param area The spatio-temporal area of interest, or {@code null} if none.
      */
-    public void setAreaOfInterest(final GeographicBoundingBox area) {
+    public void setAreaOfInterest(final Extent area) {
         areaOfInterest = area;
     }
 
     /**
+     * Returns the geographic component of the area of interest, or {@code null} if none.
+     * This convenience method extracts the bounding box from the spatio-temporal {@link Extent}.
+     *
+     * @return The geographic area of interest, or {@code null} if none.
+     */
+    public GeographicBoundingBox getGeographicBoundingBox() {
+        if (bbox == null) {
+            bbox = Extents.getGeographicBoundingBox(areaOfInterest);
+        }
+        return bbox;
+    }
+
+    /**
+     * Sets the geographic component of the area of interest, or {@code null} if none.
+     * This convenience method set the bounding box into the spatio-temporal {@link Extent}.
+     *
+     * @param area The geographic area of interest, or {@code null} if none.
+     */
+    public void setGeographicBoundingBox(final GeographicBoundingBox area) {
+        areaOfInterest = setGeographicBoundingBox(areaOfInterest, area);
+        bbox = area;
+    }
+
+    /**
+     * Sets the given geographic bounding box in the given extent.
+     */
+    static Extent setGeographicBoundingBox(Extent areaOfInterest, final GeographicBoundingBox bbox) {
+        if (areaOfInterest != null) {
+            final DefaultExtent ex = DefaultExtent.castOrCopy(areaOfInterest);
+            ex.setGeographicElements(CollectionsExt.singletonOrEmpty(bbox));
+            areaOfInterest = ex;
+        } else if (bbox != null) {
+            areaOfInterest = new DefaultExtent(null, bbox, null, null);
+        }
+        return areaOfInterest;
+    }
+
+    /**
      * Returns the desired accuracy in metres.
      * A value of 0 means to search for the most accurate operation.
      *

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=1735974&r1=1735973&r2=1735974&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] Mon Mar 21 13:49:07 2016
@@ -30,35 +30,39 @@ import org.opengis.referencing.crs.*;
 import org.opengis.referencing.datum.*;
 import org.opengis.referencing.operation.*;
 import org.opengis.metadata.Identifier;
+import org.opengis.metadata.extent.Extent;
 import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.metadata.quality.PositionalAccuracy;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.apache.sis.internal.metadata.ReferencingServices;
-import org.apache.sis.internal.referencing.Formulas;
 import org.apache.sis.internal.referencing.PositionalAccuracyConstant;
-import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.referencing.provider.Affine;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.measure.Units;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.metadata.iso.extent.Extents;
 import org.apache.sis.parameter.Parameterized;
-import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.CRS;
+import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.NamedIdentifier;
+import org.apache.sis.referencing.cs.AxesConvention;
 import org.apache.sis.referencing.cs.CoordinateSystems;
 import org.apache.sis.referencing.datum.BursaWolfParameters;
 import org.apache.sis.referencing.datum.DefaultGeodeticDatum;
+import org.apache.sis.referencing.operation.matrix.Matrix4;
 import org.apache.sis.referencing.operation.matrix.Matrices;
-import org.apache.sis.referencing.operation.matrix.MatrixSIS;
+import org.apache.sis.referencing.operation.transform.MathTransforms;
+import org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.Classes;
-import org.apache.sis.util.Utilities;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Vocabulary;
 
+import static org.apache.sis.util.Utilities.equalsIgnoreMetadata;
+import static org.apache.sis.internal.referencing.ReferencingUtilities.getGreenwichLongitude;
+
 // Branch-dependent imports
 import java.util.Objects;
 
@@ -138,9 +142,14 @@ public class CoordinateOperationInferenc
     private final DefaultCoordinateOperationFactory factorySIS;
 
     /**
-     * The area of interest, or {@code null} if none.
+     * The spatio-temporal area of interest, or {@code null} if none.
+     */
+    private Extent areaOfInterest;
+
+    /**
+     * The geographic component of the area of interest, or {@code null} if none.
      */
-    private GeographicBoundingBox areaOfInterest;
+    private GeographicBoundingBox bbox;
 
     /**
      * The desired accuracy in metres, or 0 for the best accuracy available.
@@ -163,6 +172,7 @@ public class CoordinateOperationInferenc
         if (context != null) {
             areaOfInterest  = context.getAreaOfInterest();
             desiredAccuracy = context.getDesiredAccuracy();
+            bbox            = context.getGeographicBoundingBox();
         }
     }
 
@@ -184,6 +194,19 @@ public class CoordinateOperationInferenc
     }
 
     /**
+     * If the domain of interest was not set, defines it to the domain of validity of the given CRS.
+     */
+    private void updateDomainOfInterest(final CoordinateReferenceSystem sourceCRS,
+                                        final CoordinateReferenceSystem targetCRS)
+    {
+        if (bbox == null) {
+            bbox = Extents.intersection(CRS.getGeographicBoundingBox(sourceCRS),
+                                        CRS.getGeographicBoundingBox(targetCRS));
+            areaOfInterest = CoordinateOperationContext.setGeographicBoundingBox(areaOfInterest, bbox);
+        }
+    }
+
+    /**
      * Infers an operation for conversion or transformation between two coordinate reference systems.
      * This method inspects the given CRS and delegates the work to one or many {@code createOperationStep(…)} methods.
      * This method fails if no path between the CRS is found.
@@ -200,10 +223,6 @@ public class CoordinateOperationInferenc
     {
         ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
         ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
-        if (areaOfInterest == null) {
-            areaOfInterest = Extents.intersection(CRS.getGeographicBoundingBox(sourceCRS),
-                                                  CRS.getGeographicBoundingBox(targetCRS));
-        }
         ////////////////////////////////////////////////////////////////////////////////
         ////                                                                        ////
         ////                        Compound  →  various CRS                        ////
@@ -314,71 +333,101 @@ public class CoordinateOperationInferenc
      * @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.
-     *
-     * @todo Rotation of prime meridian not yet implemented.
-     * @todo Conversion between Cartesian and spherical CS not yet implemented.
      */
     protected CoordinateOperation createOperationStep(final GeocentricCRS sourceCRS,
                                                       final GeocentricCRS targetCRS)
             throws FactoryException
     {
+        updateDomainOfInterest(sourceCRS, targetCRS);
         final GeodeticDatum sourceDatum = sourceCRS.getDatum();
         final GeodeticDatum targetDatum = targetCRS.getDatum();
         final CoordinateSystem sourceCS = sourceCRS.getCoordinateSystem();
         final CoordinateSystem targetCS = targetCRS.getCoordinateSystem();
-        if (Utilities.equalsIgnoreMetadata(sourceDatum, targetDatum)) {
+        CoordinateSystem sourceNormalized = null;
+        CoordinateSystem targetNormalized = null;
+        Matrix           datumShift       = null;       // Those 3 variables will be null or non-null together.
+        /*
+         * If both CRS use the same datum and the same prime meridian, then the coordinate operation is just
+         * an axis swapping, unit conversion or change between spherical and Cartesian coordinate system type.
+         * Otherwise (if the datum are not the same), we need to perform a scale, translation and rotation in
+         * Cartesian space using the Bursa-Wolf parameters.
+         */
+        Identifier identifier;
+        if (equalsIgnoreMetadata(sourceDatum, targetDatum)) {
+            identifier = equalsIgnoreMetadata(sourceCS, targetCS) ? IDENTITY : AXIS_CHANGES;
+        } else {
+            identifier = ELLIPSOID_CHANGE;
+            if (sourceDatum instanceof DefaultGeodeticDatum) {
+                datumShift = ((DefaultGeodeticDatum) sourceDatum).getPositionVectorTransformation(targetDatum, areaOfInterest);
+                if (datumShift != null) {
+                    identifier = DATUM_SHIFT;
+                    sourceNormalized = CommonCRS.WGS84.geocentric().getCoordinateSystem();
+                    targetNormalized = sourceNormalized;
+                }
+            }
             /*
-             * If both CRS use the same datum and the same prime meridian, then the coordinate operation is just
-             * an axis swapping and unit conversion except if the coordinate systems are not of the same kind.
+             * If there is a change of prime meridian, concatenate that change before or after the datum shift.
+             * Actually we do not know if we should concatenate longitude rotation before or after datum shift.
+             * But this ambiguity does not apply to EPSG dataset 8.9 because source and target prime meridians
+             * are always Greenwich. For reducing ambiguity in other cases, the SIS DefaultGeodeticDatum class
+             * ensures that if the prime meridian are not the same, then the target meridian must be Greenwich.
              */
-            final Matrix matrix = swapAndScaleAxes(sourceCS, targetCS);
-            return createFromAffineTransform(AXIS_CHANGES, sourceCRS, targetCRS, matrix);
-        }
-        if (!isGreenwichLongitudeEquals(sourceDatum.getPrimeMeridian(), targetDatum.getPrimeMeridian())) {
-            throw new OperationNotFoundException("Rotation of prime meridian not yet implemented");
+            final double sourceMeridian = getGreenwichLongitude(sourceDatum.getPrimeMeridian(), NonSI.DEGREE_ANGLE);
+            final double targetMeridian = getGreenwichLongitude(targetDatum.getPrimeMeridian(), NonSI.DEGREE_ANGLE);
+            if (sourceMeridian != targetMeridian) {
+                if (sourceNormalized == null) {
+                    sourceNormalized = CoordinateSystems.replaceAxes(sourceCS, AxesConvention.NORMALIZED);
+                    targetNormalized = CoordinateSystems.replaceAxes(targetCS, AxesConvention.NORMALIZED);
+                }
+                final boolean isTargetCartesian = (targetNormalized instanceof CartesianCS);
+                if (!(isTargetCartesian || targetNormalized instanceof SphericalCS)) {
+                    throw new FactoryException(Errors.format(Errors.Keys.IllegalCoordinateSystem_1, targetCS.getClass()));
+                }
+                final Matrix4 rot = new Matrix4();
+                boolean isSource = true;
+                do {                                // Executed exactly twice: once for source, then once for target.
+                    double θ = isSource ? sourceMeridian : -targetMeridian;
+                    if (θ != 0) {
+                        if (isTargetCartesian) {
+                            θ = Math.toRadians(θ);
+                            rot.m00 =   rot.m11 = Math.cos(θ);
+                            rot.m01 = -(rot.m10 = Math.sin(θ));
+                        } else {
+                            rot.m02 = θ;
+                        }
+                        if (datumShift == null) {
+                            datumShift = rot;
+                        } else if (isSource) {
+                            datumShift = Matrices.multiply(datumShift, rot);    // Apply rotation before datum shift.
+                        } else {
+                            datumShift = Matrices.multiply(rot, datumShift);    // Apply rotation after datum shift.
+                        }
+                    }
+                } while ((isSource = !isSource) == false);
+            }
         }
         /*
-         * Transform between differents ellipsoids using Bursa Wolf parameters.
-         * The Bursa Wolf parameters are used with "standard" geocentric CS, i.e.
-         * with x axis towards the prime meridian, y axis towards East and z axis
-         * toward North. The following steps are applied:
+         * Transform between differents datums using Bursa Wolf parameters. The Bursa Wolf parameters are used
+         * with "standard" geocentric CS, i.e. with X axis towards the prime meridian, Y axis towards East and
+         * Z axis toward North. The following steps are applied:
          *
-         *     source CRS                      →
-         *     standard CRS with source datum  →
-         *     standard CRS with target datum  →
+         *     source CRS                        →
+         *     normalized CRS with source datum  →
+         *     normalized CRS with target datum  →
          *     target CRS
          */
-        Matrix datumShift = null;
-        Identifier identifier = DATUM_SHIFT;
-        final GeodeticDatum datum = null;//TemporaryDatum.unwrap(sourceDatum);
-//        if (datum instanceof DefaultGeodeticDatum) {
-//            datumShift = ((DefaultGeodeticDatum) datum).getPositionVectorTransformation(
-//                    TemporaryDatum.unwrap(targetDatum), null);
-//        }
-//        if (datumShift == null) {
-//            if (lenientDatumShift) {
-//                datumShift = new Matrix4(); // Identity transform.
-//                identifier = ELLIPSOID_CHANGE;
-//            } else {
-//                throw new OperationNotFoundException(Errors.format(
-//                            Errors.Keys.BursaWolfParametersRequired));
-//            }
-//        }
-        MatrixSIS matrix;
-        final CartesianCS standard = (CartesianCS) CommonCRS.WGS84.geocentric().getCoordinateSystem();
-        final Matrix normalizeSource = swapAndScaleAxes(sourceCS, standard);
-        final Matrix normalizeTarget = swapAndScaleAxes(standard, targetCS);
-        /*
-         * Since all steps are matrices, we can multiply them and get a single matrix.
-         * MatrixSIS.multiply(Matrix) is equivalent to AffineTransform.concatenate(…):
-         * First transform by the supplied transform and then transform the result by
-         * the original transform. So we compute;
-         *
-         *     matrix = normalizeTarget × datumShift × normalizeSource
-         */
-        matrix = Matrices.multiply(normalizeTarget, datumShift);
-        matrix = matrix.multiply(normalizeSource);
-        return createFromAffineTransform(identifier, sourceCRS, targetCRS, matrix);
+        MathTransform tr;
+        final DefaultMathTransformFactory mtFactory = factorySIS.getDefaultMathTransformFactory();
+        if (datumShift != null) {
+            final MathTransform normalize   = mtFactory.createCoordinateSystemChange(sourceCS, sourceNormalized);
+            final MathTransform denormalize = mtFactory.createCoordinateSystemChange(targetNormalized, targetCS);
+            tr = mtFactory.createAffineTransform(datumShift);
+            tr = mtFactory.createConcatenatedTransform(normalize,
+                 mtFactory.createConcatenatedTransform(tr, denormalize));
+        } else {
+            tr = mtFactory.createCoordinateSystemChange(sourceCS, targetCS);
+        }
+        return createFromMathTransform(properties(identifier), sourceCRS, targetCRS, tr, null, null);
     }
 
     /**
@@ -397,14 +446,20 @@ public class CoordinateOperationInferenc
                                                       final VerticalCRS targetCRS)
             throws FactoryException
     {
+        updateDomainOfInterest(sourceCRS, targetCRS);
         final VerticalDatum sourceDatum = sourceCRS.getDatum();
         final VerticalDatum targetDatum = targetCRS.getDatum();
-        if (!Utilities.equalsIgnoreMetadata(sourceDatum, targetDatum)) {
+        if (!equalsIgnoreMetadata(sourceDatum, targetDatum)) {
             throw new OperationNotFoundException(notFoundMessage(sourceDatum, targetDatum));
         }
         final VerticalCS sourceCS = sourceCRS.getCoordinateSystem();
         final VerticalCS targetCS = targetCRS.getCoordinateSystem();
-        final Matrix     matrix   = swapAndScaleAxes(sourceCS, targetCS);
+        final Matrix matrix;
+        try {
+            matrix = CoordinateSystems.swapAndScaleAxes(sourceCS, targetCS);
+        } catch (IllegalArgumentException | ConversionException exception) {
+            throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS), exception);
+        }
         return createFromAffineTransform(AXIS_CHANGES, sourceCRS, targetCRS, matrix);
     }
 
@@ -422,6 +477,7 @@ public class CoordinateOperationInferenc
                                                       final TemporalCRS targetCRS)
             throws FactoryException
     {
+        updateDomainOfInterest(sourceCRS, targetCRS);
         final TemporalDatum sourceDatum = sourceCRS.getDatum();
         final TemporalDatum targetDatum = targetCRS.getDatum();
         final TimeCS sourceCS = sourceCRS.getCoordinateSystem();
@@ -445,7 +501,12 @@ public class CoordinateOperationInferenc
          *
          * The "epoch shift" previously computed is a translation. Consequently, it is added to element (0,1).
          */
-        final Matrix matrix = swapAndScaleAxes(sourceCS, targetCS);
+        final Matrix matrix;
+        try {
+            matrix = CoordinateSystems.swapAndScaleAxes(sourceCS, targetCS);
+        } catch (IllegalArgumentException | ConversionException exception) {
+            throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS), exception);
+        }
         final int translationColumn = matrix.getNumCol() - 1;           // Paranoiac check: should always be 1.
         final double translation = matrix.getElement(0, translationColumn);
         matrix.setElement(0, translationColumn, translation + epochShift);
@@ -471,36 +532,8 @@ public class CoordinateOperationInferenc
                                                           final Matrix                    matrix)
             throws FactoryException
     {
-        final MathTransformFactory mtFactory = factorySIS.getMathTransformFactory();
-        final MathTransform transform  = mtFactory.createAffineTransform(matrix);
-        final Map<String,?> properties = properties(name);
-        final Class<? extends SingleOperation> type =
-                properties.containsKey(CoordinateOperation.COORDINATE_OPERATION_ACCURACY_KEY)
-                ? Transformation.class : Conversion.class;
-        return createFromMathTransform(properties, sourceCRS, targetCRS, transform,
-                   Affine.getProvider(transform.getSourceDimensions(),
-                                      transform.getTargetDimensions(),
-                                      Matrices.isAffine(matrix)), type);
-    }
-
-    /**
-     * Creates a coordinate operation from a math transform.
-     *
-     * @param  name       The identifier for the operation to be created.
-     * @param  sourceCRS  The source coordinate reference system.
-     * @param  targetCRS  The destination coordinate reference system.
-     * @param  transform  The math transform.
-     * @return A coordinate operation using the specified math transform.
-     * @throws FactoryException if the operation can not be constructed.
-     */
-    private CoordinateOperation createFromMathTransform(final Identifier                name,
-                                                        final CoordinateReferenceSystem sourceCRS,
-                                                        final CoordinateReferenceSystem targetCRS,
-                                                        final MathTransform             transform)
-            throws FactoryException
-    {
-        return createFromMathTransform(Collections.singletonMap(CoordinateOperation.NAME_KEY, name),
-                sourceCRS, targetCRS, transform, null, SingleOperation.class);
+        final MathTransform transform  = factorySIS.getMathTransformFactory().createAffineTransform(matrix);
+        return createFromMathTransform(properties(name), sourceCRS, targetCRS, transform, null, null);
     }
 
     /**
@@ -516,6 +549,11 @@ public class CoordinateOperationInferenc
      *       and a {@code MathTransform}, but that combination is not forbidden. Since such practice is sometime
      *       convenient for the implementor, Apache SIS allows that.</div></li>
      *
+     *   <li>If the given {@code type} is null, then this method infers the type from whether the given properties
+     *       specify and accuracy or not. If those properties were created by the {@link #properties(Identifier)}
+     *       method, then the operation will be a {@link Transformation} instance instead of {@link Conversion} if
+     *       the {@code name} identifier was {@link #DATUM_SHIFT} or {@link #ELLIPSOID_CHANGE}.</li>
+     *
      *   <li>If the given {@code method} is {@code null}, then infer an operation method by inspecting the given transform.
      *       The transform needs to implement the {@link Parameterized} interface in order to allow operation method discovery.</li>
      *
@@ -528,16 +566,16 @@ public class CoordinateOperationInferenc
      * @param  targetCRS  The destination coordinate reference system.
      * @param  transform  The math transform.
      * @param  method     The operation method, or {@code null} if unknown.
-     * @param  type       The required super-class (e.g. <code>{@linkplain Transformation}.class</code>).
+     * @param  type       {@code Conversion.class}, {@code Transformation.class}, or {@code null} if unknown.
      * @return A coordinate operation using the specified math transform.
-     * @throws FactoryException if the operation can't be constructed.
+     * @throws FactoryException if the operation can not be created.
      */
     private CoordinateOperation createFromMathTransform(final Map<String,?>             properties,
                                                         final CoordinateReferenceSystem sourceCRS,
                                                         final CoordinateReferenceSystem targetCRS,
                                                         final MathTransform             transform,
                                                               OperationMethod           method,
-                                                        final Class<? extends CoordinateOperation> type)
+                                                        Class<? extends CoordinateOperation> type)
             throws FactoryException
     {
         /*
@@ -556,21 +594,35 @@ public class CoordinateOperationInferenc
             }
         }
         /*
+         * If the operation type was not explicitely specified, infers it from whether an accuracy is specified
+         * or not. In principle, only transformations has an accuracy property; conversions do not. This policy
+         * is applied by the properties(Identifier) method in this class.
+         */
+        if (type == null) {
+            type = properties.containsKey(CoordinateOperation.COORDINATE_OPERATION_ACCURACY_KEY)
+                    ? Transformation.class : Conversion.class;
+        }
+        /*
          * The operation method is mandatory. If the user did not provided one, we need to infer it ourselves.
          * If we fail to infer an OperationMethod, let it to null - the exception will be thrown by the factory.
          */
-        if (method == null && transform instanceof Parameterized) {
-            final ParameterDescriptorGroup descriptor = ((Parameterized) transform).getParameterDescriptors();
-            if (descriptor != null) {
-                final Identifier name = descriptor.getName();
-                if (name != null) {
-                    method = factory.getOperationMethod(name.getCode());
-                }
-                if (method == null) {
-                    method = factory.createOperationMethod(properties,
-                            sourceCRS.getCoordinateSystem().getDimension(),
-                            targetCRS.getCoordinateSystem().getDimension(),
-                            descriptor);
+        if (method == null) {
+            final Matrix matrix = MathTransforms.getMatrix(transform);
+            if (matrix != null) {
+                method = Affine.getProvider(transform.getSourceDimensions(), transform.getTargetDimensions(), Matrices.isAffine(matrix));
+            } else if (transform instanceof Parameterized) {
+                final ParameterDescriptorGroup descriptor = ((Parameterized) transform).getParameterDescriptors();
+                if (descriptor != null) {
+                    final Identifier name = descriptor.getName();
+                    if (name != null) {
+                        method = factory.getOperationMethod(name.getCode());
+                    }
+                    if (method == null) {
+                        method = factory.createOperationMethod(properties,
+                                sourceCRS.getCoordinateSystem().getDimension(),
+                                targetCRS.getCoordinateSystem().getDimension(),
+                                descriptor);
+                    }
                 }
             }
         }
@@ -632,56 +684,6 @@ public class CoordinateOperationInferenc
     }
 
     /**
-     * Returns {@code true} if the Greenwich longitude of the {@code actual} prime meridian is equals to the
-     * Greenwich longitude of the {@code expected} prime meridian. The comparison is performed in degrees.
-     *
-     * <p>A {@code null} argument is interpreted as "unknown prime meridian". Consequently this method
-     * unconditionally returns {@code false} if one or both arguments is {@code null}.</p>
-     *
-     * @param expected The expected prime meridian, or {@code null}.
-     * @param actual The actual prime meridian, or {@code null}.
-     * @return {@code true} if both prime meridians have the same Greenwich longitude.
-     */
-    private static boolean isGreenwichLongitudeEquals(final PrimeMeridian expected, final PrimeMeridian actual) {
-        if (expected == null || actual == null) {
-            return false;                               // See method javadoc.
-        }
-        if (expected == actual) {
-            return true;
-        }
-        final double diff = ReferencingUtilities.getGreenwichLongitude(expected, NonSI.DEGREE_ANGLE)
-                          - ReferencingUtilities.getGreenwichLongitude(actual,   NonSI.DEGREE_ANGLE);
-        return Math.abs(diff) <= Formulas.ANGULAR_TOLERANCE;
-    }
-
-    /**
-     * Returns an affine transform between two coordinate systems. Only units and axis order
-     * (e.g. transforming from (NORTH,WEST) to (EAST,NORTH)) are taken in account.
-     *
-     * <p>This method delegates to {@link CoordinateSystems#swapAndScaleAxes(CoordinateSystem, CoordinateSystem)}
-     * and wraps the unchecked exceptions into the checked {@link OperationNotFoundException}.</p>
-     *
-     * @param  sourceCS  the source coordinate system.
-     * @param  targetCS  the target coordinate system.
-     * @return The transformation from {@code sourceCS} to {@code targetCS} as an affine transform.
-     * @throws OperationNotFoundException if the affine transform can't be constructed.
-     *
-     * @see CoordinateSystems#swapAndScaleAxes(CoordinateSystem, CoordinateSystem)
-     */
-    private static Matrix swapAndScaleAxes(final CoordinateSystem sourceCS,
-                                           final CoordinateSystem targetCS)
-            throws OperationNotFoundException
-    {
-        try {
-            return CoordinateSystems.swapAndScaleAxes(sourceCS,targetCS);
-        } catch (IllegalArgumentException | ConversionException exception) {
-            throw new OperationNotFoundException(notFoundMessage(sourceCS, targetCS), exception);
-        }
-        // No attempt to catch ClassCastException since such
-        // exception would indicates a programming error.
-    }
-
-    /**
      * Returns the specified identifier in a map to be given to coordinate operation constructors.
      * In the special case where the {@code name} identifier is {@link #DATUM_SHIFT} or {@link #ELLIPSOID_CHANGE},
      * the map will contains extra informations like positional accuracy.

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=1735974&r1=1735973&r2=1735974&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] Mon Mar 21 13:49:07 2016
@@ -162,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"}).

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CoordinateSystemTransform.java [UTF-8] Mon Mar 21 13:49:07 2016
@@ -35,7 +35,6 @@ import org.apache.sis.internal.util.Cons
 import org.apache.sis.metadata.iso.ImmutableIdentifier;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
-import org.apache.sis.referencing.cs.AbstractCS;
 import org.apache.sis.referencing.cs.AxesConvention;
 import org.apache.sis.referencing.cs.CoordinateSystems;
 import org.apache.sis.referencing.operation.DefaultOperationMethod;
@@ -170,20 +169,20 @@ abstract class CoordinateSystemTransform
         if (source instanceof CartesianCS) {
             if (target instanceof SphericalCS) {
                 kernel = CartesianToSpherical.INSTANCE;
-            } else if (target instanceof CylindricalCS) {
-                passthrough = 1;
-                kernel = CartesianToPolar.INSTANCE;
             } else if (target instanceof PolarCS) {
                 kernel = CartesianToPolar.INSTANCE;
+            } else if (target instanceof CylindricalCS) {
+                kernel = CartesianToPolar.INSTANCE;
+                passthrough = 1;
             }
         } else if (target instanceof CartesianCS) {
             if (source instanceof SphericalCS) {
                 kernel = SphericalToCartesian.INSTANCE;
-            } else if (source instanceof CylindricalCS) {
-                passthrough = 1;
-                kernel = PolarToCartesian.INSTANCE;
             } else if (source instanceof PolarCS) {
                 kernel = PolarToCartesian.INSTANCE;
+            } else if (source instanceof CylindricalCS) {
+                kernel = PolarToCartesian.INSTANCE;
+                passthrough = 1;
             }
         }
         Exception cause = null;
@@ -196,8 +195,14 @@ abstract class CoordinateSystemTransform
                 final MathTransform tr = (passthrough == 0)
                         ? kernel.completeTransform(factory)
                         : kernel.passthrough(factory);
-                return factory.createConcatenatedTransform(normalize(factory, source, false),
-                       factory.createConcatenatedTransform(tr, normalize(factory, target, true)));
+                final MathTransform before = factory.createAffineTransform(
+                        CoordinateSystems.swapAndScaleAxes(source,
+                        CoordinateSystems.replaceAxes(source, AxesConvention.NORMALIZED)));
+                final MathTransform after = factory.createAffineTransform(
+                        CoordinateSystems.swapAndScaleAxes(
+                        CoordinateSystems.replaceAxes(target, AxesConvention.NORMALIZED), target));
+                return factory.createConcatenatedTransform(before,
+                       factory.createConcatenatedTransform(tr, after));
             }
         } catch (IllegalArgumentException | ConversionException e) {
             cause = e;
@@ -206,20 +211,4 @@ abstract class CoordinateSystemTransform
                 WKTUtilities.toType(CoordinateSystem.class, source.getClass()),
                 WKTUtilities.toType(CoordinateSystem.class, target.getClass())), cause);
     }
-
-    /**
-     * Returns the conversion between the given coordinate system and its normalized form.
-     */
-    private static MathTransform normalize(final MathTransformFactory factory, final CoordinateSystem cs,
-            final boolean inverse) throws FactoryException, ConversionException
-    {
-        AbstractCS source = AbstractCS.castOrCopy(cs);
-        AbstractCS target = source.forConvention(AxesConvention.NORMALIZED);
-        if (inverse) {
-            AbstractCS tmp = source;
-            source = target;
-            target = tmp;
-        }
-        return factory.createAffineTransform(CoordinateSystems.swapAndScaleAxes(source, target));
-    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java [UTF-8] Mon Mar 21 13:49:07 2016
@@ -965,7 +965,7 @@ public class DefaultMathTransformFactory
 
     /**
      * Given a transform between normalized spaces,
-     * create a transform taking in account axis directions and units of measurement.
+     * creates a transform taking in account axis directions and units of measurement.
      * This method {@linkplain #createConcatenatedTransform concatenates} the given parameterized transform
      * with any other transform required for performing units changes and ordinates swapping.
      *

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/BursaWolfParametersTest.java [UTF-8] Mon Mar 21 13:49:07 2016
@@ -37,7 +37,7 @@ import static org.apache.sis.test.Assert
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  */
 public final strictfp class BursaWolfParametersTest extends TestCase {
@@ -55,7 +55,7 @@ public final strictfp class BursaWolfPar
         bursaWolf.tZ = 4.5;
         bursaWolf.rZ = 0.554;
         bursaWolf.dS = 0.219;
-        bursaWolf.verify();
+        bursaWolf.verify(PrimeMeridianMock.GREENWICH);
         assertFalse("isIdentity",    bursaWolf.isIdentity());
         assertFalse("isTranslation", bursaWolf.isTranslation());
         return bursaWolf;
@@ -75,7 +75,7 @@ public final strictfp class BursaWolfPar
         bursaWolf.rY =    0.1503;
         bursaWolf.rZ =    0.3898;
         bursaWolf.dS =   -0.3143;
-        bursaWolf.verify();
+        bursaWolf.verify(PrimeMeridianMock.GREENWICH);
         assertFalse("isIdentity",    bursaWolf.isIdentity());
         assertFalse("isTranslation", bursaWolf.isTranslation());
         return bursaWolf;
@@ -91,7 +91,7 @@ public final strictfp class BursaWolfPar
         bursaWolf.tX = -168;
         bursaWolf.tY =  -60;
         bursaWolf.tZ =  320;
-        bursaWolf.verify();
+        bursaWolf.verify(PrimeMeridianMock.GREENWICH);
         assertFalse("isIdentity",    bursaWolf.isIdentity());
         assertTrue ("isTranslation", bursaWolf.isTranslation());
         return bursaWolf;

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Mon Mar 21 13:49:07 2016
@@ -589,6 +589,11 @@ public final class Errors extends Indexe
         public static final short MismatchedParameterDescriptor_1 = 146;
 
         /**
+         * Expected the “{0}” prime meridian but found “{1}”.
+         */
+        public static final short MismatchedPrimeMeridian_2 = 220;
+
+        /**
          * Mismatched type for “{0}” property.
          */
         public static final short MismatchedPropertyType_1 = 154;

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Mon Mar 21 13:49:07 2016
@@ -128,6 +128,7 @@ MismatchedDimension_3             = Argu
 MismatchedGridGeometry_2          = The grid geometry must be the same for \u201c{0}\u201d and \u201c{1}\u201d.
 MismatchedMatrixSize_4            = Mismatched matrix sizes: expected {0}\u00d7{1} but got {2}\u00d7{3}.
 MismatchedParameterDescriptor_1   = Mismatched descriptor for \u201c{0}\u201d parameter.
+MismatchedPrimeMeridian_2         = Expected the \u201c{0}\u201d prime meridian but found \u201c{1}\u201d.
 MismatchedPropertyType_1          = Mismatched type for \u201c{0}\u201d property.
 MismatchedTransformDimension_3    = The transform has {2} {0,choice,0#source|1#target} dimension{2,choice,1#|2#s}, while {1} was expected.
 MismatchedValueClass_3            = Class of \u201c{0}\u201d values is \u2018{2}\u2019, but the requested type is \u2018{1}\u2019.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] Mon Mar 21 13:49:07 2016
@@ -125,6 +125,7 @@ MismatchedDimension_3             = L\u2
 MismatchedGridGeometry_2          = La g\u00e9om\u00e9trie de la grille doit \u00eatre la m\u00eame pour \u00ab\u202f{0}\u202f\u00bb et \u00ab\u202f{1}\u202f\u00bb.
 MismatchedMatrixSize_4            = Une matrice de taille de {0}\u00d7{1} \u00e9tait attendue mais la matrice donn\u00e9e est de taille {2}\u00d7{3}.
 MismatchedParameterDescriptor_1   = Le descripteur du param\u00e8tre \u00ab\u202f{0}\u202f\u00bb ne correspond pas.
+MismatchedPrimeMeridian_2         = Le m\u00e9ridien d\u2019origine \u00ab\u202f{0}\u202f\u00bb \u00e9tait attendu, mais \u00ab\u202f{1}\u202f\u00bb a \u00e9t\u00e9 trouv\u00e9.
 MismatchedPropertyType_1          = Le type de la propri\u00e9t\u00e9 \u00ab\u202f{0}\u202f\u00bb ne correspond pas.
 MismatchedTransformDimension_3    = La {0,choice,0#source|1#destination} de la transformation a {2} dimension{2,choice,1#|2#s}, alors qu\u2019on en attendait {1}.
 MismatchedValueClass_3            = Les valeurs de \u00ab\u202f{0}\u202f\u00bb sont de la classe \u2018{2}\u2019, alors que le type demand\u00e9 \u00e9tait \u2018{1}\u2019.

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/LoggingWatcher.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/LoggingWatcher.java?rev=1735974&r1=1735973&r2=1735974&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/LoggingWatcher.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/test/LoggingWatcher.java [UTF-8] Mon Mar 21 13:49:07 2016
@@ -20,6 +20,7 @@ import java.util.Queue;
 import java.util.LinkedList;
 import java.util.ConcurrentModificationException;
 import java.util.logging.Filter;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.LogRecord;
 import java.util.logging.SimpleFormatter;
@@ -127,7 +128,9 @@ public final strictfp class LoggingWatch
      */
     @Override
     public final boolean isLoggable(final LogRecord record) {
-        messages.add(formatter.formatMessage(record));
+        if (record.getLevel().intValue() >= Level.INFO.intValue()) {
+            messages.add(formatter.formatMessage(record));
+        }
         return TestCase.VERBOSE;
     }
 



Mime
View raw message