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

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

commit b35ebd489f42d2e5a37b1a51f3ea7d7cab173df1
Merge: eaa46cbfba b86dbe8b92
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Fri Apr 5 16:05:56 2024 +0200

    Merge branch 'geoapi-3.1'.
    This is the beginning of an upgrade to ISO 19111:2019.

 .../org/apache/sis/metadata/PropertyAccessor.java  |   7 +-
 .../apache/sis/metadata/PropertyComparator.java    |   2 +-
 .../main/org/apache/sis/util/iso/Types.java        |   2 +-
 .../apache/sis/metadata/PropertyAccessorTest.java  |  22 +--
 .../apache/sis/test/mock/GeographicCRSMock.java    |  45 ++++++
 .../org/apache/sis/test/mock/VerticalCRSMock.java  |  34 ++---
 .../test/org/apache/sis/util/iso/TypesTest.java    |   1 +
 .../sis/openoffice/ReferencingFunctions.java       |   2 +-
 .../main/module-info.java                          |   1 +
 .../sis/coordinate/AbstractCoordinateSet.java      | 122 +++++++++++++++
 .../sis/coordinate/DefaultCoordinateMetadata.java  | 169 +++++++++++++++++++++
 .../org/apache/sis/coordinate/package-info.java    |  28 ++++
 .../apache/sis/geometry/WraparoundAdjustment.java  |   2 +-
 .../main/org/apache/sis/io/wkt/Convention.java     |   3 +-
 .../main/org/apache/sis/io/wkt/Formatter.java      |  24 ++-
 .../main/org/apache/sis/io/wkt/VerticalInfo.java   |   4 +-
 .../main/org/apache/sis/io/wkt/WKTDictionary.java  |  20 ++-
 .../geoapi/referencing/DynamicReferenceFrame.java  |  36 +++++
 .../pending/geoapi/referencing/package-info.java   |  21 +++
 .../main/org/apache/sis/referencing/CRS.java       |  67 +++++++-
 .../org/apache/sis/referencing/DisplayName.java    |  84 ++++++++++
 .../apache/sis/referencing/IdentifiedObjects.java  |  24 ++-
 .../sis/referencing/StandardDefinitions.java       |   4 +-
 .../sis/referencing/crs/DefaultCompoundCRS.java    |  27 ++--
 .../sis/referencing/crs/DefaultDerivedCRS.java     |  10 +-
 .../sis/referencing/crs/DefaultEngineeringCRS.java |   2 +
 .../sis/referencing/crs/DefaultImageCRS.java       |   4 +
 .../org/apache/sis/referencing/crs/SubTypes.java   |   7 +-
 .../sis/referencing/cs/DefaultUserDefinedCS.java   |   3 +
 .../org/apache/sis/referencing/cs/SubTypes.java    |   1 +
 .../sis/referencing/datum/AbstractDatum.java       | 103 +++++++++----
 .../referencing/datum/DefaultEngineeringDatum.java |   8 +-
 .../referencing/datum/DefaultGeodeticDatum.java    |   8 +-
 .../sis/referencing/datum/DefaultImageDatum.java   |  14 +-
 .../referencing/datum/DefaultParametricDatum.java  |   9 +-
 .../referencing/datum/DefaultTemporalDatum.java    |   8 +-
 .../referencing/datum/DefaultVerticalDatum.java    |  17 ++-
 .../org/apache/sis/referencing/datum/SubTypes.java |   1 +
 .../apache/sis/referencing/datum/package-info.java |   2 +-
 .../referencing/factory/AuthorityFactoryProxy.java |  25 +--
 .../factory/CommonAuthorityFactory.java            |  30 ++--
 .../factory/ConcurrentAuthorityFactory.java        |  19 ++-
 .../factory/GeodeticAuthorityFactory.java          |  61 +++++++-
 .../referencing/factory/GeodeticObjectFactory.java |  22 ++-
 .../factory/IdentifiedObjectFinder.java            |   4 +-
 .../factory/MultiAuthoritiesFactory.java           |  22 ++-
 .../referencing/factory/sql/AuthorityCodes.java    |   8 +-
 .../referencing/factory/sql/EPSGDataAccess.java    |  37 +++--
 .../sis/referencing/factory/sql/package-info.java  |   2 +-
 .../referencing/internal/EPSGFactoryProxyCRS.java  |   1 +
 .../internal/EPSGFactoryProxyDatum.java            |   1 +
 .../org/apache/sis/referencing/internal/Epoch.java |  93 ++++++++++++
 .../apache/sis/referencing/internal/Legacy.java    |  51 +++++++
 .../apache/sis/referencing/internal/Resources.java |   5 +
 .../sis/referencing/internal/Resources.properties  |   1 +
 .../referencing/internal/Resources_fr.properties   |   1 +
 .../operation/AbstractCoordinateOperation.java     |  91 +++++++++--
 .../operation/DefaultConcatenatedOperation.java    |   4 +-
 .../referencing/operation/DefaultConversion.java   |   5 +-
 .../DefaultCoordinateOperationFactory.java         |   2 +-
 .../operation/TransformedCoordinateSet.java        | 148 ++++++++++++++++++
 .../sis/referencing/privy/AxisDirections.java      |   8 +-
 .../apache/sis/referencing/privy/WKTKeywords.java  |   7 +-
 .../sis/xml/bind/referencing/CD_ImageDatum.java    |   1 +
 .../sis/xml/bind/referencing/CS_UserDefinedCS.java |   1 +
 .../sis/io/wkt/GeodeticObjectParserTest.java       |   2 +-
 .../org/apache/sis/io/wkt/WKTDictionaryTest.java   |  20 ++-
 .../sis/parameter/DefaultParameterValueTest.java   |   6 +-
 .../sis/referencing/AuthorityFactoriesTest.java    |  17 ++-
 .../sis/referencing/EPSGFactoryFallbackTest.java   |   1 +
 .../sis/referencing/crs/DefaultImageCRSTest.java   |   1 +
 .../apache/sis/referencing/crs/HardCodedCRS.java   |   1 +
 .../referencing/cs/DefaultCylindricalCSTest.java   |   2 +-
 .../sis/referencing/cs/DefaultPolarCSTest.java     |   2 +-
 .../sis/referencing/cs/DefaultSphericalCSTest.java |   2 +-
 .../apache/sis/referencing/cs/HardCodedAxes.java   |   4 +-
 .../datum/DefaultGeodeticDatumTest.java            |  35 +++--
 .../datum/DefaultVerticalDatumTest.java            |   2 +-
 .../sis/referencing/datum/HardCodedDatum.java      |   1 +
 .../factory/CommonAuthorityFactoryTest.java        |  18 ++-
 .../factory/MultiAuthoritiesFactoryTest.java       |   2 +-
 .../referencing/factory/sql/EPSGFactoryTest.java   |  12 +-
 .../apache/sis/referencing/internal/EpochTest.java |  92 +++++++++++
 .../operation/SingleOperationMarshallingTest.java  |   8 +-
 .../operation/provider/ProvidersTest.java          |   1 -
 .../sis/referencing/privy/AxisDirectionsTest.java  |   2 +
 .../apache/sis/test/integration/MetadataTest.java  |  81 +++++-----
 .../sis/test/integration/MetadataVerticalTest.java |   6 +-
 .../org/apache/sis/storage/netcdf/base/Axis.java   |   2 +-
 .../apache/sis/storage/netcdf/base/Linearizer.java |   5 +-
 .../main/org/apache/sis/storage/wkt/Store.java     |   5 +-
 .../main/org/apache/sis/util/Utilities.java        |  12 +-
 .../sis/util/logging/MonolineFormatterTest.java    |   4 +
 .../apache/sis/gui/referencing/AuthorityCodes.java |   3 +-
 94 files changed, 1610 insertions(+), 337 deletions(-)

diff --cc 
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/Types.java
index c9de32dd5a,af97040987..f92b64afc2
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/Types.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/util/iso/Types.java
@@@ -497,8 -506,8 +497,8 @@@ public final class Types extends Stati
       * The package prefix (e.g. {@code "CI_"} in {@code "CI_Citation"}) can 
be omitted.
       * The flexibility is provided for allowing transition to newer ISO 
standards,
       * which are dropping the package prefixes.
 -     * For example, {@code "AxisDirection"} in ISO 19111:2007
 -     * has been renamed {@code "AxisDirection"} in ISO 19111:2018.
 +     * For example, {@code "CS_AxisDirection"} in ISO 19111:2007
-      * has been renamed {@code "AxisDirection"} in ISO 19111:2018.
++     * has been renamed {@code "AxisDirection"} in ISO 19111:2019.
       *
       * <p>Only identifiers for the stable part of GeoAPI or for some Apache 
SIS classes are recognized.
       * This method does not handle the identifiers for interfaces in the 
{@code geoapi-pending} module.</p>
diff --cc 
endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/PropertyAccessorTest.java
index b76c0b5be4,b3389026ae..e5a8c9a11d
--- 
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/PropertyAccessorTest.java
+++ 
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/PropertyAccessorTest.java
@@@ -238,17 -240,16 +239,16 @@@ public final class PropertyAccessorTes
       */
      @Test
      public void testConstructorWithCovariantReturnType() {
-         final Class<?> type = GeographicCRS.class;
-         assertMappingEquals(new PropertyAccessor(type, type, type),
-         //……Declaring 
type……………………………Method……………………………………………JavaBeans……………………………UML 
identifier………………Sentence…………………………………Type…………………………………………………………
-             GeographicCRS.class,    "getCoordinateSystem", 
"coordinateSystem", "coordinateSystem", "Coordinate system",  
EllipsoidalCS.class,       // Covariant return type
-             GeodeticCRS.class,      "getDatum",            "datum",           
 "datum",            "Datum",              GeodeticDatum.class,       // 
Covariant return type
-             IdentifiedObject.class, "getName",             "name",            
 "name",             "Name",               ReferenceIdentifier.class,
-             IdentifiedObject.class, "getAlias",            "alias",           
 "alias",            "Alias",              GenericName[].class,
-             ReferenceSystem.class,  "getDomainOfValidity", 
"domainOfValidity", "domainOfValidity", "Domain of validity", Extent.class,
-             IdentifiedObject.class, "getIdentifiers",      "identifiers",     
 "identifier",       "Identifiers",        ReferenceIdentifier[].class,
-             IdentifiedObject.class, "getRemarks",          "remarks",         
 "remarks",          "Remarks",            InternationalString.class,
-             ReferenceSystem.class,  "getScope",            "scope",           
 "SC_CRS.scope",     "Scope",              InternationalString.class);
+         assertMappingEquals(new PropertyAccessor(GeographicCRS.class, 
GeographicCRSMock.class, GeographicCRSMock.class),
+         //……Declaring 
type……………………………Method……………………………………………JavaBeans……………………………UML 
identifier……………………Sentence………………………………Type…………………………………………………………
+             GeographicCRS.class,    "getCoordinateSystem", 
"coordinateSystem", "coordinateSystem",   "Coordinate system", 
EllipsoidalCS.class,       // Covariant return type
+             GeodeticCRS.class,      "getDatum",            "datum",           
 "datum",              "Datum",             GeodeticDatum.class,       // 
Covariant return type
 -            GeodeticCRS.class,      "getDatumEnsemble",    "datumEnsemble",   
 "datumEnsemble",      "Datum ensemble",    DatumEnsemble.class,       // 
Covariant return type
+             IdentifiedObject.class, "getName",             "name",            
 "name",               "Name",              ReferenceIdentifier.class,
+             IdentifiedObject.class, "getAlias",            "alias",           
 "alias",              "Alias",             GenericName[].class,
+             IdentifiedObject.class, "getIdentifiers",      "identifiers",     
 "identifier",         "Identifiers",       ReferenceIdentifier[].class,
 -            IdentifiedObject.class, "getDomains",          "domains",         
 "ObjectUsage.domain", "Domains",           ObjectDomain[].class,
 -            IdentifiedObject.class, "getRemarks",          "remarks",         
 "remarks",            "Remarks",           InternationalString.class);
++            ReferenceSystem.class,  "getScope",            "scope",           
 "SC_CRS.scope",     "Scope",               InternationalString.class,
++            ReferenceSystem.class,  "getDomainOfValidity", 
"domainOfValidity", "domainOfValidity", "Domain of validity",  Extent.class,
++            IdentifiedObject.class, "getRemarks",          "remarks",         
 "remarks",          "Remarks",             InternationalString.class);
      }
  
      /**
diff --cc 
endorsed/src/org.apache.sis.metadata/test/org/apache/sis/test/mock/GeographicCRSMock.java
index 0000000000,7a3e43ef1f..c2a0594866
mode 000000,100644..100644
--- 
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/test/mock/GeographicCRSMock.java
+++ 
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/test/mock/GeographicCRSMock.java
@@@ -1,0 -1,45 +1,45 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ package org.apache.sis.test.mock;
+ 
+ import jakarta.xml.bind.annotation.XmlType;
+ import org.opengis.referencing.crs.GeographicCRS;
+ 
+ 
+ /**
+  * A dummy class for {@link GeographicCRS}. Used for defining property order 
in
+  * {@link 
org.apache.sis.metadata.PropertyAccessorTest#testConstructorWithCovariantReturnType()}.
+  *
+  * @author  Martin Desruisseaux (Geomatys)
+  */
+ @XmlType(name = "GeodeticCRSType", propOrder = {
+     "coordinateSystem",
+     "datum",
 -    "datumEnsemble",
+     "name",
+     "alias",
+     "identifiers",
 -    "domains",
++    "scope",
++    "domainOfValidity",
+     "remarks"
+ })
+ public abstract class GeographicCRSMock implements GeographicCRS {
+     /**
+      * Do not allow (for now) instantiation of this class.
+      */
+     private GeographicCRSMock() {
+     }
+ }
diff --cc 
endorsed/src/org.apache.sis.metadata/test/org/apache/sis/test/mock/VerticalCRSMock.java
index e1a52bbc0c,aecb15b43e..82e971b46f
--- 
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/test/mock/VerticalCRSMock.java
+++ 
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/test/mock/VerticalCRSMock.java
@@@ -95,12 -106,13 +95,12 @@@ public final class VerticalCRSMock exte
       * Creates a new vertical CRS for the given name.
       *
       * @param name          the CRS, CS, datum and axis name.
