sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1708262 - in /sis/branches/JDK8/core/sis-referencing/src: main/java/org/apache/sis/internal/jaxb/referencing/ main/java/org/apache/sis/parameter/ main/java/org/apache/sis/referencing/ main/java/org/apache/sis/referencing/crs/ main/java/org...
Date Mon, 12 Oct 2015 22:14:06 GMT
Author: desruisseaux
Date: Mon Oct 12 22:14:05 2015
New Revision: 1708262

URL: http://svn.apache.org/viewvc?rev=1708262&view=rev
Log:
Add GML support for DefaultConcatenatedOperation (SIS-292).

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_CoordinateOperation.java
      - copied, changed from r1708129, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_Conversion.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/referencing/operation/ConcatenatedOperation.xml   (with props)
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java

Copied: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_CoordinateOperation.java (from r1708129, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_Conversion.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_CoordinateOperation.java?p2=sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_CoordinateOperation.java&p1=sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_Conversion.java&r1=1708129&r2=1708262&rev=1708262&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_Conversion.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_CoordinateOperation.java [UTF-8] Mon Oct 12 22:14:05 2015
@@ -16,12 +16,10 @@
  */
 package org.apache.sis.internal.jaxb.referencing;
 
-import javax.xml.bind.annotation.XmlElement;
-import org.opengis.referencing.crs.SingleCRS;
-import org.opengis.referencing.operation.Conversion;
-import org.apache.sis.internal.jaxb.Context;
+import javax.xml.bind.annotation.XmlElementRef;
+import org.opengis.referencing.operation.CoordinateOperation;
 import org.apache.sis.internal.jaxb.gco.PropertyType;
-import org.apache.sis.referencing.operation.DefaultConversion;
+import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
 
 
 /**
@@ -29,24 +27,15 @@ import org.apache.sis.referencing.operat
  * package documentation for more information about JAXB and interface.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @since   0.6
- * @version 0.6
+ * @since   0.7
+ * @version 0.7
  * @module
  */
-public final class CC_Conversion extends PropertyType<CC_Conversion, Conversion> {
-    /**
-     * Temporary storage for the {@code baseCRS} during {@link org.apache.sis.referencing.crs.AbstractDerivedCRS}
-     * unmarshalling. A temporary location is needed because {@code AbstractDerivedCRS} does not have any explicit
-     * field for {@code baseCRS}.
-     *
-     * @see #setBaseCRS(Conversion, SingleCRS)
-     */
-    private SingleCRS baseCRS;
-
+public final class CC_CoordinateOperation extends PropertyType<CC_CoordinateOperation, CoordinateOperation> {
     /**
      * Empty constructor for JAXB only.
      */
-    public CC_Conversion() {
+    public CC_CoordinateOperation() {
     }
 
     /**
@@ -54,42 +43,42 @@ public final class CC_Conversion extends
      * This method is indirectly invoked by the private constructor
      * below, so it shall not depend on the state of this object.
      *
-     * @return {@code Conversion.class}
+     * @return {@code CoordinateOperation.class}
      */
     @Override
-    protected Class<Conversion> getBoundType() {
-        return Conversion.class;
+    protected Class<CoordinateOperation> getBoundType() {
+        return CoordinateOperation.class;
     }
 
     /**
      * Constructor for the {@link #wrap} method only.
      */
-    private CC_Conversion(final Conversion conversion) {
+    private CC_CoordinateOperation(final CoordinateOperation conversion) {
         super(conversion);
     }
 
     /**
      * Invoked by {@link PropertyType} at marshalling time for wrapping the given value
-     * in a {@code <gml:Conversion>} XML element.
+     * in a {@code <gml:CoordinateOperation>} XML element.
      *
      * @param  conversion The element to marshall.
      * @return A {@code PropertyType} wrapping the given the element.
      */
     @Override
-    protected CC_Conversion wrap(final Conversion conversion) {
-        return new CC_Conversion(conversion);
+    protected CC_CoordinateOperation wrap(final CoordinateOperation conversion) {
+        return new CC_CoordinateOperation(conversion);
     }
 
     /**
      * Invoked by JAXB at marshalling time for getting the actual element to write
-     * inside the {@code <gml:Conversion>} XML element.
+     * inside the {@code <gml:CoordinateOperation>} XML element.
      * This is the value or a copy of the value given in argument to the {@code wrap} method.
      *
      * @return The element to be marshalled.
      */
-    @XmlElement(name = "Conversion")
-    public DefaultConversion getElement() {
-        return DefaultConversion.castOrCopy(metadata);
+    @XmlElementRef
+    public AbstractCoordinateOperation getElement() {
+        return AbstractCoordinateOperation.castOrCopy(metadata);
     }
 
     /**
@@ -97,40 +86,7 @@ public final class CC_Conversion extends
      *
      * @param conversion The unmarshalled element.
      */
-    public void setElement(final DefaultConversion conversion) {
+    public void setElement(final AbstractCoordinateOperation conversion) {
         metadata = conversion;
-        Context.setWrapper(Context.current(), this);
-    }
-
-    /**
-     * Temporarily stores the {@code baseCRS} associated to the given {@code Conversion}.  This temporary storage is
-     * needed because {@code org.apache.sis.referencing.crs.AbstractDerivedCRS} does not have any explicit field for
-     * {@code baseCRS}. Instead the base CRS is stored in {@link Conversion#getSourceCRS()}, but we can set this
-     * property only after the {@code DerivedCRS} coordinate system has been unmarshalled.
-     *
-     * See {@code AbstractDerivedCRS.afterUnmarshal(Unmarshaller, Object parent)} for more information.
-     *
-     * @param  conversion The conversion to which to associate a base CRS.
-     * @param  crs The base CRS to associate to the given conversion.
-     * @return The previous base CRS, or {@code null} if none.
-     */
-    public static SingleCRS setBaseCRS(final Conversion conversion, final SingleCRS crs) {
-        /*
-         * Implementation note: we store the base CRS in the marshalling context because:
-         *
-         *   - we want to keep each thread isolated (using ThreadLocal), and
-         *   - we want to make sure that the reference is disposed even if the unmarshaller throws an exception.
-         *     This is guaranteed because the Context is disposed by Apache SIS in "try … finally" constructs.
-         */
-        final PropertyType<?,?> wrapper = Context.getWrapper(Context.current());
-        if (wrapper instanceof CC_Conversion) {
-            final CC_Conversion c = (CC_Conversion) wrapper;
-            if (c.getElement() == conversion) {  // For making sure that we do not confuse with another conversion.
-                final SingleCRS previous = c.baseCRS;
-                c.baseCRS = crs;
-                return previous;
-            }
-        }
-        return null;
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java?rev=1708262&r1=1708261&r2=1708262&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java [UTF-8] Mon Oct 12 22:14:05 2015
@@ -511,7 +511,7 @@ public class ParameterFormat extends Tab
         /*
          * Finished to collect the values. Now transform the values:
          *
-         *   - Singleton value of array types (either primitive or not) are expanded to a list.
+         *   - Singleton value of array types (either primitive or not) are wrapped into a list.
          *   - Values are formatted.
          *   - Value domains are formatted.
          *   - Position of the character on which to do the alignment are remembered.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java?rev=1708262&r1=1708261&r2=1708262&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] Mon Oct 12 22:14:05 2015
@@ -436,7 +436,7 @@ public final class CRS extends Static {
      *   <li>If the given CRS is an instance of {@link SingleCRS}, returns that instance in a singleton list.</li>
      *   <li>If the given CRS is an instance of {@link CompoundCRS}, returns a flattened list of its
      *       {@linkplain DefaultCompoundCRS#getComponents() components}. Some components may themselves be
-     *       other {@code CompoundCRS} instances, in which case those compound CRS are also expanded in their
+     *       other {@code CompoundCRS} instances, in which case those compound CRS are also flattened in their
      *       list of {@code SingleCRS} components.</li>
      *   <li>Otherwise throws a {@code ClassCastException}.</li>
      * </ul>

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java?rev=1708262&r1=1708261&r2=1708262&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java [UTF-8] Mon Oct 12 22:14:05 2015
@@ -125,13 +125,13 @@ public class DefaultCompoundCRS extends
      * May be the same reference than {@link #singles}.
      *
      * <p><b>Consider this field as final!</b>
-     * This field is modified only at unmarshalling time by {@link #setComponents(List)}</p>
+     * This field is modified only at construction and unmarshalling time by {@link #setComponents(List)}</p>
      */
     private List<? extends CoordinateReferenceSystem> components;
 
     /**
      * A decomposition of the CRS list into the single elements.
-     * Computed by {@link #setSingleComponents(List)} on construction or deserialization.
+     * Computed by {@link #setSingleComponents(List)} on construction, deserialization or unmarshalling.
      */
     private transient List<SingleCRS> singles;
 
@@ -303,7 +303,7 @@ public class DefaultCompoundCRS extends
 
     /**
      * Returns the ordered list of single coordinate reference systems. If this compound CRS contains
-     * other compound CRS, then all of them are expanded in a sequence of {@code SingleCRS} objects.
+     * other compound CRS, then all of them are flattened in a sequence of {@code SingleCRS} objects.
      * See class Javadoc for more information.
      *
      * @return The single coordinate reference systems as an unmodifiable list.
@@ -325,9 +325,9 @@ public class DefaultCompoundCRS extends
      * @see #getSingleComponents()
      */
     private boolean setSingleComponents(final List<? extends CoordinateReferenceSystem> crs) {
-        final List<SingleCRS> expanded = new ArrayList<>(crs.size());
-        final boolean identical = ReferencingUtilities.getSingleComponents(crs, expanded);
-        singles = UnmodifiableArrayList.wrap(expanded.toArray(new SingleCRS[expanded.size()]));
+        final List<SingleCRS> flattened = new ArrayList<>(crs.size());
+        final boolean identical = ReferencingUtilities.getSingleComponents(crs, flattened);
+        singles = UnmodifiableArrayList.wrap(flattened.toArray(new SingleCRS[flattened.size()]));
         return identical;
     }
 

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java?rev=1708262&r1=1708261&r2=1708262&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java [UTF-8] Mon Oct 12 22:14:05 2015
@@ -89,7 +89,7 @@ import java.util.Objects;
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  */
 @XmlType(name="AbstractCoordinateOperationType", propOrder = {
@@ -102,7 +102,8 @@ import java.util.Objects;
 })
 @XmlRootElement(name = "AbstractCoordinateOperation")
 @XmlSeeAlso({
-    AbstractSingleOperation.class
+    AbstractSingleOperation.class,
+    DefaultConcatenatedOperation.class
 })
 public class AbstractCoordinateOperation extends AbstractIdentifiedObject implements CoordinateOperation {
     /**
@@ -114,29 +115,34 @@ public class AbstractCoordinateOperation
      * The source CRS, or {@code null} if not available.
      *
      * <p><b>Consider this field as final!</b>
-     * This field is modified only at unmarshalling time by {@link #setSource(CoordinateReferenceSystem)}</p>
+     * This field is non final only for the convenience of constructors and for initialization
+     * at XML unmarshalling time by {@link #setSource(CoordinateReferenceSystem)}.</p>
      *
      * @see #getSourceCRS()
      */
-    private CoordinateReferenceSystem sourceCRS;
+    CoordinateReferenceSystem sourceCRS;
 
     /**
      * The target CRS, or {@code null} if not available.
      *
      * <p><b>Consider this field as final!</b>
-     * This field is modified only at unmarshalling time by {@link #setTarget(CoordinateReferenceSystem)}</p>
+     * This field is non final only for the convenience of constructors and for initialization
+     * at XML unmarshalling time by {@link #setTarget(CoordinateReferenceSystem)}.</p>
      *
      * @see #getTargetCRS()
      */
-    private CoordinateReferenceSystem targetCRS;
+    CoordinateReferenceSystem targetCRS;
 
     /**
      * The CRS which is neither the {@linkplain #getSourceCRS() source CRS} or
      * {@linkplain #getTargetCRS() target CRS} but still required for performing the operation.
      *
+     * <p><b>Consider this field as final!</b>
+     * This field is non final only for the convenience of constructors.</p>
+     *
      * @see #getInterpolationCRS()
      */
-    private final CoordinateReferenceSystem interpolationCRS;
+    private CoordinateReferenceSystem interpolationCRS;
 
     /**
      * Version of the coordinate transformation
@@ -147,9 +153,14 @@ public class AbstractCoordinateOperation
 
     /**
      * Estimate(s) of the impact of this operation on point accuracy, or {@code null} if none.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is non final only for the convenience of constructors.</p>
+     *
+     * @see #getCoordinateOperationAccuracy()
      */
     @XmlElement
-    private final Collection<PositionalAccuracy> coordinateOperationAccuracy;
+    Collection<PositionalAccuracy> coordinateOperationAccuracy;
 
     /**
      * Area in which this operation is valid, or {@code null} if not available.
@@ -168,9 +179,10 @@ public class AbstractCoordinateOperation
      * to positions in the {@linkplain #getTargetCRS target coordinate reference system}.
      *
      * <p><b>Consider this field as final!</b>
-     * This field is modified only at unmarshalling time by {@link #afterUnmarshal(Unmarshaller, Object)}</p>
+     * This field is non final only for the convenience of constructors and for initialization
+     * at XML unmarshalling time by {@link #afterUnmarshal(Unmarshaller, Object)}</p>
      */
-    private MathTransform transform;
+    MathTransform transform;
 
     /**
      * Creates a new coordinate operation with the same values than the specified defining conversion,
@@ -197,6 +209,30 @@ public class AbstractCoordinateOperation
     }
 
     /**
+     * Creates a new coordinate operation initialized from the given properties.
+     * It is caller's responsibility to:
+     *
+     * <ul>
+     *   <li>Set the {@link #sourceCRS}, {@link #targetCRS} and {@link #transform} fields.</li>
+     *   <li>Invoke {@link #checkDimensions(Map)} after the above-cited fields have been set.</li>
+     * </ul>
+     */
+    AbstractCoordinateOperation(final Map<String,?> properties) {
+        super(properties);
+        this.scope            = Types.toInternationalString(properties, SCOPE_KEY);
+        this.domainOfValidity = Containers.property(properties, DOMAIN_OF_VALIDITY_KEY, Extent.class);
+        this.operationVersion = Containers.property(properties, OPERATION_VERSION_KEY, String.class);
+        Object value = properties.get(COORDINATE_OPERATION_ACCURACY_KEY);
+        if (value != null) {
+            if (value instanceof PositionalAccuracy[]) {
+                coordinateOperationAccuracy = CollectionsExt.nonEmptySet((PositionalAccuracy[]) value);
+            } else {
+                coordinateOperationAccuracy = Collections.singleton((PositionalAccuracy) value);
+            }
+        }
+    }
+
+    /**
      * Creates a coordinate operation from the given properties.
      * The properties given in argument follow the same rules than for the
      * {@linkplain AbstractIdentifiedObject#AbstractIdentifiedObject(Map) super-class constructor}.
@@ -291,20 +327,11 @@ public class AbstractCoordinateOperation
                                        final CoordinateReferenceSystem interpolationCRS,
                                        final MathTransform             transform)
     {
-        super(properties);
+        this(properties);
         this.sourceCRS        = sourceCRS;
         this.targetCRS        = targetCRS;
         this.interpolationCRS = interpolationCRS;
         this.transform        = transform;
-        this.domainOfValidity = Containers.property(properties, DOMAIN_OF_VALIDITY_KEY, Extent.class);
-        this.scope            = Types.toInternationalString(properties, SCOPE_KEY);
-        this.operationVersion = Containers.property(properties, OPERATION_VERSION_KEY, String.class);
-        Object value = properties.get(COORDINATE_OPERATION_ACCURACY_KEY);
-        if (value instanceof PositionalAccuracy[]) {
-            coordinateOperationAccuracy = CollectionsExt.nonEmptySet((PositionalAccuracy[]) value);
-        } else {
-            coordinateOperationAccuracy = (value != null) ? Collections.singleton((PositionalAccuracy) value) : null;
-        }
         checkDimensions(properties);
     }
 
@@ -312,7 +339,7 @@ public class AbstractCoordinateOperation
      * Ensures that {@link #sourceCRS}, {@link #targetCRS} and {@link #interpolationCRS} dimensions
      * are consistent with {@link #transform} input and output dimensions.
      */
-    private void checkDimensions(final Map<String,?> properties) {
+    final void checkDimensions(final Map<String,?> properties) {
         final MathTransform transform = this.transform;   // Protect from changes.
         if (transform != null) {
             final int interpDim = ReferencingUtilities.getDimension(interpolationCRS);
@@ -836,11 +863,9 @@ check:      for (int isTarget=0; ; isTar
      */
     AbstractCoordinateOperation() {
         super(org.apache.sis.internal.referencing.NilReferencingObject.INSTANCE);
-        interpolationCRS            = null;
-        operationVersion            = null;
-        coordinateOperationAccuracy = null;
-        domainOfValidity            = null;
-        scope                       = null;
+        operationVersion = null;
+        domainOfValidity = null;
+        scope            = null;
     }
 
     /**
@@ -880,32 +905,4 @@ check:      for (int isTarget=0; ; isTar
             ReferencingUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setTarget", "targetCRS");
         }
     }
-
-    /**
-     * Invoked by JAXB after unmarshalling. This method needs information provided by:
-     *
-     * <ul>
-     *   <li>{@link #setSource(CoordinateReferenceSystem)}</li>
-     *   <li>{@link #setTarget(CoordinateReferenceSystem)}</li>
-     *   <li>{@link AbstractSingleOperation#setParameters(GeneralParameterValue[])}</li>
-     * </ul>
-     *
-     * Note that the later method is defined in a subclass, but experience suggests that it still works
-     * at least with the JAXB implementation provided in JDK.
-     */
-    private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
-        if (transform == null && sourceCRS != null && targetCRS != null) {
-            transform = createMathTransform();
-        }
-    }
-
-    /**
-     * Implemented by subclasses at unmarshalling time for creating the math transform from available information.
-     * Can return {@code null} if there is not enough information.
-     *
-     * @see <a href="http://issues.apache.org/jira/browse/SIS-291">SIS-291</a>
-     */
-    MathTransform createMathTransform() {
-        return null;
-    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java?rev=1708262&r1=1708261&r2=1708262&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java [UTF-8] Mon Oct 12 22:14:05 2015
@@ -19,6 +19,7 @@ package org.apache.sis.referencing.opera
 import java.util.Map;
 import java.util.List;
 import java.util.IdentityHashMap;
+import javax.xml.bind.Unmarshaller;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlSeeAlso;
 import javax.xml.bind.annotation.XmlElement;
@@ -510,17 +511,22 @@ class AbstractSingleOperation extends Ab
     }
 
     /**
-     * Invoked at unmarshalling time for creating the math transform from available information.
-     * Can return {@code null} if there is not enough information.
+     * Invoked by JAXB after unmarshalling. This method needs information provided by:
+     *
+     * <ul>
+     *   <li>{@link #setSource(CoordinateReferenceSystem)}</li>
+     *   <li>{@link #setTarget(CoordinateReferenceSystem)}</li>
+     *   <li>{@link #setParameters(GeneralParameterValue[])}</li>
+     * </ul>
+     *
+     * @see <a href="http://issues.apache.org/jira/browse/SIS-291">SIS-291</a>
      */
-    @Override
-    final MathTransform createMathTransform() {
-        if (parameters != null) try {
-            return DefaultFactories.forBuildin(MathTransformFactory.class).createBaseToDerived(
-                    super.getSourceCRS(), parameters, super.getTargetCRS().getCoordinateSystem());
+    private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
+        if (transform == null && sourceCRS != null && targetCRS != null && parameters != null) try {
+            transform = DefaultFactories.forBuildin(MathTransformFactory.class)
+                    .createBaseToDerived(sourceCRS, parameters, targetCRS.getCoordinateSystem());
         } catch (FactoryException e) {
-            Context.warningOccured(Context.current(), AbstractCoordinateOperation.class, "createMathTransform", e, true);
+            Context.warningOccured(Context.current(), AbstractSingleOperation.class, "afterUnmarshal", e, true);
         }
-        return super.createMathTransform();
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java?rev=1708262&r1=1708261&r2=1708262&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java [UTF-8] Mon Oct 12 22:14:05 2015
@@ -19,10 +19,12 @@ package org.apache.sis.referencing.opera
 import java.util.Map;
 import java.util.Set;
 import java.util.List;
-import java.util.HashMap;
 import java.util.ArrayList;
 import java.util.Collection;
 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;
@@ -31,7 +33,9 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.Transformation;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
+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;
@@ -52,10 +56,11 @@ import java.util.Objects;
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  */
-// Missing JAXB annotation. See http://issues.apache.org/jira/browse/SIS-292
+@XmlType(name = "ConcatenatedOperationType")
+@XmlRootElement(name = "ConcatenatedOperation")
 final class DefaultConcatenatedOperation extends AbstractCoordinateOperation implements ConcatenatedOperation {
     /**
      * Serial number for inter-operability with different versions.
@@ -64,8 +69,11 @@ final class DefaultConcatenatedOperation
 
     /**
      * The sequence of operations.
+     *
+     * <p><b>Consider this field as final!</b>
+     * This field is modified only at unmarshalling time by {@link #setSteps(CoordinateOperation[])}</p>
      */
-    private final List<? extends CoordinateOperation> operations;
+    private List<? extends CoordinateOperation> operations;
 
     /**
      * Constructs a concatenated operation from a set of properties and a
@@ -96,125 +104,55 @@ final class DefaultConcatenatedOperation
      *
      * @param  properties The properties to be given to the identified object.
      * @param  operations The sequence of operations. Shall contains at least two operations.
-     * @param  factory    The math transform factory to use for math transforms concatenation.
-     * @throws FactoryException if the factory can not concatenate the math transforms.
-     */
-    public DefaultConcatenatedOperation(final Map<String,?> properties,
-                                        final CoordinateOperation[] operations,
-                                        final MathTransformFactory factory)
-            throws FactoryException
-    {
-        this(properties, new ArrayList<>(operations.length), operations, factory);
-    }
-
-    /**
-     * Work around for RFE #4093999 in Sun's bug database
-     * ("Relax constraint on placement of this()/super() call in constructors").
-     */
-    private DefaultConcatenatedOperation(final Map<String,?> properties,
-                                         final ArrayList<CoordinateOperation> list,
-                                         final CoordinateOperation[] operations,
-                                         final MathTransformFactory factory)
-            throws FactoryException
-    {
-        this(properties, expand(properties, operations, list, factory, true), list);
-    }
-
-    /**
-     * Work around for RFE #4093999 in Sun's bug database
-     * ("Relax constraint on placement of this()/super() call in constructors").
-     */
-    private DefaultConcatenatedOperation(final Map<String,?> properties,
-                                         final MathTransform transform,
-                                         final List<CoordinateOperation> operations)
-    {
-        super(mergeAccuracy(properties, operations),
-              operations.get(0).getSourceCRS(),
-              operations.get(operations.size() - 1).getTargetCRS(),
-              null, transform);
-
-        this.operations = UnmodifiableArrayList.wrap(operations.toArray(new CoordinateOperation[operations.size()]));
-    }
-
-    /**
-     * Transforms the list of operations into a list of single operations.
-     * This method also checks for null value and makes sure that all CRS dimensions match.
-     *
-     * @param  operations    The array of operations to expand.
-     * @param  target        The destination list in which to add {@code SingleOperation}.
-     * @param  factory       The math transform factory to use.
-     * @param  wantTransform {@code true} if the concatenated math transform should be computed.
-     *         This is set to {@code false} only when this method invokes itself recursively.
-     * @return The concatenated math transform, or {@code null} if {@code wantTransform} was {@code false}.
+     * @param  mtFactory  The math transform factory to use for math transforms concatenation.
      * @throws FactoryException if the factory can not concatenate the math transforms.
      */
-    private static MathTransform expand(final Map<String,?> properties,
-            final CoordinateOperation[] operations,
-            final List<CoordinateOperation> target,
-            final MathTransformFactory  factory,
-            final boolean wantTransform)
-            throws FactoryException
+    public DefaultConcatenatedOperation(final Map<String,?> properties, CoordinateOperation[] operations,
+            final MathTransformFactory mtFactory) throws FactoryException
     {
-        MathTransform transform = null;
+        super(properties);
         ArgumentChecks.ensureNonNull("operations", operations);
-        for (int i=0; i<operations.length; i++) {
-            ArgumentChecks.ensureNonNullElement("operations", i, operations);
-            final CoordinateOperation op = operations[i];
-            if (op instanceof ConcatenatedOperation) {
-                final ConcatenatedOperation cop = (ConcatenatedOperation) op;
-                final List<? extends CoordinateOperation> cops = cop.getOperations();
-                expand(properties, cops.toArray(new CoordinateOperation[cops.size()]), target, factory, false);
-            } else {
-                target.add(op);
-            }
-            /*
-             * Checks the CRS dimensions.
-             */
-            if (i != 0) {
-                final CoordinateReferenceSystem previous = operations[i-1].getTargetCRS();
-                if (previous != null) {
-                    final CoordinateReferenceSystem next = op.getSourceCRS();
-                    if (next != null) {
-                        final int dim1 = previous.getCoordinateSystem().getDimension();
-                        final int dim2 = next.getCoordinateSystem().getDimension();
-                        if (dim1 != dim2) {
-                            throw new IllegalArgumentException(Errors.getResources(properties).getString(
-                                    Errors.Keys.MismatchedDimension_3, "operations[" + i + "].sourceCRS", dim1, dim2));
-                        }
-                    }
-                }
-            }
-            /*
-             * Concatenates the math transform.
-             */
-            if (wantTransform) {
-                final MathTransform step = op.getMathTransform();
-                if (transform == null) {
-                    transform = step;
-                } else {
-                    transform = factory.createConcatenatedTransform(transform, step);
-                }
-            }
-        }
-        if (wantTransform && target.size() <= 1) {
+        final boolean setAccuracy = (coordinateOperationAccuracy == null);
+        final List<CoordinateOperation> flattened = new ArrayList<>(operations.length);
+        initialize(properties, operations, flattened, mtFactory, setAccuracy);
+        if (flattened.size() < 2) {
             throw new IllegalArgumentException(Errors.getResources(properties).getString(
                     Errors.Keys.TooFewOccurrences_2, 2, CoordinateOperation.class));
         }
-        return transform;
+        operations      = flattened.toArray(new CoordinateOperation[flattened.size()]);
+        this.operations = UnmodifiableArrayList.wrap(operations);
+        this.sourceCRS  = operations[0].getSourceCRS();
+        this.targetCRS  = operations[operations.length - 1].getTargetCRS();
+        if (setAccuracy) {
+            coordinateOperationAccuracy = CollectionsExt.unmodifiableOrCopy(
+                    (Set<PositionalAccuracy>) coordinateOperationAccuracy);
+        }
+        checkDimensions(properties);
     }
 
     /**
-     * If no accuracy were specified in the given properties map, adds all accuracies found in the operations
-     * to concatenate. This method considers only {@link Transformation} components and ignores all conversions.
-     *
-     * <div class="note"><b>Why we ignore conversions:</b>
-     * if a concatenated operation contains a datum shift (i.e. a transformation) with unknown accuracy,
-     * and a projection (i.e. a conversion) with a declared 0 meter error, we don't want to declare this
-     * 0 meter error as the concatenated operation  accuracy; it would be a false information.
+     * Performs the part of {@code DefaultConcatenatedOperations} construction that requires an iteration over
+     * the sequence of coordinate operations. This method performs the following processing:
      *
-     * <p>An other reason is that a concatenated operation typically contains an arbitrary amount of conversions,
+     * <ul>
+     *   <li>Verify the validity of the {@code operations} argument.</li>
+     *   <li>Add the single operations in the {@code flattened} array.</li>
+     *   <li>Set the {@link #transform} field to the concatenated transform.</li>
+     *   <li>Set the {@link #coordinateOperationAccuracy} field, but only if {@code setAccuracy} is {@code true}.</li>
+     * </ul>
+     *
+     * This method invokes itself recursively if there is nested {@code ConcatenatedOperation} instances
+     * 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:
+     * 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.
+     * 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.</p></div>
+     * in the given {@code operations} list, which make things clearer.
      *
      * <div class="note"><b>Note:</b>
      * according ISO 19111, the accuracy attribute is allowed only for transformations. However this restriction
@@ -222,32 +160,75 @@ final class DefaultConcatenatedOperation
      * which is conceptually exact. In this class we are departing from strict interpretation of the specification
      * since we are adding accuracy informations to a concatenated operation. This departure should be considered
      * as a convenience feature only; accuracies are really relevant in transformations only.</div>
+     *
+     * @param  properties  The properties specified at construction time, or {@code null} if unknown.
+     * @param  operations  The operations to concatenate.
+     * @param  flattened   The destination list in which to add the {@code SingleOperation} instances.
+     * @param  mtFactory   The math transform factory to use, or {@code null} for not performing concatenation.
+     * @param  setAccuracy {@code true} for setting the {@link #coordinateOperationAccuracy} field.
+     * @throws FactoryException if the factory can not concatenate the math transforms.
      */
-    private static Map<String,?> mergeAccuracy(final Map<String,?> properties,
-            final List<? extends CoordinateOperation> operations)
+    private void initialize(final Map<String,?>             properties,
+                            final CoordinateOperation[]     operations,
+                            final List<CoordinateOperation> flattened,
+                            final MathTransformFactory      mtFactory,
+                            final boolean                   setAccuracy)
+            throws FactoryException
     {
-        if (!properties.containsKey(COORDINATE_OPERATION_ACCURACY_KEY)) {
-            Set<PositionalAccuracy> accuracy = null;
-            for (final CoordinateOperation op : operations) {
-                if (op instanceof Transformation) {
-                    // See javadoc for a rational why we take only transformations in account.
-                    Collection<PositionalAccuracy> candidates = op.getCoordinateOperationAccuracy();
-                    if (!Containers.isNullOrEmpty(candidates)) {
-                        if (accuracy == null) {
-                            accuracy = new LinkedHashSet<>();
-                        }
-                        accuracy.addAll(candidates);
+        CoordinateReferenceSystem previous = null;
+        for (int i=0; i<operations.length; i++) {
+            final CoordinateOperation op = operations[i];
+            ArgumentChecks.ensureNonNullElement("operations", i, op);
+            /*
+             * Verify consistency of user argument: for each coordinate operation, the number of dimensions of the
+             * source CRS shall be equals to the number of dimensions of the target CRS in the previous operation.
+             */
+            if (previous != null) {
+                final CoordinateReferenceSystem next = op.getSourceCRS();
+                if (next != null) {
+                    final int dim1 = previous.getCoordinateSystem().getDimension();
+                    final int dim2 = next.getCoordinateSystem().getDimension();
+                    if (dim1 != dim2) {
+                        throw new IllegalArgumentException(Errors.getResources(properties).getString(
+                                Errors.Keys.MismatchedDimension_3, "operations[" + i + "].sourceCRS", dim1, dim2));
                     }
                 }
             }
-            if (accuracy != null) {
-                final Map<String,Object> merged = new HashMap<>(properties);
-                merged.put(COORDINATE_OPERATION_ACCURACY_KEY,
-                        accuracy.toArray(new PositionalAccuracy[accuracy.size()]));
-                return merged;
+            previous = op.getTargetCRS();   // For next iteration cycle.
+            /*
+             * Now that we have verified the CRS dimensions, we should be able to concatenate the transforms.
+             * If an operation is a nested ConcatenatedOperation (not allowed by ISO 19111, but we try to be
+             * safe), we will first try to use the ConcatenatedOperation.transform as a whole.  Only if that
+             * concatenated operation does not provide a transform we will concatenate its components.  Note
+             * however that we traverse nested concatenated operations unconditionally at least for checking
+             * its consistency.
+             */
+            MathTransform step = op.getMathTransform();
+            if (op instanceof ConcatenatedOperation) {
+                final List<? extends CoordinateOperation> children = ((ConcatenatedOperation) op).getOperations();
+                @SuppressWarnings("SuspiciousToArrayCall")
+                final CoordinateOperation[] asArray = children.toArray(new CoordinateOperation[children.size()]);
+                initialize(properties, asArray, flattened, (step == null) ? mtFactory : null, setAccuracy);
+            } else {
+                flattened.add(op);
+            }
+            if (mtFactory != null) {
+                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.
+             */
+            if (setAccuracy && op instanceof Transformation) {
+                Collection<PositionalAccuracy> candidates = op.getCoordinateOperationAccuracy();
+                if (!Containers.isNullOrEmpty(candidates)) {
+                    if (coordinateOperationAccuracy == null) {
+                        coordinateOperationAccuracy = new LinkedHashSet<>();
+                    }
+                    coordinateOperationAccuracy.addAll(candidates);
+                }
             }
         }
-        return properties;
     }
 
     /**
@@ -342,4 +323,47 @@ final class DefaultConcatenatedOperation
     protected long computeHashCode() {
         return super.computeHashCode() + 37 * operations.hashCode();
     }
+
+
+
+
+    //////////////////////////////////////////////////////////////////////////////////////////////////
+    ////////                                                                                  ////////
+    ////////                               XML support with JAXB                              ////////
+    ////////                                                                                  ////////
+    ////////        The following methods are invoked by JAXB using reflection (even if       ////////
+    ////////        they are private) or are helpers for other methods invoked by JAXB.       ////////
+    ////////        Those methods can be safely removed if Geographic Markup Language         ////////
+    ////////        (GML) support is not needed.                                              ////////
+    ////////                                                                                  ////////
+    //////////////////////////////////////////////////////////////////////////////////////////////////
+
+    /**
+     * Constructs a new object in which every attributes are set to a null value.
+     * <strong>This is not a valid object.</strong> This constructor is strictly
+     * reserved to JAXB, which will assign values to the fields using reflexion.
+     */
+    private DefaultConcatenatedOperation() {
+    }
+
+    /**
+     * Returns the operations to marshal. We use this private methods instead than annotating
+     * {@link #getOperations()} in order to force JAXB to invoke the setter method on unmarshalling.
+     */
+    @SuppressWarnings("SuspiciousToArrayCall")
+    @XmlElement(name = "coordOperation", required = true)
+    private CoordinateOperation[] getSteps() {
+        final List<? extends CoordinateOperation> operations = getOperations();
+        return (operations != null) ? operations.toArray(new CoordinateOperation[operations.size()]) : null;
+    }
+
+    /**
+     * Invoked by JAXB for setting the operations.
+     */
+    private void setSteps(final CoordinateOperation[] steps) throws FactoryException {
+        final List<CoordinateOperation> flattened = new ArrayList<>(steps.length);
+        initialize(null, steps, flattened, DefaultFactories.forBuildin(MathTransformFactory.class), true);
+        operations = UnmodifiableArrayList.wrap(flattened.toArray(new CoordinateOperation[flattened.size()]));
+        coordinateOperationAccuracy = CollectionsExt.unmodifiableOrCopy((Set<PositionalAccuracy>) coordinateOperationAccuracy);
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java?rev=1708262&r1=1708261&r2=1708262&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java [UTF-8] Mon Oct 12 22:14:05 2015
@@ -54,7 +54,7 @@
  * </ul>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.6
+ * @version 0.7
  * @since   0.6
  * @module
  */
@@ -68,6 +68,7 @@
     @XmlJavaTypeAdapter(CI_Citation.class),
     @XmlJavaTypeAdapter(DQ_PositionalAccuracy.class),
     @XmlJavaTypeAdapter(CC_OperationMethod.class),
+    @XmlJavaTypeAdapter(CC_CoordinateOperation.class),
     @XmlJavaTypeAdapter(CC_GeneralParameterValue.class),
     @XmlJavaTypeAdapter(CC_GeneralOperationParameter.class),
     @XmlJavaTypeAdapter(SC_CRS.class),

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java?rev=1708262&r1=1708261&r2=1708262&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] Mon Oct 12 22:14:05 2015
@@ -393,8 +393,8 @@ class ConcatenatedTransform extends Abst
     }
 
     /**
-     * Returns all concatenated transforms. The returned list contains only <cite>single</cite>
-     * transforms, i.e. all nested concatenated transforms (if any) have been expanded.
+     * Returns all concatenated transforms. The returned list contains only <cite>single</cite> transforms,
+     * i.e. all nested concatenated transforms (if any) have been flattened.
      *
      * @return All single math transforms performed by this concatenated transform.
      *

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java?rev=1708262&r1=1708261&r2=1708262&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java [UTF-8] Mon Oct 12 22:14:05 2015
@@ -330,7 +330,7 @@ public final class MathTransforms extend
      * <ul>
      *   <li>If {@code transform} is {@code null}, returns an empty list.</li>
      *   <li>Otherwise if {@code transform} is the result of a call to a {@code concatenate(…)} method,
-     *       returns all components. All nested concatenated transforms (if any) will be expanded.</li>
+     *       returns all components. All nested concatenated transforms (if any) will be flattened.</li>
      *   <li>Otherwise returns the given transform in a list of size 1.</li>
      * </ul>
      *

Added: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java?rev=1708262&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java [UTF-8] Mon Oct 12 22:14:05 2015
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.referencing.operation;
+
+import org.opengis.test.Validators;
+import javax.xml.bind.JAXBException;
+import org.apache.sis.test.DependsOn;
+import org.apache.sis.test.XMLTestCase;
+import org.junit.Test;
+
+import static org.apache.sis.test.ReferencingAssert.*;
+
+
+/**
+ * Tests the {@link DefaultConcatenatedOperation} class.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.7
+ * @version 0.7
+ * @module
+ */
+@DependsOn({
+    DefaultTransformationTest.class,
+    OperationMarshallingTest.class
+})
+public class DefaultConcatenatedOperationTest extends XMLTestCase {
+    /**
+     * An XML file in this package containing a projected CRS definition.
+     */
+    private static final String XML_FILE = "ConcatenatedOperation.xml";
+
+
+    /**
+     * Tests (un)marshalling of a concatenated operation.
+     *
+     * @throws JAXBException If an error occurred during (un)marshalling.
+     */
+    @Test
+    public void testXML() throws JAXBException {
+        final DefaultConcatenatedOperation op = unmarshalFile(DefaultConcatenatedOperation.class, XML_FILE);
+        Validators.validate(op);
+        if (false) assertEpsgNameAndIdentifierEqual("WGS 84", 4979, op);
+        /*
+         * Test marshalling and compare with the original file.
+         */
+//        assertMarshalEqualsFile(XML_FILE, op, "xmlns:*", "xsi:schemaLocation");
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1708262&r1=1708261&r2=1708262&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] Mon Oct 12 22:14:05 2015
@@ -139,6 +139,7 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.operation.DefaultTransformationTest.class,
     org.apache.sis.referencing.operation.DefaultConversionTest.class,
     org.apache.sis.referencing.operation.OperationMarshallingTest.class,
+    org.apache.sis.referencing.operation.DefaultConcatenatedOperationTest.class,
     org.apache.sis.referencing.crs.DefaultProjectedCRSTest.class,
     org.apache.sis.referencing.crs.DefaultDerivedCRSTest.class,
     org.apache.sis.referencing.crs.SubTypesTest.class,

Added: sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/referencing/operation/ConcatenatedOperation.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/referencing/operation/ConcatenatedOperation.xml?rev=1708262&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/referencing/operation/ConcatenatedOperation.xml (added)
+++ sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/referencing/operation/ConcatenatedOperation.xml Mon Oct 12 22:14:05 2015
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+
+<gml:ConcatenatedOperation xsi:schemaLocation = "http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/datums.xsd"
+                           xmlns:gml          = "http://www.opengis.net/gml/3.2"
+                           xmlns:gmd          = "http://www.isotc211.org/2005/gmd"
+                           xmlns:gco          = "http://www.isotc211.org/2005/gco"
+                           xmlns:xsi          = "http://www.w3.org/2001/XMLSchema-instance"
+                           xmlns:xlink        = "http://www.w3.org/1999/xlink"
+                           gml:id             = "test-operation-concatenated">
+
+  <!--
+    For this test we use the "NTF (Paris) to NTF (1)" transformation (EPSG:1763), but separated
+    in two steps for no reason other than making an easy test for concatenated operation.
+  -->
+  <gml:identifier codeSpace="test">concatenated</gml:identifier>
+  <gml:name>Concatenation test</gml:name>
+  <gml:scope>Change of prime meridian.</gml:scope>
+  <gml:sourceCRS>
+    <gml:GeodeticCRS gml:id="test-crs-source">
+      <gml:identifier codeSpace="test">source</gml:identifier>
+      <gml:name>NTF (Paris)</gml:name>
+      <gml:scope>None.</gml:scope>
+      <gml:ellipsoidalCS>
+        <!--
+          The real EPSG:4807 CRS uses the EPSG:6403 coordinate system (with unit in grads),
+          but this test uses EPSG:6422 (with unit in degrees) instead in order to make the
+          test smaller by reusing the same coordinate system in <gml:targetCRS>.
+        -->
+        <gml:EllipsoidalCS gml:id="epsg-cs-6422">
+          <gml:identifier codeSpace="IOGP">urn:ogc:def:cs:EPSG::6422</gml:identifier>
+          <gml:name>Latitude (north), Longitude (east)</gml:name>
+          <gml:axis>
+            <gml:CoordinateSystemAxis gml:id="epsg-axis-106" uom="urn:ogc:def:uom:EPSG::9122">
+              <gml:identifier codeSpace="IOGP">urn:ogc:def:axis:EPSG::106</gml:identifier>
+              <gml:name codeSpace="EPSG">Geodetic latitude</gml:name>
+              <gml:axisAbbrev>φ</gml:axisAbbrev>
+              <gml:axisDirection codeSpace="EPSG">north</gml:axisDirection>
+            </gml:CoordinateSystemAxis>
+          </gml:axis>
+          <gml:axis>
+            <gml:CoordinateSystemAxis gml:id="epsg-axis-107" uom="urn:ogc:def:uom:EPSG::9122">
+              <gml:identifier codeSpace="IOGP">urn:ogc:def:axis:EPSG::107</gml:identifier>
+              <gml:name codeSpace="EPSG">Geodetic longitude</gml:name>
+              <gml:axisAbbrev>λ</gml:axisAbbrev>
+              <gml:axisDirection codeSpace="EPSG">east</gml:axisDirection>
+            </gml:CoordinateSystemAxis>
+          </gml:axis>
+        </gml:EllipsoidalCS>
+      </gml:ellipsoidalCS>
+      <gml:geodeticDatum>
+        <gml:GeodeticDatum gml:id="epsg-datum-6807">
+          <gml:identifier codeSpace="IOGP">urn:ogc:def:datum:EPSG::6807</gml:identifier>
+          <gml:name codeSpace="EPSG">Nouvelle Triangulation Française (Paris)</gml:name>
+          <gml:scope>Topographic mapping.</gml:scope>
+          <gml:primeMeridian>
+            <gml:PrimeMeridian gml:id="epsg-meridian-8903">
+              <gml:identifier codeSpace="IOGP">urn:ogc:def:meridian:EPSG::8903</gml:identifier>
+              <gml:name codeSpace="EPSG">Paris</gml:name>
+              <gml:greenwichLongitude uom="urn:ogc:def:uom:EPSG::9105">2.5969213</gml:greenwichLongitude>
+            </gml:PrimeMeridian>
+          </gml:primeMeridian>
+          <gml:ellipsoid>
+            <gml:Ellipsoid gml:id="epsg-ellipsoid-7011">
+              <gml:identifier codeSpace="IOGP">urn:ogc:def:ellipsoid:EPSG::7011</gml:identifier>
+              <gml:name codeSpace="EPSG">Clarke 1880 (IGN)</gml:name>
+              <gml:semiMajorAxis uom="urn:ogc:def:uom:EPSG::9001">6378249.2</gml:semiMajorAxis>
+              <gml:secondDefiningParameter>
+                <gml:SecondDefiningParameter>
+                  <gml:semiMinorAxis uom="urn:ogc:def:uom:EPSG::9001">6356515</gml:semiMinorAxis>
+                </gml:SecondDefiningParameter>
+              </gml:secondDefiningParameter>
+            </gml:Ellipsoid>
+          </gml:ellipsoid>
+        </gml:GeodeticDatum>
+      </gml:geodeticDatum>
+    </gml:GeodeticCRS>
+  </gml:sourceCRS>
+  <!--
+    Same definition than the above <gml:sourceCRS> except for the prime meridian.
+  -->
+  <gml:targetCRS>
+    <gml:GeodeticCRS gml:id="test-crs-target">
+      <gml:identifier codeSpace="test">target</gml:identifier>
+      <gml:name>NTF</gml:name>
+      <gml:scope>Geodetic survey.</gml:scope>
+      <gml:ellipsoidalCS xlink:href="#epsg-cs-6422"/>
+      <gml:geodeticDatum>
+        <gml:GeodeticDatum gml:id="epsg-datum-6275">
+          <gml:identifier codeSpace="IOGP">urn:ogc:def:datum:EPSG::6275</gml:identifier>
+          <gml:name codeSpace="EPSG">Nouvelle Triangulation Française</gml:name>
+          <gml:scope>Topographic mapping.</gml:scope>
+          <gml:primeMeridian>
+            <gml:PrimeMeridian gml:id="epsg-meridian-8901">
+              <gml:identifier codeSpace="IOGP">urn:ogc:def:meridian:EPSG::8901</gml:identifier>
+              <gml:name codeSpace="EPSG">Greenwich</gml:name>
+              <gml:greenwichLongitude uom="urn:ogc:def:uom:EPSG::9102">0</gml:greenwichLongitude>
+            </gml:PrimeMeridian>
+          </gml:primeMeridian>
+          <gml:ellipsoid xlink:href="#epsg-ellipsoid-7011"/>
+        </gml:GeodeticDatum>
+      </gml:geodeticDatum>
+    </gml:GeodeticCRS>
+  </gml:targetCRS>
+  <!--
+    The actual concatenated operation. Contains yet another CRS, used as an artificial intermediate step
+    between the real source and real target CRS.
+  -->
+  <gml:coordOperation>
+    <gml:Transformation gml:id="test-crs-step1">
+      <gml:identifier codeSpace="test">step-1</gml:identifier>
+      <gml:name>Paris to tmp</gml:name>
+      <gml:scope>None.</gml:scope>
+      <gml:operationVersion>1</gml:operationVersion>
+      <gml:sourceCRS xlink:href="#test-crs-source"/>
+      <gml:targetCRS>
+        <gml:GeodeticCRS gml:id="test-crs-tmp">
+          <gml:identifier codeSpace="test">tmp</gml:identifier>
+          <gml:name>Non-existent</gml:name>
+          <gml:scope>None.</gml:scope>
+          <gml:ellipsoidalCS xlink:href="#epsg-cs-6422"/>
+          <gml:geodeticDatum>
+            <gml:GeodeticDatum gml:id="test-datum-tmp">
+              <gml:identifier codeSpace="test">tmp</gml:identifier>
+              <gml:name>Non-existent</gml:name>
+              <gml:scope>None.</gml:scope>
+              <gml:primeMeridian>
+                <gml:PrimeMeridian gml:id="test-meridian-tmp">
+                  <gml:identifier codeSpace="test">tmp</gml:identifier>
+                  <gml:name>Non-existent</gml:name>
+                  <gml:greenwichLongitude uom="urn:ogc:def:uom:EPSG::9102">2</gml:greenwichLongitude>
+                </gml:PrimeMeridian>
+              </gml:primeMeridian>
+              <gml:ellipsoid xlink:href="#epsg-ellipsoid-7011"/>
+            </gml:GeodeticDatum>
+          </gml:geodeticDatum>
+        </gml:GeodeticCRS>
+      </gml:targetCRS>
+      <gml:method>
+        <gml:OperationMethod gml:id="epsg-method-9601">
+          <gml:identifier codeSpace="IOGP">urn:ogc:def:method:EPSG::9601</gml:identifier>
+          <gml:name>Longitude rotation</gml:name>
+          <gml:formula>Target longitude = Source longitude + longitude offset.</gml:formula>
+          <gml:sourceDimensions>2</gml:sourceDimensions>
+          <gml:targetDimensions>2</gml:targetDimensions>
+          <gml:parameter>
+            <gml:OperationParameter gml:id="epsg-parameter-8602">
+              <gml:identifier codeSpace="IOGP">urn:ogc:def:parameter:EPSG::8602</gml:identifier>
+              <gml:name>Longitude offset</gml:name>
+            </gml:OperationParameter>
+          </gml:parameter>
+        </gml:OperationMethod>
+      </gml:method>
+      <gml:parameterValue>
+        <gml:ParameterValue>
+          <gml:value uom="urn:ogc:def:uom:EPSG::9105">2.0</gml:value>
+          <gml:operationParameter xlink:href="#epsg-parameter-8602"/>
+        </gml:ParameterValue>
+      </gml:parameterValue>
+    </gml:Transformation>
+  </gml:coordOperation>
+  <!--
+    Second transformation step, reusing above elements.
+  -->
+  <gml:coordOperation>
+    <gml:Transformation gml:id="test-crs-step2">
+      <gml:identifier codeSpace="test">step-2</gml:identifier>
+      <gml:name>Tmp to Greenwich</gml:name>
+      <gml:scope>None.</gml:scope>
+      <gml:operationVersion>1</gml:operationVersion>
+      <gml:sourceCRS xlink:href="#test-crs-tmp"/>
+      <gml:targetCRS xlink:href="#test-crs-target"/>
+      <gml:method xlink:href="#epsg-method-9601"/>
+      <gml:parameterValue>
+        <gml:ParameterValue>
+          <gml:value uom="urn:ogc:def:uom:EPSG::9105">0.5969213</gml:value>
+          <gml:operationParameter xlink:href="#epsg-parameter-8602"/>
+        </gml:ParameterValue>
+      </gml:parameterValue>
+    </gml:Transformation>
+  </gml:coordOperation>
+</gml:ConcatenatedOperation>

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/referencing/operation/ConcatenatedOperation.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/referencing/operation/ConcatenatedOperation.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml



Mime
View raw message