This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 17ef3cb68ea24f0527e68d024903493ca8245199
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Tue Sep 9 14:02:23 2025 +0200

    WKT 2 consolidation:
    * Support the `CoordinateMetadata` and `Version` elements.
    * Make `ConcatenatedOperation` formatting compliant with the standard.
    * Reorganize the list of keywords by alphabetical order for easier 
maintenance.
---
 .../sis/coverage/grid/ClippedGridCoverageTest.java |   2 +-
 .../apache/sis/io/wkt/GeodeticObjectParser.java    |  84 +++++--
 .../operation/AbstractCoordinateOperation.java     |  61 +++--
 .../operation/DefaultConcatenatedOperation.java    |  11 +-
 .../apache/sis/referencing/privy/WKTKeywords.java  | 267 ++++++++-------------
 .../DefaultConcatenatedOperationTest.java          |  54 ++++-
 .../operation/DefaultTransformationTest.java       |   3 +-
 7 files changed, 264 insertions(+), 218 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/ClippedGridCoverageTest.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/ClippedGridCoverageTest.java
index cc80efe1dd..8ab2fa5ab6 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/ClippedGridCoverageTest.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/ClippedGridCoverageTest.java
@@ -72,7 +72,7 @@ public final class ClippedGridCoverageTest extends TestCase {
         RenderedImage image = data;
         if (processor != null) {
             // We are not really interrested in statistics, we just want to 
get a different implementation class.
-            image = processor.imageProcessor.statistics(image, null, null);
+            image = processor.imageProcessor.statistics(image, null);
         }
         return new 
GridCoverageBuilder().setDomain(domain).setValues(image).build();
     }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
index b1684dc0b2..93742a1ddf 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
@@ -81,6 +81,7 @@ import 
org.apache.sis.metadata.iso.extent.DefaultGeographicDescription;
 import org.apache.sis.metadata.iso.extent.DefaultVerticalExtent;
 import org.apache.sis.metadata.iso.extent.DefaultTemporalExtent;
 import org.apache.sis.metadata.privy.AxisNames;
+import org.apache.sis.coordinate.DefaultCoordinateMetadata;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.privy.Constants;
 import org.apache.sis.util.privy.Numerics;
@@ -89,6 +90,7 @@ import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.iso.Types;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.coordinate.CoordinateMetadata;
 import org.opengis.referencing.ObjectDomain;
 
 // Specific to the geoapi-4.0 branch:
@@ -297,6 +299,13 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
         return object;
     }
 
+    /**
+     * Returns the prime meridian to use by default when none is specified.
+     */
+    private static PrimeMeridian greenwich() {
+        return CommonCRS.WGS84.primeMeridian();
+    }
+
     /**
      * Parses the next element in the specified <i>Well Know Text</i> (WKT) 
tree.
      *
@@ -308,6 +317,7 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
     final Object buildFromTree(final Element element) throws ParseException {
         Object object;
         if    (null == (object = parseCoordinateReferenceSystem(element, 
false))
+            && null == (object = parseCoordinateMetadata(FIRST, element))
             && null == (object = parseMathTransform            (element, 
false))
             && null == (object = parseAxis              (FIRST, element, null, 
 Units.METRE ))
             && null == (object = parsePrimeMeridian     (FIRST, element, 
false, Units.DEGREE))
@@ -378,6 +388,25 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
         return crs;
     }
 
+    /**
+     * Parses a {@code "CoordinateMetadata"} element.
+     *
+     * @param  mode    {@link #FIRST}, {@link #OPTIONAL} or {@link #MANDATORY}.
+     * @param  parent  the parent element.
+     * @return the {@code "CoordinateMetadata"} element.
+     * @throws ParseException if the {@code "CoordinateMetadata"} element 
cannot be parsed.
+     */
+    private CoordinateMetadata parseCoordinateMetadata(final int mode, final 
Element parent) throws ParseException {
+        final Element element = parent.pullElement(mode, 
WKTKeywords.CoordinateMetadata);
+        if (element == null) {
+            return null;
+        }
+        final CoordinateReferenceSystem crs = 
parseCoordinateReferenceSystem(element, true);
+        final Temporal epoch = parseEpoch(OPTIONAL, element, 
WKTKeywords.Epoch);
+        element.close(ignoredElements);
+        return new DefaultCoordinateMetadata(crs, epoch);
+    }
+
     /**
      * Returns the value associated to {@link 
IdentifiedObject#IDENTIFIERS_KEY} as an {@code Identifier} object.
      * This method shall accept all value types that {@link 
#parseMetadataAndClose(Element, String, IdentifiedObject)}
@@ -410,6 +439,7 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
      * @return a properties map with the parent name and the optional 
authority code.
      * @throws ParseException if an element cannot be parsed.
      *
+     * @see #parseAnchorAndClose(Element, String)
      * @see #parseParametersAndClose(Element, String, OperationMethod)
      */
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
@@ -510,19 +540,6 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
         return properties;
     }
 
