sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1708416 - in /sis/branches/JDK7: ./ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/...
Date Tue, 13 Oct 2015 14:45:55 GMT
Author: desruisseaux
Date: Tue Oct 13 14:45:55 2015
New Revision: 1708416

URL: http://svn.apache.org/viewvc?rev=1708416&view=rev
Log:
Merge from the JDK8 branch. Contains GML support for ConcatenatedOperation.

Added:
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_CoordinateOperation.java
      - copied unchanged from r1708411, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_CoordinateOperation.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java
      - copied unchanged from r1708411, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/SingleOperationMarshallingTest.java
      - copied unchanged from r1708411, sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/SingleOperationMarshallingTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/referencing/operation/ConcatenatedOperation.xml
      - copied unchanged from r1708411, sis/branches/JDK8/core/sis-referencing/src/test/resources/org/apache/sis/referencing/operation/ConcatenatedOperation.xml
Removed:
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/OperationMarshallingTest.java
Modified:
    sis/branches/JDK7/   (props changed)
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/NameMeaning.java
    sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
    sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/referencing/crs/DerivedCRS.xml
    sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/referencing/datum/TemporalDatum.xml
    sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/test/integration/Metadata with vertical CRS.xml
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gml/Measure.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/DefinitionURITest.java

Propchange: sis/branches/JDK7/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Oct 13 14:45:55 2015
@@ -1,4 +1,4 @@
 /sis/branches/Android:1430670-1480699
 /sis/branches/JDK6:1394913-1508480
-/sis/branches/JDK8:1584960-1708129
+/sis/branches/JDK8:1584960-1708411
 /sis/trunk:1394364-1508466,1519089-1519674

Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/NameMeaning.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/NameMeaning.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/NameMeaning.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/NameMeaning.java [UTF-8] Tue Oct 13 14:45:55 2015
@@ -16,6 +16,9 @@
  */
 package org.apache.sis.internal.metadata;
 
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Locale;
 import org.opengis.parameter.*;
 import org.opengis.referencing.*;
 import org.opengis.referencing.cs.*;
@@ -32,7 +35,7 @@ import org.apache.sis.internal.util.Cons
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.5
- * @version 0.5
+ * @version 0.7
  * @module
  *
  * @see org.apache.sis.internal.util.DefinitionURI
@@ -77,21 +80,56 @@ public final class NameMeaning extends S
     };
 
     /**
+     * Naming authorities allowed to appear in {@code "urn:ogc:def:"}.
+     *
+     * <p><b>Note on the case:</b> The <cite>"Name type specification — definitions"</cite> document (OGC 09-048) writes
+     * authorities in upper cases, while <a href="http://www.opengis.net/def/auth/">http://www.opengis.net/def/auth/</a>
+     * use lower cases. Apache SIS uses upper cases for now.</p>
+     *
+     * @see <a href="http://www.opengis.net/def/auth/">http://www.opengis.net/def/auth/</a>
+     *
+     * @since 0.7
+     */
+    private static final Map<String,String> AUTHORITIES = new HashMap<>(12);
+    static {
+        add(Constants.EPSG);    // IOGP
+        add(Constants.OGC);     // Open Geospatial Consortium
+        add("OGC-WFS");         // OGC Web Feature Service
+        add("SI");              // Système International d'Unités
+        add("UCUM");            // Unified Code for Units of Measure
+        add("UNSD");            // United Nations Statistics Division
+        add("USNO");            // United States Naval Observatory
+    }
+
+    /**
+     * Adds the given authority to the {@link #AUTHORITIES} map.
+     * This method shall be invoked at class initialization time only.
+     */
+    private static void add(final String authority) {
+        AUTHORITIES.put(authority, authority);
+    }
+
+    /**
      * Do not allow instantiation of this class.
      */
     private NameMeaning() {
     }
 
     /**
-     * Returns {@code true} if codes in the given code space are often represented using the URN syntax.
-     * Current implementation conservatively returns {@code true} only for {@code "EPSG"}.
-     * The list of accepted code spaces may be expanded in any future SIS version.
+     * Returns the authority to format for the given code space, or {@code null} if there is no known authority
+     * in URN syntax for the given code space. The return value is used for fixing the Apache SIS policy regarding
+     * lower or upper cases (both conventions are used in different OGC resources).
      *
      * @param  codeSpace The code space (can be {@code null}).
-     * @return {@code true} if the given code space is known to use the URN syntax.
+     * @return The authority to format in the URN, or {@code null} if none.
+     *
+     * @since 0.7
      */
