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

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

commit 11f6114609a60dd63a69c68ac6e09f5043a39c7b
Merge: a1e3ecb82c 94cdd0cb3b
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Mon Sep 8 16:51:53 2025 +0200

    Merge branch 'geoapi-4.0' into geoapi-3.1.
    This merge complete the upgrade of the CRS part of WKT 2 to ISO 19162:2019,
    except for a some advanced elements such as `GeoidModel` and `Calendar[…]`.
    This commit does not include the upgrade for the coordinate operation part.

 .../main/org/apache/sis/console/CommandRunner.java |   2 +-
 .../apache/sis/console/FormattedOutputCommand.java |   6 +
 .../org/apache/sis/console/CRSCommandTest.java     |  15 +-
 .../sis/metadata/iso/citation/Citations.java       |   2 +-
 .../org/apache/sis/temporal/LenientDateFormat.java |   4 +-
 .../sis/metadata/iso/citation/CitationsTest.java   |   2 +-
 .../sis/coordinate/DefaultCoordinateMetadata.java  |   2 +-
 .../main/org/apache/sis/io/wkt/AbstractParser.java |  82 +++
 .../main/org/apache/sis/io/wkt/Convention.java     | 122 ++---
 .../main/org/apache/sis/io/wkt/Element.java        |  18 +-
 .../org/apache/sis/io/wkt/FormattableObject.java   |  10 +-
 .../main/org/apache/sis/io/wkt/Formatter.java      |  97 ++--
 .../apache/sis/io/wkt/GeodeticObjectParser.java    | 558 ++++++++++++++-------
 .../org/apache/sis/io/wkt/MathTransformParser.java |  27 +-
 .../main/org/apache/sis/io/wkt/Transliterator.java |  21 +-
 .../main/org/apache/sis/io/wkt/WKTFormat.java      |  12 +-
 .../main/org/apache/sis/io/wkt/package-info.java   |  11 +-
 .../sis/parameter/DefaultParameterValue.java       | 167 +++---
 .../org/apache/sis/parameter/TensorParameters.java |   4 +-
 .../sis/referencing/AbstractIdentifiedObject.java  |  20 +-
 .../main/org/apache/sis/referencing/CRS.java       |  12 +-
 .../sis/referencing/DefaultObjectDomain.java       |   1 +
 .../sis/referencing/ImmutableIdentifier.java       |   2 -
 .../apache/sis/referencing/crs/AbstractCRS.java    |  93 ++--
 .../sis/referencing/crs/AbstractDerivedCRS.java    |  14 +
 .../sis/referencing/crs/DefaultCompoundCRS.java    |  14 +-
 .../sis/referencing/crs/DefaultDerivedCRS.java     |  44 +-
 .../sis/referencing/crs/DefaultEngineeringCRS.java |  20 +-
 .../sis/referencing/crs/DefaultGeocentricCRS.java  |   2 -
 .../sis/referencing/crs/DefaultGeodeticCRS.java    |  43 +-
 .../sis/referencing/crs/DefaultGeographicCRS.java  |   6 +-
 .../sis/referencing/crs/DefaultImageCRS.java       |   2 -
 .../sis/referencing/crs/DefaultParametricCRS.java  |  20 +-
 .../sis/referencing/crs/DefaultProjectedCRS.java   |  14 +-
 .../sis/referencing/crs/DefaultTemporalCRS.java    |  20 +-
 .../sis/referencing/crs/DefaultVerticalCRS.java    |  20 +-
 .../org/apache/sis/referencing/crs/DynamicCRS.java |  73 +++
 .../org/apache/sis/referencing/cs/AbstractCS.java  |   2 -
 .../sis/referencing/cs/CoordinateSystems.java      |   3 +-
 .../cs/DefaultCoordinateSystemAxis.java            | 109 ++--
 .../sis/referencing/cs/DirectionAlongMeridian.java |   2 -
 .../sis/referencing/datum/AbstractDatum.java       |  33 +-
 .../referencing/datum/DefaultDatumEnsemble.java    |  74 ++-
 .../sis/referencing/datum/DefaultEllipsoid.java    |   2 -
 .../referencing/datum/DefaultEngineeringDatum.java |  16 +-
 .../referencing/datum/DefaultGeodeticDatum.java    |  12 +-
 .../sis/referencing/datum/DefaultImageDatum.java   |  23 +-
 .../referencing/datum/DefaultParametricDatum.java  |  18 +-
 .../referencing/datum/DefaultPrimeMeridian.java    |   4 +-
 .../referencing/datum/DefaultTemporalDatum.java    |  16 +-
 .../referencing/datum/DefaultVerticalDatum.java    |  11 +-
 .../referencing/factory/GeodeticObjectFactory.java |   6 +-
 .../referencing/factory/sql/EPSGDataAccess.java    |  13 +-
 .../org/apache/sis/referencing/internal/Epoch.java |  69 ++-
 .../internal/PositionalAccuracyConstant.java       |  58 ++-
 .../operation/AbstractCoordinateOperation.java     |  12 +-
 .../operation/DefaultOperationMethod.java          |   2 -
 .../provider/MercatorAuxiliarySphere.java          |   3 +-
 .../referencing/operation/provider/Mollweide.java  |   3 +-
 .../provider/ObliqueMercatorTwoPoints.java         |   5 +-
 .../transform/DefaultMathTransformFactory.java     |   3 +-
 .../apache/sis/referencing/privy/WKTKeywords.java  |  54 +-
 .../apache/sis/referencing/privy/WKTUtilities.java |  87 +---
 .../org/apache/sis/geometry/ArrayEnvelopeTest.java |  11 +-
 .../apache/sis/geometry/GeneralEnvelopeTest.java   |   3 +-
 .../test/org/apache/sis/io/wkt/ElementTest.java    |   4 +-
 .../sis/io/wkt/GeodeticObjectParserTest.java       | 135 ++++-
 .../test/org/apache/sis/io/wkt/WKTFormatTest.java  |   1 +
 .../DefaultParameterDescriptorGroupTest.java       |   7 +-
 .../parameter/DefaultParameterDescriptorTest.java  |   6 +-
 .../sis/parameter/DefaultParameterValueTest.java   |   3 +-
 .../org/apache/sis/parameter/TensorValuesTest.java |   5 +-
 .../referencing/AbstractReferenceSystemTest.java   |  36 +-
 .../org/apache/sis/referencing/Assertions.java     |  18 +-
 .../referencing/crs/DefaultCompoundCRSTest.java    |   9 +-
 .../sis/referencing/crs/DefaultDerivedCRSTest.java |   4 +-
 .../referencing/crs/DefaultEngineeringCRSTest.java |   2 +-
 .../referencing/crs/DefaultGeocentricCRSTest.java  |   5 +-
 .../referencing/crs/DefaultGeographicCRSTest.java  |  27 +-
 .../sis/referencing/crs/DefaultImageCRSTest.java   |   2 +-
 .../referencing/crs/DefaultProjectedCRSTest.java   |  25 +-
 .../referencing/crs/DefaultTemporalCRSTest.java    |   2 +-
 .../referencing/crs/DefaultVerticalCRSTest.java    |   2 +-
 .../cs/DefaultCoordinateSystemAxisTest.java        |  52 +-
 .../referencing/datum/DefaultEllipsoidTest.java    |   5 +-
 .../datum/DefaultGeodeticDatumTest.java            |  12 +-
 .../datum/DefaultVerticalDatumTest.java            |   4 +-
 .../factory/CommonAuthorityFactoryTest.java        |   2 +-
 .../apache/sis/referencing/internal/EpochTest.java |  22 +-
 .../operation/CoordinateOperationFinderTest.java   |   6 +-
 .../operation/CoordinateOperationRegistryTest.java |  10 +-
 .../DefaultConcatenatedOperationTest.java          |   4 +-
 .../DefaultCoordinateOperationFactoryTest.java     |   6 +-
 .../operation/DefaultOperationMethodTest.java      |   2 +-
 .../operation/DefaultTransformationTest.java       |   2 +-
 .../operation/HardCodedConversions.java            |   5 +-
 .../referencing/operation/provider/AffineTest.java |   7 +-
 .../operation/provider/LongitudeRotationTest.java  |   3 +-
 .../report/CoordinateOperationMethods.java         |   8 +-
 .../sis/test/integration/ConsistencyTest.java      |   4 +-
 .../org/apache/sis/storage/base/PRJDataStore.java  |  14 +-
 .../apache/sis/storage/esri/WritableStoreTest.java |   2 +-
 .../main/org/apache/sis/setup/GeometryLibrary.java |   3 +-
 .../main/org/apache/sis/util/Characters.java       |   1 -
 .../main/org/apache/sis/util/privy/Constants.java  |   5 +
 .../main/org/apache/sis/util/privy/URLs.java       |   5 -
 .../org/apache/sis/gui/referencing/WKTPane.java    |   2 +
 107 files changed, 1666 insertions(+), 1049 deletions(-)

diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
index 2f364380b5,be3ca10f52..94eb593acc
--- 
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
@@@ -1378,8 -1421,93 +1420,93 @@@ class GeodeticObjectParser extends Math
      }
  
      /**
-      * Parses a {@code "Datum"} (WKT 2) element. The syntax is given by
-      * <a 
href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#54";>WKT 2 
specification §8.2.4</a>.
+      * Parses a {@code "FrameEoch"} (WKT 2) element.
+      *
+      * @param  parent  the parent element.
+      * @return the frame epoch, or {@code null} if none.
+      * @throws ParseException if the {@code "FrameEoch"} element cannot be 
parsed.
+      */
+     private Temporal parseDynamic(final Element parent) throws ParseException 
{
+         final Element element = parent.pullElement(OPTIONAL, 
WKTKeywords.Dynamic);
+         if (element == null) {
+             return null;
+         }
+         Temporal epoch = Epoch.fromYear(pullElementAsDouble(element, 
WKTKeywords.FrameEpoch, MANDATORY), 0);
+         element.close(ignoredElements);
+         return epoch;
+     }
+ 
+     /**
+      * Parses an {@code "Ensemble"} (WKT 2) element.
+      *
+      * @param  mode       {@link #FIRST}, {@link #OPTIONAL} or {@link 
#MANDATORY}.
+      * @param  parent     the parent element.
+      * @param  datumType  GeoAPI interface of the type of datum to create.
+      * @param  meridian   the prime meridian, or {@code null} if the ensemble 
is not geodetic.
+      * @return the {@code "Ensemble"} element as a {@link DatumEnsemble} 
object.
+      * @throws ParseException if the {@code "Ensemble"} element cannot be 
parsed.
+      *
+      * @see 
org.apache.sis.referencing.datum.DefaultDatumEnsemble#formatTo(Formatter)
+      */
+     private <D extends Datum> DatumEnsemble<D> parseEnsemble(final int mode, 
final Element parent,
+             final Class<D> datumType, final PrimeMeridian meridian) throws 
ParseException
+     {
+         final Element ensemble = parent.pullElement(mode, 
WKTKeywords.Ensemble);
+         if (ensemble == null) {
+             return null;
+         }
+         final String ensembleName = ensemble.pullString("name");
+         final Ellipsoid ellipsoid;
+         final boolean vertical;
+         if (datumType == GeodeticDatum.class) {
+             ellipsoid = parseEllipsoid(MANDATORY, ensemble);
+             vertical  = false;
+         } else if (datumType == Datum.class) {
+             // Unspecified datum type, use the presence of `ELLIPSOID` for 
detecting the geodetic case.
+             ellipsoid = parseEllipsoid(OPTIONAL, ensemble);
+             vertical  = (ellipsoid == null);
+         } else {
+             ellipsoid = null;
+             vertical  = (datumType == VerticalDatum.class);
+         }
+         final DatumFactory datumFactory = factories.getDatumFactory();
+         final var members = new ArrayList<D>();
+         try {
+             Element element = ensemble.pullElement(MANDATORY, 
WKTKeywords.Member);
+             do {
+                 final Datum member;
+                 try {
+                     final String name = element.pullString("name");
+                     final Map<String,Object> properties = 
parseAnchorAndClose(element, name);
+                     if (ellipsoid != null) {    // `memberType` may be 
`Datum` or `GeodeticDatum`
+                         member = datumFactory.createGeodeticDatum(properties, 
ellipsoid, meridian);
+                     } else if (vertical) {
 -                        member = datumFactory.createVerticalDatum(properties, 
null);
++                        member = datumFactory.createVerticalDatum(properties, 
(RealizationMethod) null);
+                     } else if (datumType == TemporalDatum.class) {
 -                        member = datumFactory.createTemporalDatum(properties, 
null);
++                        member = datumFactory.createTemporalDatum(properties, 
(Temporal) null);
+                     } else if (datumType == ParametricDatum.class) {
+                         member = 
datumFactory.createParametricDatum(properties);
+                     } else if (datumType == EngineeringDatum.class) {
+                         member = 
datumFactory.createEngineeringDatum(properties);
+                     } else {
+                         // Should never happen because this method is private 
and we checked all calls.
+                         throw new AssertionError(datumType);
+                     }
+                 } catch (FactoryException exception) {
+                     throw element.parseFailed(exception);
+                 }
+                 members.add(datumType.cast(member));
+                 element = ensemble.pullElement(OPTIONAL, WKTKeywords.Member);
+             } while (element != null);
+             var accuracy = 
PositionalAccuracyConstant.ensemble(pullElementAsDouble(ensemble, 
WKTKeywords.EnsembleAccuracy, MANDATORY));
+             return 
datumFactory.createDatumEnsemble(parseAnchorAndClose(ensemble, ensembleName), 
members, accuracy);
+         } catch (FactoryException exception) {
+             throw ensemble.parseFailed(exception);
+         }
+     }
+ 
+     /**
+      * Parses a {@code "Datum"} (WKT 2) element.
       *
       * The legacy WKT 1 pattern was:
       *
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
index 457b834f88,275ed71dfb..52b4d3ce8f
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
@@@ -42,13 -45,14 +45,14 @@@ import org.apache.sis.util.Utilities
  import org.apache.sis.util.ComparisonMode;
  import org.apache.sis.util.resources.Errors;
  
 +// Specific to the main and geoapi-3.1 branches:
 +import org.opengis.referencing.crs.GeneralDerivedCRS;
 +import org.opengis.geometry.MismatchedDimensionException;
 +
  // Specific to the geoapi-3.1 and geoapi-4.0 branches:
  import org.opengis.metadata.Identifier;
+ import org.opengis.referencing.datum.DatumEnsemble;
  
 -// Specific to the geoapi-4.0 branch:
 -import org.opengis.referencing.crs.DerivedCRS;
 -import org.opengis.coordinate.MismatchedDimensionException;
 -
  
  /**
   * Coordinate reference system, defined by a {@linkplain AbstractCS 
coordinate system}
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
index 1f523146a1,dba0e2c4c1..9133cbb2a3
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
@@@ -207,6 -187,19 +208,19 @@@ abstract class AbstractDerivedCRS<C ext
          return conversionFromBase;
      }
  
+     /**
+      * Formats the datum or a view of the ensemble as a datum.
+      */
+     @Override
+     final void formatDatum(final Formatter formatter) {
 -        final SingleCRS baseCRS = getBaseCRS();
++        final CoordinateReferenceSystem baseCRS = getBaseCRS();
+         if (baseCRS instanceof AbstractCRS) {
+             ((AbstractCRS) baseCRS).formatDatum(formatter);
+         } else {
+             super.formatDatum(formatter);
+         }
+     }
+ 
      /**
       * Compares this coordinate reference system with the specified object 
for equality.
       *
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
index 07991ac8b4,93fa957ec0..703457ad2b
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
@@@ -47,9 -51,14 +51,9 @@@ import static org.apache.sis.util.Utili
  
  // Specific to the geoapi-3.1 and geoapi-4.0 branches:
  import org.opengis.metadata.Identifier;
+ import org.opengis.referencing.datum.DatumEnsemble;
  import org.opengis.referencing.datum.DynamicReferenceFrame;
  
 -// Specific to the geoapi-4.0 branch:
 -import org.opengis.annotation.UML;
 -import static org.opengis.annotation.Obligation.*;
 -import static org.opengis.annotation.Specification.*;
 -
  
  /**
   * Specifies the relationship of a Coordinate System to the earth.
@@@ -195,11 -203,11 +199,11 @@@ public class AbstractDatum extends Abst
          super(properties);
          anchorDefinition = Types.toInternationalString(properties, 
ANCHOR_DEFINITION_KEY);
          if (anchorDefinition == null) {
 -            anchorDefinition = Types.toInternationalString(properties, 
"anchorPoint");      // Legacy name.
 +            anchorDefinition = Types.toInternationalString(properties, 
ANCHOR_POINT_KEY);
          }
-         anchorEpoch = property(properties, ANCHOR_EPOCH_KEY, Temporal.class);
+         anchorEpoch = Containers.property(properties, ANCHOR_EPOCH_KEY, 
Temporal.class);
          if (anchorEpoch == null) {
-             Date date = property(properties, REALIZATION_EPOCH_KEY, 
Date.class);
 -            Date date = Containers.property(properties, "realizationEpoch", 
Date.class);    // Legacy name.
++            Date date = Containers.property(properties, 
REALIZATION_EPOCH_KEY, Date.class);
              if (date != null) {
                  anchorEpoch = date.toInstant();
              }
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java
index 8c576db562,6a216fc196..fbead3b304
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java
@@@ -49,11 -51,8 +51,12 @@@ import org.apache.sis.util.Classes
  import org.apache.sis.util.ComparisonMode;
  import org.apache.sis.util.Utilities;
  import org.apache.sis.util.resources.Errors;
+ import org.apache.sis.util.privy.CollectionsExt;
  
 +// Specific to the main and geoapi-3.1 branches:
 +import java.util.Date;
 +import org.opengis.referencing.datum.VerticalDatumType;
 +
  // Specific to the geoapi-3.1 and geoapi-4.0 branches:
  import java.util.Optional;
  import java.time.temporal.Temporal;
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultImageDatum.java
index 5c8cf74906,5118816d1b..23d7e01633
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultImageDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultImageDatum.java
@@@ -26,13 -26,8 +26,12 @@@ import org.opengis.util.InternationalSt
  import org.apache.sis.referencing.privy.WKTKeywords;
  import org.apache.sis.metadata.privy.ImplementationHelper;
  import org.apache.sis.io.wkt.Formatter;
- import org.apache.sis.io.wkt.Convention;
  import org.apache.sis.util.ComparisonMode;
  
 +// Specific to the main and geoapi-3.1 branches:
 +import org.opengis.referencing.datum.PixelInCell;
 +import org.opengis.referencing.datum.ImageDatum;
 +
  // Specific to the geoapi-3.1 and geoapi-4.0 branches:
  import org.opengis.metadata.Identifier;
  
@@@ -241,12 -184,17 +239,17 @@@ public final class DefaultImageDatum ex
       */
      @Override
      protected String formatTo(final Formatter formatter) {
-         super.formatTo(formatter);
-         final Convention convention = formatter.getConvention();
-         if (convention == Convention.INTERNAL) {
-             formatter.append(getPixelInCell());         // This is an 
extension compared to ISO 19162.
-         } else if (convention.majorVersion() == 1) {
+         final String name = super.formatTo(formatter);
+         if (name != null) {
+             // Member of a datum ensemble, but ISO 19162:2019 allows that for 
geodetic and vertical datum only.
              formatter.setInvalidWKT(this, null);
+             return name;
+         }
+         switch (formatter.getConvention()) {
+             // `PixelInCell` is an extension compared to ISO 19162.
 -            case INTERNAL: formatter.append(getPixelInCell(), 
ElementKind.CODE_LIST); break;
++            case INTERNAL: formatter.append(getPixelInCell()); break;
+             case WKT2_2015: break;      // The only standard where this 
element is defined.
+             default: formatter.setInvalidWKT(this, null); break;
          }
          return formatter.shortOrLong(WKTKeywords.IDatum, 
WKTKeywords.ImageDatum);
      }
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultTemporalDatum.java
index 629a91cc7f,f851aa3604..880adb9c82
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultTemporalDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultTemporalDatum.java
@@@ -268,8 -266,13 +269,13 @@@ public class DefaultTemporalDatum exten
       */
      @Override
      protected String formatTo(final Formatter formatter) {
-         super.formatTo(formatter);
+         final String name = super.formatTo(formatter);
+         if (name != null) {
+             // Member of a datum ensemble, but ISO 19162:2019 allows that for 
geodetic and vertical datum only.
+             formatter.setInvalidWKT(this, null);
+             return name;
+         }
 -        formatter.append(new Origin(getOrigin()));
 +        formatter.append(new Origin(TemporalDate.toTemporal(getOrigin())));
          if (formatter.getConvention().majorVersion() == 1) {
              formatter.setInvalidWKT(this, null);
          }
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultOperationMethod.java
index 77a1abd1b3,d8584e6075..27e66e0b76
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultOperationMethod.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultOperationMethod.java
@@@ -511,11 -470,8 +511,9 @@@ public class DefaultOperationMethod ext
       * Formats this operation as a <i>Well Known Text</i> {@code Method[…]} 
element.
       *
       * @return {@code "Method"} (WKT 2) or {@code "Projection"} (WKT 1).
-      *
-      * @see <a 
href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#118";>WKT 2 
specification §17.2.3</a>
       */
      @Override
 +    @SuppressWarnings("deprecation")
      protected String formatTo(final Formatter formatter) {
          final boolean isWKT1 = formatter.getConvention().majorVersion() == 1;
          /*
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
index d86fac6209,c1dee42c2f..ef915aa086
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
@@@ -1132,22 -1004,8 +1132,21 @@@ public class DefaultMathTransformFactor
          return unique(tr);
      }
  
 +    /**
 +     * There is no XML format for math transforms.
 +     *
 +     * @param  xml  math transform encoded in XML format.
 +     * @throws FactoryException if the object creation failed.
 +     */
 +    @Override
 +    @Deprecated
 +    public MathTransform createFromXML(String xml) throws FactoryException {
 +        lastMethod.remove();
 +        throw new 
FactoryException(Errors.format(Errors.Keys.UnsupportedOperation_1, 
"createFromXML"));
 +    }
 +
      /**
-      * Creates a math transform object from a
-      * <a 
href="http://www.geoapi.org/snapshot/javadoc/org/opengis/referencing/doc-files/WKT.html";>Well
 Known Text (WKT)</a>.
+      * Creates a math transform object from a Well Known Text 
(<abbr>WKT</abbr>).
       * If the given text contains non-fatal anomalies (unknown or unsupported 
WKT elements,
       * inconsistent unit definitions, <i>etc.</i>), warnings may be reported 
in a
       * {@linkplain java.util.logging.Logger logger} named {@code 
"org.apache.sis.io.wkt"}.
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
index 73826a2bc1,2ab3b9764b..8993a6d39e
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
@@@ -890,6 -981,35 +984,35 @@@ public final class GeodeticObjectParser
                    "AXIS[" + axis + "]]");
      }
  
+     /**
+      * Tests the parsing of a vertical <abbr>CRS</abbr>.
+      *
+      * @throws ParseException if the parsing failed.
+      */
+     @Test
+     public void testVerticalCRS() throws ParseException {
+         final VerticalCRS crs = parse(VerticalCRS.class,
+                 "VerticalCRS[“RH2000 height”,\n" +
+                 "  Dynamic[FrameEpoch[2000]],\n" +
+                 "  VerticalDatum[“Rikets hojdsystem 2000”],\n" +
+                 "  CS[vertical, 1],\n" +
+                 "    Axis[“Gravity-related height (H)”, up],\n" +
+                 "    Unit[“metre”, 1],\n" +
+                 "  Usage[\n" +
+                 "    Scope[“Geodesy, engineering survey.”],\n" +
+                 "    Area[“Sweden - onshore.”],\n" +
+                 "    BBox[55.28, 10.93, 69.07, 24.17]],\n" +
+                 "  Id[“EPSG”, 5613, “12.013”, 
URI[“urn:ogc:def:crs:EPSG:12.013:5613”]],\n" +
+                 "  Remark[“Replaces RH70 (CRS code 5718) from 2005.”]]");
+ 
+         assertNameAndIdentifierEqual("RH2000 height", 5613, crs);
+         assertNameAndIdentifierEqual("Rikets hojdsystem 2000", 0, 
crs.getDatum());
+         Temporal epoch = assertInstanceOf(DynamicReferenceFrame.class, 
crs.getDatum()).getFrameReferenceEpoch();
+         assertEquals(Year.of(2000), epoch);
+         assertEquals("Geodesy, engineering survey.", 
getSingleton(crs.getDomains()).getScope().toString());
 -        assertEquals("Replaces RH70 (CRS code 5718) from 2005.", 
crs.getRemarks().orElseThrow().toString());
++        assertEquals("Replaces RH70 (CRS code 5718) from 2005.", 
crs.getRemarks().toString());
+     }
+ 
      /**
       * Returns the conversion from {@code north} to {@code south}.
       */

Reply via email to