-    /**
-     * Parses the datum {@code ANCHOR[]} element and pass the values to the 
{@link #parseMetadataAndClose(Element,
-     * String, IdentifiedObject)} method. If an anchor has been found, its 
value is stored in the returned map.
-     */
-    private Map<String,Object> parseAnchorAndClose(final Element element, 
final String name) throws ParseException {
-        String   anchor = pullElementAsString(element, WKTKeywords.Anchor);
-        Temporal epoch  = Epoch.fromYear(pullElementAsDouble(element, 
WKTKeywords.AnchorEpoch, OPTIONAL), 0);
-        final Map<String,Object> properties = parseMetadataAndClose(element, 
name, null);
-        if (anchor != null) properties.put(Datum.ANCHOR_DEFINITION_KEY, 
anchor);
-        if (epoch  != null) properties.put(Datum.ANCHOR_EPOCH_KEY, epoch);
-        return properties;
-    }
-
     /**
      * Parses the {@code AREA}, {@code BBOX}, {@code VERTICALEXTENT} and 
{@code TIMEEXTENT} elements if present.
      * These elements were directly inside the <abbr>CRS</abbr> element in 
<abbr>ISO</abbr> 19162:2015, but became
@@ -1421,7 +1438,20 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
     }
 
     /**
-     * Parses a {@code "FrameEoch"} (WKT 2) element.
+     * Parses an epoch.
+     *
+     * @param  mode     {@link #FIRST}, {@link #OPTIONAL} or {@link 
#MANDATORY}.
+     * @param  parent   the parent element.
+     * @param  keyword  {@code "Epoch"}, {@code "FrameEpoch"} or {@code 
"AnchorEpoch"}.
+     * @return the epoch, or {@code null} if none.
+     * @throws ParseException if the epoch cannot be parsed.
+     */
+    private Temporal parseEpoch(final int mode, final Element parent, final 
String keyword) throws ParseException {
+        return Epoch.fromYear(pullElementAsDouble(parent, keyword, mode), 0);
+    }
+
+    /**
+     * Parses a {@code "FrameEpoch"} (WKT 2) element.
      *
      * @param  parent  the parent element.
      * @return the frame epoch, or {@code null} if none.
@@ -1432,11 +1462,24 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
         if (element == null) {
             return null;
         }
-        Temporal epoch = Epoch.fromYear(pullElementAsDouble(element, 
WKTKeywords.FrameEpoch, MANDATORY), 0);
+        Temporal epoch = parseEpoch(MANDATORY, element, 
WKTKeywords.FrameEpoch);
         element.close(ignoredElements);
         return epoch;
     }
 
+    /**
+     * Parses the datum {@code ANCHOR[]} element and pass the values to the 
{@link #parseMetadataAndClose(Element,
+     * String, IdentifiedObject)} method. If an anchor has been found, its 
value is stored in the returned map.
+     */
+    private Map<String,Object> parseAnchorAndClose(final Element element, 
final String name) throws ParseException {
+        String   anchor = pullElementAsString(element, WKTKeywords.Anchor);
+        Temporal epoch  = parseEpoch(OPTIONAL, element, 
WKTKeywords.AnchorEpoch);
+        final Map<String,Object> properties = parseMetadataAndClose(element, 
name, null);
+        if (anchor != null) properties.put(Datum.ANCHOR_DEFINITION_KEY, 
anchor);
+        if (epoch  != null) properties.put(Datum.ANCHOR_EPOCH_KEY, epoch);
+        return properties;
+    }
+
     /**
      * Parses an {@code "Ensemble"} (WKT 2) element.
      *
@@ -2462,12 +2505,16 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
             return null;
         }
         final String name = element.pullString("name");
+        final String version = pullElementAsString(element, 
WKTKeywords.Version);
         final CoordinateReferenceSystem sourceCRS        = 
parseCoordinateReferenceSystem(element, MANDATORY, WKTKeywords.SourceCRS);
         final CoordinateReferenceSystem targetCRS        = 
parseCoordinateReferenceSystem(element, MANDATORY, WKTKeywords.TargetCRS);
         final CoordinateReferenceSystem interpolationCRS = 
parseCoordinateReferenceSystem(element, OPTIONAL,  
WKTKeywords.InterpolationCRS);
         final OperationMethod           method           = 
parseMethod(element, WKTKeywords.Method);
         final double                    accuracy         = 
pullElementAsDouble(element, WKTKeywords.OperationAccuracy, OPTIONAL);
         final Map<String,Object>        properties       = 
parseParametersAndClose(element, name, method);
+        if (version != null) {
+            properties.put(CoordinateOperation.OPERATION_VERSION_KEY, version);
+        }
         if (Double.isFinite(accuracy)) {
             
properties.put(CoordinateOperation.COORDINATE_OPERATION_ACCURACY_KEY,
                            
PositionalAccuracyConstant.transformation(accuracy));
@@ -2512,11 +2559,4 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
             return DefaultCoordinateOperationFactory.provider();
         }
     }
-
-    /**
-     * Returns the prime meridian to use by default when none is specified.
-     */
-    private static PrimeMeridian greenwich() {
-        return CommonCRS.WGS84.primeMeridian();
-    }
 }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
