sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1740177 [5/8] - in /sis/trunk: ./ 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/sis-fea...
Date Wed, 20 Apr 2016 17:40:13 GMT
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/CoordinateSystems.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -18,11 +18,13 @@ package org.apache.sis.referencing.cs;
 
 import java.util.Arrays;
 import javax.measure.unit.Unit;
+import javax.measure.quantity.Length;
 import javax.measure.converter.UnitConverter;
 import javax.measure.converter.LinearConverter;
 import javax.measure.converter.ConversionException;
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.cs.CoordinateSystem;
+import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.opengis.referencing.operation.Matrix;
 import org.apache.sis.measure.Angle;
 import org.apache.sis.measure.ElevationAngle;
@@ -49,7 +51,7 @@ import org.apache.sis.internal.jdk7.Obje
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  */
 public final class CoordinateSystems extends Static {
@@ -306,8 +308,8 @@ public final class CoordinateSystems ext
          * not a matrix multiplication. The last column is processed in a special
          * way, since it contains the offset values.
          */
-        final int sourceDim = matrix.getNumCol() - 1;  // == sourceCS.getDimension()
-        final int targetDim = matrix.getNumRow() - 1;  // == targetCS.getDimension()
+        final int sourceDim = matrix.getNumCol() - 1;                       // == sourceCS.getDimension()
+        final int targetDim = matrix.getNumRow() - 1;                       // == targetCS.getDimension()
         for (int j=0; j<targetDim; j++) {
             final Unit<?> targetUnit = targetCS.getAxis(j).getUnit();
             for (int i=0; i<sourceDim; i++) {
@@ -405,4 +407,106 @@ public final class CoordinateSystems ext
         }
         return cs;
     }
+
+    /**
+     * Returns a coordinate system derived from the given one but with all linear units replaced by the given unit.
+     * Non-linear units (e.g. angular or scale units) are left unchanged.
+     *
+     * <p>This convenience method is equivalent to the following code:</p>
+     * {@preformat java
+     *     return CoordinateSystems.replaceAxes(cs, new AxisFilter() {
+     *         &#64;Override public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, Unit<?> unit) {
+     *             return Units.isLinear(unit) ? newUnit : unit;
+     *         }
+     *     });
+     * }
+     *
+     * @param  cs       The coordinate system in which to replace linear units, or {@code null}.
+     * @param  newUnit  The new linear unit.
+     * @return The modified coordinate system as a new instance,
+     *         or {@code cs} if all linear units were already equal to the given one.
+     *
+     * @see Units#isLinear(Unit)
+     *
+     * @since 0.7
+     */
+    public static CoordinateSystem replaceLinearUnit(final CoordinateSystem cs, final Unit<Length> newUnit) {
+        ensureNonNull("newUnit", newUnit);
+        return CoordinateSystems.replaceAxes(cs, new AxisFilter() {
+            @Override public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, Unit<?> unit) {
+                return Units.isLinear(unit) ? newUnit : unit;
+            }
+
+            @Override
+            public boolean accept(CoordinateSystemAxis axis) {
+                return true;
+            }
+
+            @Override
+            public AxisDirection getDirectionReplacement(CoordinateSystemAxis axis, AxisDirection direction) {
+                return direction;
+            }
+
+            @Deprecated @Override
+            public AxisDirection getDirectionReplacement(AxisDirection direction) {
+                return direction;
+            }
+
+            @Deprecated @Override
+            public Unit<?> getUnitReplacement(Unit<?> unit) {
+                return getUnitReplacement(null, unit);
+            }
+        });
+    }
+
+    /**
+     * Returns a coordinate system derived from the given one but with all angular units replaced by the given unit.
+     * Non-angular units (e.g. linear or scale units) are left unchanged.
+     *
+     * <p>This convenience method is equivalent to the following code:</p>
+     * {@preformat java
+     *     return CoordinateSystems.replaceAxes(cs, new AxisFilter() {
+     *         &#64;Override public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, Unit<?> unit) {
+     *             return Units.isAngular(unit) ? newUnit : unit;
+     *         }
+     *     });
+     * }
+     *
+     * @param  cs       The coordinate system in which to replace angular units, or {@code null}.
+     * @param  newUnit  The new angular unit.
+     * @return The modified coordinate system as a new instance,
+     *         or {@code cs} if all angular units were already equal to the given one.
+     *
+     * @see Units#isAngular(Unit)
+     *
+     * @since 0.7
+     */
+    public static CoordinateSystem replaceAngularUnit(final CoordinateSystem cs, final Unit<javax.measure.quantity.Angle> newUnit) {
+        ensureNonNull("newUnit", newUnit);
+        return CoordinateSystems.replaceAxes(cs, new AxisFilter() {
+            @Override public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, Unit<?> unit) {
+                return Units.isAngular(unit) ? newUnit : unit;
+            }
+
+            @Override
+            public boolean accept(CoordinateSystemAxis axis) {
+                return true;
+            }
+
+            @Override
+            public AxisDirection getDirectionReplacement(CoordinateSystemAxis axis, AxisDirection direction) {
+                return direction;
+            }
+
+            @Deprecated @Override
+            public AxisDirection getDirectionReplacement(AxisDirection direction) {
+                return direction;
+            }
+
+            @Deprecated @Override
+            public Unit<?> getUnitReplacement(Unit<?> unit) {
+                return getUnitReplacement(null, unit);
+            }
+        });
+    }
 }

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCompoundCS.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCompoundCS.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCompoundCS.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultCompoundCS.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -139,7 +139,7 @@ public class DefaultCompoundCS extends A
         ensureNonNull("components", components);
         components = components.clone();
         for (int i=0; i<components.length; i++) {
-            ensureNonNullElement("components", i, components);
+            ensureNonNullElement("components", i, components[i]);
         }
         return components;
     }

Copied: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java (from r1740152, sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java)
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java?p2=sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java&p1=sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java&r1=1740152&r2=1740177&rev=1740177&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/DefaultParametricCS.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -20,7 +20,6 @@ import java.util.Map;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
 import org.opengis.referencing.cs.CoordinateSystemAxis;
-import org.opengis.referencing.cs.ParametricCS;
 
 
 /**
@@ -53,7 +52,7 @@ import org.opengis.referencing.cs.Parame
  */
 @XmlType(name = "ParametricCSType")
 @XmlRootElement(name = "ParametricCS")
