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;
     }
 


Reply via email to