sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1740152 [3/8] - in /sis/branches/JDK6: ./ core/sis-feature/ core/sis-feature/src/main/java/org/apache/sis/feature/ core/sis-feature/src/main/java/org/apache/sis/internal/ core/sis-feature/src/main/java/org/apache/sis/internal/feature/ core...
Date Wed, 20 Apr 2016 14:53:33 GMT
Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Legacy.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Legacy.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Legacy.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Legacy.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -18,9 +18,9 @@ package org.apache.sis.internal.referenc
 
 import javax.measure.unit.SI;
 import javax.measure.unit.Unit;
+import javax.measure.quantity.Length;
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.cs.CartesianCS;
-import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.cs.AxisFilter;
 import org.apache.sis.referencing.cs.CoordinateSystems;
@@ -40,10 +40,10 @@ import static org.opengis.referencing.Id
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  */
-public final class Legacy implements AxisFilter {
+public final class Legacy {
     /**
      * A three-dimensional Cartesian CS with the legacy set of geocentric axes.
      * OGC 01-009 defines the default geocentric axes as:
@@ -62,6 +62,12 @@ public final class Legacy implements Axi
             new DefaultCoordinateSystemAxis(singletonMap(NAME_KEY, "Z"), "Z", AxisDirection.NORTH, SI.METRE));
 
     /**
+     * Do not allow instantiation of this class.
+     */
+    private Legacy() {
+    }
+
+    /**
      * The standard three-dimensional Cartesian CS as defined by ISO 19111.
      *
      * @param  unit The linear unit of the desired coordinate system, or {@code null} for metres.
@@ -108,71 +114,8 @@ public final class Legacy implements Axi
      */
     public static CartesianCS replaceUnit(CartesianCS cs, final Unit<?> unit) {
         if (unit != null && !unit.equals(SI.METRE)) {
-            cs = (CartesianCS) CoordinateSystems.replaceAxes(cs, new Legacy(unit));
+            cs = (CartesianCS) CoordinateSystems.replaceLinearUnit(cs, unit.asType(Length.class));
         }
         return cs;
     }
-
-
-
-
-    // -----------------------------------------------------------------
-    //         AxisFilter implementation for internal usage only
-    // -----------------------------------------------------------------
-
-    /**
-     * The value to be returned by {@link #getUnitReplacement(CoordinateSystemAxis, Unit)},
-     * or {@code null} if no replacement should be done.
-     */
-    private final Unit<?> replacement;
-
-    /**
-     * For internal usage by {@link #replaceUnit(CartesianCS, Unit)} only.
-     */
-    private Legacy(final Unit<?> unit) {
-        replacement = unit;
-    }
-
-    @Override
-    @Deprecated
-    public Unit<?> getUnitReplacement(Unit<?> unit) {
-        return getUnitReplacement(null, unit);
-    }
-
-    /**
-     * For internal usage by {@link #replaceUnit(CartesianCS, Unit)} only.
-     *
-     * @param  axis ignored.
-     * @param  unit ignored.
-     * @return The unit of the new coordinate system.
-     */
-    @Override
-    public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, final Unit<?> unit) {
-        return replacement;
-    }
-
-    /**
-     * Returns the given axis unchanged.
-     */
-    @Override
-    public boolean accept(final CoordinateSystemAxis axis) {
-        return true;
-    }
-
-    /**
-     * Returns the given direction unchanged.
-     */
-    @Override
-    @Deprecated
-    public AxisDirection getDirectionReplacement(final AxisDirection direction) {
-        return direction;
-    }
-
-    /**
-     * Returns the given direction unchanged.
-     */
-    @Override
-    public AxisDirection getDirectionReplacement(CoordinateSystemAxis axis, final AxisDirection direction) {
-        return direction;
-    }
 }

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/PositionalAccuracyConstant.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -67,7 +67,7 @@ public final class PositionalAccuracyCon
      *
      * @see org.apache.sis.referencing.operation.AbstractCoordinateOperation#getLinearAccuracy()
      */