-public class DefaultParametricCS extends AbstractCS implements ParametricCS {
+public class DefaultParametricCS extends AbstractCS {
     /**
      * Serial number for inter-operability with different versions.
      */
@@ -119,46 +118,16 @@ public class DefaultParametricCS extends
      *
      * <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
      *
-     * @param cs The coordinate system to copy.
+     * <div class="warning"><b>Warning:</b> in a future SIS version, the parameter type may be changed
+     * to {@code org.opengis.referencing.cs.ParametricCS}. This change is pending GeoAPI revision.</div>
      *
-     * @see #castOrCopy(ParametricCS)
+     * @param cs The coordinate system to copy.
      */
-    protected DefaultParametricCS(final ParametricCS cs) {
+    protected DefaultParametricCS(final DefaultParametricCS cs) {
         super(cs);
     }
 
     /**
-     * Returns a SIS coordinate system implementation with the same values than the given arbitrary implementation.
-     * If the given object is {@code null}, then this method returns {@code null}.
-     * Otherwise if the given object is already a SIS implementation, then the given object is returned unchanged.
-     * Otherwise a new SIS implementation is created and initialized to the attribute values of the given object.
-     *
-     * @param  object The object to get as a SIS implementation, or {@code null} if none.
-     * @return A SIS implementation containing the values of the given object (may be the
-     *         given object itself), or {@code null} if the argument was null.
-     */
-    public static DefaultParametricCS castOrCopy(final ParametricCS object) {
-        return (object == null) || (object instanceof DefaultParametricCS)
-                ? (DefaultParametricCS) object : new DefaultParametricCS(object);
-    }
-
-    /**
-     * Returns the GeoAPI interface implemented by this class.
-     * The SIS implementation returns {@code ParametricCS.class}.
-     *
-     * <div class="note"><b>Note for implementors:</b>
-     * Subclasses usually do not need to override this method since GeoAPI does not define {@code ParametricCS}
-     * sub-interface. Overriding possibility is left mostly for implementors who wish to extend GeoAPI with
-     * their own set of interfaces.</div>
-     *
-     * @return {@code ParametricCS.class} or a user-defined sub-interface.
-     */
-    @Override
-    public Class<? extends ParametricCS> getInterface() {
-        return ParametricCS.class;
-    }
-
-    /**
      * {@inheritDoc}
      *
      * @return {@inheritDoc}

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/AbstractDatum.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -83,6 +83,7 @@ import org.apache.sis.internal.jdk7.Obje
     DefaultGeodeticDatum.class,
     DefaultVerticalDatum.class,
     DefaultTemporalDatum.class,
+    DefaultParametricDatum.class,
     DefaultEngineeringDatum.class,
     DefaultImageDatum.class
 })

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/BursaWolfParameters.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -238,7 +238,7 @@ public class BursaWolfParameters extends
      *
      * <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
+     * implementations in {@link org.apache.sis.referencing.operation.CoordinateOperationFinder} 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>
      *

Copied: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java (from r1740152, sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java)
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java?p2=sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java&p1=sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java&r1=1740152&r2=1740177&rev=1740177&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultParametricDatum.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -20,7 +20,6 @@ import java.util.Date;
 import java.util.Map;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
-import org.opengis.referencing.datum.ParametricDatum;
 import org.apache.sis.internal.metadata.WKTKeywords;
 import org.apache.sis.io.wkt.Formatter;
 
@@ -57,7 +56,7 @@ import org.apache.sis.io.wkt.Formatter;
  */
 @XmlType(name = "ParametricDatumType")
 @XmlRootElement(name = "ParametricDatum")
-public class DefaultParametricDatum extends AbstractDatum implements ParametricDatum {
+public class DefaultParametricDatum extends AbstractDatum {
     /**
      * Serial number for inter-operability with different versions.
      */
@@ -132,46 +131,16 @@ public class DefaultParametricDatum exte
      *
      * <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
      *
-     * @param datum The datum to copy.
+     * <div class="warning"><b>Warning:</b> in a future SIS version, the parameter type may be changed
+     * to {@code org.opengis.referencing.datum.ParametricDatum}. This change is pending GeoAPI revision.</div>
      *
-     * @see #castOrCopy(ParametricDatum)
+     * @param datum The datum to copy.
      */
-    protected DefaultParametricDatum(final ParametricDatum datum) {
+    protected DefaultParametricDatum(final DefaultParametricDatum datum) {
         super(datum);
     }
 
     /**
-     * Returns a SIS datum implementation with the same values than the given arbitrary implementation.
-     * If the given object is {@code null}, then this method returns {@code null}.
-     * Otherwise if the given object is already a SIS implementation, then the given object is returned unchanged.
-     * Otherwise a new SIS implementation is created and initialized to the attribute values of the given object.
-     *
-     * @param  object The object to get as a SIS implementation, or {@code null} if none.
-     * @return A SIS implementation containing the values of the given object (may be the
-     *         given object itself), or {@code null} if the argument was null.
-     */
-    public static DefaultParametricDatum castOrCopy(final ParametricDatum object) {
-        return (object == null) || (object instanceof DefaultParametricDatum) ?
-                (DefaultParametricDatum) object : new DefaultParametricDatum(object);
-    }
-
-    /**
-     * Returns the GeoAPI interface implemented by this class.
-     * The SIS implementation returns {@code ParametricDatum.class}.
-     *
-     * <div class="note"><b>Note for implementors:</b>
-     * Subclasses usually do not need to override this method since GeoAPI does not define {@code TemporalDatum}
-     * sub-interface. Overriding possibility is left mostly for implementors who wish to extend GeoAPI with their
-     * own set of interfaces.</div>
-     *
-     * @return {@code ParametricDatum.class} or a user-defined sub-interface.
-     */
-    @Override
-    public Class<? extends ParametricDatum> getInterface() {
-        return ParametricDatum.class;
-    }
-
-    /**
      * Formats this datum as a <cite>Well Known Text</cite> {@code ParametricDatum[…]} element.
      *
      * <div class="note"><b>Compatibility note:</b>

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -26,6 +26,7 @@ import java.util.Arrays;
 import javax.measure.unit.SI;
 import javax.measure.unit.NonSI;
 import javax.measure.unit.Unit;
+import javax.measure.quantity.Length;
 import org.opengis.util.FactoryException;
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.citation.Citation;
@@ -42,7 +43,6 @@ import org.opengis.referencing.crs.Singl
 import org.opengis.referencing.cs.CSFactory;
 import org.opengis.referencing.cs.CartesianCS;
 import org.opengis.referencing.cs.AxisDirection;
-import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.opengis.referencing.datum.DatumFactory;
 import org.opengis.referencing.datum.EngineeringDatum;
 import org.apache.sis.internal.referencing.GeodeticObjectBuilder;
@@ -52,7 +52,6 @@ import org.apache.sis.internal.system.Lo
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.measure.Units;
 import org.apache.sis.referencing.CommonCRS;
-import org.apache.sis.referencing.cs.AxisFilter;
 import org.apache.sis.referencing.cs.CoordinateSystems;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ArraysExt;
@@ -627,36 +626,14 @@ public class CommonAuthorityFactory exte
              * At this point we got a coordinate system with axes in metres.
              * If the user asked for another unit of measurement, change the axes now.
              */
-            final Unit<?> unit;
+            final Unit<Length> unit;
             if (isLegacy) {
-                unit = createUnitFromEPSG(factor);
+                unit = createUnitFromEPSG(factor).asType(Length.class);
             } else {
                 unit = (factor != 1) ? Units.multiply(SI.METRE, factor) : SI.METRE;
             }
             if (!SI.METRE.equals(unit)) {
-                cs = (CartesianCS) CoordinateSystems.replaceAxes(cs, new AxisFilter() {
-                    @Override public Unit<?> getUnitReplacement(Unit<?> ignored) {
-                        assert SI.METRE.equals(ignored) : ignored;
-                        return unit;
-                    }
-
-                    @Override public Unit<?> getUnitReplacement(CoordinateSystemAxis axis, Unit<?> ignored) {
-                        assert SI.METRE.equals(ignored) : ignored;
-                        return unit;
-                    }
-
-                    @Override public boolean accept(CoordinateSystemAxis axis) {
-                        return true;
-                    }
-
-                    @Override public AxisDirection getDirectionReplacement(AxisDirection direction) {
-                        return direction;
-                    }
-
-                    @Override public AxisDirection getDirectionReplacement(CoordinateSystemAxis axis, AxisDirection direction) {
-                        return direction;
-                    }
-                });
+                cs = (CartesianCS) CoordinateSystems.replaceLinearUnit(cs, unit);
             }
             /*
              * Set the projection name, operation method and parameters. The parameters for the Transverse Mercator

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -40,6 +40,11 @@ import org.apache.sis.util.CharSequences
 import org.apache.sis.util.Classes;
 import org.apache.sis.util.Debug;
 
+// Branch-dependent imports
+import org.apache.sis.referencing.cs.DefaultParametricCS;
+import org.apache.sis.referencing.crs.DefaultParametricCRS;
+import org.apache.sis.referencing.datum.DefaultParametricDatum;
+
 
 /**
  * Creates geodetic objects from codes defined by an authority.
@@ -62,6 +67,7 @@ import org.apache.sis.util.Debug;
  * However, other methods may be overridden as well for better performances.</p>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @author  Johann Sorel (Geomatys)
  * @since   0.7
  * @version 0.7
  * @module
@@ -393,6 +399,27 @@ public abstract class GeodeticAuthorityF
     }
 
     /**
+     * Creates a 1-dimensional parametric coordinate reference system.
+     *
+     * <div class="section">Default implementation</div>
+     * The default implementation delegates to {@link #createCoordinateReferenceSystem(String)} and casts the result.
+     * If the result can not be casted, then a {@link NoSuchAuthorityCodeException} is thrown.
+     *
+     * <div class="warning"><b>Warning:</b> in a future SIS version, the return type may be changed
+     * to {@code org.opengis.referencing.crs.ParametricCRS}. This change is pending GeoAPI revision.</div>
+     *
+     * @param  code Value allocated by authority.
+     * @return The coordinate reference system for the given code.
+     * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found.
+     * @throws FactoryException if the object creation failed for some other reason.
+     *
+     * @see org.apache.sis.referencing.crs.DefaultParametricCRS
+     */
+    public DefaultParametricCRS createParametricCRS(final String code) throws NoSuchAuthorityCodeException, FactoryException {
+        return cast(DefaultParametricCRS.class, createCoordinateReferenceSystem(code), code);
+    }
+
+    /**
      * Creates a CRS describing the position of points through two or more independent coordinate reference systems.
      *
      * <div class="note"><b>Example:</b>
@@ -610,6 +637,27 @@ public abstract class GeodeticAuthorityF
     }
 
     /**
+     * Creates a datum defining the origin of a parametric coordinate reference system.
+     *
+     * <div class="section">Default implementation</div>
+     * The default implementation delegates to {@link #createDatum(String)} and casts the result.
+     * If the result can not be casted, then a {@link NoSuchAuthorityCodeException} is thrown.
+     *
+     * <div class="warning"><b>Warning:</b> in a future SIS version, the return type may be changed
+     * to {@code org.opengis.referencing.datum.ParametricDatum}. This change is pending GeoAPI revision.</div>
+     *
+     * @param  code Value allocated by authority.
+     * @return The datum for the given code.
+     * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found.
+     * @throws FactoryException if the object creation failed for some other reason.
+     *
+     * @see org.apache.sis.referencing.datum.DefaultParametricDatum
+     */
+    public DefaultParametricDatum createParametricDatum(final String code) throws NoSuchAuthorityCodeException, FactoryException {
+        return cast(DefaultParametricDatum.class, createDatum(code), code);
+    }
+
+    /**
      * Creates a datum defining the origin of an engineering coordinate reference system.
      * An engineering datum is used in a region around that origin.
      * This origin can be fixed with respect to the earth or be a defined point on a moving vehicle.
@@ -870,6 +918,27 @@ public abstract class GeodeticAuthorityF
     }
 
     /**
+     * Creates a 1-dimensional parametric coordinate system.
+     *
+     * <div class="section">Default implementation</div>
+     * The default implementation delegates to {@link #createCoordinateSystem(String)} and casts the result.
+     * If the result can not be casted, then a {@link NoSuchAuthorityCodeException} is thrown.
+     *
+     * <div class="warning"><b>Warning:</b> in a future SIS version, the return type may be changed
+     * to {@code org.opengis.referencing.cs.ParametricCS}. This change is pending GeoAPI revision.</div>
+     *
+     * @param  code Value allocated by authority.
+     * @return The coordinate system for the given code.
+     * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found.
+     * @throws FactoryException if the object creation failed for some other reason.
+     *
+     * @see org.apache.sis.referencing.cs.DefaultParametricCS
+     */
+    public DefaultParametricCS createParametricCS(final String code) throws NoSuchAuthorityCodeException, FactoryException {
+        return cast(DefaultParametricCS.class, createCoordinateSystem(code), code);
+    }
+
+    /**
      * Creates a 2- or 3-dimensional Cartesian coordinate system made of straight orthogonal axes.
      * All axes shall have the same linear unit of measure.
      *

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticObjectFactory.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -189,6 +189,7 @@ import org.apache.sis.xml.XML;
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Guilhem Legal (Geomatys)
+ * @author  Johann Sorel (Geomatys)
  * @since   0.6
  * @version 0.7
  * @module
@@ -1036,6 +1037,103 @@ public class GeodeticObjectFactory exten
     }
 
     /**
+     * Creates a parametric coordinate reference system.
+     * Parametric CRS can be used for physical properties or functions that vary monotonically with height.
+     * A typical example is the pressure in meteorological applications.
+     *
+     * <div class="note"><b>Dependencies:</b>
+     * the components needed by this method can be created by the following methods:
+     * <ol>
+     *   <li>{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}</li>
+     *   <li>{@link #createParametricCS(Map, CoordinateSystemAxis)}</li>
+     *   <li>{@link #createParametricDatum(Map)}</li>
+     * </ol></div>
+     *
+     * The default implementation creates a {@link DefaultParametricCRS} instance.
+     *
+     * <div class="warning"><b>Warning:</b> in a future SIS version, the parameter types may be changed to
+     * {@code org.opengis.referencing.datum.ParametricDatum} and {@code org.opengis.referencing.cs.ParametricCS},
+     * and the return type may be changed to {@code org.opengis.referencing.crs.ParametricCRS}.
+     * Those change are pending GeoAPI revision.</div>
+     *
+     * @param  properties Name and other properties to give to the new object.
+     * @param  datum      The parametric datum to use in created CRS.
+     * @param  cs         The parametric coordinate system for the created CRS.
+     * @throws FactoryException if the object creation failed.
+     *
+     * @see DefaultParametricCRS#DefaultParametricCRS(Map, DefaultParametricDatum, DefaultParametricCS)
+     * @see GeodeticAuthorityFactory#createParametricCRS(String)
+     */
+    public DefaultParametricCRS createParametricCRS(final Map<String,?> properties,
+            final DefaultParametricDatum datum, final DefaultParametricCS cs) throws FactoryException
+    {
+        final DefaultParametricCRS crs;
+        try {
+            crs = new DefaultParametricCRS(complete(properties), datum, cs);
+        } catch (IllegalArgumentException exception) {
+            throw new InvalidGeodeticParameterException(exception);
+        }
+        return unique("createParametricCRS", crs);
+    }
+
+    /**
+     * Creates a parametric datum.
+     * The default implementation creates a {@link DefaultParametricDatum} instance.
+     *
+     * <div class="warning"><b>Warning:</b> in a future SIS version, the return type may be changed
+     * to {@code org.opengis.referencing.datum.ParametricDatum}. This change is pending GeoAPI revision.</div>
+     *
+     * @param  properties Name and other properties to give to the new object.
+     * @throws FactoryException if the object creation failed.
+     *
+     * @see DefaultParametricDatum#DefaultParametricDatum(Map)
+     * @see GeodeticAuthorityFactory#createParametricDatum(String)
+     */
+    public DefaultParametricDatum createParametricDatum(final Map<String,?> properties)
+            throws FactoryException
+    {
+        final DefaultParametricDatum datum;
+        try {
+            datum = new DefaultParametricDatum(complete(properties));
+        } catch (IllegalArgumentException exception) {
+            throw new InvalidGeodeticParameterException(exception);
+        }
+        return unique("createParametricDatum", datum);
+    }
+
+    /**
+     * Creates a parametric coordinate system.
+     * This coordinate system can be used only with parametric CRS.
+     *
+     * <div class="note"><b>Dependencies:</b>
+     * the components needed by this method can be created by the following methods:
+     * <ol>
+     *   <li>{@link #createCoordinateSystemAxis(Map, String, AxisDirection, Unit)}</li>
+     * </ol></div>
+     *
+     * The default implementation creates a {@link DefaultParametricCS} instance.
+     *
+     * <div class="warning"><b>Warning:</b> in a future SIS version, the return type may be changed
+     * to {@code org.opengis.referencing.cs.ParametricCS}. This change is pending GeoAPI revision.</div>
+     *
+     * @param  properties Name and other properties to give to the new object.
+     * @param  axis The single axis.
+     * @throws FactoryException if the object creation failed.
+     *
+     * @see DefaultParametricCS#DefaultParametricCS(Map, CoordinateSystemAxis)
+     * @see GeodeticAuthorityFactory#createParametricCS(String)
+     */
+    public DefaultParametricCS createParametricCS(Map<String, ?> properties, CoordinateSystemAxis axis) throws FactoryException {
+        final DefaultParametricCS cs;
+        try {
+            cs = new DefaultParametricCS(complete(properties), axis);
+        } catch (IllegalArgumentException exception) {
+            throw new InvalidGeodeticParameterException(exception);
+        }
+        return unique("createParametricCS", cs);
+    }
+
+    /**
      * Creates a compound coordinate reference system from an ordered list of {@code CoordinateReferenceSystem} objects.
      * Apache SIS puts no restriction on the components that can be used in a compound CRS.
      * However for better inter-operability, users are encouraged to follow the order mandated by ISO 19162:
@@ -1458,6 +1556,7 @@ public class GeodeticObjectFactory exten
      * @throws FactoryException if the object creation failed.
      *
      * @see XML#unmarshal(String)
+     * @see org.apache.sis.referencing.CRS#fromXML(String)
      */
     @Override
     public CoordinateReferenceSystem createFromXML(final String xml) throws FactoryException {

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/IdentifiedObjectFinder.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -341,7 +341,7 @@ public class IdentifiedObjectFinder {
      * If the set returned by {@link #find(IdentifiedObject)} contains exactly one element,
      * then that element is returned. Otherwise this method returns {@code null}.
      *
-     * <p>Note that this method returns {@code null} even if there is more than one element,
+     * <p>This method returns {@code null} if there is more than one element
      * because in such case we consider that there is an ambiguity.</p>
      *
      * @param  object The object looked up.

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -1591,11 +1591,11 @@ public class MultiAuthoritiesFactory ext
      */
     public void reload() {
         for (int type=0; type < providers.length; type++) {
-            Iterable<?> provider = providers[type];
+            final Iterable<?> provider = providers[type];
             if (provider != null) {
                 synchronized (provider) {
                     if (provider instanceof LazySet<?>) {
-                        provider = ((LazySet<?>) provider).reload();
+                        ((LazySet<?>) provider).reload();
                     }
                     if (provider instanceof ServiceLoader<?>) {
                         ((ServiceLoader<?>) provider).reload();

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -67,10 +67,12 @@ import org.opengis.referencing.Identifie
 import org.opengis.referencing.NoSuchAuthorityCodeException;
 import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.metadata.TransformationAccuracy;
+import org.apache.sis.internal.metadata.WKTKeywords;
 import org.apache.sis.internal.metadata.sql.SQLUtilities;
 import org.apache.sis.internal.referencing.DeprecatedCode;
 import org.apache.sis.internal.referencing.EPSGParameterDomain;
 import org.apache.sis.internal.referencing.ReferencingUtilities;
+import org.apache.sis.internal.referencing.SignReversalComment;
 import org.apache.sis.internal.referencing.Formulas;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.system.Semaphores;
@@ -121,6 +123,8 @@ import org.apache.sis.internal.jdk7.JDK7
 import org.apache.sis.internal.jdk8.JDK8;
 import org.apache.sis.internal.jdk7.AutoCloseable;
 import org.apache.sis.internal.util.StandardDateFormat;
+import org.apache.sis.referencing.cs.DefaultParametricCS;
+import org.apache.sis.referencing.datum.DefaultParametricDatum;
 
 
 /**
@@ -1064,13 +1068,13 @@ addURIs:    for (int i=0; ; i++) {
      * @param  table       The table on which a query has been executed.
      * @param  name        The name for the {@link IndentifiedObject} to construct.
      * @param  code        The EPSG code of the object to construct.
-     * @param  remarks     Remarks, or {@code null} if none.
+     * @param  remarks     Remarks as a {@link String} or {@link InternationalString}, or {@code null} if none.
      * @param  deprecated  {@code true} if the object to create is deprecated.
      * @return The name together with a set of properties.
      */
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
     private Map<String,Object> createProperties(final String table, String name, final Integer code,
-            String remarks, final boolean deprecated) throws SQLException, FactoryDataException
+            CharSequence remarks, final boolean deprecated) throws SQLException, FactoryDataException
     {
         /*
          * Search for aliases. Note that searching for the object code is not sufficient. We also need to check if the
@@ -1172,8 +1176,12 @@ addURIs:    for (int i=0; ; i++) {
      * @return The name together with a set of properties.
      */
     private Map<String,Object> createProperties(final String table, final String name, final Integer code,
-            final String domainCode, String scope, String remarks, final boolean deprecated) throws SQLException, FactoryException
+            final String domainCode, String scope, final String remarks, final boolean deprecated)
+            throws SQLException, FactoryException
     {
+        if ("?".equals(scope)) {                // EPSG sometime uses this value for unspecified scope.
+            scope = null;
+        }
         final Map<String,Object> properties = createProperties(table, name, code, remarks, deprecated);
         if (domainCode != null) {
             properties.put(Datum.DOMAIN_OF_VALIDITY_KEY, owner.createExtent(domainCode));
@@ -1537,6 +1545,15 @@ addURIs:    for (int i=0; ; i++) {
                                 name, epsg, area, scope, remarks, deprecated), datum, cs);
                     }
                     /* ----------------------------------------------------------------------
+                     *   PARAMETRIC CRS
+                     * ---------------------------------------------------------------------- */
+                    else if (type.equalsIgnoreCase("engineering")) {
+                        final DefaultParametricCS    cs    = owner.createParametricCS   (getString(code, result, 8));
+                        final DefaultParametricDatum datum = owner.createParametricDatum(getString(code, result, 9));
+                        crs = ReferencingServices.getInstance().createParametricCRS(createProperties("Coordinate Reference System",
+                                name, epsg, area, scope, remarks, deprecated), datum, cs, crsFactory);
+                    }
+                    /* ----------------------------------------------------------------------
                      *   UNKNOWN CRS
                      * ---------------------------------------------------------------------- */
                     else {
@@ -1685,6 +1702,9 @@ addURIs:    for (int i=0; ; i++) {
                     else if (type.equalsIgnoreCase("engineering")) {
                         datum = datumFactory.createEngineeringDatum(properties);
                     }
+                    else if (type.equalsIgnoreCase("parametric")) {
+                        datum = ReferencingServices.getInstance().createParametricDatum(properties, datumFactory);
+                    }
                     else {
                         throw new FactoryDataException(error().getString(Errors.Keys.UnknownType_1, type));
                     }
@@ -2136,49 +2156,54 @@ addURIs:    for (int i=0; ; i++) {
                 final CSFactory csFactory = owner.csFactory;
                 CoordinateSystem cs = null;
                 {   // On the JDK7 branch, this is a switch on strings.
-                    if (type.equalsIgnoreCase("ellipsoidal")) {
+                    if (type.equalsIgnoreCase(WKTKeywords.ellipsoidal)) {
                         switch (dimension) {
                             case 2: cs = csFactory.createEllipsoidalCS(properties, axes[0], axes[1]); break;
                             case 3: cs = csFactory.createEllipsoidalCS(properties, axes[0], axes[1], axes[2]); break;
                         }
                     }
-                    else if (type.equalsIgnoreCase("cartesian")) {
+                    else if (type.equalsIgnoreCase("cartesian")) {          // Need lower-case "c"
                         switch (dimension) {
                             case 2: cs = csFactory.createCartesianCS(properties, axes[0], axes[1]); break;
                             case 3: cs = csFactory.createCartesianCS(properties, axes[0], axes[1], axes[2]); break;
                         }
                     }
-                    else if (type.equalsIgnoreCase("spherical")) {
+                    else if (type.equalsIgnoreCase(WKTKeywords.spherical)) {
                         switch (dimension) {
                             case 3: cs = csFactory.createSphericalCS(properties, axes[0], axes[1], axes[2]); break;
                         }
                     }
-                    else if (type.equalsIgnoreCase("vertical") || type.equalsIgnoreCase("gravity-related")) {
+                    else if (type.equalsIgnoreCase(WKTKeywords.vertical) || type.equalsIgnoreCase("gravity-related")) {
                         switch (dimension) {
                             case 1: cs = csFactory.createVerticalCS(properties, axes[0]); break;
                         }
                     }
-                    else if (type.equalsIgnoreCase("time") || type.equalsIgnoreCase("temporal")) {
+                    else if (type.equalsIgnoreCase("time") || type.equalsIgnoreCase(WKTKeywords.temporal)) {
                         switch (dimension) {
                             case 1: cs = csFactory.createTimeCS(properties, axes[0]); break;
                         }
                     }
-                    else if (type.equalsIgnoreCase("linear")) {
+                    else if (type.equalsIgnoreCase(WKTKeywords.parametric)) {
+                        switch (dimension) {
+                            case 1: cs = ReferencingServices.getInstance().createParametricCS(properties, axes[0], csFactory); break;
+                        }
+                    }
+                    else if (type.equalsIgnoreCase(WKTKeywords.linear)) {
                         switch (dimension) {
                             case 1: cs = csFactory.createLinearCS(properties, axes[0]); break;
                         }
                     }
-                    else if (type.equalsIgnoreCase("polar")) {
+                    else if (type.equalsIgnoreCase(WKTKeywords.polar)) {
                         switch (dimension) {
                             case 2: cs = csFactory.createPolarCS(properties, axes[0], axes[1]); break;
                         }
                     }
-                    else if (type.equalsIgnoreCase("cylindrical")) {
+                    else if (type.equalsIgnoreCase(WKTKeywords.cylindrical)) {
                         switch (dimension) {
                             case 3: cs = csFactory.createCylindricalCS(properties, axes[0], axes[1], axes[2]); break;
                         }
                     }
-                    else if (type.equalsIgnoreCase("affine")) {
+                    else if (type.equalsIgnoreCase(WKTKeywords.affine)) {
                         switch (dimension) {
                             case 2: cs = csFactory.createAffineCS(properties, axes[0], axes[1]); break;
                             case 3: cs = csFactory.createAffineCS(properties, axes[0], axes[1], axes[2]); break;
@@ -2506,10 +2531,10 @@ addURIs:    for (int i=0; ; i++) {
                     " WHERE PARAMETER_CODE = ?", code);
 
             while (result.next()) {
-                final Integer epsg       = getInteger  (code, result, 1);
-                final String  name       = getString   (code, result, 2);
-                final String  remarks    = getOptionalString (result, 3);
-                final boolean deprecated = getOptionalBoolean(result, 4);
+                final Integer epsg        = getInteger  (code, result, 1);
+                final String  name        = getString   (code, result, 2);
+                final String  description = getOptionalString (result, 3);
+                final boolean deprecated  = getOptionalBoolean(result, 4);
                 Class<?> type = Double.class;
                 /*
                  * If the parameter appears to have at least one non-null value in the "Parameter File Name" column,
@@ -2560,6 +2585,29 @@ next:               while (r.next()) {
                     r.close();
                 }
                 /*
+                 * Determines if the inverse operation can be performed by reversing the parameter sign.
+                 * The EPSG dataset uses "Yes" or "No" value, but SIS scripts use boolean type. We have
+                 * to accept both.
+                 */
+                InternationalString isReversible = null;
+                r = executeQuery("ParameterSign",
+                        "SELECT DISTINCT PARAM_SIGN_REVERSAL FROM [Coordinate_Operation Parameter Usage]" +
+                        " WHERE (PARAMETER_CODE = ?)", epsg);
+                try {
+                    if (r.next()) {
+                        final String v = r.getString(1);
+                        if (v != null && !r.next()) {
+                            if (v.equalsIgnoreCase("true") || v.equalsIgnoreCase("yes") || v.equals("1")) {
+                                isReversible = SignReversalComment.OPPOSITE;
+                            } else if (v.equalsIgnoreCase("false") || v.equalsIgnoreCase("no") || v.equals("0")) {
+                                isReversible = SignReversalComment.SAME;
+                            }
+                        }
+                    }
+                } finally {
+                    r.close();
+                }
+                /*
                  * Now creates the parameter descriptor.
                  */
                 final NumberRange<?> valueDomain;
@@ -2569,9 +2617,11 @@ next:               while (r.next()) {
                     case 1:  valueDomain = MeasurementRange.create(Double.NEGATIVE_INFINITY, false,
                                     Double.POSITIVE_INFINITY, false, CollectionsExt.first(units)); break;
                 }
+                final Map<String, Object> properties =
+                        createProperties("Coordinate_Operation Parameter", name, epsg, isReversible, deprecated);
+                properties.put(ImmutableIdentifier.DESCRIPTION_KEY, description);
                 @SuppressWarnings({"unchecked", "rawtypes"})
-                final ParameterDescriptor<?> descriptor = new DefaultParameterDescriptor(
-                        createProperties("Coordinate_Operation Parameter", name, epsg, remarks, deprecated),
+                final ParameterDescriptor<?> descriptor = new DefaultParameterDescriptor(properties,
                         1, 1, type, valueDomain, null, null);
                 returnValue = ensureSingleton(descriptor, returnValue, code);
             }
@@ -2974,6 +3024,7 @@ next:               while (r.next()) {
                             }
                         }
                         opProperties.put(ReferencingServices.OPERATION_TYPE_KEY, opType);
+                        opProperties.put(ReferencingServices.PARAMETERS_KEY, parameters);
                         /*
                          * Following restriction will be removed in a future SIS version if the method is added to GeoAPI.
                          */

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/InstallationScriptProvider.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -202,7 +202,7 @@ public abstract class InstallationScript
      *
      * @param  authority The value given at construction time (e.g. {@code "EPSG"}).
      * @param  resource Index of the SQL script to read, from 0 inclusive to
-     *         <code>{@linkplain #getScriptNames()}.length</code> exclusive.
+     *         <code>{@linkplain #getResourceNames getResourceNames}(authority).length</code> exclusive.
      * @return A reader for the content of SQL script to execute.
      * @throws IllegalArgumentException if the given {@code authority} argument is not the expected value.
      * @throws IndexOutOfBoundsException if the given {@code resource} argument is out of bounds.
@@ -239,7 +239,7 @@ public abstract class InstallationScript
      *
      * <div class="note"><b>Example 1:</b>
      * if this {@code InstallationScriptProvider} instance gets the SQL scripts from files in a well-known directory
-     * and if the names given at {@linkplain #InstallationScriptProvider(String...) construction time} are the
+     * and if the names given at {@linkplain #InstallationScriptProvider(String, String...) construction time} are the
      * filenames in that directory, then this method can be implemented as below:
      *
      * {@preformat java

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/TableInfo.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/TableInfo.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/TableInfo.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/TableInfo.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -22,6 +22,7 @@ import org.opengis.referencing.crs.*;
 import org.opengis.referencing.datum.*;
 import org.opengis.referencing.operation.*;
 import org.opengis.parameter.ParameterDescriptor;
+import org.apache.sis.internal.metadata.WKTKeywords;
 
 
 /**
@@ -53,19 +54,31 @@ final class TableInfo {
                 "COORD_REF_SYS_CODE",
                 "COORD_REF_SYS_NAME",
                 "COORD_REF_SYS_KIND",
-                new Class<?>[] { ProjectedCRS.class, GeographicCRS.class, GeocentricCRS.class,
-                                 VerticalCRS.class,  CompoundCRS.class,   EngineeringCRS.class},
-                new String[]   {"projected",        "geographic",        "geocentric",
-                                "vertical",         "compound",          "engineering"},
+                new Class<?>[] { ProjectedCRS.class,   GeographicCRS.class,   GeocentricCRS.class,
+                                 VerticalCRS.class,    CompoundCRS.class,     EngineeringCRS.class},
+                              // TemporalCRS.class,    ParametricCRS.class    (See comment below)
+                new String[]   {"projected",          "geographic",          "geocentric",
+                                "vertical",           "compound",            "engineering"},
+                             // "temporal",           "parametric"
                 "SHOW_CRS"),
+                /*
+                 * Above declaration omitted Temporal and Parametric cases because they are not defined
+                 * by the EPSG registry (at least as of version 8.9). In particular, we are not sure if
+                 * EPSG would chose to use "time" or "temporal".  Omitting those types for now does not
+                 * prevent SIS to find CRS of those types; the operation will only be more costly.
+                 */
 
         new TableInfo(CoordinateSystem.class,
                 "[Coordinate System]",
                 "COORD_SYS_CODE",
                 "COORD_SYS_NAME",
                 "COORD_SYS_TYPE",
-                new Class<?>[] { CartesianCS.class, EllipsoidalCS.class, SphericalCS.class, VerticalCS.class},
-                new String[]   {"Cartesian",       "ellipsoidal",       "spherical",       "vertical"},    //Really upper-case C.
+                new Class<?>[] {CartesianCS.class,      EllipsoidalCS.class,      VerticalCS.class,      LinearCS.class,
+                                SphericalCS.class,      PolarCS.class,            CylindricalCS.class},
+                             // TimeCS.class,           ParametricCS.class,       AffineCS.class         (see above comment)
+                new String[]   {WKTKeywords.Cartesian,  WKTKeywords.ellipsoidal,  WKTKeywords.vertical,  WKTKeywords.linear,
+                                WKTKeywords.spherical,  WKTKeywords.polar,        WKTKeywords.cylindrical},
+                             // WKTKeywords.temporal,   WKTKeywords.parametric,   WKTKeywords.affine
                 null),
 
         new TableInfo(CoordinateSystemAxis.class,
@@ -80,8 +93,10 @@ final class TableInfo {
                 "DATUM_CODE",
                 "DATUM_NAME",
                 "DATUM_TYPE",
-                new Class<?>[] { GeodeticDatum.class, VerticalDatum.class, EngineeringDatum.class},
-                new String[]   {"geodetic",          "vertical",          "engineering"},
+                new Class<?>[] { GeodeticDatum.class,  VerticalDatum.class,   EngineeringDatum.class},
+                              // TemporalDatum.class,  ParametricDatum.class  (see above comment),
+                new String[]   {"geodetic",           "vertical",            "engineering"},
+                             // "temporal",           "parametric",
                 null),
 
         new TableInfo(Ellipsoid.class,

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -35,6 +35,7 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.PassThroughOperation;
 import org.opengis.parameter.GeneralParameterValue;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.parameter.ParameterValueGroup;
@@ -158,7 +159,7 @@ public class AbstractCoordinateOperation
      * (i.e., instantiation due to the stochastic nature of the parameters).
      *
      * <p><b>Consider this field as final!</b>
-     * This field is modified only at unmarshalling time by {@link #setOperationVersion(String)}</p>
+     * This field is modified only at unmarshalling time by {@link #setOperationVersion(String)}.</p>
      *
      * @see #getOperationVersion()
      */
@@ -179,7 +180,7 @@ public class AbstractCoordinateOperation
      * Area in which this operation is valid, or {@code null} if not available.
      *
      * <p><b>Consider this field as final!</b>
-     * This field is modified only at unmarshalling time by {@link #setDomainOfValidity(Extent)}</p>
+     * This field is modified only at unmarshalling time by {@link #setDomainOfValidity(Extent)}.</p>
      *
      * @see #getDomainOfValidity()
      */
@@ -189,7 +190,7 @@ public class AbstractCoordinateOperation
      * Description of domain of usage, or limitations of usage, for which this operation is valid.
      *
      * <p><b>Consider this field as final!</b>
-     * This field is modified only at unmarshalling time by {@link #setScope(InternationalString)}</p>
+     * This field is modified only at unmarshalling time by {@link #setScope(InternationalString)}.</p>
      *
      * @see #getScope()
      */
@@ -201,7 +202,7 @@ public class AbstractCoordinateOperation
      *
      * <p><b>Consider this field as final!</b>
      * This field is non-final only for the convenience of constructors and for initialization
-     * at XML unmarshalling time by {@link AbstractSingleOperation#afterUnmarshal(Unmarshaller, Object)}</p>
+     * at XML unmarshalling time by {@link AbstractSingleOperation#afterUnmarshal(Unmarshaller, Object)}.</p>
      */
     MathTransform transform;
 
@@ -513,7 +514,7 @@ check:      for (int isTarget=0; ; isTar
     /**
      * Returns the interpolation CRS of the given coordinate operation, or {@code null} if none.
      */
-    private static CoordinateReferenceSystem getInterpolationCRS(final CoordinateOperation operation) {
+    static CoordinateReferenceSystem getInterpolationCRS(final CoordinateOperation operation) {
         return (operation instanceof AbstractCoordinateOperation)
                ? ((AbstractCoordinateOperation) operation).getInterpolationCRS() : null;
     }
@@ -556,33 +557,34 @@ check:      for (int isTarget=0; ; isTar
      * Note that those rules may change in any future SIS version.
      *
      * <ul>
-     *   <li>If a {@linkplain org.apache.sis.metadata.iso.quality.DefaultQuantitativeResult quantitative result}
-     *     is found with a linear unit, then this accuracy estimate is converted to
-     *     {@linkplain javax.measure.unit.SI#METRE metres} and returned.</li>
-     *
-     *   <li>Otherwise, if the operation is a {@linkplain 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 DefaultTransformation transformation}, then checks if
-     *     the datum shift were applied with the help of Bursa-Wolf parameters.
-     *     If a datum shift has been applied, returns 25 meters.
-     *     If a datum shift should have been applied but has been omitted, returns 3000 meters.
-     *
-     *     <div class="note"><b>Note:</b>
-     *     the 3000 meters value is higher than the highest value (999 meters) found in the EPSG
-     *     database version 6.7. The 25 meters value is the next highest value found in the EPSG
-     *     database for a significant number of transformations.</div>
-     *
-     *   <li>Otherwise, if the operation is a {@linkplain DefaultConcatenatedOperation concatenated operation},
-     *     returns the sum of the accuracy of all components. This is a conservative scenario where we assume that
-     *     errors cumulate linearly.
-     *
-     *     <div class="note"><b>Note:</b>
-     *     this is not necessarily the "worst case" scenario since the accuracy could be worst if the math transforms
-     *     are highly non-linear.</div></li>
+     *   <li>If at least one {@linkplain org.apache.sis.metadata.iso.quality.DefaultQuantitativeResult quantitative
+     *       result} is found with a linear unit, then returns the largest result value converted to metres.</li>
+     *
+     *   <li>Otherwise if the operation is a {@linkplain 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 DefaultTransformation transformation},
+     *       then checks if the datum shift were applied with the help of Bursa-Wolf parameters.
+     *       If a datum shift has been applied, returns 25 meters.
+     *       If a datum shift should have been applied but has been omitted, returns 3000 meters.
+     *
+     *       <div class="note"><b>Note:</b>
+     *       the 3000 meters value is higher than the highest value (999 meters) found in the EPSG
+     *       database version 6.7. The 25 meters value is the next highest value found in the EPSG
+     *       database for a significant number of transformations.</div>
+     *
+     *   <li>Otherwise if the operation is a {@linkplain DefaultConcatenatedOperation concatenated operation},
+     *       returns the sum of the accuracy of all components.
+     *       This is a conservative scenario where we assume that errors cumulate linearly.
+     *
+     *       <div class="note"><b>Note:</b>
+     *       this is not necessarily the "worst case" scenario since the accuracy could be worst
+     *       if the math transforms are highly non-linear.</div></li>
      * </ul>
      *
      * @return The accuracy estimation (always in meters), or NaN if unknown.
+     *
+     * @see org.apache.sis.referencing.CRS#getLinearAccuracy(CoordinateOperation)
      */
     public double getLinearAccuracy() {
         return PositionalAccuracyConstant.getLinearAccuracy(this);
@@ -858,12 +860,17 @@ check:      for (int isTarget=0; ; isTar
         super.formatTo(formatter);
         formatter.newLine();
         /*
-         * If the WKT is a component of a ConcatenatedOperation, do not format the source and target CRS.
-         * This decision SIS-specific since the WKT 2 specification does not define concatenated operations.
-         * The choice of content to omit may change in any future version.
+         * If the WKT is a component of a ConcatenatedOperation, do not format the source CRS since it is identical
+         * to the target CRS of the previous step, or to the source CRS of the enclosing "ConcatenatedOperation" if
+         * this step is the first step.
+         *
+         * This decision is SIS-specific since the WKT 2 specification does not define concatenated operations.
+         * This choice may change in any future SIS version.
          */
-        final boolean isComponent = (formatter.getEnclosingElement(1) instanceof ConcatenatedOperation);
-        if (!isComponent) {
+        final FormattableObject enclosing = formatter.getEnclosingElement(1);
+        final boolean isSubOperation = (enclosing instanceof PassThroughOperation);
+        final boolean isComponent    = (enclosing instanceof ConcatenatedOperation);
+        if (!isSubOperation && !isComponent) {
             append(formatter, getSourceCRS(), WKTKeywords.SourceCRS);
             append(formatter, getTargetCRS(), WKTKeywords.TargetCRS);
         }
@@ -880,12 +887,14 @@ check:      for (int isTarget=0; ; isTar
             }
             if (parameters != null) {
                 formatter.newLine();
+                formatter.indent(+1);
                 for (final GeneralParameterValue param : parameters.values()) {
                     WKTUtilities.append(param, formatter);
                 }
+                formatter.indent(-1);
             }
         }
-        if (!isComponent) {
+        if (!isSubOperation && !(this instanceof ConcatenatedOperation)) {
             append(formatter, getInterpolationCRS(), WKTKeywords.InterpolationCRS);
             final double accuracy = getLinearAccuracy();
             if (accuracy > 0) {
@@ -900,7 +909,7 @@ check:      for (int isTarget=0; ; isTar
         if (formatter.getConvention().majorVersion() == 1) {
             formatter.setInvalidWKT(this, null);
         }
-        return WKTKeywords.CoordinateOperation;
+        return isComponent ? "CoordinateOperationStep" : WKTKeywords.CoordinateOperation;
     }
 
     /**

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

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -19,11 +19,15 @@ package org.apache.sis.referencing.opera
 import java.io.Serializable;
 import org.opengis.metadata.extent.Extent;
 import org.opengis.metadata.extent.GeographicBoundingBox;
+import org.opengis.referencing.operation.CoordinateOperation;
 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;
 
+// Branch-dependent imports
+import org.apache.sis.internal.jdk8.Predicate;
+
 
 /**
  * Optional information about the context in which a requested coordinate operation will be used.
@@ -38,7 +42,7 @@ import org.apache.sis.util.ArgumentCheck
  * to choose the most suitable coordinate transformation between two CRS.
  *
  * <div class="note"><b>Example:</b>
- * if a transformation from NAD27 to NAD83 is requested without providing context, then Apache SIS will return the
+ * if a transformation from NAD27 to WGS84 is requested without providing context, then Apache SIS will return the
  * transformation applicable to the widest North American surface. But if the user provides a context saying that
  * he wants to transform coordinates in Texas, then Apache SIS may return another coordinate transformation with
  * different {@linkplain org.apache.sis.referencing.datum.BursaWolfParameters Bursa-Wolf parameters} more suitable
@@ -66,11 +70,6 @@ public class CoordinateOperationContext
     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.
      * See {@link #getDesiredAccuracy()} for more details about what we mean by <cite>"best accuracy"</cite>.
      */
@@ -99,6 +98,8 @@ public class CoordinateOperationContext
      * Returns the spatio-temporal area of interest, or {@code null} if none.
      *
      * @return The spatio-temporal area of interest, or {@code null} if none.
+     *
+     * @see Extents#getGeographicBoundingBox(Extent)
      */
     public Extent getAreaOfInterest() {
         return areaOfInterest;
@@ -109,32 +110,24 @@ public class CoordinateOperationContext
      *
      * @param area The spatio-temporal area of interest, or {@code null} if none.
      */
-    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);
+    public void setAreaOfInterest(Extent area) {
+        if (area != null) {
+            area = new DefaultExtent(area);
         }
-        return bbox;
+        areaOfInterest = area;
     }
 
     /**
      * 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}.
      *
+     * <p>The reverse operation can be done with <code>{@linkplain Extents#getGeographicBoundingBox(Extent)
+     * Extents.getGeographicBoundingBox}({@linkplain #getAreaOfInterest()})</code>.</p>
+     *
      * @param area The geographic area of interest, or {@code null} if none.
      */
-    public void setGeographicBoundingBox(final GeographicBoundingBox area) {
+    public void setAreaOfInterest(final GeographicBoundingBox area) {
         areaOfInterest = setGeographicBoundingBox(areaOfInterest, area);
-        bbox = area;
     }
 
     /**
@@ -177,4 +170,13 @@ public class CoordinateOperationContext
         ArgumentChecks.ensurePositive("accuracy", accuracy);
         desiredAccuracy = accuracy;
     }
+
+    /**
+     * Returns a filter that can be used for applying additional restrictions on the coordinate operation.
+     *
+     * @todo Not yet implemented.
+     */
+    Predicate<CoordinateOperation> getOperationFilter() {
+        return null;
+    }
 }

Copied: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java (from r1740152, sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java)
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java?p2=sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java&p1=sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java&r1=1740152&r2=1740177&rev=1740177&view=diff
==============================================================================
--- sis/branches/JDK6/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -672,7 +672,7 @@ class CoordinateOperationRegistry {
                     method = DefaultOperationMethod.redimension(method, sourceDimensions, targetDimensions);
                 } catch (IllegalArgumentException ex) {
                     try {
-                        method = factory.getOperationMethod(method.getName().getCode());
+                        method = factorySIS.getOperationMethod(method.getName().getCode());
                         method = DefaultOperationMethod.redimension(method, sourceDimensions, targetDimensions);
                     } catch (NoSuchIdentifierException se) {
                         // ex.addSuppressed(se) on the JDK7 branch.
@@ -964,10 +964,10 @@ class CoordinateOperationRegistry {
                 if (descriptor != null) {
                     final Identifier name = descriptor.getName();
                     if (name != null) {
-                        method = factory.getOperationMethod(name.getCode());
+                        method = factorySIS.getOperationMethod(name.getCode());
                     }
                     if (method == null) {
-                        method = factory.createOperationMethod(properties,
+                        method = factorySIS.createOperationMethod(properties,
                                 sourceCRS.getCoordinateSystem().getDimension(),
                                 targetCRS.getCoordinateSystem().getDimension(),
                                 descriptor);

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java?rev=1740177&r1=1740176&r2=1740177&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java [UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java [UTF-8] Wed Apr 20 17:40:11 2016
@@ -17,27 +17,22 @@
 package org.apache.sis.referencing.operation;
 
 import java.util.Map;
-import java.util.Set;
 import java.util.List;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
-import java.util.LinkedHashSet;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 import org.opengis.util.FactoryException;
-import org.opengis.metadata.quality.PositionalAccuracy;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.ConcatenatedOperation;
 import org.opengis.referencing.operation.Transformation;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
+import org.apache.sis.internal.referencing.PositionalAccuracyConstant;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.util.UnmodifiableArrayList;
-import org.apache.sis.internal.util.CollectionsExt;
-import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
@@ -115,9 +110,8 @@ final class DefaultConcatenatedOperation
     {
         super(properties);
         ArgumentChecks.ensureNonNull("operations", operations);
-        final boolean setAccuracy = (coordinateOperationAccuracy == null);
         final List<CoordinateOperation> flattened = new ArrayList<CoordinateOperation>(operations.length);
-        initialize(properties, operations, flattened, mtFactory, setAccuracy);
+        initialize(properties, operations, flattened, mtFactory, (coordinateOperationAccuracy == null));
         if (flattened.size() < 2) {
             throw new IllegalArgumentException(Errors.getResources(properties).getString(
                     Errors.Keys.TooFewOccurrences_2, 2, CoordinateOperation.class));
@@ -128,10 +122,6 @@ final class DefaultConcatenatedOperation
         this.operations = UnmodifiableArrayList.wrap((SingleOperation[]) operations);
         this.sourceCRS  = operations[0].getSourceCRS();
         this.targetCRS  = operations[operations.length - 1].getTargetCRS();
-        if (setAccuracy) {
-            coordinateOperationAccuracy = CollectionsExt.unmodifiableOrCopy(
-                    (Set<PositionalAccuracy>) coordinateOperationAccuracy);
-        }
         checkDimensions(properties);
     }
 
@@ -150,11 +140,11 @@ final class DefaultConcatenatedOperation
      * in the given list. This should not happen according ISO 19111 standard, but we try to be safe.
      *
      * <div class="section">How coordinate operation accuracy is determined</div>
-     * If {@code setAccuracy} is {@code true}, then this method collects all accuracy information found in the
-     * {@link Transformation} instances. This method ignores instances of other kinds for the following reason:
+     * If {@code setAccuracy} is {@code true}, then this method copies accuracy information found in the single
+     * {@link Transformation} instance. This method ignores instances of other kinds for the following reason:
      * some {@link Conversion} instances declare an accuracy, which is typically close to zero. If a concatenated
      * operation contains such conversion together with a transformation with unknown accuracy, then we do not want
-     * to declare that a 0 meter error as the concatenated operation accuracy; it would be a false information.
+     * to declare "0 meter" as the concatenated operation accuracy; it would be a false information.
      * An other reason is that a concatenated operation typically contains an arbitrary amount of conversions,
      * but only one transformation. So considering only transformations usually means to pickup only one operation
      * in the given {@code operations} list, which make things clearer.
@@ -177,7 +167,7 @@ final class DefaultConcatenatedOperation
                             final CoordinateOperation[]     operations,
                             final List<CoordinateOperation> flattened,
                             final MathTransformFactory      mtFactory,
-                            final boolean                   setAccuracy)
+                            boolean                         setAccuracy)
             throws FactoryException
     {
         CoordinateReferenceSystem previous = null;
@@ -221,16 +211,22 @@ final class DefaultConcatenatedOperation
                 transform = (transform != null) ? mtFactory.createConcatenatedTransform(transform, step) : step;
             }
             /*
-             * Optionally update the coordinate operation accuracy.
-             * See javadoc for a rational about why we take only transformations in account.
+             * Optionally copy the coordinate operation accuracy from the transformation (or from a concatenated
+             * operation on the assumption that its accuracy was computed by the same algorithm than this method).
+             * See javadoc for a rational about why we take only transformations in account. If more than one
+             * transformation is found, clear the collection and abandon the attempt to set the accuracy information.
+             * Instead the user will get a better result by invoking PositionalAccuracyConstant.getLinearAccuracy(…)
+             * since that method conservatively computes the sum of all linear accuracy.
              */
-            if (setAccuracy && op instanceof Transformation) {
-                Collection<PositionalAccuracy> candidates = op.getCoordinateOperationAccuracy();
-                if (!Containers.isNullOrEmpty(candidates)) {
-                    if (coordinateOperationAccuracy == null) {
-                        coordinateOperationAccuracy = new LinkedHashSet<PositionalAccuracy>();
+            if (setAccuracy && (op instanceof Transformation || op instanceof ConcatenatedOperation)) {
+                if (coordinateOperationAccuracy == null) {
+                    setAccuracy = (PositionalAccuracyConstant.getLinearAccuracy(op) > 0);
+                    if (setAccuracy) {
+                        coordinateOperationAccuracy = op.getCoordinateOperationAccuracy();
                     }
-                    coordinateOperationAccuracy.addAll(candidates);
+                } else {
+                    coordinateOperationAccuracy = null;
+                    setAccuracy = false;
                 }
             }
         }
@@ -346,6 +342,7 @@ final class DefaultConcatenatedOperation
     protected String formatTo(final Formatter formatter) {
         super.formatTo(formatter);
         for (final CoordinateOperation component : operations) {
+            formatter.newLine();
             formatter.append(castOrCopy(component));
         }
         formatter.setInvalidWKT(this, null);
@@ -391,8 +388,7 @@ final class DefaultConcatenatedOperation
      */
     private void setSteps(final CoordinateOperation[] steps) throws FactoryException {
         final List<CoordinateOperation> flattened = new ArrayList<CoordinateOperation>(steps.length);
-        initialize(null, steps, flattened, DefaultFactories.forBuildin(MathTransformFactory.class), true);
+        initialize(null, steps, flattened, DefaultFactories.forBuildin(MathTransformFactory.class), coordinateOperationAccuracy == null);
         operations = UnmodifiableArrayList.wrap(flattened.toArray(new SingleOperation[flattened.size()]));
-        coordinateOperationAccuracy = CollectionsExt.unmodifiableOrCopy((Set<PositionalAccuracy>) coordinateOperationAccuracy);
     }
 }



Mime
View raw message