-      * @param up            {@code true} if the axis direction is up, or 
{@code false} if down.
-      * @param unit          the unit of measurement.
 -     * @param method        the realization method (geoid, tidal, 
<i>etc.</i>).
       * @param minimumValue  the minium value.
       * @param maximumValue  the maximum value.
+      * @param unit          the unit of measurement.
+      * @param up            {@code true} if the axis direction is up, or 
{@code false} if down.
       */
 -    private VerticalCRSMock(final String name, final RealizationMethod 
method, VerticalDatumType type,
 +    private VerticalCRSMock(final String name, VerticalDatumType type,
              final double minimumValue, final double maximumValue, final 
Unit<?> unit, final boolean up)
      {
          super(name);
@@@ -119,19 -132,18 +119,19 @@@
          return new Object[] {getCode(), alias, minimumValue, maximumValue, 
unit, up};
      }
  
-     @Override public String               getAbbreviation()      {return up ? 
"h" : "d";}
-     @Override public InternationalString  getScope()             {return 
null;}
-     @Override public InternationalString  getAnchorPoint()       {return 
null;}
-     @Override public Date                 getRealizationEpoch()  {return 
null;}
-     @Override public Extent               getDomainOfValidity()  {return 
null;}
-     @Override public VerticalDatumType    getVerticalDatumType() {return 
type;}
-     @Override public VerticalDatum        getDatum()             {return 
this;}
-     @Override public VerticalCS           getCoordinateSystem()  {return 
this;}
-     @Override public int                  getDimension()         {return 1;}
-     @Override public CoordinateSystemAxis getAxis(int dimension) {return 
this;}
-     @Override public AxisDirection        getDirection()         {return up ? 
AxisDirection.UP : AxisDirection.DOWN;}
-     @Override public double               getMinimumValue()      {return 
minimumValue;}
-     @Override public double               getMaximumValue()      {return 
maximumValue;}
-     @Override public RangeMeaning         getRangeMeaning()      {return 
RangeMeaning.EXACT;}
-     @Override public Unit<?>              getUnit()              {return 
unit;}
+     @Override public String                      getAbbreviation()      
{return up ? "h" : "d";}
+     @Override public InternationalString         getScope()             
{return null;}
++    @Override public InternationalString         getAnchorPoint()       
{return null;}
++    @Override public Date                        getRealizationEpoch()  
{return null;}
+     @Override public Extent                      getDomainOfValidity()  
{return null;}
 -    @Override public Optional<RealizationMethod> getRealizationMethod() 
{return Optional.ofNullable(method);}
+     @Override public VerticalDatumType           getVerticalDatumType() 
{return type;}
+     @Override public VerticalDatum               getDatum()             
{return this;}
+     @Override public VerticalCS                  getCoordinateSystem()  
{return this;}
+     @Override public int                         getDimension()         
{return 1;}
+     @Override public CoordinateSystemAxis        getAxis(int dimension) 
{return this;}
+     @Override public AxisDirection               getDirection()         
{return up ? AxisDirection.UP : AxisDirection.DOWN;}
+     @Override public double                      getMinimumValue()      
{return minimumValue;}
+     @Override public double                      getMaximumValue()      
{return maximumValue;}
+     @Override public RangeMeaning                getRangeMeaning()      
{return RangeMeaning.EXACT;}
+     @Override public Unit<?>                     getUnit()              
{return unit;}
  }
diff --cc 
endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java
index 9109fa275f,2701a8bf28..c6a2624b8e
--- 
a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java
+++ 
b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java
@@@ -174,8 -173,8 +174,8 @@@ public class ReferencingFunctions exten
              if (object != null) {
                  return object.getName().getCode();
              }
-             // In Apache SIS implementation, 'getDescriptionText' returns the 
name.
+             // In Apache SIS implementation, `getDescriptionText(…)` returns 
the identified object name.
 -            name = 
CRS.getAuthorityFactory(null).getDescriptionText(IdentifiedObject.class, 
codeOrPath).orElse(null);
 +            name = 
CRS.getAuthorityFactory(null).getDescriptionText(codeOrPath);
          } catch (Exception exception) {
              return getLocalizedMessage(exception);
          }
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/coordinate/AbstractCoordinateSet.java
index 0000000000,212b77f0f6..bea3303341
mode 000000,100644..100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/coordinate/AbstractCoordinateSet.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/coordinate/AbstractCoordinateSet.java
@@@ -1,0 -1,80 +1,122 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ package org.apache.sis.coordinate;
+ 
+ import java.util.Objects;
+ import java.io.Serializable;
+ import org.apache.sis.referencing.IdentifiedObjects;
+ 
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.coordinate.CoordinateSet;
 -import org.opengis.coordinate.CoordinateMetadata;
++// Specific to the main branch:
++import java.util.Iterator;
++import java.util.stream.Stream;
++import java.util.stream.StreamSupport;
++import static org.opengis.annotation.Obligation.MANDATORY;
++import static org.opengis.annotation.Specification.ISO_19111;
++import org.opengis.annotation.UML;
++import org.opengis.geometry.DirectPosition;
+ 
+ 
+ /**
+  * Skeletal implementation of a collection of coordinate tuples referenced to 
the same <abbr>CRS</abbr> and epoch.
+  * This implementation is serializable if the coordinate metadata given at 
construction time is also serializable.
+  *
++ * <h2>Future evolution</h2>
++ * This class is expected to implement a {@code CoordinateSet} interface 
after the next GeoAPI release.
++ *
+  * @author  Martin Desruisseaux (Geomatys)
+  * @version 1.5
+  * @since   1.5
+  */
 -public abstract class AbstractCoordinateSet implements CoordinateSet, 