-    private static final double UNKNOWN_ACCURACY = 3000;
+    public static final double UNKNOWN_ACCURACY = 3000;
 
     /**
      * Default accuracy of datum shift, if not explicitly provided in the EPSG database.
@@ -131,8 +131,8 @@ public final class PositionalAccuracyCon
      * This method tries each of the following procedures and returns the first successful one:
      *
      * <ul>
-     *   <li>If a {@link QuantitativeResult} is found with a linear unit, then this accuracy estimate
-     *       is converted to {@linkplain SI#METRE metres} and returned.</li>
+     *   <li>If at least one {@link QuantitativeResult} is found with a linear unit, then the largest
+     *       accuracy estimate is converted to {@linkplain SI#METRE metres} and returned.</li>
      *   <li>Otherwise, if the operation is a {@link Conversion}, then returns 0 since a conversion
      *       is by definition accurate up to rounding errors.</li>
      *   <li>Otherwise, if the operation is a {@link Transformation}, then checks if the datum shift
@@ -152,9 +152,10 @@ public final class PositionalAccuracyCon
      * @see org.apache.sis.referencing.operation.AbstractCoordinateOperation#getLinearAccuracy()
      */
     public static double getLinearAccuracy(final CoordinateOperation operation) {
+        double accuracy = Double.NaN;
         final Collection<PositionalAccuracy> accuracies = operation.getCoordinateOperationAccuracy();
-        for (final PositionalAccuracy accuracy : accuracies) {
-            for (final Result result : accuracy.getResults()) {
+        for (final PositionalAccuracy metadata : accuracies) {
+            for (final Result result : metadata.getResults()) {
                 if (result instanceof QuantitativeResult) {
                     final QuantitativeResult quantity = (QuantitativeResult) result;
                     final Collection<? extends Record> records = quantity.getValues();
@@ -167,7 +168,9 @@ public final class PositionalAccuracyCon
                                     if (value instanceof Number) {
                                         double v = ((Number) value).doubleValue();
                                         v = unitOfLength.getConverterTo(SI.METRE).convert(v);
-                                        return v;
+                                        if (v >= 0 && !(v <= accuracy)) {       // '!' is for replacing the NaN value.
+                                            accuracy = v;
+                                        }
                                     }
                                 }
                             }
@@ -176,40 +179,41 @@ public final class PositionalAccuracyCon
                 }
             }
         }
-        /*
-         * No quantitative (linear) accuracy were found. If the coordinate operation is actually
-         * a conversion, the accuracy is up to rounding error (i.e. conceptually 0) by definition.
-         */
-        if (operation instanceof Conversion) {
-            return 0;
-        }
-        /*
-         * If the coordinate operation is actually a transformation, checks if Bursa-Wolf parameters
-         * were available for the datum shift. This is SIS-specific. See field javadoc for a rational
-         * about the return values chosen.
-         */
-        if (operation instanceof Transformation) {
-            if (accuracies.contains(DATUM_SHIFT_APPLIED)) {
-                return DATUM_SHIFT_ACCURACY;
+        if (Double.isNaN(accuracy)) {
+            /*
+             * No quantitative (linear) accuracy were found. If the coordinate operation is actually
+             * a conversion, the accuracy is up to rounding error (i.e. conceptually 0) by definition.
+             */
+            if (operation instanceof Conversion) {
+                return 0;
             }
-            if (accuracies.contains(DATUM_SHIFT_OMITTED)) {
-                return UNKNOWN_ACCURACY;
+            /*
+             * If the coordinate operation is actually a transformation, checks if Bursa-Wolf parameters
+             * were available for the datum shift. This is SIS-specific. See field javadoc for a rational
+             * about the return values chosen.
+             */
+            if (operation instanceof Transformation) {
+                if (accuracies.contains(DATUM_SHIFT_APPLIED)) {
+                    return DATUM_SHIFT_ACCURACY;
+                }
+                if (accuracies.contains(DATUM_SHIFT_OMITTED)) {
+                    return UNKNOWN_ACCURACY;
+                }
             }
-        }
-        /*
-         * If the coordinate operation is a compound of other coordinate operations, returns the sum of their accuracy,
-         * skipping unknown ones. Making the sum is a conservative approach (not exactly the "worst case" scenario,
-         * since it could be worst if the transforms are highly non-linear).
-         */
-        double accuracy = Double.NaN;
-        if (operation instanceof ConcatenatedOperation) {
-            for (final CoordinateOperation op : ((ConcatenatedOperation) operation).getOperations()) {
-                final double candidate = Math.abs(getLinearAccuracy(op));
-                if (!Double.isNaN(candidate)) {
-                    if (Double.isNaN(accuracy)) {
-                        accuracy = candidate;
-                    } else {
-                        accuracy += candidate;
+            /*
+             * If the coordinate operation is a compound of other coordinate operations, returns the sum of their accuracy,
+             * skipping unknown ones. Making the sum is a conservative approach (not exactly the "worst case" scenario,
+             * since it could be worst if the transforms are highly non-linear).
+             */
+            if (operation instanceof ConcatenatedOperation) {
+                for (final CoordinateOperation op : ((ConcatenatedOperation) operation).getOperations()) {
+                    final double candidate = Math.abs(getLinearAccuracy(op));
+                    if (!Double.isNaN(candidate)) {
+                        if (Double.isNaN(accuracy)) {
+                            accuracy = candidate;
+                        } else {
+                            accuracy += candidate;
+                        }
                     }
                 }
             }

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingUtilities.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -247,9 +247,16 @@ public final class ReferencingUtilities
     /**
      * Returns the properties of the given object but potentially with a modified name.
      * Current implement truncates the name at the first non-white character which is not
-     * a valid Unicode identifier part.
+     * a valid Unicode identifier part, with the following exception:
+     *
+     * <ul>
+     *   <li>If the character is {@code '('} and the content until the closing {@code ')'} is a valid
+     *       Unicode identifier, then that part is included. The intend is to keep the prime meridian
+     *       name in names like <cite>"NTF (Paris)"</cite>.</li>
+     * </ul>
      *
      * <div class="note"><b>Example:</b><ul>
+     *   <li><cite>"NTF (Paris)"</cite> is left unchanged.</li>
      *   <li><cite>"WGS 84 (3D)"</cite> is truncated as <cite>"WGS 84"</cite>.</li>
      *   <li><cite>"Ellipsoidal 2D CS. Axes: latitude, longitude. Orientations: north, east. UoM: degree"</cite>
      *       is truncated as <cite>"Ellipsoidal 2D CS"</cite>.</li>
@@ -272,6 +279,15 @@ public final class ReferencingUtilities
                 for (int i=0; i < name.length();) {
                     final int c = name.codePointAt(i);
                     if (!Character.isUnicodeIdentifierPart(c) && !Character.isSpaceChar(c)) {
+                        if (c == '(') {
+                            final int endAt = name.indexOf(')', i);
+                            if (endAt >= 0) {
+                                final String extra = name.substring(i+1, endAt);
+                                if (CharSequences.isUnicodeIdentifier(extra)) {
+                                    i += extra.length() + 2;
+                                }
+                            }
+                        }
                         name = CharSequences.trimWhitespaces(name, 0, i).toString();
                         if (!name.isEmpty()) {
                             final Map<String,Object> copy = new HashMap<String,Object>(properties);

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ServicesForMetadata.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -17,8 +17,10 @@
 package org.apache.sis.internal.referencing;
 
 import java.util.Map;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Locale;
 import javax.measure.unit.Unit;
 import javax.measure.quantity.Length;
@@ -34,6 +36,9 @@ import org.opengis.referencing.crs.Tempo
 import org.opengis.referencing.crs.VerticalCRS;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.crs.CRSFactory;
+import org.opengis.referencing.cs.CSFactory;
+import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.cs.CartesianCS;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.cs.CoordinateSystemAxis;
@@ -54,7 +59,6 @@ import org.opengis.metadata.extent.Geogr
 import org.opengis.metadata.extent.VerticalExtent;
 import org.opengis.geometry.Envelope;
 
-import org.opengis.referencing.cs.AxisDirection;
 import org.apache.sis.geometry.Envelopes;
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.CommonCRS;
@@ -88,6 +92,9 @@ import org.apache.sis.util.resources.Err
 import org.apache.sis.util.Exceptions;
 import org.apache.sis.util.Utilities;
 
+// Branch-dependent imports
+import org.apache.sis.internal.jdk8.JDK8;
+
 
 /**
  * Implements the referencing services needed by the {@code "sis-metadata"} module.
@@ -151,7 +158,7 @@ public final class ServicesForMetadata e
                 !Utilities.equalsIgnoreMetadata(cs2.getAxis(1), cs1.getAxis(1)))
             {
                 final CoordinateOperation operation;
-                final CoordinateOperationFactory factory = DefaultFactories.forBuildin(CoordinateOperationFactory.class);
+                final CoordinateOperationFactory factory = CoordinateOperations.factory();
                 try {
                     operation = factory.createOperation(crs, normalizedCRS);
                 } catch (FactoryException e) {
@@ -611,7 +618,7 @@ public final class ServicesForMetadata e
         if (factory instanceof DefaultCoordinateOperationFactory) {
             df = (DefaultCoordinateOperationFactory) factory;
         } else {
-            df = DefaultFactories.forBuildin(CoordinateOperationFactory.class, DefaultCoordinateOperationFactory.class);
+            df = CoordinateOperations.factory();
         }
         return df.createSingleOperation(properties, sourceCRS, targetCRS, interpolationCRS, method, null);
     }
@@ -623,17 +630,30 @@ public final class ServicesForMetadata e
      *
      * @param  properties The default properties.
      * @param  mtFactory  The math transform factory to use.
+     * @param  crsFactory The factory to use if the operation factory needs to create CRS for intermediate steps.
+     * @param  csFactory  The factory to use if the operation factory needs to create CS for intermediate steps.
      * @return The coordinate operation factory to use.
      *
-     * @since 0.6
+     * @since 0.7
      */
     @Override
-    public CoordinateOperationFactory getCoordinateOperationFactory(Map<String,?> properties, MathTransformFactory mtFactory) {
-        if (Containers.isNullOrEmpty(properties) && DefaultFactories.isDefaultInstance(MathTransformFactory.class, mtFactory)) {
-            return DefaultFactories.forBuildin(CoordinateOperationFactory.class);
-        } else {
-            return new DefaultCoordinateOperationFactory(properties, mtFactory);
+    public CoordinateOperationFactory getCoordinateOperationFactory(Map<String,?> properties,
+            final MathTransformFactory mtFactory, final CRSFactory crsFactory, final CSFactory csFactory)
+    {
+        if (Containers.isNullOrEmpty(properties)) {
+            if (DefaultFactories.isDefaultInstance(MathTransformFactory.class, mtFactory) &&
+                DefaultFactories.isDefaultInstance(CRSFactory.class, crsFactory) &&
+                DefaultFactories.isDefaultInstance(CSFactory.class, csFactory))
+            {
+                return CoordinateOperations.factory();
+            }
+            properties = Collections.emptyMap();
         }
+        final HashMap<String,Object> p = new HashMap<String,Object>(properties);
+        JDK8.putIfAbsent(p, CRS_FACTORY, crsFactory);
+        JDK8.putIfAbsent(p, CS_FACTORY,  csFactory);
+        properties = p;
+        return new DefaultCoordinateOperationFactory(properties, mtFactory);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbridgedMolodensky.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbridgedMolodensky.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbridgedMolodensky.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbridgedMolodensky.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -22,10 +22,8 @@ import org.opengis.parameter.ParameterVa
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
-import org.opengis.referencing.operation.OperationMethod;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.parameter.Parameters;
-import org.apache.sis.util.ArgumentChecks;
 
 
 /**
@@ -70,22 +68,11 @@ public final class AbridgedMolodensky ex
     }
 
     /**
-     * The providers for all combinations between 2D and 3D cases.
-     * Array length is 4. Index is build with following rule:
-     * <ul>
-     *   <li>Bit 1: dimension of source coordinates (0 for 2D, 1 for 3D).</li>
-     *   <li>Bit 0: dimension of target coordinates (0 for 2D, 1 for 3D).</li>
-     * </ul>
-     */
-    private final AbridgedMolodensky[] redimensioned;
-
-    /**
      * Constructs a new provider.
      */
     @SuppressWarnings("ThisEscapedInObjectConstruction")
     public AbridgedMolodensky() {
-        super(3, 3, PARAMETERS);
-        redimensioned = new AbridgedMolodensky[4];
+        this(3, 3, new AbridgedMolodensky[4]);
         redimensioned[0] = new AbridgedMolodensky(2, 2, redimensioned);
         redimensioned[1] = new AbridgedMolodensky(2, 3, redimensioned);
         redimensioned[2] = new AbridgedMolodensky(3, 2, redimensioned);
@@ -95,27 +82,12 @@ public final class AbridgedMolodensky ex
     /**
      * Constructs a provider for the given dimensions.
      *
-     * @param sourceDimension Number of dimensions in the source CRS of this operation method.
-     * @param targetDimension Number of dimensions in the target CRS of this operation method.
-     * @param redimensioned   Providers for all combinations between 2D and 3D cases.
-     */
-    private AbridgedMolodensky(final int sourceDimension, final int targetDimension, final AbridgedMolodensky[] redimensioned) {
-        super(sourceDimension, targetDimension, PARAMETERS);
-        this.redimensioned = redimensioned;
-    }
-
-    /**
-     * Returns the same operation method, but for different number of dimensions.
-     *
-     * @param  sourceDimensions The desired number of input dimensions.
-     * @param  targetDimensions The desired number of output dimensions.
-     * @return The redimensioned operation method, or {@code this} if no change is needed.
+     * @param sourceDimensions  number of dimensions in the source CRS of this operation method.
+     * @param targetDimensions  number of dimensions in the target CRS of this operation method.
+     * @param redimensioned     providers for all combinations between 2D and 3D cases, or {@code null}.
      */
-    @Override
-    public OperationMethod redimension(final int sourceDimensions, final int targetDimensions) {
-        ArgumentChecks.ensureBetween("sourceDimensions", 2, 3, sourceDimensions);
-        ArgumentChecks.ensureBetween("targetDimensions", 2, 3, targetDimensions);
-        return redimensioned[((sourceDimensions & 1) << 1) | (targetDimensions & 1)];
+    private AbridgedMolodensky(int sourceDimension, int targetDimension, GeodeticOperation[] redimensioned) {
+        super(sourceDimension, targetDimension, PARAMETERS, redimensioned);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -76,15 +76,15 @@ public abstract class AbstractProvider e
      * Constructs a math transform provider from a set of parameters. The provider name and
      * {@linkplain #getIdentifiers() identifiers} will be the same than the parameter ones.
      *
-     * @param sourceDimension Number of dimensions in the source CRS of this operation method.
-     * @param targetDimension Number of dimensions in the target CRS of this operation method.
-     * @param parameters      The set of parameters (never {@code null}).
+     * @param sourceDimensions Number of dimensions in the source CRS of this operation method.
+     * @param targetDimensions Number of dimensions in the target CRS of this operation method.
+     * @param parameters       Description of parameters expected by this operation.
      */
-    AbstractProvider(final int sourceDimension,
-                     final int targetDimension,
+    AbstractProvider(final int sourceDimensions,
+                     final int targetDimensions,
                      final ParameterDescriptorGroup parameters)
     {
-        super(toMap(parameters), sourceDimension, targetDimension, parameters);
+        super(toMap(parameters), sourceDimensions, targetDimensions, parameters);
     }
 
     /**
@@ -180,7 +180,7 @@ public abstract class AbstractProvider e
     }
 
     /**
-     * Creates a false easting or northing parameter in metre with a default value of 0.
+     * Creates a false easting, false northing or height parameter in metre with a default value of 0.
      */
     static ParameterDescriptor<Double> createShift(final ParameterBuilder builder) {
         return builder.create(0.0, SI.METRE);
@@ -219,7 +219,24 @@ public abstract class AbstractProvider e
      * Returns {@code true} if the inverse of this operation method is the same operation method with some parameter
      * values changed (typically with sign inverted). The default implementation returns {@code false}.
      *
+     * <p>This is a SIS-specific information which may be changed in any future SIS version.
+     * Current implementation provides this information in a "all or nothing" way: either all parameter values
+     * can have their sign reversed, or either the operation is considered not revertible at all.
+     * This is different than the EPSG dataset in two way:</p>
+     *
+     * <ul class="verbose">
+     *   <li>EPSG provides an equivalent information in the {@code PARAM_SIGN_REVERSAL} column of the
+     *       {@code [Coordinate_Operation Parameter Usage]} table, but on a parameter-by-parameter basis
+     *       instead than for the whole operation (which is probably better).</li>
+     *
+     *   <li>EPSG provides another information in the {@code REVERSE_OP} column of the
+     *       {@code [Coordinate_Operation Method]} table, but this is not equivalent to this method because it
+     *       does not differentiate the map projection methods from <em>inverse</em> map projection methods.</li>
+     * </ul>
+     *
      * @return {@code true} if the inverse of this operation method can be described by the same operation method.
+     *
+     * @see org.apache.sis.internal.referencing.SignReversalComment
      */
     public boolean isInvertible() {
         return false;

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Affine.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -236,10 +236,10 @@ public final class Affine extends Abstra
      * Returns the operation method for the specified source and target dimensions.
      * This method provides different {@code Affine} instances for different dimensions.
      *
-     * @param sourceDimensions The number of source dimensions.
-     * @param targetDimensions The number of target dimensions.
-     * @param isAffine {@code true} if the transform is affine.
-     * @return The provider for transforms of the given source and target dimensions.
+     * @param  sourceDimensions  the number of source dimensions.
+     * @param  targetDimensions  the number of target dimensions.
+     * @param  isAffine          {@code true} if the transform is affine.
+     * @return the provider for transforms of the given source and target dimensions.
      */
     public static Affine getProvider(final int sourceDimensions, final int targetDimensions, final boolean isAffine) {
         Affine method;

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -57,7 +57,7 @@ public final class CoordinateFrameRotati
      * Constructs the provider.
      */
     public CoordinateFrameRotation() {
-        super(3, 3, PARAMETERS);
+        super(3, 3, PARAMETERS, null);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation2D.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation2D.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation2D.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -57,7 +57,22 @@ public final class CoordinateFrameRotati
      * Constructs the provider.
      */
     public CoordinateFrameRotation2D() {
-        super(2, 2, PARAMETERS);
+        this(null);
+    }
+
+    /**
+     * Constructs a provider that can be resized.
+     */
+    CoordinateFrameRotation2D(GeodeticOperation[] redimensioned) {
+        super(2, 2, PARAMETERS, redimensioned);
+    }
+
+    /**
+     * Returns the three-dimensional variant of this operation method.
+     */
+    @Override
+    Class<CoordinateFrameRotation3D> variant3D() {
+        return CoordinateFrameRotation3D.class;
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation3D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation3D.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation3D.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation3D.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -56,8 +56,24 @@ public final class CoordinateFrameRotati
     /**
      * Constructs the provider.
      */
+    @SuppressWarnings("ThisEscapedInObjectConstruction")
     public CoordinateFrameRotation3D() {
-        super(3, 3, PARAMETERS);
+        this(3, 3, new GeocentricAffineBetweenGeographic[4]);
+        redimensioned[0] = new CoordinateFrameRotation2D(      redimensioned);
+        redimensioned[1] = new CoordinateFrameRotation3D(2, 3, redimensioned);
+        redimensioned[2] = new CoordinateFrameRotation3D(3, 2, redimensioned);
+        redimensioned[3] = this;
+    }
+
+    /**
+     * Constructs a provider for the given dimensions.
+     *
+     * @param sourceDimensions  number of dimensions in the source CRS of this operation method.
+     * @param targetDimensions  number of dimensions in the target CRS of this operation method.
+     * @param redimensioned     providers for all combinations between 2D and 3D cases, or {@code null}.
+     */
+    private CoordinateFrameRotation3D(int sourceDimensions, int targetDimensions, GeodeticOperation[] redimensioned) {
+        super(sourceDimensions, targetDimensions, PARAMETERS, redimensioned);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/FranceGeocentricInterpolation.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -38,8 +38,6 @@ import org.opengis.parameter.InvalidPara
 import org.opengis.referencing.datum.Ellipsoid;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
-import org.opengis.referencing.operation.Transformation;
-import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.NoninvertibleTransformException;
 import org.opengis.util.FactoryException;
 import org.apache.sis.internal.system.Loggers;
@@ -47,7 +45,6 @@ import org.apache.sis.internal.system.Da
 import org.apache.sis.internal.referencing.NilReferencingObject;
 import org.apache.sis.parameter.ParameterBuilder;
 import org.apache.sis.parameter.Parameters;
-import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Errors;
@@ -93,7 +90,7 @@ import org.apache.sis.internal.jdk8.JDK8
  * @module
  */
 @XmlTransient
-public class FranceGeocentricInterpolation extends AbstractProvider {
+public class FranceGeocentricInterpolation extends GeodeticOperation {
     /**
      * Serial number for inter-operability with different versions.
      */
@@ -172,18 +169,6 @@ public class FranceGeocentricInterpolati
     }
 
     /**
-     * The providers for all combinations between 2D and 3D cases.
-     * Array length is 4. Index is built with following rule:
-     * <ul>
-     *   <li>Bit 1: dimension of source coordinates (0 for 2D, 1 for 3D).</li>
-     *   <li>Bit 0: dimension of target coordinates (0 for 2D, 1 for 3D).</li>
-     * </ul>
-     *
-     * This array is initialized at construction time and shall not be modified after.
-     */
-    final FranceGeocentricInterpolation[] redimensioned;
-
-    /**
      * Constructs a provider.
      */
     @SuppressWarnings("ThisEscapedInObjectConstruction")
@@ -198,32 +183,17 @@ public class FranceGeocentricInterpolati
     /**
      * Constructs a provider for the given number of dimensions.
      *
-     * @param sourceDimensions Number of dimensions in the source CRS of this operation method.
-     * @param targetDimensions Number of dimensions in the target CRS of this operation method.
-     * @param parameters       The set of parameters (never {@code null}).
-     * @param redimensioned    Providers for all combinations between 2D and 3D cases.
+     * @param sourceDimensions  number of dimensions in the source CRS of this operation method.
+     * @param targetDimensions  number of dimensions in the target CRS of this operation method.
+     * @param parameters        description of parameters expected by this operation.
+     * @param redimensioned     providers for all combinations between 2D and 3D cases, or {@code null}.
      */
     FranceGeocentricInterpolation(final int sourceDimensions,
                                   final int targetDimensions,
                                   final ParameterDescriptorGroup parameters,
-                                  final FranceGeocentricInterpolation[] redimensioned)
+                                  final GeodeticOperation[] redimensioned)
     {
-        super(sourceDimensions, targetDimensions, parameters);
-        this.redimensioned = redimensioned;
-    }
-
-    /**
-     * Returns the same operation method, but for different number of dimensions.
-     *
-     * @param  sourceDimensions The desired number of input dimensions.
-     * @param  targetDimensions The desired number of output dimensions.
-     * @return The redimensioned operation method, or {@code this} if no change is needed.
-     */
-    @Override
-    public OperationMethod redimension(final int sourceDimensions, final int targetDimensions) {
-        ArgumentChecks.ensureBetween("sourceDimensions", 2, 3, sourceDimensions);
-        ArgumentChecks.ensureBetween("targetDimensions", 2, 3, targetDimensions);
-        return redimensioned[((sourceDimensions & 1) << 1) | (targetDimensions & 1)];
+        super(sourceDimensions, targetDimensions, parameters, redimensioned);
     }
 
     /**
@@ -240,13 +210,13 @@ public class FranceGeocentricInterpolati
     }
 
     /**
-     * Returns the base interface of the {@code CoordinateOperation} instances that use this method.
+     * The inverse of {@code FranceGeocentricInterpolation} is a different operation.
      *
-     * @return Fixed to {@link Transformation}.
+     * @return {@code false}.
      */
     @Override
-    public Class<Transformation> getOperationType() {
-        return Transformation.class;
+    public final boolean isInvertible() {
+        return false;
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricAffine.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricAffine.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricAffine.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricAffine.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -30,7 +30,6 @@ import org.opengis.referencing.cs.Coordi
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
-import org.opengis.referencing.operation.Transformation;
 import org.apache.sis.internal.referencing.Formulas;
 import org.apache.sis.internal.referencing.WKTUtilities;
 import org.apache.sis.internal.metadata.WKTKeywords;
@@ -64,7 +63,7 @@ import org.apache.sis.util.logging.Loggi
  * @module
  */
 @XmlTransient
-public abstract class GeocentricAffine extends AbstractProvider {
+public abstract class GeocentricAffine extends GeodeticOperation {
     /**
      * Serial number for inter-operability with different versions.
      */
@@ -153,21 +152,13 @@ public abstract class GeocentricAffine e
     /**
      * Constructs a provider with the specified parameters.
      *
-     * @param sourceDimensions Number of dimensions in the source CRS of this operation method.
-     * @param targetDimensions Number of dimensions in the target CRS of this operation method.
+     * @param sourceDimensions  number of dimensions in the source CRS of this operation method.
+     * @param targetDimensions  number of dimensions in the target CRS of this operation method.
+     * @param parameters        description of parameters expected by this operation.
+     * @param redimensioned     providers for all combinations between 2D and 3D cases, or {@code null}.
      */
-    GeocentricAffine(int sourceDimensions, int targetDimensions, ParameterDescriptorGroup parameters) {
-        super(sourceDimensions, targetDimensions, parameters);
-    }
-
-    /**
-     * Returns the interface implemented by all coordinate operations that extends this class.
-     *
-     * @return Fixed to {@link Transformation}.
-     */
-    @Override
-    public final Class<Transformation> getOperationType() {
-        return Transformation.class;
+    GeocentricAffine(int sourceDimensions, int targetDimensions, ParameterDescriptorGroup parameters, GeodeticOperation[] redimensioned) {
+        super(sourceDimensions, targetDimensions, parameters, redimensioned);
     }
 
     /**
@@ -177,16 +168,6 @@ public abstract class GeocentricAffine e
     abstract int getType();
 
     /**
-     * The inverse of this operation is the same operation with parameter signs inverted.
-     *
-     * @return {@code true} for all {@code GeocentricAffine}.
-     */
-    @Override
-    public final boolean isInvertible() {
-        return true;
-    }
-
-    /**
      * Creates a math transform from the specified group of parameter values.
      * The default implementation creates an affine transform, but some subclasses
      * will wrap that affine operation into Geographic/Geocentric conversions.
@@ -206,12 +187,12 @@ public abstract class GeocentricAffine e
         boolean reverseRotation = false;
         switch (getType()) {
             default:             throw new AssertionError();
-            case FRAME_ROTATION: reverseRotation = true;               // Fall through
+            case FRAME_ROTATION: reverseRotation = true;                    // Fall through
             case SEVEN_PARAM:    parameters.rX = pv.doubleValue(RX);
                                  parameters.rY = pv.doubleValue(RY);
                                  parameters.rZ = pv.doubleValue(RZ);
                                  parameters.dS = pv.doubleValue(DS);
-            case TRANSLATION:    parameters.tX = pv.doubleValue(TX);   // Fall through
+            case TRANSLATION:    parameters.tX = pv.doubleValue(TX);        // Fall through
                                  parameters.tY = pv.doubleValue(TY);
                                  parameters.tZ = pv.doubleValue(TZ);
         }
@@ -275,7 +256,7 @@ public abstract class GeocentricAffine e
         @SuppressWarnings("null")
         int dimension  = sourceCS.getDimension();
         if (dimension != targetCS.getDimension()) {
-            dimension  = 0;                             // Sentinal value for mismatched dimensions.
+            dimension  = 4;     // Any value greater than 3 means "mismatched dimensions" for this method.
         }
         /*
          * Try to convert the matrix into (tX, tY, tZ, rX, rY, rZ, dS) parameters.
@@ -312,7 +293,7 @@ public abstract class GeocentricAffine e
             }
         }
         final Parameters values = createParameters(descriptor, parameters, isTranslation);
-        if (useMolodensky && dimension != 0) {
+        if (useMolodensky && dimension <= 3) {
             values.getOrCreate(Molodensky.DIMENSION).setValue(dimension);
         }
         return values;

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricAffineBetweenGeographic.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricAffineBetweenGeographic.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricAffineBetweenGeographic.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricAffineBetweenGeographic.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -101,11 +101,15 @@ public abstract class GeocentricAffineBe
     /**
      * Constructs a provider with the specified parameters.
      *
-     * @param sourceDimensions Number of dimensions in the source CRS of this operation method.
-     * @param targetDimensions Number of dimensions in the target CRS of this operation method.
+     * @param sourceDimensions  number of dimensions in the source CRS of this operation method.
+     * @param targetDimensions  number of dimensions in the target CRS of this operation method.
+     * @param parameters        description of parameters expected by this operation.
+     * @param redimensioned     providers for all combinations between 2D and 3D cases, or {@code null}.
      */
-    GeocentricAffineBetweenGeographic(int sourceDimensions, int targetDimensions, ParameterDescriptorGroup parameters) {
-        super(sourceDimensions, targetDimensions, parameters);
+    GeocentricAffineBetweenGeographic(int sourceDimensions, int targetDimensions,
+            ParameterDescriptorGroup parameters, GeodeticOperation[] redimensioned)
+    {
+        super(sourceDimensions, targetDimensions, parameters, redimensioned);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -52,7 +52,7 @@ public final class GeocentricTranslation
      * Constructs the provider.
      */
     public GeocentricTranslation() {
-        super(3, 3, PARAMETERS);
+        super(3, 3, PARAMETERS, null);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation2D.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation2D.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation2D.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -56,7 +56,22 @@ public final class GeocentricTranslation
      * Constructs the provider.
      */
     public GeocentricTranslation2D() {
-        super(2, 2, PARAMETERS);
+        this(null);
+    }
+
+    /**
+     * Constructs a provider that can be resized.
+     */
+    GeocentricTranslation2D(GeodeticOperation[] redimensioned) {
+        super(2, 2, PARAMETERS, redimensioned);
+    }
+
+    /**
+     * Returns the three-dimensional variant of this operation method.
+     */
+    @Override
+    Class<GeocentricTranslation3D> variant3D() {
+        return GeocentricTranslation3D.class;
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation3D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation3D.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation3D.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation3D.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -51,8 +51,24 @@ public final class GeocentricTranslation
     /**
      * Constructs the provider.
      */
+    @SuppressWarnings("ThisEscapedInObjectConstruction")
     public GeocentricTranslation3D() {
-        super(3, 3, PARAMETERS);
+        this(3, 3, new GeocentricAffineBetweenGeographic[4]);
+        redimensioned[0] = new GeocentricTranslation2D(      redimensioned);
+        redimensioned[1] = new GeocentricTranslation3D(2, 3, redimensioned);
+        redimensioned[2] = new GeocentricTranslation3D(3, 2, redimensioned);
+        redimensioned[3] = this;
+    }
+
+    /**
+     * Constructs a provider for the given dimensions.
+     *
+     * @param sourceDimensions  number of dimensions in the source CRS of this operation method.
+     * @param targetDimensions  number of dimensions in the target CRS of this operation method.
+     * @param redimensioned     providers for all combinations between 2D and 3D cases, or {@code null}.
+     */
+    private GeocentricTranslation3D(int sourceDimensions, int targetDimensions, GeodeticOperation[] redimensioned) {
+        super(sourceDimensions, targetDimensions, PARAMETERS, redimensioned);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic3Dto2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic3Dto2D.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic3Dto2D.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Geographic3Dto2D.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -37,7 +37,7 @@ import org.apache.sis.internal.referenci
 /**
  * The provider for <cite>"Geographic 3D to 2D conversion"</cite> (EPSG:9659).
  * This is a trivial operation that just drop the height in a geographic coordinate.
- * The inverse operation arbitrarily set the ellipsoidal height to zero.
+ * The inverse operation arbitrarily sets the ellipsoidal height to zero.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.7
@@ -54,7 +54,7 @@ public final class Geographic3Dto2D exte
     /**
      * The group of all parameters expected by this coordinate operation (in this case, none).
      */
-    static final ParameterDescriptorGroup PARAMETERS = builder()
+    public static final ParameterDescriptorGroup PARAMETERS = builder()
             .addIdentifier("9659").addName("Geographic3D to 2D conversion").createGroup();
 
     /**
@@ -113,9 +113,9 @@ public final class Geographic3Dto2D exte
     }
 
     /**
-     * A temporary placeholder used for formatting a {@code PARAM_MT["Geographic 3D to 2D conversion"]}
-     * element in Well-Known Text format. This placeholder is needed there is no {@link MathTransform}
-     * implementation for the Geographic 3D to 2D conversion, since we use affine transform instead.
+     * A temporary placeholder used for formatting a {@code PARAM_MT["Geographic 3D to 2D conversion"]} element in
+     * Well-Known Text format. This placeholder is needed because there is no {@link MathTransform} implementation
+     * for the Geographic 3D to 2D conversion, since we use affine transform instead.
      */
     public static final class WKT extends FormattableObject implements Parameterized {
         /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicOffsets.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicOffsets.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicOffsets.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicOffsets.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -25,7 +25,6 @@ import org.opengis.parameter.ParameterDe
 import org.opengis.parameter.ParameterNotFoundException;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
-import org.opengis.referencing.operation.Transformation;
 import org.apache.sis.parameter.ParameterBuilder;
 import org.apache.sis.parameter.Parameters;
 import org.apache.sis.referencing.operation.matrix.Matrix4;
@@ -43,7 +42,7 @@ import org.apache.sis.referencing.operat
  * @module
  */
 @XmlTransient
-public class GeographicOffsets extends AbstractProvider {
+public class GeographicOffsets extends GeodeticOperation {
     /**
      * Serial number for inter-operability with different versions.
      */
@@ -79,35 +78,22 @@ public class GeographicOffsets extends A
     /**
      * Constructs a provider with default parameters.
      */
+    @SuppressWarnings("ThisEscapedInObjectConstruction")
     public GeographicOffsets() {
-        super(3, 3, PARAMETERS);
+        super(3, 3, PARAMETERS, new GeographicOffsets[4]);
+        redimensioned[0] = new GeographicOffsets2D(redimensioned);
+        redimensioned[1] = new GeographicOffsets(2, 3, PARAMETERS, redimensioned);
+        redimensioned[2] = new GeographicOffsets(3, 2, PARAMETERS, redimensioned);
+        redimensioned[3] = this;
     }
 
     /**
      * For subclasses constructor only.
      */
-    GeographicOffsets(int dim, ParameterDescriptorGroup parameters) {
-        super(dim, dim, parameters);
-    }
-
-    /**
-     * Returns the operation type.
-     *
-     * @return Interface implemented by all coordinate operations that use this method.
-     */
-    @Override
-    public final Class<Transformation> getOperationType() {
-        return Transformation.class;
-    }
-
-    /**
-     * The inverse of this operation is the same operation with parameter signs inverted.
-     *
-     * @return {@code true} for all {@code GeocentricAffine}.
-     */
-    @Override
-    public final boolean isInvertible() {
-        return true;
+    GeographicOffsets(int sourceDimensions, int targetDimensions,
+            ParameterDescriptorGroup parameters, GeodeticOperation[] redimensioned)
+    {
+        super(sourceDimensions, targetDimensions, parameters, redimensioned);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicOffsets2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicOffsets2D.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicOffsets2D.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicOffsets2D.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -53,7 +53,22 @@ public final class GeographicOffsets2D e
      * Constructs a provider with default parameters.
      */
     public GeographicOffsets2D() {
-        super(2, PARAMETERS);
+        this(null);
+    }
+
+    /**
+     * Constructs a provider that can be resized.
+     */
+    GeographicOffsets2D(GeodeticOperation[] redimensioned) {
+        super(2, 2, PARAMETERS, redimensioned);
+    }
+
+    /**
+     * Returns the three-dimensional variant of this operation method.
+     */
+    @Override
+    Class<GeographicOffsets> variant3D() {
+        return GeographicOffsets.class;
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LongitudeRotation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LongitudeRotation.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LongitudeRotation.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/LongitudeRotation.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -65,8 +65,24 @@ public final class LongitudeRotation ext
     /**
      * Constructs a provider with default parameters.
      */
+    @SuppressWarnings("ThisEscapedInObjectConstruction")
     public LongitudeRotation() {
-        super(2, PARAMETERS);
+        this(2, 2, new LongitudeRotation[4]);
+        redimensioned[0] = this;
+        redimensioned[1] = new LongitudeRotation(2, 3, redimensioned);
+        redimensioned[2] = new LongitudeRotation(3, 2, redimensioned);
+        redimensioned[3] = new LongitudeRotation(3, 3, redimensioned);
+    }
+
+    /**
+     * Constructs a provider for the given dimensions.
+     *
+     * @param sourceDimensions  number of dimensions in the source CRS of this operation method.
+     * @param targetDimensions  number of dimensions in the target CRS of this operation method.
+     * @param redimensioned     providers for all combinations between 2D and 3D cases.
+     */
+    private LongitudeRotation(int sourceDimensions, int targetDimensions, GeodeticOperation[] redimensioned) {
+        super(sourceDimensions, targetDimensions, PARAMETERS, redimensioned);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Molodensky.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Molodensky.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Molodensky.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/Molodensky.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -29,7 +29,6 @@ import org.opengis.parameter.ParameterNo
 import org.opengis.parameter.InvalidParameterValueException;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
-import org.opengis.referencing.operation.OperationMethod;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.parameter.ParameterBuilder;
 import org.apache.sis.parameter.Parameters;
@@ -39,7 +38,6 @@ import org.apache.sis.internal.referenci
 import org.apache.sis.internal.referencing.Formulas;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.Debug;
 
 
@@ -134,22 +132,11 @@ public final class Molodensky extends Ge
     }
 
     /**
-     * The providers for all combinations between 2D and 3D cases.
-     * Array length is 4. Index is built with following rule:
-     * <ul>
-     *   <li>Bit 1: dimension of source coordinates (0 for 2D, 1 for 3D).</li>
-     *   <li>Bit 0: dimension of target coordinates (0 for 2D, 1 for 3D).</li>
-     * </ul>
-     */
-    private final Molodensky[] redimensioned;
-
-    /**
      * Constructs a new provider.
      */
     @SuppressWarnings("ThisEscapedInObjectConstruction")
     public Molodensky() {
-        super(3, 3, PARAMETERS);
-        redimensioned = new Molodensky[4];
+        this(3, 3, new Molodensky[4]);
         redimensioned[0] = new Molodensky(2, 2, redimensioned);
         redimensioned[1] = new Molodensky(2, 3, redimensioned);
         redimensioned[2] = new Molodensky(3, 2, redimensioned);
@@ -159,27 +146,12 @@ public final class Molodensky extends Ge
     /**
      * Constructs a provider for the given dimensions.
      *
-     * @param sourceDimensions Number of dimensions in the source CRS of this operation method.
-     * @param targetDimensions Number of dimensions in the target CRS of this operation method.
-     * @param redimensioned    Providers for all combinations between 2D and 3D cases.
-     */
-    private Molodensky(final int sourceDimensions, final int targetDimensions, final Molodensky[] redimensioned) {
-        super(sourceDimensions, targetDimensions, PARAMETERS);
-        this.redimensioned = redimensioned;
-    }
-
-    /**
-     * Returns the same operation method, but for different number of dimensions.
-     *
-     * @param  sourceDimensions The desired number of input dimensions.
-     * @param  targetDimensions The desired number of output dimensions.
-     * @return The redimensioned operation method, or {@code this} if no change is needed.
-     */
-    @Override
-    public OperationMethod redimension(final int sourceDimensions, final int targetDimensions) {
-        ArgumentChecks.ensureBetween("sourceDimensions", 2, 3, sourceDimensions);
-        ArgumentChecks.ensureBetween("targetDimensions", 2, 3, targetDimensions);
-        return redimensioned[((sourceDimensions & 1) << 1) | (targetDimensions & 1)];
+     * @param sourceDimensions  number of dimensions in the source CRS of this operation method.
+     * @param targetDimensions  number of dimensions in the target CRS of this operation method.
+     * @param redimensioned     providers for all combinations between 2D and 3D cases.
+     */
+    private Molodensky(int sourceDimensions, int targetDimensions, GeodeticOperation[] redimensioned) {
+        super(sourceDimensions, targetDimensions, PARAMETERS, redimensioned);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MolodenskyInterpolation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MolodenskyInterpolation.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MolodenskyInterpolation.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/MolodenskyInterpolation.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -68,15 +68,15 @@ public final class MolodenskyInterpolati
     /**
      * Constructs a provider for the given number of dimensions.
      *
-     * @param sourceDimensions Number of dimensions in the source CRS of this operation method.
-     * @param targetDimensions Number of dimensions in the target CRS of this operation method.
-     * @param parameters       The set of parameters (never {@code null}).
-     * @param redimensioned    Providers for all combinations between 2D and 3D cases.
+     * @param sourceDimensions  number of dimensions in the source CRS of this operation method.
+     * @param targetDimensions  number of dimensions in the target CRS of this operation method.
+     * @param parameters        description of parameters expected by this operation.
+     * @param redimensioned     providers for all combinations between 2D and 3D cases, or {@code null}.
      */
     private MolodenskyInterpolation(final int sourceDimensions,
                                     final int targetDimensions,
                                     final ParameterDescriptorGroup parameters,
-                                    final FranceGeocentricInterpolation[] redimensioned)
+                                    final GeodeticOperation[] redimensioned)
     {
         super(sourceDimensions, targetDimensions, parameters, redimensioned);
     }

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -56,7 +56,7 @@ public final class PositionVector7Param
      * Constructs the provider.
      */
     public PositionVector7Param() {
-        super(3, 3, PARAMETERS);
+        super(3, 3, PARAMETERS, null);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param2D.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param2D.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param2D.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -59,7 +59,22 @@ public final class PositionVector7Param2
      * Constructs the provider.
      */
     public PositionVector7Param2D() {
-        super(2, 2, PARAMETERS);
+        this(null);
+    }
+
+    /**
+     * Constructs a provider that can be resized.
+     */
+    PositionVector7Param2D(GeodeticOperation[] redimensioned) {
+        super(2, 2, PARAMETERS, redimensioned);
+    }
+
+    /**
+     * Returns the three-dimensional variant of this operation method.
+     */
+    @Override
+    Class<PositionVector7Param3D> variant3D() {
+        return PositionVector7Param3D.class;
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param3D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param3D.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param3D.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param3D.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -54,8 +54,24 @@ public final class PositionVector7Param3
     /**
      * Constructs the provider.
      */
+    @SuppressWarnings("ThisEscapedInObjectConstruction")
     public PositionVector7Param3D() {
-        super(3, 3, PARAMETERS);
+        this(3, 3, new GeocentricAffineBetweenGeographic[4]);
+        redimensioned[0] = new PositionVector7Param2D(      redimensioned);
+        redimensioned[1] = new PositionVector7Param3D(2, 3, redimensioned);
+        redimensioned[2] = new PositionVector7Param3D(3, 2, redimensioned);
+        redimensioned[3] = this;
+    }
+
+    /**
+     * Constructs a provider for the given dimensions.
+     *
+     * @param sourceDimensions  number of dimensions in the source CRS of this operation method.
+     * @param targetDimensions  number of dimensions in the target CRS of this operation method.
+     * @param redimensioned     providers for all combinations between 2D and 3D cases, or {@code null}.
+     */
+    private PositionVector7Param3D(int sourceDimensions, int targetDimensions, GeodeticOperation[] redimensioned) {
+        super(sourceDimensions, targetDimensions, PARAMETERS, redimensioned);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/VerticalOffset.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/VerticalOffset.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/VerticalOffset.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/VerticalOffset.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -70,7 +70,7 @@ public final class VerticalOffset extend
      * Constructs a provider with default parameters.
      */
     public VerticalOffset() {
-        super(1, PARAMETERS);
+        super(1, 1, PARAMETERS, null);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptorGroup.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptorGroup.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptorGroup.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/parameter/DefaultParameterDescriptorGroup.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -210,8 +210,9 @@ public class DefaultParameterDescriptorG
      */
     private static void verifyNames(final Map<String,?> properties, final GeneralParameterDescriptor[] parameters) {
         for (int i=0; i<parameters.length; i++) {
-            ArgumentChecks.ensureNonNullElement("parameters", i, parameters);
-            final String name = parameters[i].getName().getCode();
+            final GeneralParameterDescriptor parameter = parameters[i];
+            ArgumentChecks.ensureNonNullElement("parameters", i, parameter);
+            final String name = parameter.getName().getCode();
             for (int j=0; j<i; j++) {
                 if (IdentifiedObjects.isHeuristicMatchForName(parameters[j], name)) {
                     throw new InvalidParameterNameException(Errors.getResources(properties).getString(

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/AbstractIdentifiedObject.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -393,7 +393,7 @@ public class AbstractIdentifiedObject ex
             final Map<String,?> properties, final String key, final Object value)
     {
         return new IllegalArgumentException(Errors.getResources(properties)
-                .getString(Errors.Keys.IllegalPropertyClass_2, key, value.getClass()));
+                .getString(Errors.Keys.IllegalPropertyValueClass_2, key, value.getClass()));
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/AuthorityFactories.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -89,7 +89,7 @@ final class AuthorityFactories<T extends
      * Creates a new provider for factories of the given type.
      */
     private AuthorityFactories(final Class<T> type) {
-        super(ServiceLoader.load(type));
+        super(type);
     }
 
     /**

Modified: sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java?rev=1740152&r1=1740151&r2=1740152&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] (original)
+++ sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] Wed Apr 20 14:53:31 2016
@@ -44,6 +44,8 @@ import org.opengis.metadata.extent.Exten
 import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.apache.sis.internal.metadata.AxisDirections;
+import org.apache.sis.internal.referencing.PositionalAccuracyConstant;
+import org.apache.sis.internal.referencing.CoordinateOperations;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.referencing.cs.DefaultVerticalCS;
@@ -51,6 +53,7 @@ import org.apache.sis.referencing.cs.Def
 import org.apache.sis.referencing.crs.DefaultGeographicCRS;
 import org.apache.sis.referencing.crs.DefaultVerticalCRS;
 import org.apache.sis.referencing.crs.DefaultCompoundCRS;
+import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
 import org.apache.sis.referencing.operation.CoordinateOperationContext;
 import org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory;
 import org.apache.sis.referencing.factory.UnavailableFactoryException;
@@ -66,13 +69,34 @@ import static java.util.Collections.sing
 
 /**
  * Static methods working on {@linkplain CoordinateReferenceSystem Coordinate Reference Systems}.
- * The methods defined in this class can be grouped in two categories:
+ * The methods defined in this class can be grouped in three categories:
  *
  * <ul>
  *   <li>Factory methods, the most notable one being {@link #forCode(String)}.</li>
  *   <li>Methods providing information, like {@link #isHorizontalCRS(CoordinateReferenceSystem)}.</li>
+ *   <li>Finding coordinate operations between a source and a target CRS.</li>
  * </ul>
  *
+ * <div class="section">Usage example</div>
+ * The most frequently used methods in this class are {@link #forCode forCode(…)}, {@link #fromWKT fromWKT(…)}
+ * and {@link #findOperation findOperation(…)}. An usage example is like below
+ * (see the <a href="http://sis.apache.org/book/tables/CoordinateReferenceSystems.html">Apache SIS™ Coordinate
+ * Reference System (CRS) codes</a> page for the complete list of EPSG codes):
+ *
+ * {@preformat java
+ *   CoordinateReferenceSystem source = CRS.forCode("EPSG:4326");                   // WGS 84
+ *   CoordinateReferenceSystem target = CRS.forCode("EPSG:3395");                   // WGS 84 / World Mercator
+ *   CoordinateOperation operation = CRS.findOperation(source, target, null);
+ *   if (CRS.getLinearAccuracy(operation) > 100) {
+ *       // If the accuracy is coarser than 100 metres (or any other threshold at application choice)
+ *       // maybe the operation is not suitable. Decide here what to do (throw an exception, etc).
+ *   }
+ *   MathTransform mt = operation.getMathTransform();
+ *   DirectPosition position = new DirectPosition2D(20, 30);            // 20°N 30°E   (watch out axis order!)
+ *   position = mt.transform(position, position);
+ *   System.out.println(position);
+ * }
+ *
  * <div class="section">Note on kinds of CRS</div>
  * The {@link #getSingleComponents(CoordinateReferenceSystem)} method decomposes an arbitrary CRS into a flat
  * list of single components. In such flat list, vertical and temporal components can easily be identified by
@@ -101,9 +125,10 @@ public final class CRS extends Static {
     /**
      * Returns the Coordinate Reference System for the given authority code.
      * The set of available codes depends on the {@link CRSAuthorityFactory} instances available on the classpath.
-     * There is many thousands of CRS defined by EPSG authority or by other authorities.
+     * There is many thousands of <a href="http://sis.apache.org/book/tables/CoordinateReferenceSystems.html">CRS
+     * defined by EPSG authority or by other authorities</a>.
      * The following table lists a very small subset of codes which are guaranteed to be available
-     * on any installation of Apache SIS version 0.4 or above:
+     * on any installation of Apache SIS:
      *
      * <blockquote><table class="sis">
      *   <caption>Minimal set of supported authority codes</caption>
@@ -218,14 +243,141 @@ public final class CRS extends Static {
     }
 
     /**
+     * Creates a coordinate reference system object from a XML string.
+     * Note that the given argument is the XML document itself, <strong>not</strong> a URL to a XML document.
+     * For reading XML documents from readers or input streams,
+     * see static methods in the {@link org.apache.sis.xml.XML} class.
+     *
+     * @param  xml Coordinate reference system encoded in XML format.
+     * @return The unmarshalled Coordinate Reference System.
+     * @throws FactoryException if the object creation failed.
+     *
+     * @see org.apache.sis.xml.XML#unmarshal(String)
+     *
+     * @since 0.7
+     */
+    public static CoordinateReferenceSystem fromXML(final String xml) throws FactoryException {
+        ArgumentChecks.ensureNonNull("text", xml);
+        return DefaultFactories.forBuildin(CRSFactory.class).createFromXML(xml);
+    }
+
+    /**
+     * Finds a mathematical operation that transforms or converts coordinates from the given source to the
+     * given target coordinate reference system. If an estimation of the geographic area containing the points
+     * to transform is known, it can be specified for helping this method to find a better suited operation.
+     *
+     * <div class="note"><b>Note:</b>
+     * the area of interest is just one aspect that may affect the coordinate operation.
+     * Other aspects are the time of interest (because some coordinate operations take in account the
+     * plate tectonics movement) or the desired accuracy. For more control on the coordinate operation
+     * to create, see {@link CoordinateOperationContext}.</div>
+     *
+     * After the caller received a {@code CoordinateOperation} instance, the following methods can be invoked
+     * for checking if the operation suits the caller's needs:
+     *
+     * <ul>
+     *   <li>{@link #getGeographicBoundingBox(CoordinateOperation)}
+     *       for checking if the operation is valid in the caller's area of interest.</li>
+     *   <li>{@link #getLinearAccuracy(CoordinateOperation)}
+     *       for checking if the operation has sufficient accuracy for caller's purpose.</li>
+     * </ul>
+     *
+     * @param  sourceCRS      the CRS of source coordinates.
+     * @param  targetCRS      the CRS of target coordinates.
+     * @param  areaOfInterest the area of interest, or {@code null} if none.
+     * @return the mathematical operation from {@code sourceCRS} to {@code targetCRS}.
+     * @throws FactoryException if the operation can not be created.
+     *
+     * @see DefaultCoordinateOperationFactory#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, CoordinateOperationContext)
+     *
+     * @since 0.7
+     */
+    public static CoordinateOperation findOperation(final CoordinateReferenceSystem sourceCRS,
+                                                    final CoordinateReferenceSystem targetCRS,
+                                                    final GeographicBoundingBox areaOfInterest)
+            throws FactoryException
+    {
+        ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
+        ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
+        CoordinateOperationContext context = null;
+        if (areaOfInterest != null) {
+            if (areaOfInterest instanceof DefaultGeographicBoundingBox && ((DefaultGeographicBoundingBox) areaOfInterest).isEmpty()) {
+                throw new IllegalArgumentException(Errors.format(Errors.Keys.EmptyArgument_1, "areaOfInterest"));
+            }
+            context = new CoordinateOperationContext();
+            context.setAreaOfInterest(areaOfInterest);
+        }
+        return CoordinateOperations.factory().createOperation(sourceCRS, targetCRS, context);
+    }
+
+    /**
+     * Returns a positional accuracy estimation in metres for the given operation, or {@code NaN} if unknown.
+     * This method applies the following heuristics:
+     *
+     * <ul>
+     *   <li>If the given operation is an instance of {@link AbstractCoordinateOperation}, then delegate to the
+     *       operation {@link AbstractCoordinateOperation#getLinearAccuracy() getLinearAccuracy()} method.</li>
+     *
+     *   <li>Otherwise if at least one {@linkplain org.apache.sis.metadata.iso.quality.DefaultQuantitativeResult
+     *       quantitative result} is found with a linear unit, then return the largest value converted to metres.</li>
+     *
+     *   <li>Otherwise if the operation is a {@linkplain org.apache.sis.referencing.operation.DefaultConversion
+     *       conversion}, then returns 0 since a conversion is by definition accurate up to rounding errors.</li>
+     *
+     *   <li>Otherwise if the operation is a {@linkplain org.apache.sis.referencing.operation.DefaultTransformation
+     *       transformation}, then the returned value depends on whether the datum shift were applied with the help
+     *       of Bursa-Wolf parameters of not.</li>
+     * </ul>
+     *
+     * See {@link AbstractCoordinateOperation#getLinearAccuracy()} for more details on the above heuristic rules.
+     *
+     * @param  operation The coordinate operation for which to get the accuracy estimation, or {@code null}.
+     * @return The accuracy estimation (always in meters), or NaN if unknown.
+     *
+     * @see #findOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, GeographicBoundingBox)
+     *
+     * @since 0.7
+     */
+    public static double getLinearAccuracy(final CoordinateOperation operation) {
+        if (operation == null) {
+            return Double.NaN;
+        } else if (operation instanceof AbstractCoordinateOperation) {
+            return ((AbstractCoordinateOperation) operation).getLinearAccuracy();
+        } else {
+            return PositionalAccuracyConstant.getLinearAccuracy(operation);
+        }
+    }
+
+    /**
+     * Returns the valid geographic area for the given coordinate operation, or {@code null} if unknown.
+     * This method explores the {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of validity}
+     * associated with the given operation. If more than one geographic bounding box is found, then they will be
+     * {@linkplain org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox#add(GeographicBoundingBox) added}
+     * together.
+     *
+     * @param  operation The coordinate operation for which to get the domain of validity, or {@code null}.
+     * @return The geographic area where the operation is valid, or {@code null} if unspecified.
+     *
+     * @see #findOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, GeographicBoundingBox)
+     * @see Extents#getGeographicBoundingBox(Extent)
+     *
+     * @category information
+     *
+     * @since 0.7
+     */
+    public static GeographicBoundingBox getGeographicBoundingBox(final CoordinateOperation operation) {
+        return (operation != null) ? Extents.getGeographicBoundingBox(operation.getDomainOfValidity()) : null;
+    }
+
+    /**
      * Returns the valid geographic area for the given coordinate reference system, or {@code null} if unknown.
-     * This method explores the {@linkplain CoordinateReferenceSystem#getDomainOfValidity() domain of validity}
-     * associated with the given CRS. If more than one geographic bounding box is found, then they will be
-     * {@linkplain org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox#add(GeographicBoundingBox)
-     * added} together.
+     * This method explores the {@linkplain org.apache.sis.referencing.crs.AbstractCRS#getDomainOfValidity() domain of
+     * validity} associated with the given CRS. If more than one geographic bounding box is found, then they will be
+     * {@linkplain org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox#add(GeographicBoundingBox) added}
+     * together.
      *
-     * @param  crs The coordinate reference system, or {@code null}.
-     * @return The geographic area, or {@code null} if none.
+     * @param  crs The coordinate reference system for which to get the domain of validity, or {@code null}.
+     * @return The geographic area where the coordinate reference system is valid, or {@code null} if unspecified.
      *
      * @see #getEnvelope(CoordinateReferenceSystem)
      * @see Extents#getGeographicBoundingBox(Extent)
@@ -596,43 +748,4 @@ check:  while (lower != 0 || upper != di
         }
         return AuthorityFactories.ALL.getAuthorityFactory(CRSAuthorityFactory.class, authority, null);
     }
-
-    /**
-     * Finds a mathematical operation that transforms or converts coordinates from the given source to the
-     * given target coordinate reference system. If an estimation of the geographic area containing the points
-     * to transform is known, it can be specified for helping this method to find a better suited operation.
-     *
-     * <p>Note that the area of interest is just one aspect that may affect the coordinate operation.
-     * Other aspects are the time of interest (because some coordinate operations take in account the
-     * plate tectonics movement) or the desired accuracy. For more control on the coordinate operation
-     * to create, see {@link CoordinateOperationContext}.</p>
-     *
-     * @param  sourceCRS      the CRS of source coordinates.
-     * @param  targetCRS      the CRS of target coordinates.
-     * @param  areaOfInterest the area of interest, or {@code null} if none.
-     * @return the mathematical operation from {@code sourceCRS} to {@code targetCRS}.
-     * @throws FactoryException if the operation can not be created.
-     *
-     * @see DefaultCoordinateOperationFactory#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, CoordinateOperationContext)
-     *
-     * @since 0.7
-     */
-    public static CoordinateOperation findOperation(final CoordinateReferenceSystem sourceCRS,
-                                                    final CoordinateReferenceSystem targetCRS,
-                                                    final GeographicBoundingBox areaOfInterest)
-            throws FactoryException
-    {
-        ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
-        ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
-        CoordinateOperationContext context = null;
-        if (areaOfInterest != null) {
-            final DefaultGeographicBoundingBox bbox = DefaultGeographicBoundingBox.castOrCopy(areaOfInterest);
-            if (bbox.isEmpty()) {
-                throw new IllegalArgumentException(Errors.format(Errors.Keys.EmptyArgument_1, "areaOfInterest"));
-            }
-            context = new CoordinateOperationContext();
-            context.setGeographicBoundingBox(bbox);
-        }
-        return CoordinateOperations.factory.createOperation(sourceCRS, targetCRS, context);
-    }
 }




Mime
View raw message