-    public static boolean usesURN(final String codeSpace) {
-        return (codeSpace != null) && codeSpace.equalsIgnoreCase(Constants.EPSG);
+    public static String authority(String codeSpace) {
+        if (codeSpace != null) {
+            codeSpace = AUTHORITIES.get(codeSpace.toUpperCase(Locale.US));
+        }
+        return codeSpace;
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java [UTF-8] Tue Oct 13 14:45:55 2015
@@ -550,10 +550,11 @@ public class ImmutableIdentifier extends
                      * Other conventions format only for the ID[…] of root element.
                      */
                     if (isRoot && enclosing != null && convention != Convention.INTERNAL) {
-                        if (NameMeaning.usesURN(cs)) {
+                        final String auth = NameMeaning.authority(cs);
+                        if (auth != null) {
                             final String type = NameMeaning.toObjectType(enclosing.getClass());
                             if (type != null) {
-                                formatter.append(new URI(type, cs, version, code));
+                                formatter.append(new URI(type, auth, version, code));
                             }
                         }
                     }

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/Code.java [UTF-8] Tue Oct 13 14:45:55 2015
@@ -37,7 +37,7 @@ import static org.apache.sis.internal.ut
  * @author  Cédric Briançon (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  */
 @XmlType(name = "CodeType")
@@ -193,7 +193,9 @@ public final class Code {
              */
             if (fallback != null) {
                 if (!isHTTP) {
-                    final String urn = DefinitionURI.format(NameMeaning.toObjectType(type), fallback);
+                    final String urn = DefinitionURI.format(NameMeaning.toObjectType(type),
+                                                            NameMeaning.authority(fallback.getCodeSpace()),
+                                                            fallback.getVersion(), fallback.getCode());
                     if (urn != null) {
                         final Code code = new Code();
                         /*

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/parameter/ParameterFormat.java [UTF-8] Tue Oct 13 14:45:55 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/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java [UTF-8] Tue Oct 13 14:45:55 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/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultCompoundCRS.java [UTF-8] Tue Oct 13 14:45:55 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/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/SubTypes.java [UTF-8] Tue Oct 13 14:45:55 2015
@@ -51,7 +51,7 @@ import org.apache.sis.referencing.cs.Axe
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  */
 final class SubTypes implements Comparator<Object> {
@@ -119,6 +119,9 @@ final class SubTypes implements Comparat
             if (object instanceof GeocentricCRS) {
                 return DefaultGeocentricCRS.castOrCopy((GeocentricCRS) object);
             }
+            if (object instanceof DefaultGeodeticCRS) {     // Result of XML unmarshalling - keep as-is.
+                return (DefaultGeodeticCRS) object;
+            }
             /*
              * The GeographicCRS and GeocentricCRS types are not part of ISO 19111.
              * ISO uses a single type, GeodeticCRS, for both of them and infer the

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java [UTF-8] Tue Oct 13 14:45:55 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,32 +179,37 @@ 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,
-     * except for the source CRS, target CRS and the math transform which are set the given values.
+     * Creates a new coordinate operation initialized from the given properties.
+     * It is caller's responsibility to:
      *
-     * <p>This constructor is (indirectly) for {@link DefaultConversion} usage only,
-     * in order to create a "real" conversion from a defining conversion.</p>
+     * <ul>
+     *   <li>Set the following fields:<ul>
+     *     <li>{@link #sourceCRS}</li>
+     *     <li>{@link #targetCRS}</li>
+     *     <li>{@link #transform}</li>
+     *   </ul></li>
+     *   <li>Invoke {@link #checkDimensions(Map)} after the above-cited fields have been set.</li>
+     * </ul>
      */
-    AbstractCoordinateOperation(final CoordinateOperation definition,
-                                final CoordinateReferenceSystem sourceCRS,
-                                final CoordinateReferenceSystem targetCRS,
-                                final MathTransform transform)
-    {
-        super(definition);
-        this.sourceCRS                   = sourceCRS;
-        this.targetCRS                   = targetCRS;
-        this.interpolationCRS            = getInterpolationCRS(definition);
-        this.operationVersion            = definition.getOperationVersion();
-        this.coordinateOperationAccuracy = definition.getCoordinateOperationAccuracy();
-        this.domainOfValidity            = definition.getDomainOfValidity();
-        this.scope                       = definition.getScope();
-        this.transform                   = transform;
-        checkDimensions(null);
+    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);
+            }
+        }
     }
 
     /**
@@ -291,20 +307,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 +319,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);
@@ -485,7 +492,7 @@ check:      for (int isTarget=0; ; isTar
     /**
      * Returns the interpolation CRS of the given coordinate operation, or {@code null} if none.
      */
-    static CoordinateReferenceSystem getInterpolationCRS(final CoordinateOperation operation) {
+    private static CoordinateReferenceSystem getInterpolationCRS(final CoordinateOperation operation) {
         return (operation instanceof AbstractCoordinateOperation)
                ? ((AbstractCoordinateOperation) operation).getInterpolationCRS() : null;
     }
@@ -836,11 +843,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 +885,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/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java [UTF-8] Tue Oct 13 14:45:55 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;
@@ -64,7 +65,7 @@ import java.util.Objects;
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  */
 @XmlType(name="AbstractSingleOperationType", propOrder = {
@@ -92,9 +93,10 @@ class AbstractSingleOperation extends Ab
      * The parameter values, or {@code null} for inferring it from the math transform.
      *
      * <p><b>Consider this field as final!</b>
-     * This field is modified only at unmarshalling time by {@link #setParameters(GeneralParameterValue[])}</p>
+     * This field is non-final only for the convenience of constructors and for initialization
+     * at XML unmarshalling time by {@link #setParameters(GeneralParameterValue[])}</p>
      */
-    private ParameterValueGroup parameters;
+    ParameterValueGroup parameters;
 
     /**
      * Creates a coordinate operation from the given properties.
@@ -121,50 +123,23 @@ class AbstractSingleOperation extends Ab
     }
 
     /**
-     * Creates a defining conversion from the given transform and/or parameters.
-     * See {@link DefaultConversion#DefaultConversion(Map, OperationMethod, MathTransform, ParameterValueGroup)}
-     * for more information.
-     */
-    AbstractSingleOperation(final Map<String,?>       properties,
-                            final OperationMethod     method,
-                            final MathTransform       transform,
-                            final ParameterValueGroup parameters)
-    {
-        super(properties, null, null, null, transform);
-        ArgumentChecks.ensureNonNull("method", method);
-        if (transform != null) {
-            checkDimensions(method, 0, transform, properties);
-        } else if (parameters == null) {
-            throw new IllegalArgumentException(Errors.getResources(properties)
-                    .getString(Errors.Keys.UnspecifiedParameterValues));
-        }
-        this.method = method;
-        this.parameters = (parameters != null) ? parameters.clone() : null;
-    }
-
-    /**
-     * Creates a new coordinate operation with the same values than the specified defining conversion,
-     * except for the source CRS, target CRS and the math transform which are set the given values.
+     * Creates a new coordinate operation initialized from the given properties.
+     * It is caller's responsibility to:
      *
-     * <p>This constructor is for {@link DefaultConversion} usage only,
-     * in order to create a "real" conversion from a defining conversion.</p>
-     *
-     * @param definition The defining conversion.
-     * @param sourceCRS  The source CRS.
-     * @param targetCRS  The target CRS.
-     * @param transform  The math transform, optionally with the parameters used for creating it.
-     *        Bundled in a {@code Map.Entry} as an ugly workaround for RFE #4093999 in Java bug database
-     *        ("Relax constraint on placement of this()/super() call in constructors").
+     * <ul>
+     *   <li>Set the following fields:<ul>
+     *     <li>{@link #sourceCRS}</li>
+     *     <li>{@link #targetCRS}</li>
+     *     <li>{@link #transform}</li>
+     *     <li>{@link #parameters}</li>
+     *   </ul></li>
+     *   <li>Invoke {@link #checkDimensions(Map)} after the above-cited fields have been set.</li>
+     * </ul>
      */
-    AbstractSingleOperation(final SingleOperation definition,
-                            final CoordinateReferenceSystem sourceCRS,
-                            final CoordinateReferenceSystem targetCRS,
-                            final Map.Entry<ParameterValueGroup,MathTransform> transform)
-    {
-        super(definition, sourceCRS, targetCRS, transform.getValue());
-        method = definition.getMethod();
-        final ParameterValueGroup p = transform.getKey();
-        parameters = (p != null) ? p : getParameterValues(definition);
+    AbstractSingleOperation(final Map<String,?> properties, final OperationMethod method) {
+        super(properties);
+        ArgumentChecks.ensureNonNull("method", method);
+        this.method = method;
     }
 
     /**
@@ -510,17 +485,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/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java [UTF-8] Tue Oct 13 14:45:55 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<CoordinateOperation>(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;
     }
 
     /**
@@ -340,6 +321,49 @@ final class DefaultConcatenatedOperation
      */
     @Override
     protected long computeHashCode() {
-        return super.computeHashCode() + 37 * operations.hashCode();
+        return super.computeHashCode() + 37 * Objects.hashCode(operations);
+    }
+
+
+
+
+    //////////////////////////////////////////////////////////////////////////////////////////////////
+    ////////                                                                                  ////////
+    ////////                               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/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConversion.java [UTF-8] Tue Oct 13 14:45:55 2015
@@ -17,7 +17,6 @@
 package org.apache.sis.referencing.operation;
 
 import java.util.Map;
-import java.util.AbstractMap;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.measure.converter.ConversionException;
@@ -39,7 +38,6 @@ import org.apache.sis.referencing.operat
 import org.apache.sis.internal.referencing.ReferencingUtilities;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.util.Workaround;
 import org.apache.sis.util.Utilities;
 
 
@@ -81,7 +79,7 @@ import org.apache.sis.util.Utilities;
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  *
  * @see DefaultTransformation
@@ -207,7 +205,18 @@ public class DefaultConversion extends A
                              final MathTransform       transform,
                              final ParameterValueGroup parameters)
     {
-        super(properties, method, transform, parameters);
+        super(properties, method);
+        if (transform != null) {
+            this.transform = transform;
+            checkDimensions(method, 0, transform, properties);
+        } else if (parameters == null) {
+            throw new IllegalArgumentException(Errors.getResources(properties)
+                    .getString(Errors.Keys.UnspecifiedParameterValues));
+        }
+        if (parameters != null) {
+            this.parameters = parameters.clone();
+        }
+        checkDimensions(properties);
     }
 
     /**
@@ -216,16 +225,58 @@ public class DefaultConversion extends A
      * typically a defining conversion.
      *
      * @param definition The defining conversion.
-     * @param sourceCRS  The source CRS.
-     * @param targetCRS  The target CRS.
+     * @param source     The new source CRS.
+     * @param target     The new target CRS.
      * @param factory    The factory to use for creating a transform from the parameters or for performing axis changes.
      */
     DefaultConversion(final Conversion definition,
-                      final CoordinateReferenceSystem sourceCRS,
-                      final CoordinateReferenceSystem targetCRS,
+                      final CoordinateReferenceSystem source,
+                      final CoordinateReferenceSystem target,
                       final MathTransformFactory factory) throws FactoryException
     {
-        super(definition, sourceCRS, targetCRS, createMathTransform(definition, sourceCRS, targetCRS, factory));
+        super(definition);
+        int interpDim = ReferencingUtilities.getDimension(super.getInterpolationCRS());
+        if (transform == null) {
+            /*
+             * If the user did not specified explicitely a MathTransform, we will need to create it
+             * from the parameters. This case happen often when creating a ProjectedCRS, because the
+             * user often did not have all needed information when he created the defining conversion:
+             * the length of semi-major and semi-minor axes were often missing. But now we know those
+             * lengths thanks to the 'sourceCRS' argument given to this method. So we can complete the
+             * parameters. This is the job of MathTransformFactory.createBaseToDerived(…).
+             */
+            if (parameters == null) {
+                throw new IllegalArgumentException(Errors.format(Errors.Keys.UnspecifiedParameterValues));
+            }
+            transform = factory.createBaseToDerived(source, parameters, target.getCoordinateSystem());
+        } else {
+            /*
+             * If the user specified explicitely a MathTransform, we may still need to swap or scale axes.
+             * If this conversion is a defining conversion (which is usually the case when creating a new
+             * ProjectedCRS), then DefaultMathTransformFactory has a specialized createBaseToDerived(…)
+             * method for this job.
+             */
+            if (sourceCRS == null && targetCRS == null && factory instanceof DefaultMathTransformFactory) {
+                transform = ((DefaultMathTransformFactory) factory).createBaseToDerived(
+                        source.getCoordinateSystem(), transform,
+                        target.getCoordinateSystem());
+            } else {
+                /*
+                 * If we can not use our SIS factory implementation, or if this conversion is not a defining
+                 * conversion (i.e. if this is the conversion of an existing ProjectedCRS, in which case the
+                 * math transform may not be normalized), then we fallback on a simpler swapAndScaleAxes(…)
+                 * method defined in this class. This is needed for AbstractCRS.forConvention(AxisConvention).
+                 */
+                transform = swapAndScaleAxes(transform, source, sourceCRS, interpDim, true,  factory);
+                transform = swapAndScaleAxes(transform, targetCRS, target, interpDim, false, factory);
+                interpDim = 0;  // Skip createPassThroughTransform(…) since it was handled by swapAndScaleAxes(…).
+            }
+        }
+        if (interpDim != 0) {
+            transform = factory.createPassThroughTransform(interpDim, transform, 0);
+        }
+        sourceCRS = source;
+        targetCRS = target;
     }
 
     /**
@@ -378,78 +429,6 @@ public class DefaultConversion extends A
     }
 
     /**
-     * Creates the math transform to be given to the sub-class constructor.
-     * This method is a workaround for RFE #4093999 in Java bug database
-     * ("Relax constraint on placement of this()/super() call in constructors").
-     *
-     * <p>This method may also return the parameters used for creating the math transform because those parameters
-     * may have been augmented with the semi-major and semi-minor axis lengths.  Since those parameter values have
-     * been set on a clone of {@code definition.getParameterValues()}, those values are lost (ignoring MathTransform
-     * internal) if we do not return them here.</p>
-     *
-     * @return The math transform, optionally with the parameters used for creating it.
-     *         Bundled in a {@code Map.Entry} as an ugly workaround for RFE #4093999.
-     */
-    @Workaround(library="JDK", version="1.7")
-    private static Map.Entry<ParameterValueGroup,MathTransform> createMathTransform(
-            final Conversion definition,
-            final CoordinateReferenceSystem sourceCRS,
-            final CoordinateReferenceSystem targetCRS,
-            final MathTransformFactory factory) throws FactoryException
-    {
-        final int interpDim = ReferencingUtilities.getDimension(getInterpolationCRS(definition));
-        MathTransform mt = definition.getMathTransform();
-        final Map.Entry<ParameterValueGroup,MathTransform> pair;
-        if (mt == null) {
-            /*
-             * If the user did not specified explicitely a MathTransform, we will need to create it
-             * from the parameters. This case happen often when creating a ProjectedCRS, because the
-             * user often did not have all needed information when he created the defining conversion:
-             * the length of semi-major and semi-minor axes were often missing. But now we know those
-             * lengths thanks to the 'sourceCRS' argument given to this method. So we can complete the
-             * parameters. This is the job of MathTransformFactory.createBaseToDerived(…).
-             */
-            final ParameterValueGroup parameters = definition.getParameterValues();
-            if (parameters == null) {
-                throw new IllegalArgumentException(Errors.format(Errors.Keys.UnspecifiedParameterValues));
-            }
-            mt = factory.createBaseToDerived(sourceCRS, parameters, targetCRS.getCoordinateSystem());
-            pair = new AbstractMap.SimpleEntry<>(parameters, mt);
-        } else {
-            pair = new AbstractMap.SimpleEntry<>(null, mt);
-            /*
-             * If the user specified explicitely a MathTransform, we may still need to swap or scale axes.
-             * If this conversion is a defining conversion (which is usually the case when creating a new
-             * ProjectedCRS), then DefaultMathTransformFactory has a specialized createBaseToDerived(…)
-             * method for this job.
-             */
-            final CoordinateReferenceSystem mtSource = definition.getSourceCRS();
-            final CoordinateReferenceSystem mtTarget = definition.getTargetCRS();
-            if (mtSource == null && mtTarget == null && factory instanceof DefaultMathTransformFactory) {
-                mt = ((DefaultMathTransformFactory) factory).createBaseToDerived(
-                        sourceCRS.getCoordinateSystem(), mt,
-                        targetCRS.getCoordinateSystem());
-            } else {
-                /*
-                 * If we can not use our SIS factory implementation, or if this conversion is not a defining
-                 * conversion (i.e. if this is the conversion of an existing ProjectedCRS, in which case the
-                 * math transform may not be normalized), then we fallback on a simpler swapAndScaleAxes(…)
-                 * method defined in this class. This is needed for AbstractCRS.forConvention(AxisConvention).
-                 */
-                mt = swapAndScaleAxes(mt, sourceCRS, mtSource, interpDim, true,  factory);
-                mt = swapAndScaleAxes(mt, mtTarget, targetCRS, interpDim, false, factory);
-                pair.setValue(mt);
-                return pair;  // Skip createPassThroughTransform(…) since it was handled by swapAndScaleAxes(…).
-            }
-        }
-        if (interpDim != 0) {
-            mt = factory.createPassThroughTransform(interpDim, mt, 0);
-        }
-        pair.setValue(mt);
-        return pair;
-    }
-
-    /**
      * Concatenates to the given transform the operation needed for swapping and scaling the axes.
      * The two coordinate systems must implement the same GeoAPI coordinate system interface.
      * For example if {@code sourceCRS} uses a {@code CartesianCS}, then {@code targetCRS} must use

Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java [UTF-8] Tue Oct 13 14:45:55 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/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java [UTF-8] Tue Oct 13 14:45:55 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/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java [UTF-8] Tue Oct 13 14:45:55 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>
      *

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java [UTF-8] Tue Oct 13 14:45:55 2015
@@ -138,7 +138,8 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.crs.DefaultImageCRSTest.class,
     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.SingleOperationMarshallingTest.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,

Modified: sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/referencing/crs/DerivedCRS.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/referencing/crs/DerivedCRS.xml?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/referencing/crs/DerivedCRS.xml (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/referencing/crs/DerivedCRS.xml Tue Oct 13 14:45:55 2015
@@ -24,12 +24,12 @@
                 xmlns:xsi          = "http://www.w3.org/2001/XMLSchema-instance"
                 gml:id             = "test-crs-derived">
 
-  <gml:identifier codeSpace="test">urn:ogc:def:crs:test::derived</gml:identifier>
+  <gml:identifier codeSpace="test">derived</gml:identifier>
   <gml:name codeSpace="test">Topocentric example</gml:name>
   <gml:scope>Nowhere.</gml:scope>
   <gml:conversion>
     <gml:Conversion gml:id="test-coordinateOperation-frombase">
-      <gml:identifier codeSpace="test">urn:ogc:def:coordinateOperation:test::fromBase</gml:identifier>
+      <gml:identifier codeSpace="test">fromBase</gml:identifier>
       <gml:name codeSpace="test">Topocentric example</gml:name>
       <gml:scope>Nowhere.</gml:scope>
       <gml:method>
@@ -151,11 +151,11 @@
 
   <gml:coordinateSystem>
     <gml:CartesianCS gml:id="test-cs-derivedcs">
-      <gml:identifier codeSpace="test">urn:ogc:def:cs:test::derivedCS</gml:identifier>
+      <gml:identifier codeSpace="test">derivedCS</gml:identifier>
       <gml:name>Topocentric easting and northing</gml:name>
       <gml:axis>
         <gml:CoordinateSystemAxis uom="urn:ogc:def:uom:EPSG::9001" gml:id="test-axis-east">
-          <gml:identifier codeSpace="test">urn:ogc:def:axis:test::east</gml:identifier>
+          <gml:identifier codeSpace="test">east</gml:identifier>
           <gml:name>Topocentric East</gml:name>
           <gml:axisAbbrev>U</gml:axisAbbrev>
           <gml:axisDirection codeSpace="EPSG">east</gml:axisDirection>
@@ -163,7 +163,7 @@
       </gml:axis>
       <gml:axis>
         <gml:CoordinateSystemAxis uom="urn:ogc:def:uom:EPSG::9001" gml:id="test-axis-north">
-          <gml:identifier codeSpace="test">urn:ogc:def:axis:test::north</gml:identifier>
+          <gml:identifier codeSpace="test">north</gml:identifier>
           <gml:name>Topocentric North</gml:name>
           <gml:axisAbbrev>V</gml:axisAbbrev>
           <gml:axisDirection codeSpace="EPSG">north</gml:axisDirection>
@@ -171,7 +171,7 @@
       </gml:axis>
       <gml:axis>
         <gml:CoordinateSystemAxis uom="urn:ogc:def:uom:EPSG::9001" gml:id="test-axis-up">
-          <gml:identifier codeSpace="test">urn:ogc:def:axis:test::up</gml:identifier>
+          <gml:identifier codeSpace="test">up</gml:identifier>
           <gml:name>Topocentric Up</gml:name>
           <gml:axisAbbrev>z</gml:axisAbbrev>
           <gml:axisDirection codeSpace="EPSG">up</gml:axisDirection>

Modified: sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/referencing/datum/TemporalDatum.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/referencing/datum/TemporalDatum.xml?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/referencing/datum/TemporalDatum.xml (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/referencing/datum/TemporalDatum.xml Tue Oct 13 14:45:55 2015
@@ -23,7 +23,7 @@
                    xmlns:xsi          = "http://www.w3.org/2001/XMLSchema-instance"
                    gml:id             = "sis-datum-mj">
 
-  <gml:identifier codeSpace="SIS">urn:ogc:def:datum:SIS::MJ</gml:identifier>
+  <gml:identifier codeSpace="SIS">MJ</gml:identifier>
   <gml:name>Modified Julian</gml:name>
   <gml:remarks>Time measured as days since November 17, 1858 at 00:00 UTC.</gml:remarks>
   <gml:scope>History.</gml:scope>

Modified: sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/test/integration/Metadata with vertical CRS.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/test/integration/Metadata%20with%20vertical%20CRS.xml?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/test/integration/Metadata with vertical CRS.xml (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/resources/org/apache/sis/test/integration/Metadata with vertical CRS.xml Tue Oct 13 14:45:55 2015
@@ -112,16 +112,16 @@
               <gmd:maximumValue> <gco:Real>10000</gco:Real> </gmd:maximumValue>
               <gmd:verticalCRS>
                 <gml:VerticalCRS gml:id="sis-crs-test1">
-                  <gml:identifier codeSpace="SIS">urn:ogc:def:crs:SIS::test1</gml:identifier>
+                  <gml:identifier codeSpace="SIS">test1</gml:identifier>
                   <gml:name>Depth</gml:name>
                   <gml:scope>World</gml:scope>
                   <gml:verticalCS>
                     <gml:VerticalCS gml:id="sis-cs-test3">
-                      <gml:identifier codeSpace="SIS">urn:ogc:def:cs:SIS::test3</gml:identifier>
+                      <gml:identifier codeSpace="SIS">test3</gml:identifier>
                       <gml:name>Depth</gml:name>
                       <gml:axis>
                         <gml:CoordinateSystemAxis uom="urn:ogc:def:uom:EPSG::9001" gml:id="sis-axis-test4">
-                          <gml:identifier codeSpace="SIS">urn:ogc:def:axis:SIS::test4</gml:identifier>
+                          <gml:identifier codeSpace="SIS">test4</gml:identifier>
                           <gml:name>Depth</gml:name>
                           <gml:axisAbbrev>d</gml:axisAbbrev>
                           <gml:axisDirection codeSpace="EPSG">down</gml:axisDirection>
@@ -131,7 +131,7 @@
                   </gml:verticalCS>
                   <gml:verticalDatum>
                     <gml:VerticalDatum gml:id="sis-datum-test2">
-                      <gml:identifier codeSpace="SIS">urn:ogc:def:datum:SIS::test2</gml:identifier>
+                      <gml:identifier codeSpace="SIS">test2</gml:identifier>
                       <gml:name>Depth</gml:name>
                       <gml:scope>World</gml:scope>
                     </gml:VerticalDatum>

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gml/Measure.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gml/Measure.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gml/Measure.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gml/Measure.java [UTF-8] Tue Oct 13 14:45:55 2015
@@ -25,6 +25,7 @@ import javax.xml.bind.annotation.XmlValu
 import javax.xml.bind.annotation.XmlAttribute;
 import org.apache.sis.internal.jaxb.Context;
 import org.apache.sis.internal.jaxb.Schemas;
+import org.apache.sis.internal.util.Constants;
 import org.apache.sis.internal.util.DefinitionURI;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.measure.Units;
@@ -146,7 +147,7 @@ public final class Measure {
         if (!asXPointer) {
             final Integer code = Units.getEpsgCode(unit, inAxis);
             if (code != null) {
-                return DefinitionURI.PREFIX + ":uom:EPSG::" + code;
+                return DefinitionURI.PREFIX + ":uom:" + Constants.EPSG + "::" + code;
             }
         }
         if (unit == null || unit.equals(Unit.ONE)) {

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java [UTF-8] Tue Oct 13 14:45:55 2015
@@ -18,7 +18,6 @@ package org.apache.sis.internal.util;
 
 import java.util.Map;
 import java.util.Collections;
-import org.opengis.metadata.Identifier;
 
 import static org.apache.sis.util.CharSequences.*;
 import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
@@ -97,9 +96,10 @@ import static org.apache.sis.internal.ut
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.7
  * @module
  *
+ * @see org.apache.sis.internal.metadata.NameMeaning
  * @see <a href="http://portal.opengeospatial.org/files/?artifact_id=24045">Definition identifier URNs in OGC namespace</a>
  * @see <a href="http://www.opengeospatial.org/ogcna">OGC Naming Authority</a>
  */
@@ -132,17 +132,25 @@ public final class DefinitionURI {
 
     /**
      * The type part of a URI, or {@code null} if none (empty).
+     * Note that the set of valid types in OGC namespace is restricted.
+     * See class javadoc for more information.
      *
      * <div class="note"><b>Example:</b>
      * In the {@code "urn:ogc:def:crs:EPSG:8.2:4326"} URN, this is {@code "crs"}.</div>
+     *
+     * @see org.apache.sis.internal.metadata.NameMeaning#toObjectType(Class)
      */
     public String type;
 
     /**
      * The authority part of a URI, or {@code null} if none (empty).
+     * Note that the set of valid authorities in OGC namespace is restricted.
+     * See class javadoc for more information.
      *
      * <div class="note"><b>Example:</b>
      * In the {@code "urn:ogc:def:crs:EPSG:8.2:4326"} URN, this is {@code "EPSG"}.</div>
+     *
+     * @see org.apache.sis.internal.metadata.NameMeaning#authority(String)
      */
     public String authority;
 
@@ -451,19 +459,21 @@ public final class DefinitionURI {
      * version and code are appended omitting any characters that are not valid for a Unicode identifier.
      * If some information are missing in the given identifier, then this method returns {@code null}.
      *
-     * @param  type The object type, as one of the type documented in class javadoc, or {@code null}.
-     * @param  identifier The identifier to format.
-     * @return An identifier using the URN syntax, or {@code null} if an information is missing.
+     * @param  type      The object type as one of the types documented in class javadoc, or {@code null}.
+     * @param  authority The authority as one of the values documented in class javadoc, or {@code null}.
+     * @param  version   The code version, or {@code null}. This is the only optional information.
+     * @param  code      The code, or {@code null}.
+     * @return An identifier using the URN syntax, or {@code null} if a mandatory information is missing.
      */
-    public static String format(final String type, final Identifier identifier) {
+    public static String format(final String type, final String authority, final String version, final String code) {
         final StringBuilder buffer = new StringBuilder(PREFIX);
         for (int p=0; p<4; p++) {
             final String component;
             switch (p) {
-                case 0:  component = type;                      break;
-                case 1:  component = identifier.getCodeSpace(); break;
-                case 2:  component = identifier.getVersion();   break;
-                case 3:  component = identifier.getCode();      break;
+                case 0:  component = type;      break;
+                case 1:  component = authority; break;
+                case 2:  component = version;   break;
+                case 3:  component = code;      break;
                 default: throw new AssertionError(p);
             }
             if (!appendUnicodeIdentifier(buffer.append(SEPARATOR), '\u0000', component, ".-", false)) {

Modified: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/DefinitionURITest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/DefinitionURITest.java?rev=1708416&r1=1708415&r2=1708416&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/DefinitionURITest.java [UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/internal/util/DefinitionURITest.java [UTF-8] Tue Oct 13 14:45:55 2015
@@ -17,8 +17,6 @@
 package org.apache.sis.internal.util;
 
 import org.opengis.metadata.Identifier;
-import org.apache.sis.internal.simple.SimpleIdentifier;
-import org.apache.sis.internal.simple.SimpleCitation;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
@@ -151,7 +149,7 @@ public final strictfp class DefinitionUR
      */
     @Test
     public void testToURN() {
-        final Identifier identifier = new SimpleIdentifier(new SimpleCitation("EPSG"), "4326", false);
-        assertEquals("urn:ogc:def:crs:EPSG::4326", DefinitionURI.format("crs", identifier));
+        assertEquals("urn:ogc:def:crs:EPSG::4326", DefinitionURI.format("crs", "EPSG", null, "4326"));
+        assertNull  ("Authority is not optional.", DefinitionURI.format("crs", null,   null, "4326"));
     }
 }



Mime
View raw message