Serializable {
++public abstract class AbstractCoordinateSet implements 
Iterable<DirectPosition>, Serializable {
+     /**
+      * Serial number for inter-operability with different versions.
+      */
 -    private static final long serialVersionUID = 3656426153519035462L;
++    private static final long serialVersionUID = 3656426153519035461L;
+ 
+     /**
+      * Coordinate reference system and epoch (if dynamic) of this coordinate 
set.
+      */
 -    @SuppressWarnings("serial")     // Apache SIS implementations of this 
interface are serializable.
 -    private final CoordinateMetadata metadata;
++    private final DefaultCoordinateMetadata metadata;
+ 
+     /**
+      * Creates a new set of coordinate tuples.
+      *
+      * @param metadata  coordinate reference system and epoch (if dynamic) of 
this coordinate set.
+      */
 -    protected AbstractCoordinateSet(final CoordinateMetadata metadata) {
++    protected AbstractCoordinateSet(final DefaultCoordinateMetadata metadata) 
{
+         this.metadata = Objects.requireNonNull(metadata);
+     }
+ 
+     /**
+      * Returns the coordinate metadata to which this coordinate set is 
referenced.
+      *
++     * <div class="warning"><b>Upcoming API change</b><br>
++     * {@code DefaultCoordinateMetadata} class may be replaced by {@code 
CoordinateMetadata} interface
++     * after upgrade to GeoAPI 3.1.
++     * </div>
++     *
+      * @return coordinate metadata to which this coordinate set is referenced.
+      */
 -    @Override
 -    public CoordinateMetadata getCoordinateMetadata() {
++    public DefaultCoordinateMetadata getCoordinateMetadata() {
+         return metadata;
+     }
+ 
++    /**
++     * Returns the number of dimensions of coordinate tuples. This is 
determined by the
++     * {@linkplain DefaultCoordinateMetadata#getCoordinateReferenceSystem() 
coordinate reference system}.
++     *
++     * @return the number of dimensions of coordinate tuples.
++     */
++    public int getDimension() {
++        // All methods invoked below are for attributes declared as 
mandatory. Values shall not be null.
++        return 
getCoordinateMetadata().getCoordinateReferenceSystem().getCoordinateSystem().getDimension();
++    }
++
++    /**
++     * Returns the positions described by coordinate tuples.
++     *
++     * @return position described by coordinate tuples.
++     */
++    @Override
++    @UML(identifier="coordinateTuple", obligation=MANDATORY, 
specification=ISO_19111)
++    public abstract Iterator<DirectPosition> iterator();
++
++    /**
++     * Returns a stream of coordinate tuples.
++     * Whether the stream is sequential or parallel is implementation 
dependent.
++     * The default implementation creates a sequential stream.
++     *
++     * @return a sequential or parallel stream of coordinate tuples.
++     */
++    public Stream<DirectPosition> stream() {
++        return StreamSupport.stream(spliterator(), false);
++    }
++
+     /**
+      * Returns a string representation of this coordinate set for debugging 
purposes.
+      * This string representation may change in any future version.
+      *
+      * @return a string representation for debugging purposes.
+      */
+     @Override
+     public String toString() {
+         final var sb = new StringBuilder("CoordinateSet");
+         
sb.append('[').append(IdentifiedObjects.getDisplayName(metadata.getCoordinateReferenceSystem(),
 null));
+         metadata.getCoordinateEpoch().ifPresent((epoch) -> sb.append(" @ 
").append(epoch));
+         return sb.toString();
+     }
+ }
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/coordinate/DefaultCoordinateMetadata.java
index 0000000000,facb63e4c2..7067078383
mode 000000,100644..100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/coordinate/DefaultCoordinateMetadata.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/coordinate/DefaultCoordinateMetadata.java
@@@ -1,0 -1,208 +1,169 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ package org.apache.sis.coordinate;
+ 
+ import java.util.Objects;
+ import java.util.Optional;
+ import java.io.Serializable;
+ import java.time.temporal.Temporal;
+ import org.opengis.referencing.crs.CoordinateReferenceSystem;
+ import org.apache.sis.referencing.IdentifiedObjects;
+ import org.apache.sis.referencing.privy.WKTUtilities;
+ import org.apache.sis.referencing.privy.WKTKeywords;
+ import org.apache.sis.referencing.internal.Resources;
+ import org.apache.sis.referencing.internal.Epoch;
+ import org.apache.sis.referencing.CRS;
+ import org.apache.sis.io.wkt.FormattableObject;
+ import org.apache.sis.io.wkt.Formatter;
+ import org.apache.sis.util.ComparisonMode;
+ import org.apache.sis.util.LenientComparable;
+ import org.apache.sis.util.Utilities;
+ 
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.coordinate.CoordinateMetadata;
 -
+ 
+ /**
+  * Default implementation of metadata required to reference coordinates.
+  * Metadata include a coordinate reference system and the epoch at which the 
coordinates are valid.
+  * This default implementation provides <i>Well-Known Text</i> support.
+  * It is immutable and serializable if the CRS and epoch are also 
serializable.
+  *
++ * <h2>Future evolution</h2>
++ * This class is expected to implement a {@code CoordinateMetadata} interface 
after the next GeoAPI release.
++ *
+  * @author  Martin Desruisseaux (Geomatys)
+  * @version 1.5
+  * @since   1.5
+  */
+ public class DefaultCoordinateMetadata extends FormattableObject
 -        implements CoordinateMetadata, LenientComparable, Serializable
++        implements LenientComparable, Serializable
+ {
+     /**
+      * Serial number for inter-operability with different versions.
+      */
+     private static final long serialVersionUID = -754447822292824735L;
+ 
+     /**
+      * The coordinate reference system (<abbr>CRS</abbr>) in which the 
coordinate tuples are given.
+      *
+      * @see #getCoordinateReferenceSystem()
+      */
+     @SuppressWarnings("serial")     // Apache SIS implementations of this 
interface are serializable.
+     private final CoordinateReferenceSystem crs;
+ 
+     /**
+      * Date at which coordinate tuples are valid, or {@code null} if the CRS 
is not dynamic.
+      *
+      * @see #getCoordinateEpoch()
+      */
+     @SuppressWarnings("serial")     // Java implementations of this interface 
are serializable.
+     private final Temporal epoch;
+ 
+     /**
+      * Creates a new coordinate metadata.
+      *
+      * @param  crs    the coordinate reference system (<abbr>CRS</abbr>) in 
which the coordinate tuples are given.
+      * @param  epoch  date at which coordinate tuples are valid, or {@code 
null} if the CRS is not dynamic.
+      * @throws IllegalArgumentException if {@code epoch} is null while the 
CRS is dynamic or has a dynamic component.
+      */
+     public DefaultCoordinateMetadata(final CoordinateReferenceSystem crs, 
final Temporal epoch) {
+         this.crs = Objects.requireNonNull(crs);
+         this.epoch = epoch;
+         if (epoch == null && CRS.getFrameReferenceEpoch(crs).isPresent()) {
+             throw new 
IllegalArgumentException(Resources.format(Resources.Keys.MissingReferenceFrameEpoch_1,
+                                                
IdentifiedObjects.getDisplayName(crs, null)));
+         }
+     }
+ 
 -    /**
 -     * Creates a new coordinate metadata with the same values as the 
specified one.
 -     * This copy constructor provides a way to convert an arbitrary 
implementation into a SIS one
 -     * or a user-defined one (as a subclass), usually in order to leverage 
some implementation-specific API.
 -     *
 -     * <p>This constructor performs a shallow copy, i.e. the properties are 
not cloned.</p>
 -     *
 -     * @param  metadata  the coordinate metadata to copy.
 -     *
 -     * @see #castOrCopy(CoordinateMetadata)
 -     */
 -    protected DefaultCoordinateMetadata(final CoordinateMetadata metadata) {
 -        this(metadata.getCoordinateReferenceSystem(), 
metadata.getCoordinateEpoch().orElse(null));
 -    }
 -
 -    /**
 -     * Returns a SIS datum implementation with the same values as the given 
arbitrary implementation.
 -     * If the given object is {@code null}, then this method returns {@code 
null}.
 -     * Otherwise if the given object is already a SIS implementation, then 
the given object is returned unchanged.
 -     * Otherwise a new SIS implementation is created and initialized to the 
attribute values of the given object.
 -     *
 -     * @param  object  the object to get as a SIS implementation, or {@code 
null} if none.
 -     * @return a SIS implementation containing the values of the given object 
(may be the
 -     *         given object itself), or {@code null} if the argument was null.
 -     */
 -    public static DefaultCoordinateMetadata castOrCopy(final 
CoordinateMetadata object) {
 -        if (object == null || object instanceof DefaultCoordinateMetadata) {
 -            return (DefaultCoordinateMetadata) object;
 -        } else {
 -            return new DefaultCoordinateMetadata(object);
 -        }
 -    }
 -
+     /**
+      * Returns the <abbr>CRS</abbr> in which the coordinate tuples are given.
+      * Should never be null in principle, however this implementation does 
not enforce this restriction.
+      *
+      * @return the coordinate reference system (CRS) of coordinate tuples.
+      */
 -    @Override
+     public CoordinateReferenceSystem getCoordinateReferenceSystem() {
+         return crs;
+     }
+ 
+     /**
+      * Returns the date at which coordinate tuples referenced to a dynamic 
<abbr>CRS</abbr> are valid.
+      *
+      * @return epoch at which coordinate tuples are valid.
+      */
 -    @Override
+     public Optional<Temporal> getCoordinateEpoch() {
+         return Optional.ofNullable(epoch);
+     }
+ 
+     /**
+      * Returns a hash code value for this coordinate metadata.
+      *
+      * @return a hash code value.
+      */
+     @Override
+     public int hashCode() {
+         return crs.hashCode() * 11 + Objects.hashCode(epoch);
+     }
+ 
+     /**
+      * Compares this metadata with the given object for equality.
+      *
+      * @param  obj  the object to compare with this metadata.
+      * @return whether the two objects are equal.
+      */
+     @Override
+     public final boolean equals(final Object obj) {
+         return equals(obj, ComparisonMode.STRICT);
+     }
+ 
+     /**
+      * Compares this metadata with the given object for equality.
+      *
+      * @param  obj   the object to compare to {@code this}.
+      * @param  mode  {@link ComparisonMode#STRICT STRICT} for performing a 
strict comparison, or
+      *               {@link ComparisonMode#IGNORE_METADATA IGNORE_METADATA} 
for comparing only
+      *               properties relevant to coordinate transformations.
+      * @return {@code true} if both objects are equal.
+      */
+     @Override
+     public boolean equals(final Object obj, final ComparisonMode mode) {
+         if (this == obj) {
+             return true;
+         }
+         if (obj != null) {
+             if (mode == ComparisonMode.STRICT) {
+                 if (obj.getClass() == getClass()) {
+                     final var other = (DefaultCoordinateMetadata) obj;
+                     return crs.equals(other.crs) && Objects.equals(epoch, 
other.epoch);
+                 }
 -            } else if (obj instanceof CoordinateMetadata) {
 -                final var other = (CoordinateMetadata) obj;
 -                return Utilities.deepEquals(getCoordinateReferenceSystem(), 
other.getCoordinateReferenceSystem(), mode)
 -                        && Objects.equals(getCoordinateEpoch(), 
other.getCoordinateEpoch());
+             }
+         }
+         return false;
+     }
+ 
+     /**
+      * Formats this metadata as a <i>Well Known Text</i> {@code 
CoordinateMetadata[…]} element.
+      *
+      * @param  formatter  the formatter where to format the inner content of 
this WKT element.
+      * @return {@code "CoordinateMetadata"}.
+      */
+     @Override
+     protected String formatTo(final Formatter formatter) {
+         formatter.append(WKTUtilities.toFormattable(crs));
+         if (epoch != null) {
+             formatter.append(new Epoch(epoch));
+         }
+         return WKTKeywords.CoordinateMetadata;
+     }
+ }
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/VerticalInfo.java
index 91564453bf,37275e7cc3..017d807552
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/VerticalInfo.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/VerticalInfo.java
@@@ -32,6 -31,9 +31,9 @@@ import org.apache.sis.metadata.privy.Ax
  import org.apache.sis.metadata.iso.extent.DefaultExtent;
  import org.apache.sis.metadata.iso.extent.DefaultVerticalExtent;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.referencing.datum.RealizationMethod;
++// Specific to the main branch:
++import org.opengis.referencing.datum.VerticalDatumType;
+ 
  
  /**
   * Stores temporary information needed for completing the construction of an 
{@link DefaultVerticalExtent} instance.
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/pending/geoapi/referencing/DynamicReferenceFrame.java
index 0000000000,f35ee94813..d2cf1b37cb
mode 000000,100644..100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/pending/geoapi/referencing/DynamicReferenceFrame.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/pending/geoapi/referencing/DynamicReferenceFrame.java
@@@ -1,0 -1,38 +1,36 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
 -package org.apache.sis.map.service;
++package org.apache.sis.pending.geoapi.referencing;
+ 
++import java.time.temporal.Temporal;
++import org.opengis.referencing.datum.Datum;
++import org.opengis.annotation.UML;
+ 
 -/**
 - * Exception that may be thrown by a portraying operation.
 - *
 - * @author Johann Sorel (Geomatys)
 - */
 -public class RenderingException extends Exception {
++import static org.opengis.annotation.Obligation.*;
++import static org.opengis.annotation.Specification.*;
+ 
 -    public RenderingException(String message) {
 -        super(message);
 -    }
+ 
 -    public RenderingException(Throwable cause) {
 -        super(cause);
 -    }
 -
 -    public RenderingException(String message, Throwable cause) {
 -        super(message, cause);
 -    }
++/**
++ * Placeholder for an interface that may be added in GeoAPI 3.1.
++ */
++public interface DynamicReferenceFrame extends Datum {
++    /**
++     * {@return the epoch to which the coordinates of stations defining the 
dynamic datum are referenced}.
++     */
++    @UML(identifier="frameReferenceEpoch", obligation=MANDATORY, 
specification=ISO_19111)
++    Temporal getFrameReferenceEpoch();
+ }
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/pending/geoapi/referencing/package-info.java
index 0000000000,4307e9c627..3172e99803
mode 000000,100644..100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/pending/geoapi/referencing/package-info.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/pending/geoapi/referencing/package-info.java
@@@ -1,0 -1,27 +1,21 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ 
+ /**
 - * CQL parser.
 - *
 - * @author  Johann Sorel (Geomatys)
++ * Place-holder for some interfaces not present in GeoAPI 3.0 but proposed 
for addition in GeoAPI 3.1.
+  */
 -module org.apache.sis.cql {
 -    requires transitive org.apache.sis.feature;
 -    requires org.locationtech.jts;
 -    requires org.antlr.antlr4.runtime;
 -}
++package org.apache.sis.pending.geoapi.referencing;
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
index e27e943ae6,3faccae36c..f2df4e7307
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
@@@ -90,8 -91,13 +91,10 @@@ import org.apache.sis.util.privy.Numeri
  import org.apache.sis.util.resources.Errors;
  import org.apache.sis.util.logging.Logging;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.geometry.Geometry;
 -import org.opengis.referencing.ObjectDomain;
 -import org.opengis.referencing.datum.DynamicReferenceFrame;
 -import org.opengis.coordinate.CoordinateMetadata;
 -import org.opengis.metadata.extent.BoundingPolygon;
 -import org.opengis.metadata.extent.GeographicExtent;
 +// Specific to the main branch:
++import org.apache.sis.pending.geoapi.referencing.DynamicReferenceFrame;
++import org.apache.sis.coordinate.DefaultCoordinateMetadata;
 +import org.apache.sis.referencing.internal.Legacy;
  
  
  /**
@@@ -618,6 -624,32 +621,32 @@@ public final class CRS extends Static 
          return bestCRS;
      }
  
+     /**
+      * Finds a mathematical operation that transforms or converts coordinates 
between the given <abbr>CRS</abbr>s and epochs.
+      * This method performs the same work as the {@linkplain 
#findOperation(CoordinateReferenceSystem, CoordinateReferenceSystem,
+      * GeographicBoundingBox) variant working on CRS objects}, except that 
the coordinate epochs may be taken in account.
+      *
+      * @param  source          the CRS and epoch of source coordinates.
+      * @param  target          the CRS and epoch of target coordinates.
+      * @param  areaOfInterest  the area of interest, or {@code null} if none.
+      * @return the mathematical operation from {@code source} to {@code 
target}.
+      * @throws OperationNotFoundException if no operation was found between 
the given pair of <abbr>CRS</abbr>s and epochs.
+      * @throws FactoryException if the operation cannot be created for 
another reason.
+      *
+      * @since 1.5
+      */
 -    public static CoordinateOperation findOperation(final CoordinateMetadata 
source,
 -                                                    final CoordinateMetadata 
target,
++    public static CoordinateOperation findOperation(final 
DefaultCoordinateMetadata source,
++                                                    final 
DefaultCoordinateMetadata target,
+                                                     final 
GeographicBoundingBox areaOfInterest)
+             throws FactoryException
+     {
+         // TODO: take epoch in account.
+         if (source.getCoordinateEpoch().isPresent() || 
target.getCoordinateEpoch().isPresent()) {
+             throw new FactoryException("This version of Apache SIS does not 
yet support coordinate epoch.");
+         }
+         return findOperation(source.getCoordinateReferenceSystem(), 
target.getCoordinateReferenceSystem(), areaOfInterest);
+     }
+ 
      /**
       * Finds a mathematical operation that transforms or converts coordinates 
from the given source to the
       * given target coordinate reference system. If an estimation of the 
geographic area containing the points
@@@ -882,6 -956,34 +911,34 @@@
          return envelope;
      }
  
+     /**
+      * Returns the epoch to which the coordinates of stations defining the 
dynamic CRS are referenced.
 -     * If the CRS is associated to a {@linkplain DynamicReferenceFrame 
dynamic datum}, then reference
++     * If the CRS is associated to a dynamic reference frame, then the 
reference
+      * epoch of that datum is returned. Otherwise if the CRS is {@linkplain 
CompoundCRS compound},
+      * then the first reference epoch found in a component is returned.
+      *
+      * @param  crs  the coordinate reference frame from which to get the 
epoch, or {@code null}.
+      * @return epoch to which the coordinates of stations defining the 
dynamic CRS frame are referenced.
+      *
+      * @since 1.5
+      */
+     public static Optional<Temporal> getFrameReferenceEpoch(final 
CoordinateReferenceSystem crs) {
+         if (crs instanceof SingleCRS) {
+             final Datum datum = ((SingleCRS) crs).getDatum();
+             if (datum instanceof DynamicReferenceFrame) {
+                 return Optional.of(((DynamicReferenceFrame) 
datum).getFrameReferenceEpoch());
+             }
+         } else if (crs instanceof CompoundCRS) {
 -            for (SingleCRS component : ((CompoundCRS) 
crs).getSingleComponents()) {
++            for (SingleCRS component : getSingleComponents(crs)) {
+                 final Datum datum = component.getDatum();
+                 if (datum instanceof DynamicReferenceFrame) {
+                     return Optional.of(((DynamicReferenceFrame) 
datum).getFrameReferenceEpoch());
+                 }
+             }
+         }
+         return Optional.empty();
+     }
+ 
      /**
       * Creates a compound coordinate reference system from an ordered list of 
CRS components.
       * A CRS is inferred from the given components and the domain of validity 
is set to the
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/StandardDefinitions.java
index a2718d1401,8a66d58abf..015db59586
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/StandardDefinitions.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/StandardDefinitions.java
@@@ -75,6 -74,9 +74,9 @@@ import org.apache.sis.measure.Latitude
  import org.apache.sis.measure.Units;
  import static 
org.apache.sis.metadata.privy.ReferencingServices.AUTHALIC_RADIUS;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.referencing.datum.RealizationMethod;
++// Specific to the main branch:
++import org.opengis.referencing.datum.VerticalDatumType;
+ 
  
  /**
   * Definitions of referencing objects identified by the {@link CommonCRS} 
enumeration values.
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
index 217df1d310,43869b2b63..9fe96587ce
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
@@@ -51,8 -53,10 +51,8 @@@ import org.apache.sis.util.Utilities
  import org.apache.sis.util.collection.CheckedContainer;
  import org.apache.sis.util.collection.Containers;
  import org.apache.sis.util.resources.Errors;
+ import org.apache.sis.util.privy.UnmodifiableArrayList;
 -import org.apache.sis.metadata.privy.Identifiers;
+ import org.apache.sis.xml.bind.referencing.SC_CRS;
 -import org.apache.sis.xml.NilObject;
  import org.apache.sis.io.wkt.Formatter;
  import org.apache.sis.io.wkt.Convention;
  
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
index 53d1d17533,e379725baf..f26cb27efb
--- 
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
@@@ -127,13 -129,13 +131,13 @@@ public class AbstractDatum extends Abst
       *     <th>Value type</th>
       *     <th>Returned by</th>
       *   </tr><tr>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_DEFINITION_KEY}</td>
 +     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_POINT_KEY}</td>
       *     <td>{@link InternationalString} or {@link String}</td>
-      *     <td>{@link #getAnchorPoint()}</td>
+      *     <td>{@link #getAnchorDefinition()}</td>
       *   </tr><tr>
-      *     <td>{@value 
org.opengis.referencing.datum.Datum#REALIZATION_EPOCH_KEY}</td>
-      *     <td>{@link Date}</td>
-      *     <td>{@link #getRealizationEpoch()}</td>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_EPOCH_KEY}</td>
++     *     <td>{@code "anchorEpoch"}</td>
+      *     <td>{@link Temporal}</td>
+      *     <td>{@link #getAnchorEpoch()}</td>
       *   </tr><tr>
       *     <th colspan="3" class="hsep">Defined in parent class 
(reminder)</th>
       *   </tr><tr>
@@@ -161,10 -163,20 +165,19 @@@
       *
       * @param  properties  the properties to be given to the identified 
object.
       */
 -    @SuppressWarnings("deprecation")
      public AbstractDatum(final Map<String,?> properties) {
          super(properties);
-         realizationEpoch = 
ImplementationHelper.toMilliseconds(property(properties, REALIZATION_EPOCH_KEY, 
Date.class));
-         anchorDefinition = Types.toInternationalString(properties, 
ANCHOR_POINT_KEY);
 -        anchorDefinition = Types.toInternationalString(properties, 
ANCHOR_DEFINITION_KEY);
++        anchorDefinition = Types.toInternationalString(properties, 
"anchorDefinition");
+         if (anchorDefinition == null) {
+             anchorDefinition = Types.toInternationalString(properties, 
ANCHOR_POINT_KEY);
+         }
 -        anchorEpoch = property(properties, ANCHOR_EPOCH_KEY, Temporal.class);
++        anchorEpoch = property(properties, "anchorEpoch", Temporal.class);
+         if (anchorEpoch == null) {
+             Date date = property(properties, REALIZATION_EPOCH_KEY, 
Date.class);
+             if (date != null) {
+                 anchorEpoch = date.toInstant();
+             }
+         }
      }
  
      /**
@@@ -178,8 -190,8 +191,11 @@@
       */
      protected AbstractDatum(final Datum datum) {
          super(datum);
-         realizationEpoch = 
ImplementationHelper.toMilliseconds(datum.getRealizationEpoch());
 -        anchorEpoch = datum.getAnchorEpoch().orElse(null);
 -        anchorDefinition = datum.getAnchorDefinition().orElse(null);
++        Date date = datum.getRealizationEpoch();
++        if (date != null) {
++            anchorEpoch = date.toInstant();
++        }
 +        anchorDefinition = datum.getAnchorPoint();
      }
  
      /**
@@@ -244,53 -253,58 +257,82 @@@
       * </ul>
       *
       * @return description, possibly including coordinates, of the point or 
points used to anchor the datum to the Earth.
+      *
+      * @since 1.5
+      */
 -    @Override
+     public Optional<InternationalString> getAnchorDefinition() {
+         return Optional.ofNullable(anchorDefinition);
+     }
+ 
+     /**
+      * Returns a description of the point(s) used to anchor the datum to the 
Earth.
+      *
+      * @deprecated Renamed {@link #getAnchorDefinition()} as of ISO 
19111:2019.
+      *
+      * @return a description of the point(s) used to anchor the datum to the 
Earth.
       */
      @Override
+     @Deprecated(since = "1.5")
      @XmlElement(name = "anchorDefinition")
      public InternationalString getAnchorPoint() {
          return anchorDefinition;
      }
  
      /**
-      * The time after which this datum definition is valid.
-      * This time may be precise or merely a year.
+      * Returns the epoch at which a static datum matches a dynamic datum from 
which it has been derived.
+      * This time may be precise or merely a year (e.g. 1983 for NAD83).
+      *
+      * @return epoch at which a static datum matches a dynamic datum from 
which it has been derived.
       *
-      * <p>If an old datum is superseded by a new datum, then the realization 
epoch for the new datum
-      * defines the upper limit for the validity of the old datum.</p>
+      * @see java.time.Year
+      * @see java.time.YearMonth
+      * @see java.time.LocalDate
+      *
+      * @since 1.5
+      */
 -    @Override
+     public Optional<Temporal> getAnchorEpoch() {
+         return Optional.ofNullable(anchorEpoch);
+     }
+ 
+     /**
+      * The time after which this datum definition is valid.
       *
       * @return the time after which this datum definition is valid, or {@code 
null} if none.
+      *
+      * @deprecated Since ISO 19111:2019, replaced by {@link 
#getAnchorEpoch()}.
       */
      @Override
+     @Deprecated(since = "1.5")
      @XmlSchemaType(name = "date")
      @XmlElement(name = "realizationEpoch")
      public Date getRealizationEpoch() {
-         return ImplementationHelper.toDate(realizationEpoch);
 -        return Datum.super.getRealizationEpoch();
++        return getAnchorEpoch().map(Legacy::toDate).orElse(null);
 +    }
 +
 +    /**
 +     * Returns the region or timeframe in which this datum is valid, or 
{@code null} if unspecified.
 +     *
 +     * @return area or region or timeframe in which this datum is valid, or 
{@code null}.
 +     *
 +     * @deprecated Replaced by {@link #getDomains()} as of ISO 19111:2019.
 +     */
 +    @Override
 +    @Deprecated(since = "1.4")
 +    public Extent getDomainOfValidity() {
 +        return Legacy.getDomainOfValidity(getDomains());
 +    }
 +
 +    /**
 +     * Returns the domain or limitations of usage, or {@code null} if 
unspecified.
 +     *
 +     * @return description of domain of usage, or limitations of usage, for 
which this datum object is valid.
 +     *
 +     * @deprecated Replaced by {@link #getDomains()} as of ISO 19111:2019.
 +     */
 +    @Override
 +    @Deprecated(since = "1.4")
 +    public InternationalString getScope() {
 +        return Legacy.getScope(getDomains());
      }
  
      /**
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultEngineeringDatum.java
index 10ea0de84d,5e161c9876..6cb79554d2
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultEngineeringDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultEngineeringDatum.java
@@@ -88,13 -88,13 +88,13 @@@ public class DefaultEngineeringDatum ex
       *     <td>{@link InternationalString} or {@link String}</td>
       *     <td>{@link #getRemarks()}</td>
       *   </tr><tr>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_DEFINITION_KEY}</td>
 +     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_POINT_KEY}</td>
       *     <td>{@link InternationalString} or {@link String}</td>
-      *     <td>{@link #getAnchorPoint()}</td>
+      *     <td>{@link #getAnchorDefinition()}</td>
       *   </tr><tr>
-      *     <td>{@value 
org.opengis.referencing.datum.Datum#REALIZATION_EPOCH_KEY}</td>
-      *     <td>{@link java.util.Date}</td>
-      *     <td>{@link #getRealizationEpoch()}</td>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_EPOCH_KEY}</td>
++     *     <td>{@code "anchorEpoch"}</td>
+      *     <td>{@link java.time.temporal.Temporal}</td>
+      *     <td>{@link #getAnchorEpoch()}</td>
       *   </tr>
       * </table>
       *
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
index 14d96f2598,b7273fee42..2d9a67779e
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
@@@ -232,13 -232,13 +232,13 @@@ public class DefaultGeodeticDatum exten
       *     <td>{@link InternationalString} or {@link String}</td>
       *     <td>{@link #getRemarks()}</td>
       *   </tr><tr>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_DEFINITION_KEY}</td>
 +     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_POINT_KEY}</td>
       *     <td>{@link InternationalString} or {@link String}</td>
-      *     <td>{@link #getAnchorPoint()}</td>
+      *     <td>{@link #getAnchorDefinition()}</td>
       *   </tr><tr>
-      *     <td>{@value 
org.opengis.referencing.datum.Datum#REALIZATION_EPOCH_KEY}</td>
-      *     <td>{@link Date}</td>
-      *     <td>{@link #getRealizationEpoch()}</td>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_EPOCH_KEY}</td>
++     *     <td>{@code "anchorEpoch"}</td>
+      *     <td>{@link java.time.temporal.Temporal}</td>
+      *     <td>{@link #getAnchorEpoch()}</td>
       *   </tr>
       * </table>
       *
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultImageDatum.java
index c3b7ec856a,9100a447af..204fe5b5ee
--- 
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
@@@ -104,13 -108,13 +108,13 @@@ public class DefaultImageDatum extends 
       *     <td>{@link InternationalString} or {@link String}</td>
       *     <td>{@link #getRemarks()}</td>
       *   </tr><tr>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_DEFINITION_KEY}</td>
 +     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_POINT_KEY}</td>
       *     <td>{@link InternationalString} or {@link String}</td>
-      *     <td>{@link #getAnchorPoint()}</td>
+      *     <td>{@link #getAnchorDefinition()}</td>
       *   </tr><tr>
-      *     <td>{@value 
org.opengis.referencing.datum.Datum#REALIZATION_EPOCH_KEY}</td>
-      *     <td>{@link java.util.Date}</td>
-      *     <td>{@link #getRealizationEpoch()}</td>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_EPOCH_KEY}</td>
++     *     <td>{@code "anchorEpoch"}</td>
+      *     <td>{@link java.time.temporal.Temporal}</td>
+      *     <td>{@link #getAnchorEpoch()}</td>
       *   </tr>
       * </table>
       *
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultParametricDatum.java
index 312bd0afef,1037b5b9d0..cc63fdbf93
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultParametricDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultParametricDatum.java
@@@ -94,13 -96,13 +93,13 @@@ public class DefaultParametricDatum ext
       *     <td>{@link org.opengis.util.InternationalString} or {@link 
String}</td>
       *     <td>{@link #getRemarks()}</td>
       *   </tr><tr>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_DEFINITION_KEY}</td>
 +     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_POINT_KEY}</td>
       *     <td>{@link org.opengis.util.InternationalString} or {@link 
String}</td>
-      *     <td>{@link #getAnchorPoint()}</td>
+      *     <td>{@link #getAnchorDefinition()}</td>
       *   </tr><tr>
-      *     <td>{@value 
org.opengis.referencing.datum.Datum#REALIZATION_EPOCH_KEY}</td>
-      *     <td>{@link Date}</td>
-      *     <td>{@link #getRealizationEpoch()}</td>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_EPOCH_KEY}</td>
++     *     <td>{@code "anchorEpoch"}</td>
+      *     <td>{@link java.time.temporal.Temporal}</td>
+      *     <td>{@link #getAnchorEpoch()}</td>
       *   </tr>
       * </table>
       *
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultTemporalDatum.java
index 189c199dc1,cb7a8d5e53..f7aade22ba
--- 
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
@@@ -129,13 -129,13 +129,13 @@@ public class DefaultTemporalDatum exten
       *     <td>{@link InternationalString} or {@link String}</td>
       *     <td>{@link #getRemarks()}</td>
       *   </tr><tr>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_DEFINITION_KEY}</td>
 +     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_POINT_KEY}</td>
       *     <td>{@link InternationalString} or {@link String}</td>
-      *     <td>{@link #getAnchorPoint()}</td>
+      *     <td>{@link #getAnchorDefinition()}</td>
       *   </tr><tr>
-      *     <td>{@value 
org.opengis.referencing.datum.Datum#REALIZATION_EPOCH_KEY}</td>
-      *     <td>{@link Date}</td>
-      *     <td>{@link #getRealizationEpoch()}</td>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_EPOCH_KEY}</td>
++     *     <td>{@code "anchorEpoch"}</td>
+      *     <td>{@link java.time.temporal.Temporal}</td>
+      *     <td>{@link #getAnchorEpoch()}</td>
       *   </tr>
       * </table>
       *
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultVerticalDatum.java
index 44ef22bf56,5405bca909..96e209538a
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultVerticalDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultVerticalDatum.java
@@@ -130,13 -138,13 +131,13 @@@ public class DefaultVerticalDatum exten
       *     <td>{@link InternationalString} or {@link String}</td>
       *     <td>{@link #getRemarks()}</td>
       *   </tr><tr>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_DEFINITION_KEY}</td>
 +     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_POINT_KEY}</td>
       *     <td>{@link InternationalString} or {@link String}</td>
-      *     <td>{@link #getAnchorPoint()}</td>
+      *     <td>{@link #getAnchorDefinition()}</td>
       *   </tr><tr>
-      *     <td>{@value 
org.opengis.referencing.datum.Datum#REALIZATION_EPOCH_KEY}</td>
-      *     <td>{@link java.util.Date}</td>
-      *     <td>{@link #getRealizationEpoch()}</td>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_EPOCH_KEY}</td>
++     *     <td>{@code "anchorEpoch"}</td>
+      *     <td>{@link java.time.temporal.Temporal}</td>
+      *     <td>{@link #getAnchorEpoch()}</td>
       *   </tr>
       * </table>
       *
@@@ -255,10 -314,13 +256,12 @@@
          }
          switch (mode) {
              case STRICT: {
-                 return type().equals(((DefaultVerticalDatum) object).type());
+                 final var other = (DefaultVerticalDatum) object;
 -                return Objects.equals(method, other.method) && 
type().equals(other.type());
++                return type().equals(other.type());
              }
              case BY_CONTRACT: {
-                 return Objects.equals(getVerticalDatumType(), 
((VerticalDatum) object).getVerticalDatumType());
+                 final var other = (VerticalDatum) object;
 -                return Objects.equals(getRealizationMethod(), 
other.getRealizationMethod()) &&
 -                       Objects.equals(getVerticalDatumType(), 
other.getVerticalDatumType());
++                return Objects.equals(getVerticalDatumType(), 
other.getVerticalDatumType());
              }
              default: {
                  /*
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java
index 193f65e9ce,4f7a0b5c3d..d75513bbe5
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java
@@@ -172,13 -172,15 +172,18 @@@ abstract class AuthorityFactoryProxy<T
      abstract T createFromAPI(AuthorityFactory factory, String code) throws 
FactoryException;
  
      /**
-      * The proxy for the {@link 
GeodeticAuthorityFactory#getDescriptionText(String)} method.
+      * The proxy for the {@link 
GeodeticAuthorityFactory#getDescriptionText(Class, String)} method.
+      *
+      * @param  classe  the type of object for which to get a description.
       */
-     static final AuthorityFactoryProxy<InternationalString> DESCRIPTION =
-         new 
AuthorityFactoryProxy<InternationalString>(InternationalString.class, 
AuthorityFactoryIdentifier.ANY) {
+     static final AuthorityFactoryProxy<InternationalString> description(final 
Class<? extends IdentifiedObject> classe) {
+         return new 
AuthorityFactoryProxy<InternationalString>(InternationalString.class, 
AuthorityFactoryIdentifier.ANY) {
 -            @Override InternationalString createFromAPI(AuthorityFactory 
factory, String code) throws FactoryException {
++            @Override InternationalString create(GeodeticAuthorityFactory 
factory, String code) throws FactoryException {
+                 return factory.getDescriptionText(classe, code).orElse(null);
+             }
 +            @Override InternationalString createFromAPI(AuthorityFactory 
factory, String code) throws FactoryException {
 +                return factory.getDescriptionText(code);
 +            }
              @Override AuthorityFactoryProxy<InternationalString> 
specialize(String typeName) {
                  return this;
              }
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
index e934aeecfc,981f93e539..a5d86d0ee3
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
@@@ -156,20 -152,43 +157,60 @@@ public abstract class GeodeticAuthority
       * The description can be used for example in a combo box in a graphical 
user interface.
       *
       * <h4>Default implementation</h4>
-      * The default implementation invokes {@link #createObject(String)} for 
the given code
-      * and returns the {@linkplain AbstractIdentifiedObject#getName() object 
name}.
-      * This may be costly since it involves a full object creation.
+      * The default implementation invokes {@link #createObject(Class, 
String)} for the given class and code,
+      * then returns the {@linkplain 
IdentifiedObjects#getDisplayName(IdentifiedObject) display name} of the object.
+      * This implementation may be costly because it involves a full object 
creation.
       * Subclasses are encouraged to provide a more efficient implementation 
if they can.
       *
+      * @param  type  the type of object for which to get a description.
+      * @param  code  value allocated by authority.
+      * @return a description of the object, or empty if the object exists but 
has no description.
+      * @throws NoSuchAuthorityCodeException if the specified {@code code} was 
not found.
+      * @throws FactoryException if an error occurred while fetching the 
description.
+      *
+      * @since 1.5
+      */
 -    @Override
+     public Optional<InternationalString> getDescriptionText(Class<? extends 
IdentifiedObject> type, String code)
+             throws FactoryException
+     {
+         return 
Optional.ofNullable(IdentifiedObjects.getDisplayName(createObject(type, code)));
+     }
+ 
++    /**
++     * Returns a description of the object corresponding to a code.
++     *
 +     * @param  code  value allocated by authority.
 +     * @return a description of the object, or {@code null} if the object
 +     *         corresponding to the specified {@code code} has no description.
 +     * @throws NoSuchAuthorityCodeException if the specified {@code code} was 
not found.
-      * @throws FactoryException if an error occurred while fetching the 
description.
++     * @throws FactoryException if the query failed for some other reason.
++     *
++     * @deprecated This method is ambiguous because the EPSG geodetic 
registry may allocate
++     *             the same code to different kinds of object.
 +     */
 +    @Override
++    @Deprecated(since = "1.5")
 +    public InternationalString getDescriptionText(final String code) throws 
FactoryException {
-         return new 
SimpleInternationalString(createObject(code).getName().getCode());
++        return getDescriptionText(IdentifiedObject.class, code).orElse(null);
++    }
++
+     /**
+      * Returns an object of the specified type from a code. This 
implementation forwards
+      * the method call to the most specialized methods determined by the 
given type.
+      *
+      * @param  <T>   the compile-time value of the {@code type} argument.
+      * @param  type  the type of object to create.
+      * @param  code  value allocated by authority.
+      * @return the object for the given code.
+      * @throws NoSuchAuthorityCodeException if the specified {@code code} was 
not found.
+      * @throws FactoryException if the object creation failed for some other 
reason.
+      *
+      * @since 1.5
+      */
+     public final <T extends IdentifiedObject> T createObject(final Class<T> 
type, final String code)
+             throws NoSuchAuthorityCodeException, FactoryException
+     {
+         return cast(type, (IdentifiedObject) 
AuthorityFactoryProxy.getInstance(type).create(this, code), code);
      }
  
      /**
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
index bedf50ca0f,2778ac1f24..4e0d34c89f
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
@@@ -140,15 -140,15 +140,15 @@@ import org.apache.sis.xml.XML
   *   </tr><tr>
   *     <td>{@value org.opengis.referencing.ReferenceSystem#SCOPE_KEY}</td>
   *     <td>{@link String} or {@link InternationalString}</td>
 - *     <td>{@link DefaultObjectDomain#getScope()}</td>
 + *     <td>{@link 
org.apache.sis.referencing.DefaultObjectDomain#getScope()}</td>
   *   </tr><tr>
 - *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_DEFINITION_KEY}</td>
 + *     <td>{@value org.opengis.referencing.datum.Datum#ANCHOR_POINT_KEY}</td>
   *     <td>{@link InternationalString} or {@link String}</td>
-  *     <td>{@link AbstractDatum#getAnchorPoint()}</td>
+  *     <td>{@link AbstractDatum#getAnchorDefinition()}</td>
   *   </tr><tr>
-  *     <td>{@value 
org.opengis.referencing.datum.Datum#REALIZATION_EPOCH_KEY}</td>
-  *     <td>{@link Date}</td>
-  *     <td>{@link AbstractDatum#getRealizationEpoch()}</td>
 -     *     <td>{@value 
org.opengis.referencing.datum.Datum#ANCHOR_EPOCH_KEY}</td>
 -     *     <td>{@link java.time.temporal.Temporal}</td>
 -     *     <td>{@link AbstractDatum#getAnchorEpoch()}</td>
++ *     <td>{@value "anchorEpoch"}</td>
++ *     <td>{@link java.time.temporal.Temporal}</td>
++ *     <td>{@link AbstractDatum#getAnchorEpoch()}</td>
   *   </tr><tr>
   *     <td>{@value org.opengis.referencing.IdentifiedObject#REMARKS_KEY}</td>
   *     <td>{@link InternationalString} or {@link String}</td>
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Legacy.java
index 73d7c3de26,a5abfd686b..041fa54fbf
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Legacy.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Legacy.java
@@@ -29,19 -29,6 +29,31 @@@ import org.apache.sis.referencing.cs.De
  import org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis;
  import org.apache.sis.referencing.privy.ReferencingUtilities;
  
 +// Specific to the main branch:
 +import java.util.List;
 +import java.util.Objects;
 +import java.util.Collection;
++import java.util.Date;
++import java.time.Instant;
++import java.time.Year;
++import java.time.YearMonth;
++import java.time.LocalDate;
++import java.time.LocalDateTime;
++import java.time.OffsetDateTime;
++import java.time.ZonedDateTime;
++import java.time.ZoneOffset;
++import java.time.LocalTime;
++import java.time.OffsetTime;
++import java.time.temporal.Temporal;
 +import org.opengis.referencing.ReferenceSystem;
 +import org.opengis.referencing.IdentifiedObject;
 +import org.opengis.util.InternationalString;
 +import org.opengis.metadata.extent.Extent;
 +import org.opengis.referencing.datum.Datum;
 +import org.opengis.referencing.operation.CoordinateOperation;
 +import org.apache.sis.referencing.DefaultObjectDomain;
 +import org.apache.sis.referencing.AbstractIdentifiedObject;
 +
  
  /**
   * Utilities related to version 1 of Well Known Text format, or to ISO 
19111:2007.
@@@ -122,57 -109,4 +134,96 @@@ public final class Legacy 
          }
          return cs;
      }
 +
 +    /**
 +     * Temporary getter method used as a workaround for the lack of this 
method in GeoAPI 3.0 interface.
 +     *
 +     * @param  object  the object from which to get the domain.
 +     * @return domain of the given object.
 +     */
 +    public static Collection<DefaultObjectDomain> getDomains(final 
IdentifiedObject object) {
 +        if (object instanceof AbstractIdentifiedObject) {
 +            return ((AbstractIdentifiedObject) object).getDomains();
 +        }
 +        final Extent domainOfValidity;
 +        final InternationalString scope;
 +        if (object instanceof ReferenceSystem) {
 +            final var c = (ReferenceSystem) object;
 +            scope = c.getScope();
 +            domainOfValidity = c.getDomainOfValidity();
 +        } else if (object instanceof Datum) {
 +            final var c = (Datum) object;
 +            scope = c.getScope();
 +            domainOfValidity = c.getDomainOfValidity();
 +        } else if (object instanceof CoordinateOperation) {
 +            final var c = (CoordinateOperation) object;
 +            scope = c.getScope();
 +            domainOfValidity = c.getDomainOfValidity();
 +        } else {
 +            return null;
 +        }
 +        if (scope == null && domainOfValidity == null) {
 +            return null;
 +        }
 +        return List.of(new DefaultObjectDomain(scope, domainOfValidity));
 +    }
 +
 +    /**
 +     * Returns the first non-null scope found in the given collection.
 +     *
 +     * @param  domains  the value of {@link 
AbstractIdentifiedObject#getDomains()}.
 +     * @return a description of domain of usage, or {@code null} if none.
 +     */
 +    public static InternationalString getScope(final 
Collection<DefaultObjectDomain> domains) {
 +        return 
domains.stream().map(DefaultObjectDomain::getScope).filter(Objects::nonNull).findFirst().orElse(null);
 +    }
 +
 +    /**
 +     * Returns the first non-null domain of validity found in the given 
collection.
 +     *
 +     * @param  domains  the value of {@link 
AbstractIdentifiedObject#getDomains()}.
 +     * @return the valid domain, or {@code null} if not available.
 +     */
 +    public static Extent getDomainOfValidity(final 
Collection<DefaultObjectDomain> domains) {
 +        return 
domains.stream().map(DefaultObjectDomain::getDomainOfValidity).filter(Objects::nonNull).findFirst().orElse(null);
 +    }
++
++    /**
++     * Converts a {@link java.time} object to a legacy {@link Date} object.
++     * If the time zone is not specified, UTC is assumed.
++     *
++     * @param  t  the date to convert.
++     * @return the given temporal object as a date, or {@code null} if the 
method doesn't know how to convert.
++     * @throws ArithmeticException if numeric overflow occurs.
++     */
++    public static Date toDate(final Temporal t) {
++        final Instant instant;
++        if (t instanceof Instant) {
++            instant = (Instant) t;
++        } else {
++            final OffsetDateTime odt;
++            if (t instanceof OffsetDateTime) {
++                odt = (OffsetDateTime) t;
++            } else if (t instanceof ZonedDateTime) {
++                odt = ((ZonedDateTime) t).toOffsetDateTime();
++            } else if (t instanceof LocalDateTime) {
++                odt = ((LocalDateTime) t).atOffset(ZoneOffset.UTC);
++            } else {
++                final LocalDate date;
++                if (t instanceof LocalDate) {
++                    date = (LocalDate) t;
++                } else if (t instanceof YearMonth) {
++                    date = ((YearMonth) t).atDay(1);
++                } else if (t instanceof Year) {
++                    date = ((Year) t).atDay(1);
++                } else {
++                    return null;
++                }
++                odt = date.atTime(OffsetTime.of(LocalTime.MIDNIGHT, 
ZoneOffset.UTC));
++            }
++            instant = odt.toInstant();
++        }
++        // Do not use `Date.from(Instant)` because we want the 
`ArithmeticException` in case of overflow.
++        return new Date(instant.toEpochMilli());
++    }
  }
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
index a67090b38c,3c6683a62b..f7f4ac8ea2
--- 
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
@@@ -41,6 -42,6 +42,7 @@@ import org.opengis.referencing.operatio
  import org.opengis.referencing.operation.OperationMethod;
  import org.opengis.referencing.operation.MathTransform;
  import org.opengis.referencing.operation.PassThroughOperation;
++import org.opengis.referencing.operation.TransformException;
  import org.opengis.parameter.GeneralParameterValue;
  import org.opengis.parameter.ParameterDescriptorGroup;
  import org.opengis.parameter.ParameterValueGroup;
@@@ -73,9 -74,9 +75,14 @@@ import org.apache.sis.system.Semaphores
  import org.apache.sis.system.Loggers;
  import static org.apache.sis.util.Utilities.deepEquals;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.coordinate.CoordinateSet;
 -import org.opengis.referencing.operation.TransformException;
 +// Specific to the main branch:
++import java.time.temporal.Temporal;
++import org.opengis.annotation.UML;
++import static org.opengis.annotation.Obligation.CONDITIONAL;
++import static org.opengis.annotation.Specification.ISO_19111;
 +import org.opengis.metadata.extent.Extent;
 +import org.apache.sis.referencing.internal.Legacy;
++import org.apache.sis.coordinate.AbstractCoordinateSet;
  
  
  /**
@@@ -538,20 -543,13 +548,46 @@@ check:      for (int isTarget=0; ; isTa
       * in order to interpolate in a grid. This method returns the CRS of the 
grid where such interpolations
       * are performed.
       *
-      * @return the CRS (neither source or target CRS) required for 
interpolating the values, or {@code null} if none.
+      * @return the <abbr>CRS</abbr> required for interpolating the values.
       */
-     public CoordinateReferenceSystem getInterpolationCRS() {
-         return interpolationCRS;
 -    @Override
+     public Optional<CoordinateReferenceSystem> getInterpolationCRS() {
+         return Optional.ofNullable(interpolationCRS);
      }
  
 +    /**
 +     * Returns the interpolation CRS of the given coordinate operation, or 
{@code null} if none.
 +     */
 +    static CoordinateReferenceSystem getInterpolationCRS(final 
CoordinateOperation operation) {
 +        return (operation instanceof AbstractCoordinateOperation)
-                ? ((AbstractCoordinateOperation) 
operation).getInterpolationCRS() : null;
++               ? ((AbstractCoordinateOperation) 
operation).getInterpolationCRS().orElse(null) : null;
++    }
++
++    /**
++     * Returns the date at which source coordinate tuples are valid.
++     * This is mandatory if the <abbr>CRS</abbr> is dynamic.
++     *
++     * @return epoch at which source coordinate tuples are valid.
++     *
++     * @since 1.5
++     */
++    @UML(identifier="sourceCoordinateEpoch", obligation=CONDITIONAL, 
specification=ISO_19111)
++    public Optional<Temporal> getSourceEpoch() {
++        return Optional.empty();
++    }
++
++    /**
++     * Returns the date at which target coordinate tuples are valid.
++     * This is mandatory if the <abbr>CRS</abbr> is dynamic.
++     *
++     * @return epoch at which target coordinate tuples are valid.
++     *
++     * @since 1.5
++     */
++    @UML(identifier="targetCoordinateEpoch", obligation=CONDITIONAL, 
specification=ISO_19111)
++    public Optional<Temporal> getTargetEpoch() {
++        return Optional.empty();
 +    }
 +
      /**
       * Returns the version of the coordinate operation. Different versions of 
a coordinate
       * {@linkplain DefaultTransformation transformation} may exist because of 
the stochastic
@@@ -660,6 -632,38 +696,37 @@@
          return transform;
      }
  
+     /**
+      * Changes coordinates from being referenced to the source 
<abbr>CRS</abbr>
+      * and/or epoch to being referenced to the target <abbr>CRS</abbr> and/or 
epoch.
+      * This method operates on coordinate tuples and does not deal with 
interpolation of geometry types.
+      *
+      * <h4>Implementation specific behavior</h4>
+      * The default implementation has the following characteristics. Those 
characteristics are not
+      * guaranteed to be met by all implementations of the {@link 
CoordinateOperation} interface:
+      *
+      * <ul>
+      *   <li>If the <abbr>CRS</abbr> and/or epoch of the given data are not 
equivalent to the source <abbr>CRS</abbr> and/or
+      *       epoch of this coordinate operation, this method will 
automatically prepend an additional operation step.</li>
+      *   <li>The coordinate tuples are not transformed immediately, but 
instead will be computed on-the-fly
 -     *       in the stream returned by {@link CoordinateSet#stream()}.</li>
++     *       in the stream returned by {@link 
AbstractCoordinateSet#stream()}.</li>
+      *   <li>If a {@link TransformException} occurs during on-the-fly 
coordinate operation, it will be wrapped
+      *       in an unchecked {@link 
org.apache.sis.util.collection.BackingStoreException}.</li>
+      *   <li>The returned coordinate set is serializable if the given data 
and the math transform are also serializable.</li>
+      * </ul>
+      *
+      * @param  data  the coordinates to change.
+      * @return the result of changing coordinates.
+      * @throws TransformException if some coordinates cannot be changed. Note 
that an absence of exception during
+      *         this method call is not a guarantee that the coordinate 
changes succeeded, because other errors can
+      *         occur during the stream execution.
+      *
+      * @since 1.5
+      */
 -    @Override
 -    public CoordinateSet transform(final CoordinateSet data) throws 
TransformException {
++    public AbstractCoordinateSet transform(final AbstractCoordinateSet data) 
throws TransformException {
+         return new TransformedCoordinateSet(this, data);
+     }
+ 
      /**
       * Returns the operation method. This apply only to {@link 
AbstractSingleOperation} subclasses,
       * which will make this method public.
@@@ -858,7 -862,7 +925,7 @@@
                  final CoordinateOperation that = (CoordinateOperation) object;
                  if ((mode.isIgnoringMetadata() ||
                      (deepEquals(getCoordinateOperationAccuracy(), 
that.getCoordinateOperationAccuracy(), mode))) &&
-                      deepEquals(getInterpolationCRS(),            
getInterpolationCRS(that), mode))
 -                     deepEquals(getInterpolationCRS(),            
that.getInterpolationCRS(), mode))
++                     deepEquals(getInterpolationCRS().orElse(null), 
getInterpolationCRS(that), mode))
                  {
                      /*
                       * At this point all metadata match or can be ignored. 
First, compare the targetCRS.
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/TransformedCoordinateSet.java
index 0000000000,e998216d16..6cc3fe3575
mode 000000,100644..100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/TransformedCoordinateSet.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/TransformedCoordinateSet.java
@@@ -1,0 -1,151 +1,148 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ package org.apache.sis.referencing.operation;
+ 
+ import java.util.Iterator;
+ import java.util.Spliterator;
+ import java.util.stream.Stream;
+ import java.util.function.Consumer;
+ import java.util.function.UnaryOperator;
+ import org.opengis.util.FactoryException;
+ import org.opengis.geometry.DirectPosition;
+ import org.opengis.geometry.MismatchedDimensionException;
+ import org.opengis.metadata.extent.GeographicBoundingBox;
+ import org.opengis.referencing.operation.MathTransform;
+ import org.opengis.referencing.operation.TransformException;
+ import org.apache.sis.referencing.CRS;
+ import org.apache.sis.referencing.internal.Resources;
+ import org.apache.sis.referencing.operation.transform.MathTransforms;
+ import org.apache.sis.util.collection.BackingStoreException;
+ import org.apache.sis.coordinate.DefaultCoordinateMetadata;
+ import org.apache.sis.coordinate.AbstractCoordinateSet;
+ 
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.coordinate.CoordinateSet;
 -import org.opengis.coordinate.CoordinateMetadata;
 -
+ 
+ /**
+  * The result of transforming coordinate tuples using the math transform of a 
given coordinate operation.
+  *
+  * @author  Martin Desruisseaux (Geomatys)
+  */
+ final class TransformedCoordinateSet extends AbstractCoordinateSet implements 
UnaryOperator<DirectPosition> {
+     /**
+      * Serial number for inter-operability with different versions.
+      */
 -    private static final long serialVersionUID = -6533100977777070895L;
++    private static final long serialVersionUID = -6533100977777070894L;
+ 
+     /**
+      * The data to transform.
+      */
 -    @SuppressWarnings("serial")     // Apache SIS implementations of this 
interface are serializable.
 -    private final CoordinateSet data;
++    private final AbstractCoordinateSet data;
+ 
+     /**
+      * The transform to apply on coordinate tuples.
+      *
+      * @see #iterator()
+      * @see #stream()
+      */
+     @SuppressWarnings("serial")     // Apache SIS implementations of this 
interface are serializable.
+     private final MathTransform transform;
+ 
+     /**
+      * Creates a new transformed coordinate set.
+      *
+      * @param  op    the coordinate operation to apply.
+      * @param  data  the coordinate tuples to transform.
+      * @throws TransformException if the transform cannot be prepared.
+      */
 -    TransformedCoordinateSet(final AbstractCoordinateOperation op, final 
CoordinateSet data) throws TransformException {
++    TransformedCoordinateSet(final AbstractCoordinateOperation op, final 
AbstractCoordinateSet data)
++            throws TransformException
++    {
+         super(new DefaultCoordinateMetadata(op.getTargetCRS(), 
op.getTargetEpoch().orElse(null)));
+         @SuppressWarnings("LocalVariableHidesMemberVariable")
+         MathTransform transform = op.getMathTransform();
+         if (transform == null) {
+             throw new 
TransformException(Resources.format(Resources.Keys.OperationHasNoTransform_2, 
op.getClass(), op.getName()));
+         }
 -        final CoordinateMetadata metadata = data.getCoordinateMetadata();
++        final DefaultCoordinateMetadata metadata = 
data.getCoordinateMetadata();
+         if (metadata != null) try {
+             GeographicBoundingBox aoi = CRS.getGeographicBoundingBox(op);
 -            CoordinateMetadata step = new 
DefaultCoordinateMetadata(op.getSourceCRS(), op.getSourceEpoch().orElse(null));
++            final var step = new DefaultCoordinateMetadata(op.getSourceCRS(), 
op.getSourceEpoch().orElse(null));
+             transform = 
MathTransforms.concatenate(CRS.findOperation(metadata, step, 
aoi).getMathTransform(), transform);
+         } catch (FactoryException | MismatchedDimensionException e) {
+             throw new TransformException(e.getMessage(), e);
+         }
+         this.transform = transform;
+         this.data = data;
+     }
+ 
+     /**
+      * Returns the number of dimension of output coordinate tuples.
+      * This method is overridden in case that {@link #crs} is null.
+      */
+     @Override
+     public int getDimension() {
+         return transform.getTargetDimensions();
+     }
+ 
+     /**
+      * Returns the transformed positions described by coordinate tuples.
+      */
+     @Override
+     public Iterator<DirectPosition> iterator() {
+         return stream().iterator();
+     }
+ 
+     /**
+      * Returns the transformed positions described by coordinate tuples.
+      */
+     @Override
+     public Spliterator<DirectPosition> spliterator() {
+         return stream().spliterator();
+     }
+ 
+     /**
+      * Returns a stream of transformed coordinate tuples.
+      */
+     @Override
+     public Stream<DirectPosition> stream() {
+         return data.stream().map(this);
+     }
+ 
+     /**
+      * Performs an action for each coordinate tuple of this stream.
+      *
+      * @param action the action to perform.
+      */
+     @Override
+     public void forEach(Consumer<? super DirectPosition> action) {
+         stream().forEach(action);
+     }
+ 
+     /**
+      * Transforms the given coordinate tuples.
+      *
+      * @param  source  coordinates in source CRS.
+      * @return coordinates in target CRS.
+      */
+     @Override
+     public DirectPosition apply(final DirectPosition source) {
+         try {
+             return transform.transform(source, null);
+         } catch (TransformException e) {
+             throw new BackingStoreException(e);
+         }
+     }
+ }
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTKeywords.java
index 8ea10291ce,f2d6f8561a..1c5611ce3e
--- 
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
@@@ -272,6 -274,7 +274,7 @@@ public final class WKTKeywords extends 
          addType(org.opengis.referencing.cs.CoordinateSystemAxis.class,      
Axis);
          addType(org.apache.sis.referencing.datum.BursaWolfParameters.class, 
ToWGS84);
          addType(org.opengis.referencing.operation.MathTransform.class,      
Param_MT, Concat_MT, Inverse_MT, PassThrough_MT);
 -        addType(org.opengis.coordinate.CoordinateMetadata.class,            
CoordinateMetadata);
++        addType(org.apache.sis.coordinate.DefaultCoordinateMetadata.class,  
CoordinateMetadata);
          addType(org.opengis.geometry.DirectPosition.class,                  
Point);
      }
  
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
index 07e14245c1,362722ed93..c5670c8171
--- 
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
@@@ -223,7 -223,7 +223,7 @@@ public final class GeodeticObjectParser
                  "  ANCHOR[“Tananarive observatory”]]");
  
          assertNameAndIdentifierEqual("Tananarive 1925", 0, datum);
-         assertEquals("Tananarive observatory", 
String.valueOf(datum.getAnchorPoint()));
 -        assertEquals("Tananarive observatory", 
datum.getAnchorDefinition().get().toString());
++        assertEquals("Tananarive observatory", 
datum.getAnchorPoint().toString());
  
          final Ellipsoid ellipsoid = datum.getEllipsoid();
          assertNameAndIdentifierEqual("International 1924", 0, ellipsoid);
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/DefaultCylindricalCSTest.java
index 8145de416a,0b44ba6140..ec240fd61c
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/DefaultCylindricalCSTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/DefaultCylindricalCSTest.java
@@@ -27,8 -26,8 +26,9 @@@ import org.junit.jupiter.api.Test
  import static org.junit.jupiter.api.Assertions.*;
  import org.apache.sis.test.TestCase;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import static org.opengis.test.Assertions.assertAxisDirectionsEqual;
 +// Specific to the main branch:
++import org.apache.sis.referencing.privy.AxisDirections;
 +import static org.apache.sis.test.GeoapiAssert.assertAxisDirectionsEqual;
  
  
  /**
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/DefaultPolarCSTest.java
index 1660f1da19,bb21729e08..17c96d7cb5
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/DefaultPolarCSTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/DefaultPolarCSTest.java
@@@ -27,8 -26,8 +26,9 @@@ import org.junit.jupiter.api.Test
  import static org.junit.jupiter.api.Assertions.*;
  import org.apache.sis.test.TestCase;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import static org.opengis.test.Assertions.assertAxisDirectionsEqual;
 +// Specific to the main branch:
++import org.apache.sis.referencing.privy.AxisDirections;
 +import static org.apache.sis.test.GeoapiAssert.assertAxisDirectionsEqual;
  
  
  /**
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/DefaultSphericalCSTest.java
index e335ca979b,4aadf4bb69..0022abe341
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/DefaultSphericalCSTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/DefaultSphericalCSTest.java
@@@ -25,8 -24,8 +24,9 @@@ import org.junit.jupiter.api.Test
  import static org.junit.jupiter.api.Assertions.*;
  import org.apache.sis.test.TestCase;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import static org.opengis.test.Assertions.assertAxisDirectionsEqual;
 +// Specific to the main branch:
++import org.apache.sis.referencing.privy.AxisDirections;
 +import static org.apache.sis.test.GeoapiAssert.assertAxisDirectionsEqual;
  
  
  /**
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/HardCodedAxes.java
index d226b26205,fe5edb9942..48ac69bb32
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/HardCodedAxes.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/HardCodedAxes.java
@@@ -21,9 -21,8 +21,11 @@@ import javax.measure.Unit
  import org.opengis.referencing.cs.AxisDirection;
  import org.opengis.referencing.cs.RangeMeaning;
  import org.apache.sis.metadata.privy.AxisNames;
- import org.apache.sis.referencing.privy.AxisDirections;
  import org.apache.sis.measure.Units;
  
++// Specific to the main branch:
++import org.apache.sis.referencing.privy.AxisDirections;
++
  
  /**
   * Collection of axes for testing purpose.
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java
index 5bd1bd577b,581667a272..dc96f66d81
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java
@@@ -45,7 -42,7 +45,6 @@@ public final class ProvidersTest extend
      /**
       * Returns all providers to test.
       */
-     @SuppressWarnings("removal")
 -    @SuppressWarnings("deprecation")
      private static Class<?>[] methods() {
          return new Class<?>[] {
              Affine.class,
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/privy/AxisDirectionsTest.java
index d2afcbfc18,4a347861f2..8dd70537dc
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/privy/AxisDirectionsTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/privy/AxisDirectionsTest.java
@@@ -24,10 -24,7 +24,12 @@@ import org.opengis.referencing.cs.Coord
  import org.opengis.referencing.cs.CoordinateSystemAxis;
  import static org.opengis.referencing.cs.AxisDirection.*;
  import org.apache.sis.measure.Units;
+ 
++// Specific to the main branch:
 +import static org.apache.sis.referencing.privy.AxisDirections.AWAY_FROM;
 +import static org.apache.sis.referencing.privy.AxisDirections.CLOCKWISE;
 +import static 
org.apache.sis.referencing.privy.AxisDirections.COUNTER_CLOCKWISE;
 +
  // Test dependencies
  import org.junit.jupiter.api.Test;
  import static org.junit.jupiter.api.Assertions.*;
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataTest.java
index cf83fc00a0,34b91b8cb5..b66a6e2c76
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataTest.java
@@@ -71,9 -73,6 +70,10 @@@ import org.apache.sis.test.TestUtilitie
  import org.apache.sis.xml.test.DocumentComparator;
  import org.apache.sis.xml.test.TestCase;
  
 +// Specific to the main branch:
++import org.opengis.referencing.datum.VerticalDatumType;
 +import org.apache.sis.pending.geoapi.evolution.UnsupportedCodeList;
 +
  
  /**
   * Tests XML (un)marshalling of a metadata object containing various elements
@@@ -125,19 -112,19 +125,18 @@@ public final class MetadataTest extend
           * with only the role changed. Note that we need to create an 
instance of the deprecated class,
           * because this is what will be unmarshalled from the XML document.
           */
--        @SuppressWarnings("deprecation")
-         final DefaultResponsibleParty author = new 
DefaultResponsibleParty(Role.AUTHOR);
-         final Anchor country = new Anchor(URI.create("SDN:C320:2:FR"), 
"France"); // Non-public SIS class.
 -        final var author = new DefaultResponsibleParty(Role.AUTHOR);
++        final var author  = new DefaultResponsibleParty(Role.AUTHOR);
+         final var country = new Anchor(URI.create("SDN:C320:2:FR"), 
"France"); // Non-public SIS class.
          {
-             final DefaultOnlineResource online = new 
DefaultOnlineResource(URI.create("http://www.ifremer.fr/sismer/";));
+             final var online = new 
DefaultOnlineResource(URI.create("http://www.ifremer.fr/sismer/";));
              online.setProtocol(Constants.HTTP);
-             final DefaultContact contact = new DefaultContact(online);
+             final var contact = new DefaultContact(online);
              contact.getIdentifierMap().putSpecialized(IdentifierSpace.ID, 
"IFREMER");
              contact.setPhones(List.of(
 -                    new DefaultTelephone("+33 (0)2 xx.xx.xx.x6", 
TelephoneType.VOICE),
 -                    new DefaultTelephone("+33 (0)2 xx.xx.xx.x4", 
TelephoneType.FACSIMILE)
 +                    telephone("+33 (0)2 xx.xx.xx.x6", "VOICE"),
 +                    telephone("+33 (0)2 xx.xx.xx.x4", "FACSIMILE")
              ));
-             final DefaultAddress address = new DefaultAddress();
+             final var address = new DefaultAddress();
              address.setDeliveryPoints(Set.of("Brest institute"));
              address.setCity(new SimpleInternationalString("Plouzane"));
              address.setPostalCode("29280");
@@@ -157,16 -144,16 +156,15 @@@
                      new DefaultCitationDate(TestUtilities.date("1990-06-04 
22:00:00"), DateType.REVISION),
                      new DefaultCitationDate(TestUtilities.date("1979-08-02 
22:00:00"), DateType.CREATION)));
              {
--                @SuppressWarnings("deprecation")
-                 final DefaultResponsibleParty originator = new 
DefaultResponsibleParty(Role.ORIGINATOR);
-                 final DefaultOnlineResource online = new 
DefaultOnlineResource(URI.create("http://www.com.univ-mrs.fr/LOB/";));
+                 final var originator = new 
DefaultResponsibleParty(Role.ORIGINATOR);
+                 final var online = new 
DefaultOnlineResource(URI.create("http://www.com.univ-mrs.fr/LOB/";));
                  online.setProtocol(Constants.HTTP);
-                 final DefaultContact contact = new DefaultContact(online);
+                 final var contact = new DefaultContact(online);
                  contact.setPhones(List.of(
 -                        new DefaultTelephone("+33 (0)4 xx.xx.xx.x5", 
TelephoneType.VOICE),
 -                        new DefaultTelephone("+33 (0)4 xx.xx.xx.x8", 
TelephoneType.FACSIMILE)
 +                        telephone("+33 (0)4 xx.xx.xx.x5", "VOICE"),
 +                        telephone("+33 (0)4 xx.xx.xx.x8", "FACSIMILE")
                  ));
-                 final DefaultAddress address = new DefaultAddress();
+                 final var address = new DefaultAddress();
                  address.setDeliveryPoints(Set.of("Oceanology institute"));
                  address.setCity(new SimpleInternationalString("Marseille"));
                  address.setPostalCode("13288");
@@@ -181,8 -168,8 +179,7 @@@
                      Locale.ENGLISH,                                           
  // Language,
                      TopicCategory.OCEANS);                                    
  // Topic category
              {
--                @SuppressWarnings("deprecation")
-                 final DefaultResponsibleParty custodian = new 
DefaultResponsibleParty((DefaultResponsibility) author);
+                 final var custodian = new 
DefaultResponsibleParty((DefaultResponsibility) author);
                  custodian.setRole(Role.CUSTODIAN);
                  identification.setPointOfContacts(Set.of(custodian));
              }
@@@ -213,17 -200,17 +210,16 @@@
               * Data indentification / Resource constraint.
               */
              {
-                 final DefaultLegalConstraints constraint = new 
DefaultLegalConstraints();
+                 final var constraint = new DefaultLegalConstraints();
 -                constraint.setAccessConstraints(Set.of(Restriction.LICENCE));
 +                constraint.setAccessConstraints(Set.of(Restriction.LICENSE));
                  identification.setResourceConstraints(Set.of(constraint));
              }
              /*
               * Data indentification / Aggregate information.
               */
              {
--                @SuppressWarnings("deprecation")
-                 final DefaultAggregateInformation aggregateInfo = new 
DefaultAggregateInformation();
-                 final DefaultCitation name = new DefaultCitation("Some 
oceanographic campaign");
+                 final var aggregateInfo = new DefaultAggregateInformation();
+                 final var name = new DefaultCitation("Some oceanographic 
campaign");
                  name.setAlternateTitles(Set.of(new 
SimpleInternationalString("Pseudo group of data")));
                  name.setDates(Set.of(new 
DefaultCitationDate(TestUtilities.date("1990-06-04 22:00:00"), 
DateType.REVISION)));
                  aggregateInfo.setName(name);
@@@ -235,19 -222,19 +231,19 @@@
               * Data indentification / Extent.
               */
              {
-                 final DefaultCoordinateSystemAxis axis = new 
DefaultCoordinateSystemAxis(
+                 final var axis = new DefaultCoordinateSystemAxis(
                          nameAndIdentifier("depth", "Depth", null), "D", 
AxisDirection.DOWN, Units.METRE);
  
-                 final DefaultVerticalCS cs = new DefaultVerticalCS(
+                 final var cs = new DefaultVerticalCS(
                          nameAndIdentifier("depth", "Depth", null), axis);
  
-                 final DefaultVerticalDatum datum = new DefaultVerticalDatum(
+                 final var datum = new DefaultVerticalDatum(
 -                        nameAndIdentifier("D28", "Depth below D28", "For 
testing purpose"), (RealizationMethod) null);
 +                        nameAndIdentifier("D28", "Depth below D28", "For 
testing purpose"), VerticalDatumType.OTHER_SURFACE);
  
-                 final DefaultVerticalCRS vcrs = new DefaultVerticalCRS(
+                 final var vcrs = new DefaultVerticalCRS(
                          nameAndIdentifier("D28", "Depth below D28", "CRS for 
testing purpose"), datum, cs);
  
-                 final DefaultTemporalExtent temporal = new 
DefaultTemporalExtent();
+                 final var temporal = new DefaultTemporalExtent();
                  temporal.setBounds(TestUtilities.date("1990-06-05 00:00:00"), 
TestUtilities.date("1990-07-02 00:00:00"));
                  identification.setExtents(Set.of(new DefaultExtent(
                          null,
@@@ -311,9 -298,9 +307,8 @@@
           * Distribution information.
           */
          {
--            @SuppressWarnings("deprecation")
-             final DefaultResponsibleParty distributor = new 
DefaultResponsibleParty((DefaultResponsibility) author);
-             final DefaultDistribution distributionInfo = new 
DefaultDistribution();
+             final var distributor = new 
DefaultResponsibleParty((DefaultResponsibility) author);
+             final var distributionInfo = new DefaultDistribution();
              distributor.setRole(Role.DISTRIBUTOR);
              distributionInfo.setDistributors(Set.of(new 
DefaultDistributor(distributor)));
  
diff --cc 
optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/AuthorityCodes.java
index bdbd05dce4,92e0c60078..b9e523c9fd
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/AuthorityCodes.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/AuthorityCodes.java
@@@ -392,7 -392,8 +392,8 @@@ final class AuthorityCodes extends Obse
              for (final Code code : snapshot) {
                  String text;
                  try {
-                     text = 
Strings.trimOrNull(Types.toString(factory.getDescriptionText(code.code), 
locale));
 -                    var i18n = 
factory.getDescriptionText(CoordinateReferenceSystem.class, 
code.code).orElse(null);
++                    var i18n = factory.getDescriptionText(code.code);
+                     text = Strings.trimOrNull(Types.toString(i18n, locale));
                      if (text == null) {
                          text = 
Vocabulary.forLocale(locale).getString(Vocabulary.Keys.Unnamed);
                      }

Reply via email to