index 7ba89eed2b..369e9182aa 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
@@ -953,25 +953,32 @@ check:      for (int isTarget=0; ; isTarget++) {        
// 0 == source check; 1
     @Override
     protected String formatTo(final Formatter formatter) {
         super.formatTo(formatter);
+        final Convention convention = formatter.getConvention();
+        final boolean isWKT1 = (convention.majorVersion() == 1);
+        if (convention.supports(Convention.WKT2_2019)) {
+            getOperationVersion().ifPresent((version) -> {
+                formatter.append(new FormattableObject() {
+                    @Override protected String formatTo(final Formatter 
formatter) {
+                        formatter.append(version, null);
+                        return WKTKeywords.Version;
+                    }
+                });
+            });
+        }
         formatter.newLine();
         @SuppressWarnings("LocalVariableHidesMemberVariable")
         final CoordinateReferenceSystem sourceCRS = getSourceCRS(),
                                         targetCRS = getTargetCRS();
-        final Convention convention = formatter.getConvention();
-        final boolean isWKT1 = (convention.majorVersion() == 1);
         /*
-         * If the WKT is a component of a ConcatenatedOperation, do not format 
the source CRS since it is identical
-         * to the target CRS of the previous step, or to the source CRS of the 
enclosing "ConcatenatedOperation" if
-         * this step is the first step.
-         *
-         * This decision is SIS-specific since the WKT 2 specification does 
not define concatenated operations.
+         * If the WKT is a component of a PassThroughOperation, do not format 
the source CRS since it is identical
+         * to a component of the Source CRS of the enclosing 
`PassThroughOperation`. This decision is SIS-specific
+         * because the WKT 2 specification does not define pass-through 
operations.
          * This choice may change in any future SIS version.
          */
         final FormattableObject enclosing = formatter.getEnclosingElement(1);
         final boolean isSubOperation = (enclosing instanceof 
PassThroughOperation);
-        final boolean isComponent    = (enclosing instanceof 
ConcatenatedOperation);
         boolean isGeogTran = false;
-        if (!isSubOperation && !isComponent) {
+        if (!isSubOperation) {
             isGeogTran = isWKT1 && (sourceCRS instanceof GeographicCRS) && 
(targetCRS instanceof GeographicCRS);
             if (isGeogTran) {
                 // ESRI-specific, similar to WKT 1.
@@ -1022,27 +1029,31 @@ check:      for (int isTarget=0; ; isTarget++) {        
// 0 == source check; 1
             }
         }
         /*
-         * Add interpolation CRS if we are formatting a top-level WKT 2 single 
operation.
+         * If formatting a WKT 1 string, we need to declare the string as 
invalid (because `CoordinateOperation`
+         * did not existed at that time) except if the CRS types are compliant 
with the ESRI extension and that
+         * extension was enabled. Even if the ESRI extensions are not enabled, 
we still use the ESRI keyword if
+         * applicable and use `setInvalidWKT(…)` for warning the user.
          */
-        if (!isSubOperation && !isGeogTran && !(this instanceof 
ConcatenatedOperation)) {
-            append(formatter, getInterpolationCRS().orElse(null), 
WKTKeywords.InterpolationCRS);
-            
WKTUtilities.appendElementIfPositive(WKTKeywords.OperationAccuracy, 
getLinearAccuracy(), formatter);
-        }
-        /*
-         * Verifies if what we wrote is allowed by the standard.
-         */
-        if (isGeogTran) {
-            if (method == null || convention != Convention.WKT1_IGNORE_AXES) {
+        if (isWKT1) {
+            if (!(isGeogTran && method != null && convention == 
Convention.WKT1_IGNORE_AXES)) {
                 formatter.setInvalidWKT(this, null);
             }
-            return WKTKeywords.GeogTran;
+            if (isGeogTran) {
+                return WKTKeywords.GeogTran;
+            }
         }
-        if (isWKT1) {
-            formatter.setInvalidWKT(this, null);
+        /*
+         * If the coordinate operation is a step in a chain of operations, 
returns "step".
+         * Otherwise, if formatting a top-level single operation, add the 
interpolation CRS.
+         */
+        if (enclosing instanceof ConcatenatedOperation) {
+            return WKTKeywords.Step;
         }
-        if (isComponent) {
-            formatter.setInvalidWKT(this, null);
-            return "CoordinateOperationStep";
+        if (isSubOperation) {
+            if (!(this instanceof ConcatenatedOperation)) {
+                append(formatter, getInterpolationCRS().orElse(null), 
WKTKeywords.InterpolationCRS);
+            }
+            
WKTUtilities.appendElementIfPositive(WKTKeywords.OperationAccuracy, 
getLinearAccuracy(), formatter);
         }
         return WKTKeywords.CoordinateOperation;
     }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
index 11784505da..00aec82220 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
@@ -37,6 +37,7 @@ import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.datum.DatumOrEnsemble;
 import 
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
+import org.apache.sis.referencing.privy.WKTKeywords;
 import org.apache.sis.referencing.privy.CoordinateOperations;
 import org.apache.sis.referencing.internal.PositionalAccuracyConstant;
 import org.apache.sis.referencing.internal.Resources;
@@ -47,6 +48,7 @@ import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.privy.UnmodifiableArrayList;
 import org.apache.sis.util.privy.Constants;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.io.wkt.Convention;
 import org.apache.sis.io.wkt.Formatter;
 
 
@@ -449,8 +451,7 @@ final class DefaultConcatenatedOperation extends 
AbstractCoordinateOperation imp
     }
 
     /**
-     * Formats this coordinate operation in pseudo-WKT. This is specific to 
Apache SIS since
-     * there is no concatenated operation in the Well Known Text (WKT) version 
2 format.
+     * Formats this coordinate operation in Well Known Text (WKT) version 2 
format.
      *
      * @param  formatter  the formatter to use.
      * @return {@code "ConcatenatedOperation"}.
@@ -462,8 +463,10 @@ final class DefaultConcatenatedOperation extends 
AbstractCoordinateOperation imp
             formatter.newLine();
             formatter.append(castOrCopy(component));
         }
-        formatter.setInvalidWKT(this, null);
-        return "ConcatenatedOperation";
+        if (!formatter.getConvention().supports(Convention.WKT2_2019)) {
+            formatter.setInvalidWKT(this, null);
+        }
+        return WKTKeywords.ConcatenatedOperation;
     }
 
 
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTKeywords.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTKeywords.java
index 9f9f340642..62a9bf6949 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTKeywords.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTKeywords.java
@@ -47,164 +47,118 @@ public final class WKTKeywords extends Static {
     }
 
     /**
-     * Related to {@link org.apache.sis.referencing.AbstractIdentifiedObject}
-     * (including {@link org.apache.sis.referencing.ImmutableIdentifier}).
+     * Keywords defined by <abbr>WKT</abbr> 2. Some of those keywords are 
inherited from <abbr>WKT</abbr> 1
+     * but have been kept in <abbr>WKT</abbr> 2 for compatibility reasons.
      */
     public static final String
-            Id        = "Id",
-            URI       = "URI",
-            Citation  = "Citation",
-            Authority = "Authority",
-            Usage     = "Usage",
-            Scope     = "Scope",
-            Area      = "Area",
-            BBox      = "BBox",
-            Remark    = "Remark";
+            Anchor                = "Anchor",
+            AnchorEpoch           = "AnchorEpoch",
+            AngleUnit             = "AngleUnit",
+            Area                  = "Area",
+            Authority             = "Authority",
+            Axis                  = "Axis",
+            AxisMaxValue          = "AxisMaxValue",
+            AxisMinValue          = "AxisMinValue",
+            BaseEngCRS            = "BaseEngCRS",
+            BaseGeodCRS           = "BaseGeodCRS",
+            BaseGeogCRS           = "BaseGeogCRS",
+            BaseParamCRS          = "BaseParamCRS",
+            BaseProjCRS           = "BaseProjCRS",
+            BaseTimeCRS           = "BaseTimeCRS",
+            BaseVertCRS           = "BaseVertCRS",
+            BBox                  = "BBox",
+            BoundCRS              = "BoundCRS",
+            Citation              = "Citation",
+            Compd_CS              = "Compd_CS",
+            CompoundCRS           = "CompoundCRS",
+            ConcatenatedOperation = "ConcatenatedOperation",
+            Conversion            = "Conversion",
+            CoordinateMetadata    = "CoordinateMetadata",
+            CoordinateOperation   = "CoordinateOperation",
+            CS                    = "CS",
+            Datum                 = "Datum",
+            DerivingConversion    = "DerivingConversion",
+            Dynamic               = "Dynamic",
+            EDatum                = "EDatum",
+            Ellipsoid             = "Ellipsoid",
+            EngCRS                = "EngCRS",
+            EngineeringCRS        = "EngineeringCRS",
+            EngineeringDatum      = "EngineeringDatum",
+            EnsembleAccuracy      = "EnsembleAccuracy",
+            Ensemble              = "Ensemble",
+            Epoch                 = "Epoch",
+            Formula               = "Formula",
+            FrameEpoch            = "FrameEpoch",
+            GeocCS                = "GeocCS",
+            GeodCRS               = "GeodCRS",
+            GeodeticCRS           = "GeodeticCRS",
+            GeodeticDatum         = "GeodeticDatum",
+            GeogCRS               = "GeogCRS",
+            GeogCS                = "GeogCS",
+            GeographicCRS         = "GeographicCRS",
+            IDatum                = "IDatum",
+            Id                    = "Id",
+            ImageCRS              = "ImageCRS",
+            ImageDatum            = "ImageDatum",
+            InterpolationCRS      = "InterpolationCRS",
+            LengthUnit            = "LengthUnit",
+            Local_CS              = "Local_CS",
+            Local_Datum           = "Local_Datum",
+            Member                = "Member",
+            Meridian              = "Meridian",
+            Method                = "Method",
+            OperationAccuracy     = "OperationAccuracy",
+            Order                 = "Order",
+            ParameterFile         = "ParameterFile",
+            ParameterGroup        = "ParameterGroup",
+            Parameter             = "Parameter",
+            ParametricCRS         = "ParametricCRS",
+            ParametricDatum       = "ParametricDatum",
+            ParametricUnit        = "ParametricUnit",
+            PDatum                = "PDatum",
+            Point                 = "Point",
+            PrimeMeridian         = "PrimeMeridian",
+            PrimeM                = "PrimeM",
+            ProjCRS               = "ProjCRS",
+            ProjCS                = "ProjCS",
+            ProjectedCRS          = "ProjectedCRS",
+            Projection            = "Projection",
+            RangeMeaning          = "RangeMeaning",
+            Remark                = "Remark",
+            ScaleUnit             = "ScaleUnit",
+            Scope                 = "Scope",
+            SourceCRS             = "SourceCRS",
+            Spheroid              = "Spheroid",
+            Step                  = "Step",
+            TargetCRS             = "TargetCRS",
+            TDatum                = "TDatum",
+            TemporalQuantity      = "TemporalQuantity",
+            TimeCRS               = "TimeCRS",
+            TimeDatum             = "TimeDatum",
+            TimeExtent            = "TimeExtent",
+            TimeOrigin            = "TimeOrigin",
+            TimeUnit              = "TimeUnit",
+            ToWGS84               = "ToWGS84",
+            TRF                   = "TRF",
+            Unit                  = "Unit",
+            URI                   = "URI",
+            Usage                 = "Usage",
+            VDatum                = "VDatum",
+            Version               = "Version",
+            VertCRS               = "VertCRS",
+            Vert_CS               = "Vert_CS",
+            Vert_Datum            = "Vert_Datum",
+            VerticalCRS           = "VerticalCRS",
+            VerticalDatum         = "VerticalDatum",
+            VerticalExtent        = "VerticalExtent",
+            VRF                   = "VRF";
 
     /**
-     * Related to unit of measurements.
-     */
-    public static final String
-            Unit             = "Unit",
-            LengthUnit       = "LengthUnit",
-            AngleUnit        = "AngleUnit",
-            ScaleUnit        = "ScaleUnit",
-            TimeUnit         = "TimeUnit",
-            TemporalQuantity = "TemporalQuantity",
-            ParametricUnit   = "ParametricUnit";
-
-    /**
-     * Related to {@link org.apache.sis.referencing.cs.AbstractCS}
-     * and {@link org.apache.sis.referencing.datum.AbstractDatum}.
-     */
-    public static final String
-            CS               = "CS",
-            Axis             = "Axis",
-            AxisMinValue     = "AxisMinValue",
-            AxisMaxValue     = "AxisMaxValue",
-            RangeMeaning     = "RangeMeaning",
-            Order            = "Order",
-            Meridian         = "Meridian",
-            PrimeMeridian    = "PrimeMeridian",
-            PrimeM           = "PrimeM",
-            Ellipsoid        = "Ellipsoid",
-            Spheroid         = "Spheroid",
-            Ensemble         = "Ensemble",
-            Member           = "Member",
-            EnsembleAccuracy = "EnsembleAccuracy",
-            Dynamic          = "Dynamic",
-            ToWGS84          = "ToWGS84";
-
-    /**
-     * Related to {@link org.apache.sis.referencing.crs.DefaultGeocentricCRS}
-     * and {@link org.apache.sis.referencing.crs.DefaultGeographicCRS}.
-     */
-    public static final String
-            Anchor        = "Anchor",
-            AnchorEpoch   = "AnchorEpoch",
-            TRF           = "TRF",
-            Datum         = "Datum",
-            GeodeticDatum = "GeodeticDatum",
-            GeodeticCRS   = "GeodeticCRS",
-            GeographicCRS = "GeographicCRS",
-            BaseGeodCRS   = "BaseGeodCRS",
-            BaseGeogCRS   = "BaseGeogCRS",
-            GeodCRS       = "GeodCRS",
-            GeogCRS       = "GeogCRS",
-            GeogCS        = "GeogCS",
-            GeocCS        = "GeocCS";
-
-    /**
-     * Related to {@link org.apache.sis.referencing.crs.DefaultVerticalCRS}.
-     */
-    public static final String
-            VerticalExtent = "VerticalExtent",
-            VerticalDatum  = "VerticalDatum",
-            VerticalCRS    = "VerticalCRS",
-            BaseVertCRS    = "BaseVertCRS",
-            VRF            = "VRF",
-            VDatum         = "VDatum",
-            Vert_Datum     = "Vert_Datum",
-            VertCRS        = "VertCRS",
-            Vert_CS        = "Vert_CS";
-
-    /**
-     * Related to {@link org.apache.sis.referencing.crs.DefaultTemporalCRS}.
-     */
-    public static final String
-            TimeExtent  = "TimeExtent",
-            TimeOrigin  = "TimeOrigin",
-            TimeDatum   = "TimeDatum",
-            TDatum      = "TDatum",
-            TimeCRS     = "TimeCRS",
-            BaseTimeCRS = "BaseTimeCRS";
-
-    /**
-     * Related to {@link org.apache.sis.referencing.crs.DefaultParametricCRS}.
-     */
-    public static final String
-            ParametricDatum = "ParametricDatum",
-            PDatum          = "PDatum",
-            ParametricCRS   = "ParametricCRS",
-            BaseParamCRS    = "BaseParamCRS";
-
-    /**
-     * Related to {@link org.apache.sis.referencing.crs.DefaultImageCRS}
-     * and {@link org.apache.sis.referencing.crs.DefaultEngineeringCRS}.
-     * Former can be seen as a special case of the latter.
-     */
-    public static final String
-            ImageDatum       = "ImageDatum",
-            ImageCRS         = "ImageCRS",
-            IDatum           = "IDatum",
-            EngineeringDatum = "EngineeringDatum",
-            EngineeringCRS   = "EngineeringCRS",
-            BaseEngCRS       = "BaseEngCRS",
-            EngCRS           = "EngCRS",
-            EDatum           = "EDatum",
-            Local_Datum      = "Local_Datum",
-            Local_CS         = "Local_CS";
-
-    /**
-     * Related to {@link org.apache.sis.referencing.crs.DefaultCompoundCRS}.
-     */
-    public static final String
-            CompoundCRS = "CompoundCRS",
-            Compd_CS    = "Compd_CS";
-
-    /**
-     * Related to {@link org.apache.sis.referencing.crs.DefaultProjectedCRS}.
-     */
-    public static final String
-            ProjectedCRS = "ProjectedCRS",
-            BaseProjCRS  = "BaseProjCRS",
-            ProjCRS      = "ProjCRS",
-            ProjCS       = "ProjCS";
-
-    /**
-     * Related to {@link 
org.apache.sis.referencing.operation.AbstractCoordinateOperation}.
-     */
-    public static final String
-            BoundCRS            = "BoundCRS",
-            Method              = "Method",
-            Formula             = "Formula",
-            Projection          = "Projection",
-            Conversion          = "Conversion",
-            DerivingConversion  = "DerivingConversion",
-            CoordinateOperation = "CoordinateOperation",
-            OperationAccuracy   = "OperationAccuracy",
-            SourceCRS           = "SourceCRS",
-            TargetCRS           = "TargetCRS",
-            InterpolationCRS    = "InterpolationCRS",
-            Parameter           = "Parameter",
-            ParameterFile       = "ParameterFile",
-            ParameterGroup      = "ParameterGroup",
-            GeogTran            = "GeogTran";               // ESRI-specific.
-
-    /**
-     * Related to {@link 
org.apache.sis.referencing.operation.transform.AbstractMathTransform}.
+     * The following keywords are specific to <abbr>WKT</abbr> 1 or 
<abbr>ESRI</abbr>.
+     * Those keywords have not been kept in <abbr>WKT</abbr> 2.
      */
     public static final String
+            GeogTran       = "GeogTran",               // ESRI-specific.
             Param_MT       = "Param_MT",
             Inverse_MT     = "Inverse_MT",
             Concat_MT      = "Concat_MT",
@@ -227,15 +181,6 @@ public final class WKTKeywords extends Static {
             temporal    = "temporal",
             vertical    = "vertical";
 
-    /**
-     * Coordinates and epoch.
-     */
-    public static final String
-            CoordinateMetadata = "CoordinateMetadata",
-            FrameEpoch         = "FrameEpoch",
-            Epoch              = "Epoch",
-            Point              = "Point";
-
     /**
      * Mapping between types of object and WKT keywords. Each GeoAPI 
interfaces is associated to one
      * or many WKT keywords: new keywords defined by version 2 (sometimes with 
synonymous) and legacy
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java
index c46636d736..a8ac95a57c 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java
@@ -105,7 +105,7 @@ public final class DefaultConcatenatedOperationTest extends 
TestCase {
     @Test
     public void testWKT() throws FactoryException, 
NoninvertibleTransformException {
         final DefaultConcatenatedOperation op = createGeocentricTranslation();
-        assertWktEquals(Convention.WKT2_SIMPLIFIED,                            
 // Pseudo-WKT actually.
+        assertWktEquals(Convention.WKT2_SIMPLIFIED,
                 "ConcatenatedOperation[“Tokyo to JGD2000”,\n" +
                 "  SourceCRS[GeographicCRS[“Tokyo”,\n" +
                 "    Datum[“Tokyo 1918”,\n" +
@@ -121,14 +121,60 @@ public final class DefaultConcatenatedOperationTest 
extends TestCase {
                 "      Axis[“Longitude (L)”, east, Unit[“degree”, 
0.017453292519943295]],\n" +
                 "      Axis[“Latitude (B)”, north, Unit[“degree”, 
0.017453292519943295]],\n" +
                 "      Axis[“Ellipsoidal height (h)”, up, Unit[“metre”, 
1]]]],\n" +
-                "  CoordinateOperationStep[“Geographic to geocentric”,\n" +
+                "  Step[“Geographic to geocentric”,\n" +
+                "    SourceCRS[GeographicCRS[“Tokyo”,\n" +
+                "      Datum[“Tokyo 1918”,\n" +
+                "        Ellipsoid[“Bessel 1841”, 6377397.155, 
299.1528128]],\n" +
+                "      CS[ellipsoidal, 3],\n" +
+                "        Axis[“Longitude (L)”, east, Unit[“degree”, 
0.017453292519943295]],\n" +
+                "        Axis[“Latitude (B)”, north, Unit[“degree”, 
0.017453292519943295]],\n" +
+                "        Axis[“Ellipsoidal height (h)”, up, Unit[“metre”, 
1]]]],\n" +
+                "    TargetCRS[GeodeticCRS[“Tokyo 1918”,\n" +
+                "      Datum[“Tokyo 1918”,\n" +
+                "        Ellipsoid[“Bessel 1841”, 6377397.155, 
299.1528128]],\n" +
+                "      CS[Cartesian, 3],\n" +
+                "        Axis[“(X)”, geocentricX],\n" +
+                "        Axis[“(Y)”, geocentricY],\n" +
+                "        Axis[“(Z)”, geocentricZ],\n" +
+                "        Unit[“metre”, 1]]],\n" +
                 "    Method[“Geographic/geocentric conversions”]],\n" +        
 // Omit non-EPSG parameters for EPSG method.
-                "  CoordinateOperationStep[“Tokyo to JGD2000 (GSI)”,\n" +
+                "  Step[“Tokyo to JGD2000 (GSI)”, Version[“GSI-Jpn”],\n" +
+                "    SourceCRS[GeodeticCRS[“Tokyo 1918”,\n" +
+                "      Datum[“Tokyo 1918”,\n" +
+                "        Ellipsoid[“Bessel 1841”, 6377397.155, 
299.1528128]],\n" +
+                "      CS[Cartesian, 3],\n" +
+                "        Axis[“(X)”, geocentricX],\n" +
+                "        Axis[“(Y)”, geocentricY],\n" +
+                "        Axis[“(Z)”, geocentricZ],\n" +
+                "        Unit[“metre”, 1]]],\n" +
+                "    TargetCRS[GeodeticCRS[“JGD2000”,\n" +
+                "      Datum[“Japanese Geodetic Datum 2000”,\n" +
+                "        Ellipsoid[“GRS 1980”, 6378137.0, 298.257222101]],\n" +
+                "      CS[Cartesian, 3],\n" +
+                "        Axis[“(X)”, geocentricX],\n" +
+                "        Axis[“(Y)”, geocentricY],\n" +
+                "        Axis[“(Z)”, geocentricZ],\n" +
+                "        Unit[“metre”, 1]]],\n" +
                 "    Method[“Geocentric translations”],\n" +
                 "      Parameter[“X-axis translation”, -146.414],\n" +
                 "      Parameter[“Y-axis translation”, 507.337],\n" +
                 "      Parameter[“Z-axis translation”, 680.507]],\n" +
-                "  CoordinateOperationStep[“Geocentric to geographic”,\n" +
+                "  Step[“Geocentric to geographic”,\n" +
+                "    SourceCRS[GeodeticCRS[“JGD2000”,\n" +
+                "      Datum[“Japanese Geodetic Datum 2000”,\n" +
+                "        Ellipsoid[“GRS 1980”, 6378137.0, 298.257222101]],\n" +
+                "      CS[Cartesian, 3],\n" +
+                "        Axis[“(X)”, geocentricX],\n" +
+                "        Axis[“(Y)”, geocentricY],\n" +
+                "        Axis[“(Z)”, geocentricZ],\n" +
+                "        Unit[“metre”, 1]]],\n" +
+                "    TargetCRS[GeographicCRS[“JGD2000”,\n" +
+                "      Datum[“Japanese Geodetic Datum 2000”,\n" +
+                "        Ellipsoid[“GRS 1980”, 6378137.0, 298.257222101]],\n" +
+                "      CS[ellipsoidal, 3],\n" +
+                "        Axis[“Longitude (L)”, east, Unit[“degree”, 
0.017453292519943295]],\n" +
+                "        Axis[“Latitude (B)”, north, Unit[“degree”, 
0.017453292519943295]],\n" +
+                "        Axis[“Ellipsoidal height (h)”, up, Unit[“metre”, 
1]]]],\n" +
                 "    Method[“Geographic/geocentric conversions”],\n" +
                 "      Parameter[“semi_major”, 6378137.0, Unit[“metre”, 
1]],\n" +
                 "      Parameter[“semi_minor”, 6356752.314140356, 
Unit[“metre”, 1]]]]", op);
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultTransformationTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultTransformationTest.java
index 7d25f20155..60ef8fa3f0 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultTransformationTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultTransformationTest.java
@@ -95,6 +95,7 @@ public final class DefaultTransformationTest extends TestCase 
{
          */
         final Map<String, Object> properties = new HashMap<>(4);
         properties.put(DefaultTransformation.NAME_KEY, "Tokyo to JGD2000 
(GSI)");
+        properties.put(DefaultTransformation.OPERATION_VERSION_KEY, "GSI-Jpn");
         properties.put(CoordinateOperations.PARAMETERS_KEY, pg);
         return new DefaultTransformation(properties,
                 createCRS(null,      HardCodedDatum.TOKYO),     // SourceCRS
@@ -182,7 +183,7 @@ public final class DefaultTransformationTest extends 
TestCase {
                 "    PARAMETER[“Z-axis translation”, 680.507, ID[“EPSG”, 
8607]]]", op);
 
         assertWktEquals(Convention.WKT2_SIMPLIFIED,
-                "CoordinateOperation[“Tokyo to JGD2000 (GSI)”,\n" +
+                "CoordinateOperation[“Tokyo to JGD2000 (GSI)”, 
Version[“GSI-Jpn”],\n" +
                 "  SourceCRS[GeodeticCRS[“Tokyo 1918”,\n" +
                 "    Datum[“Tokyo 1918”,\n" +
                 "      Ellipsoid[“Bessel 1841”, 6377397.155, 299.1528128]],\n" 
+


Reply via email to