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

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


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 938f77504b Avoid usage of `getScope()` and `getDomainOfValidity()` 
methods, which are deprecated in GeoAPI 3.1 and removed in GeoAPI 4.0. They are 
replaced by `ObjectDomain`.
938f77504b is described below

commit 938f77504b154880819dd631a97e481e61ce0313
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Mon Apr 8 16:46:38 2024 +0200

    Avoid usage of `getScope()` and `getDomainOfValidity()` methods,
    which are deprecated in GeoAPI 3.1 and removed in GeoAPI 4.0.
    They are replaced by `ObjectDomain`.
---
 .../apache/sis/coverage/grid/GridExtentCRS.java    |  9 ++--
 .../sis/metadata/iso/extent/DefaultExtent.java     |  3 +-
 .../apache/sis/metadata/iso/extent/Extents.java    |  4 ++
 .../metadata/simple/SimpleIdentifiedObject.java    | 34 +------------
 .../org/apache/sis/test/mock/VerticalCRSMock.java  |  4 --
 .../referencing/gazetteer/FinalLocationType.java   |  9 ++--
 .../gazetteer/ModifiableLocationType.java          |  2 +-
 .../gazetteer/ReferencingByIdentifiers.java        | 38 ++++++--------
 .../gazetteer/ReferencingByIdentifiersTest.java    |  5 +-
 .../main/org/apache/sis/io/wkt/ElementKind.java    | 50 ++++++++++++-------
 .../apache/sis/io/wkt/GeodeticObjectParser.java    |  8 +--
 .../sis/referencing/AbstractIdentifiedObject.java  | 13 +++--
 .../main/org/apache/sis/referencing/Builder.java   |  4 +-
 .../main/org/apache/sis/referencing/CRS.java       | 26 ++++------
 .../apache/sis/referencing/IdentifiedObjects.java  | 54 +++++++++++++++++++-
 .../org/apache/sis/referencing/Properties.java     | 29 +++++------
 .../sis/referencing/StandardDefinitions.java       |  2 +-
 .../apache/sis/referencing/crs/AbstractCRS.java    |  5 +-
 .../sis/referencing/crs/DefaultDerivedCRS.java     |  4 +-
 .../sis/referencing/datum/AbstractDatum.java       | 58 ++++++++++------------
 .../sis/referencing/datum/BursaWolfParameters.java |  5 +-
 .../referencing/factory/GeodeticObjectFactory.java |  4 +-
 .../referencing/factory/sql/EPSGDataAccess.java    |  7 +--
 .../apache/sis/referencing/internal/Legacy.java    | 53 ++++++++++++++++++++
 .../operation/AbstractCoordinateOperation.java     |  5 +-
 .../operation/AbstractSingleOperation.java         |  3 +-
 .../operation/CoordinateOperationFinder.java       |  3 +-
 .../operation/CoordinateOperationSorter.java       |  3 +-
 .../operation/DefaultConcatenatedOperation.java    |  3 +-
 .../referencing/operation/DefaultConversion.java   |  4 +-
 .../DefaultCoordinateOperationFactory.java         | 18 ++++---
 .../operation/DefaultPassThroughOperation.java     |  3 +-
 .../operation/DefaultTransformation.java           |  4 +-
 .../operation/InverseOperationMethod.java          |  5 +-
 .../operation/transform/AbstractMathTransform.java |  2 +-
 .../operation/transform/DomainDefinition.java      |  2 +-
 .../operation/transform/MathTransforms.java        |  2 +-
 .../privy/EllipsoidalHeightCombiner.java           | 11 ++--
 .../referencing/privy/GeodeticObjectBuilder.java   |  5 +-
 .../referencing/privy/NilReferencingObject.java    | 13 +++--
 .../referencing/AbstractReferenceSystemTest.java   | 15 ++++--
 .../test/org/apache/sis/referencing/CRSTest.java   |  5 +-
 .../sis/referencing/GeodeticObjectVerifier.java    | 39 ++++++++++-----
 .../referencing/crs/DefaultGeodeticCRSTest.java    |  3 +-
 .../referencing/crs/DefaultProjectedCRSTest.java   |  3 +-
 .../apache/sis/referencing/crs/HardCodedCRS.java   |  4 +-
 .../datum/DefaultGeodeticDatumTest.java            | 12 +++--
 .../datum/DefaultTemporalDatumTest.java            | 16 +++---
 .../datum/DefaultVerticalDatumTest.java            |  5 +-
 .../sis/referencing/datum/HardCodedDatum.java      | 22 ++++++--
 .../operation/SingleOperationMarshallingTest.java  | 12 +++--
 .../apache/sis/test/integration/MetadataTest.java  |  3 +-
 .../sis/test/integration/MetadataVerticalTest.java |  5 +-
 .../apache/sis/storage/base/MetadataBuilder.java   |  5 +-
 .../main/org/apache/sis/util/ComparisonMode.java   |  4 +-
 .../org/apache/sis/util/LenientComparable.java     |  3 +-
 .../test/org/apache/sis/test/TestUtilities.java    | 32 ++++++++++++
 .../test/org/apache/sis/util/ClassesTest.java      |  9 +---
 geoapi/snapshot                                    |  2 +-
 .../org/apache/sis/gui/referencing/CRSChooser.java | 24 +++++----
 .../gui/referencing/RecentReferenceSystems.java    |  2 +-
 .../main/org/apache/sis/gui/referencing/Utils.java | 24 ++++++---
 62 files changed, 467 insertions(+), 298 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtentCRS.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtentCRS.java
index e11b6372c8..cacfa9b7fa 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtentCRS.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtentCRS.java
@@ -62,6 +62,9 @@ import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.iso.Types;
 import org.apache.sis.measure.Units;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.referencing.ObjectDomain;
+
 
 /**
  * Builder for coordinate reference system which is derived from the coverage 
CRS by the inverse
@@ -178,12 +181,12 @@ final class GridExtentCRS {
         /*
          * Put everything together: parameters, conversion and finally the 
derived CRS.
          */
-        final HashMap<String,Object> properties = new HashMap<>(8);
+        final var properties = new HashMap<String,Object>(8);
         properties.put(IdentifiedObject.NAME_KEY, METHOD.getName());
         properties.put(DefaultConversion.LOCALE_KEY, locale);
-        properties.put(Conversion.SCOPE_KEY, SCOPE);
+        properties.put(ObjectDomain.SCOPE_KEY, SCOPE);
         gg.getGeographicExtent().ifPresent((domain) -> {
-            properties.put(Conversion.DOMAIN_OF_VALIDITY_KEY,
+            properties.put(ObjectDomain.DOMAIN_OF_VALIDITY_KEY,
                     new DefaultExtent(null, domain, null, null));
         });
         final ParameterValueGroup params = 
METHOD.getParameters().createValue();
diff --git 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultExtent.java
 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultExtent.java
index 20ca62320c..fa0dfbb2d8 100644
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultExtent.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultExtent.java
@@ -85,8 +85,7 @@ import org.apache.sis.xml.NilReason;
  * @version 1.4
  *
  * @see Extents#getGeographicBoundingBox(Extent)
- * @see 
org.apache.sis.referencing.AbstractReferenceSystem#getDomainOfValidity()
- * @see org.apache.sis.referencing.datum.AbstractDatum#getDomainOfValidity()
+ * @see org.apache.sis.referencing.DefaultObjectDomain#getDomainOfValidity()
  *
  * @since 0.3
  */
diff --git 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/Extents.java
 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/Extents.java
index 18e7e5e0f2..6bc11b1919 100644
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/Extents.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/Extents.java
@@ -61,6 +61,7 @@ import org.apache.sis.measure.Range;
 import org.apache.sis.util.OptionalCandidate;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.util.Emptiable;
 import org.apache.sis.util.Static;
 import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.resources.Vocabulary;
@@ -763,6 +764,9 @@ public final class Extents extends Static {
      * <p>This method never modify the given extents, but may return directly 
one of the given
      * arguments if it already represents the intersection result.</p>
      *
+     * <p>If there is no intersection, then the returned object implements 
{@link Emptiable}
+     * and the {@link Emptiable#isEmpty()} method returns {@code true}.</p>
+     *
      * @param  e1  the first extent, or {@code null}.
      * @param  e2  the second extent, or {@code null}.
      * @return the intersection (may be any of the {@code e1} or {@code e2} 
argument if unchanged),
diff --git 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleIdentifiedObject.java
 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleIdentifiedObject.java
index 5e1cad326c..09e22bcf63 100644
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleIdentifiedObject.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleIdentifiedObject.java
@@ -21,7 +21,6 @@ import java.io.Serializable;
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
-import org.opengis.metadata.extent.Extent;
 import org.opengis.referencing.IdentifiedObject;
 import org.apache.sis.metadata.privy.Identifiers;
 import org.apache.sis.util.LenientComparable;
@@ -85,38 +84,6 @@ public class SimpleIdentifiedObject implements 
IdentifiedObject, LenientComparab
         return name;
     }
 
-    /**
-     * Method required by most {@link IdentifiedObject} sub-interfaces.
-     * Current implementation returns {@code null}.
-     *
-     * <p>If a future version allows this method to return a non-null value,
-     * revisit {@link #equals(Object, ComparisonMode)} in subclasses.</p>
-     *
-     * @return the domain of validity, or {@code null} if none.
-     *
-     * @deprecated Removed from ISO 19111:2019 (moved to {@code ObjectDomain}).
-     */
-    @Deprecated
-    public final Extent getDomainOfValidity() {
-        return null;
-    }
-
-    /**
-     * Method required by most {@link IdentifiedObject} sub-interfaces.
-     * Current implementation returns {@code null}.
-     *
-     * <p>If a future version allows this method to return a non-null value,
-     * revisit {@link #equals(Object, ComparisonMode)} in subclasses.</p>
-     *
-     * @return the scope, or {@code null} if none.
-     *
-     * @deprecated Removed from ISO 19111:2019 (moved to {@code ObjectDomain}).
-     */
-    @Deprecated
-    public final InternationalString getScope() {
-        return null;
-    }
-
     /**
      * Returns a narrative explanation of the role of this object.
      * The default implementation returns {@link Identifier#getDescription()}.
@@ -124,6 +91,7 @@ public class SimpleIdentifiedObject implements 
IdentifiedObject, LenientComparab
      * @return a narrative explanation of the role of this object, or {@code 
null} if none.
      */
     public InternationalString getDescription() {
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         final Identifier name = this.name;
         return (name != null) ? name.getDescription() : null;
     }
diff --git 
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
index e3e3e59eea..93a0221081 100644
--- 
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
@@ -17,7 +17,6 @@
 package org.apache.sis.test.mock;
 
 import javax.measure.Unit;
-import org.opengis.metadata.extent.Extent;
 import org.opengis.referencing.crs.VerticalCRS;
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.cs.CoordinateSystemAxis;
@@ -25,7 +24,6 @@ import org.opengis.referencing.cs.RangeMeaning;
 import org.opengis.referencing.cs.VerticalCS;
 import org.opengis.referencing.datum.VerticalDatum;
 import org.opengis.referencing.datum.VerticalDatumType;
-import org.opengis.util.InternationalString;
 import org.apache.sis.measure.Units;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
@@ -133,8 +131,6 @@ public final class VerticalCRSMock extends 
IdentifiedObjectMock
     }
 
     @Override public String                      getAbbreviation()      
{return up ? "h" : "d";}
-    @Override public InternationalString         getScope()             
{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;}
diff --git 
a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/FinalLocationType.java
 
b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/FinalLocationType.java
index e1e64ecce2..887b045b1f 100644
--- 
a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/FinalLocationType.java
+++ 
b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/FinalLocationType.java
@@ -31,6 +31,7 @@ import org.apache.sis.metadata.MetadataCopier;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.metadata.citation.Party;
+import org.opengis.referencing.ObjectDomain;
 import org.opengis.referencing.gazetteer.LocationType;
 import org.opengis.referencing.gazetteer.ReferenceSystemUsingIdentifiers;
 
@@ -150,9 +151,11 @@ final class FinalLocationType extends AbstractLocationType 
implements Serializab
             if (theme == null) theme = rs.getTheme();
             if (owner == null) owner = rs.getOverallOwner();
             if (territoryOfUse == null) {
-                final Extent domainOfValidity = rs.getDomainOfValidity();
-                if (domainOfValidity instanceof GeographicExtent) {
-                    territoryOfUse = (GeographicExtent) domainOfValidity;
+                for (ObjectDomain domain : rs.getDomains()) {
+                    Extent domainOfValidity = domain.getDomainOfValidity();
+                    if (domainOfValidity instanceof GeographicExtent) {
+                        territoryOfUse = (GeographicExtent) domainOfValidity;
+                    }
                 }
             }
         }
diff --git 
a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ModifiableLocationType.java
 
b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ModifiableLocationType.java
index 961319d140..5b6e5bdf66 100644
--- 
a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ModifiableLocationType.java
+++ 
b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ModifiableLocationType.java
@@ -315,7 +315,7 @@ public class ModifiableLocationType extends 
AbstractLocationType {      // Not S
      * @return geographic area within which the location type occurs,
      *         or {@code null} if no value has been defined or can be 
inherited.
      *
-     * @see ReferencingByIdentifiers#getDomainOfValidity()
+     * @see ReferencingByIdentifiers#getDomains()
      */
     @Override
     public GeographicExtent getTerritoryOfUse() {
diff --git 
a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java
 
b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java
index c7dd878f07..0d526a2fd7 100644
--- 
a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java
+++ 
b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java
@@ -47,6 +47,7 @@ import org.apache.sis.util.resources.Vocabulary;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.metadata.citation.Party;
+import org.opengis.referencing.ObjectDomain;
 import org.opengis.referencing.gazetteer.Location;
 import org.opengis.referencing.gazetteer.LocationType;
 import org.opengis.referencing.gazetteer.ReferenceSystemUsingIdentifiers;
@@ -119,49 +120,40 @@ public abstract class ReferencingByIdentifiers extends 
AbstractReferenceSystem i
      *     <th>Property name</th>
      *     <th>Value type</th>
      *     <th>Returned by</th>
-     *   </tr>
-     *   <tr>
+     *   </tr><tr>
      *     <td>{@value 
org.opengis.referencing.gazetteer.ReferenceSystemUsingIdentifiers#THEME_KEY}</td>
      *     <td>{@link String} or {@link InternationalString}</td>
      *     <td>{@link #getTheme()}</td>
-     *   </tr>
-     *   <tr>
+     *   </tr><tr>
      *     <td>{@value 
org.opengis.referencing.gazetteer.ReferenceSystemUsingIdentifiers#OVERALL_OWNER_KEY}</td>
      *     <td>{@link Party}</td>
      *     <td>{@link #getOverallOwner()}</td>
-     *   </tr>
-     *   <tr>
+     *   </tr><tr>
      *     <th colspan="3" class="hsep">Defined in parent class (reminder)</th>
-     *   </tr>
-     *   <tr>
+     *   </tr><tr>
      *     <td>{@value org.opengis.referencing.IdentifiedObject#NAME_KEY}</td>
      *     <td>{@link org.opengis.metadata.Identifier} or {@link String}</td>
      *     <td>{@link #getName()}</td>
-     *   </tr>
-     *   <tr>
+     *   </tr><tr>
      *     <td>{@value org.opengis.referencing.IdentifiedObject#ALIAS_KEY}</td>
      *     <td>{@link org.opengis.util.GenericName} or {@link CharSequence} 
(optionally as array)</td>
      *     <td>{@link #getAlias()}</td>
-     *   </tr>
-     *   <tr>
+     *   </tr><tr>
      *     <td>{@value 
org.opengis.referencing.IdentifiedObject#IDENTIFIERS_KEY}</td>
      *     <td>{@link org.opengis.metadata.Identifier} (optionally as 
array)</td>
      *     <td>{@link #getIdentifiers()}</td>
-     *   </tr>
-     *   <tr>
+     *   </tr><tr>
      *     <td>{@value 
org.opengis.referencing.IdentifiedObject#REMARKS_KEY}</td>
      *     <td>{@link org.opengis.util.InternationalString} or {@link 
String}</td>
      *     <td>{@link #getRemarks()}</td>
-     *   </tr>
-     *   <tr>
-     *     <td>{@value 
org.opengis.referencing.ReferenceSystem#DOMAIN_OF_VALIDITY_KEY}</td>
+     *   </tr><tr>
+     *     <td>{@value 
org.opengis.referencing.ObjectDomain#DOMAIN_OF_VALIDITY_KEY}</td>
      *     <td>{@link org.opengis.metadata.extent.Extent}</td>
-     *     <td>{@link #getDomainOfValidity()}</td>
-     *   </tr>
-     *   <tr>
-     *     <td>{@value org.opengis.referencing.ReferenceSystem#SCOPE_KEY}</td>
+     *     <td>{@link 
org.apache.sis.referencing.DefaultObjectDomain#getDomainOfValidity()}</td>
+     *   </tr><tr>
+     *     <td>{@value org.opengis.referencing.ObjectDomain#SCOPE_KEY}</td>
      *     <td>{@link org.opengis.util.InternationalString} or {@link 
String}</td>
-     *     <td>{@link #getScope()}</td>
+     *     <td>{@link 
org.apache.sis.referencing.DefaultObjectDomain#getScope()}</td>
      *   </tr>
      * </table>
      *
@@ -197,7 +189,7 @@ public abstract class ReferencingByIdentifiers extends 
AbstractReferenceSystem i
         final Map<String,Object> properties = new HashMap<>(8);
         properties.put(NAME_KEY, name);
         properties.put(IDENTIFIERS_KEY, new ImmutableIdentifier(Citations.SIS, 
Constants.SIS, id));
-        properties.put(DOMAIN_OF_VALIDITY_KEY, Extents.WORLD);
+        properties.put(ObjectDomain.DOMAIN_OF_VALIDITY_KEY, Extents.WORLD);
         properties.put(THEME_KEY, 
Vocabulary.formatInternational(Vocabulary.Keys.Mapping));
         properties.put(OVERALL_OWNER_KEY, party);
         return properties;
diff --git 
a/endorsed/src/org.apache.sis.referencing.gazetteer/test/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiersTest.java
 
b/endorsed/src/org.apache.sis.referencing.gazetteer/test/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiersTest.java
index 4bbacde137..04e97af060 100644
--- 
a/endorsed/src/org.apache.sis.referencing.gazetteer/test/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiersTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing.gazetteer/test/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiersTest.java
@@ -21,6 +21,9 @@ import java.util.HashMap;
 import org.apache.sis.metadata.iso.citation.DefaultOrganisation;
 import org.apache.sis.metadata.iso.extent.DefaultExtent;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.referencing.ObjectDomain;
+
 // Test dependencies
 import org.junit.jupiter.api.Test;
 import static org.junit.jupiter.api.Assertions.*;
@@ -49,9 +52,9 @@ public final class ReferencingByIdentifiersTest extends 
TestCase {
     private static ReferencingByIdentifiers create(final boolean inherit) {
         final Map<String,Object> properties = new HashMap<>();
         assertNull(properties.put(ReferencingByIdentifiers.NAME_KEY, "UK 
property addressing"));
-        
assertNull(properties.put(ReferencingByIdentifiers.DOMAIN_OF_VALIDITY_KEY, new 
DefaultExtent("UK", null, null, null)));
         assertNull(properties.put(ReferencingByIdentifiers.THEME_KEY, 
"property"));
         assertNull(properties.put(ReferencingByIdentifiers.OVERALL_OWNER_KEY, 
new DefaultOrganisation("Office for National Statistics", null, null, null)));
+        assertNull(properties.put(ObjectDomain.DOMAIN_OF_VALIDITY_KEY, new 
DefaultExtent("UK", null, null, null)));
         return new ReferencingByIdentifiers(properties, 
LocationTypeTest.create(inherit)) {
             @Override public ReferencingByIdentifiers.Coder createCoder() {
                 throw new UnsupportedOperationException();
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/ElementKind.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/ElementKind.java
index facaa0c2c6..1e00e8b74a 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/ElementKind.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/ElementKind.java
@@ -58,65 +58,77 @@ public enum ElementKind {
     INTEGER,
 
     /**
-     * {@linkplain javax.measure.Unit Units of measurement},
-     * often represented by {@code UNIT[…]} elements.
+     * Units of measurement, often represented by {@code UNIT[…]} elements.
+     *
+     * @see javax.measure.Unit
      */
     UNIT,
 
     /**
-     * {@linkplain org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis 
Coordinate system axes},
-     * often represented by {@code AXIS[…]} elements.
+     * Coordinate system axes, often represented by {@code AXIS[…]} elements.
+     *
+     * @see org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis
      */
     AXIS,
 
     /**
-     * {@linkplain org.opengis.util.CodeList Code list} values.
+     * Code list values.
+     *
+     * @see org.opengis.util.CodeList
      */
     CODE_LIST,
 
     /**
-     * Name of {@linkplain 
org.apache.sis.parameter.AbstractParameterDescriptor parameters},
-     * often represented by {@code PARAMETER[…]} elements.
+     * Name of parameters, often represented by {@code PARAMETER[…]} elements.
+     *
+     * @see org.apache.sis.parameter.AbstractParameterDescriptor
      */
     PARAMETER,
 
     /**
-     * {@linkplain org.apache.sis.referencing.operation.DefaultOperationMethod 
Operation methods},
-     * often represented by {@code PROJECTION[…]} elements.
+     * Operation methods, often represented by {@code PROJECTION[…]} elements.
+     *
+     * @see org.apache.sis.referencing.operation.DefaultOperationMethod
      */
     METHOD,
 
     /**
-     * {@linkplain org.apache.sis.referencing.datum.AbstractDatum Datum},
-     * often represented by {@code DATUM[…]} elements.
+     * Datum or reference frame, often represented by {@code DATUM[…]} 
elements.
+     *
+     * @see org.apache.sis.referencing.datum.AbstractDatum
      */
     DATUM,
 
     /**
-     * CRS, datum or operation {@linkplain 
org.apache.sis.referencing.AbstractReferenceSystem#getScope() scope},
-     * often represented by {@code SCOPE[…]} elements.
+     * CRS, datum or operation scope, often represented by {@code SCOPE[…]} 
elements.
+     *
+     * @see org.apache.sis.referencing.DefaultObjectDomain#getScope()
      */
     SCOPE,
 
     /**
-     * CRS, datum or operation {@linkplain 
org.apache.sis.referencing.AbstractReferenceSystem#getDomainOfValidity()
-     * domain of validity}, often represented by {@code AREA[…]} or {@code 
BBOX[…]} elements.
+     * CRS, datum or operation domain of validity,
+     * often represented by {@code AREA[…]} or {@code BBOX[…]} elements.
+     *
+     * @see 
org.apache.sis.referencing.DefaultObjectDomain#getDomainOfValidity()
      */
     EXTENT,
 
     /**
-     * Citation (typically for the {@linkplain 
org.apache.sis.referencing.ImmutableIdentifier#getAuthority()
-     * authority}), often represented by {@code CITATION[…]} elements.
+     * Citation (typically for the authority), often represented by {@code 
CITATION[…]} elements.
+     *
+     * @see org.apache.sis.referencing.ImmutableIdentifier#getAuthority()
      */
     CITATION,
 
     /**
-     * {@linkplain 
org.apache.sis.referencing.AbstractIdentifiedObject#getRemarks() Remarks},
-     * often represented by {@code REMARKS[…]} elements.
+     * Remarks, often represented by {@code REMARKS[…]} elements.
      *
      * <p>When formatting an ISO 19162 Well Known Text, texts quoted as 
remarks preserve non-ASCII characters.
      * By contrast, quoted texts in any other {@code ElementKind} will have 
some non-ASCII characters replaced
      * by ASCII ones (e.g. "é" → "e").</p>
+     *
+     * @see org.apache.sis.referencing.AbstractIdentifiedObject#getRemarks()
      */
     REMARKS,
 
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
index 56001c098e..b882cec7f4 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
@@ -44,7 +44,6 @@ import javax.measure.format.MeasurementParseException;
 import org.opengis.metadata.Identifier;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.referencing.IdentifiedObject;
-import org.opengis.referencing.ReferenceSystem;
 import org.opengis.referencing.ObjectFactory;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.cs.*;
@@ -89,6 +88,9 @@ import org.apache.sis.util.iso.Types;
 import org.apache.sis.referencing.crs.DefaultImageCRS;
 import org.apache.sis.referencing.datum.DefaultImageDatum;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.referencing.ObjectDomain;
+
 
 /**
  * Well Known Text (WKT) parser for referencing objects. This include, but is 
not limited too,
@@ -475,7 +477,7 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
              */
             element = parent.pullElement(OPTIONAL, WKTKeywords.Scope);
             if (element != null) {
-                properties.put(ReferenceSystem.SCOPE_KEY, 
element.pullString("scope"));  // Other types like Datum use the same key.
+                properties.put(ObjectDomain.SCOPE_KEY, 
element.pullString("scope"));
                 element.close(ignoredElements);
             }
             /*
@@ -541,7 +543,7 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
                 }
             }
             if (extent != null) {
-                properties.put(ReferenceSystem.DOMAIN_OF_VALIDITY_KEY, extent);
+                properties.put(ObjectDomain.DOMAIN_OF_VALIDITY_KEY, extent);
             }
             /*
              * Example: REMARK["Замечание на русском языке"]
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
index d7d36f61ad..45216444f8 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
@@ -44,7 +44,6 @@ import org.opengis.metadata.citation.Citation;
 import org.opengis.referencing.ObjectFactory;
 import org.opengis.referencing.AuthorityFactory;
 import org.opengis.referencing.IdentifiedObject;
-import org.opengis.referencing.ReferenceSystem;
 import org.apache.sis.xml.Namespaces;
 import org.apache.sis.xml.bind.ScopedIdentifier;
 import org.apache.sis.xml.bind.UseLegacyMetadata;
@@ -303,13 +302,13 @@ public class AbstractIdentifiedObject extends 
FormattableObject implements Ident
      *     <td>{@link ObjectDomain} (optionally as array)</td>
      *     <td>{@link #getDomains()}</td>
      *   </tr><tr>
-     *     <td>{@value org.opengis.referencing.ReferenceSystem#SCOPE_KEY}</td>
+     *     <td>{@value org.opengis.referencing.ObjectDomain#SCOPE_KEY}</td>
      *     <td>{@link String} or {@link InternationalString}</td>
-     *     <td>{@link ObjectDomain#getScope()} on the {@linkplain 
#getDomains() domain}</td>
+     *     <td>{@link DefaultObjectDomain#getScope()} on the {@linkplain 
#getDomains() domain}</td>
      *   </tr><tr>
-     *     <td>{@value 
org.opengis.referencing.ReferenceSystem#DOMAIN_OF_VALIDITY_KEY}</td>
+     *     <td>{@value 
org.opengis.referencing.ObjectDomain#DOMAIN_OF_VALIDITY_KEY}</td>
      *     <td>{@link Extent}</td>
-     *     <td>{@link ObjectDomain#getDomainOfValidity()} on the {@linkplain 
#getDomains() domain}</td>
+     *     <td>{@link DefaultObjectDomain#getDomainOfValidity()} on the 
{@linkplain #getDomains() domain}</td>
      *   </tr><tr>
      *     <td>{@value 
org.opengis.referencing.IdentifiedObject#REMARKS_KEY}</td>
      *     <td>{@link InternationalString} or {@link String}</td>
@@ -406,8 +405,8 @@ public class AbstractIdentifiedObject extends 
FormattableObject implements Ident
             throw illegalPropertyType(properties, DOMAINS_KEY, value);
         } else {
             // Compatibility with previous way to specify domain.
-            final InternationalString scope = 
Types.toInternationalString(properties, ReferenceSystem.SCOPE_KEY);
-            final Extent domainOfValidity = Containers.property(properties, 
ReferenceSystem.DOMAIN_OF_VALIDITY_KEY, Extent.class);
+            final InternationalString scope = 
Types.toInternationalString(properties, ObjectDomain.SCOPE_KEY);
+            final Extent domainOfValidity = Containers.property(properties, 
ObjectDomain.DOMAIN_OF_VALIDITY_KEY, Extent.class);
             if (scope != null || domainOfValidity != null) {
                 domains = Collections.singleton(new DefaultObjectDomain(scope, 
domainOfValidity));
             }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/Builder.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/Builder.java
index 73893af8bf..943c717a34 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/Builder.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/Builder.java
@@ -183,8 +183,8 @@ public abstract class Builder<B extends Builder<B>> {
      * {@value org.opengis.referencing.IdentifiedObject#IDENTIFIERS_KEY} and
      * {@value org.opengis.referencing.IdentifiedObject#REMARKS_KEY} keys.
      * Subclasses may add other entries like
-     * {@value org.opengis.referencing.ReferenceSystem#DOMAIN_OF_VALIDITY_KEY} 
and
-     * {@value org.opengis.referencing.ReferenceSystem#SCOPE_KEY} keys.
+     * {@value org.opengis.referencing.ObjectDomain#DOMAIN_OF_VALIDITY_KEY} and
+     * {@value org.opengis.referencing.ObjectDomain#SCOPE_KEY} keys.
      *
      * <p>See <cite>Notes for subclass implementers</cite> in class javadoc 
for usage conditions.</p>
      *
diff --git 
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
index 8a4f1e6ab5..cf564ec9f8 100644
--- 
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
@@ -655,7 +655,7 @@ public final class CRS extends Static {
      * given target coordinate reference system. If an estimation of the 
geographic area containing the points
      * to transform is known, it can be specified for helping this method to 
find a better suited operation.
      * If no area of interest is specified, then the current default is the 
widest
-     * {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of 
validity}.
+     * {@linkplain DefaultObjectDomain#getDomainOfValidity() domain of 
validity}.
      * A future Apache SIS version may also take the country of current locale 
in account.
      *
      * <div class="note"><b>Note:</b>
@@ -730,7 +730,7 @@ public final class CRS extends Static {
      * Finds mathematical operations that transform or convert coordinates 
from the given source to the
      * given target coordinate reference system. If at least one operation 
exists, they are returned in
      * preference order: the operation having the widest intersection between 
its
-     * {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of 
validity}
+     * {@linkplain DefaultObjectDomain#getDomainOfValidity() domain of 
validity}
      * and the given area of interest are returned first.
      *
      * @param  sourceCRS       the CRS of source coordinates.
@@ -808,7 +808,7 @@ public final class CRS extends Static {
 
     /**
      * Returns the valid geographic area for the given coordinate operation, 
or {@code null} if unknown.
-     * This method explores the {@linkplain 
AbstractCoordinateOperation#getDomainOfValidity() domain of validity}
+     * This method explores the {@linkplain 
DefaultObjectDomain#getDomainOfValidity() domain of validity}
      * associated with the given operation. If more than one geographic 
bounding box is found, then this method
      * computes their {@linkplain 
DefaultGeographicBoundingBox#add(GeographicBoundingBox) union}.
      *
@@ -831,15 +831,15 @@ public final class CRS extends Static {
         if (operation == null) {
             return null;
         }
-        return getDomains(operation).orElseGet(
+        return IdentifiedObjects.getGeographicBoundingBox(operation).orElseGet(
                 () -> 
Extents.intersection(getGeographicBoundingBox(operation.getSourceCRS()),
                                            
getGeographicBoundingBox(operation.getTargetCRS())));
     }
 
     /**
      * Returns the valid geographic area for the given coordinate reference 
system, or {@code null} if unknown.
-     * This method explores the {@linkplain 
org.apache.sis.referencing.crs.AbstractCRS#getDomainOfValidity() domain of
-     * validity} associated with the given CRS. If more than one geographic 
bounding box is found, then this method
+     * This method explores the {@linkplain 
DefaultObjectDomain#getDomainOfValidity() domain of validity}
+     * associated with the given CRS. If more than one geographic bounding box 
is found, then this method
      * computes their {@linkplain 
DefaultGeographicBoundingBox#add(GeographicBoundingBox) union}.
      * together.
      *
@@ -853,15 +853,7 @@ public final class CRS extends Static {
      */
     @OptionalCandidate
     public static GeographicBoundingBox getGeographicBoundingBox(final 
CoordinateReferenceSystem crs) {
-        return (crs != null) ? getDomains(crs).orElse(null) : null;
-    }
-
-    /**
-     * Returns the geographic bounding box computed from the domain of the 
given object. This method may be renamed and
-     * refactored as a replacement of {@link 
#getGeographicBoundingBox(CoordinateReferenceSystem)} in a future version.
-     */
-    private static Optional<GeographicBoundingBox> getDomains(final 
IdentifiedObject object) {
-        return 
Extents.getGeographicBoundingBox(object.getDomains().stream().map(ObjectDomain::getDomainOfValidity));
+        return IdentifiedObjects.getGeographicBoundingBox(crs).orElse(null);
     }
 
     /**
@@ -871,8 +863,8 @@ public final class CRS extends Static {
      *
      * <p>This method looks in two places:</p>
      * <ol>
-     *   <li>First, it checks the {@linkplain 
org.apache.sis.referencing.crs.AbstractCRS#getDomainOfValidity()
-     *       domain of validity} associated with the given CRS. Only 
geographic extents that are instances of
+     *   <li>First, it checks the {@linkplain 
DefaultObjectDomain#getDomainOfValidity() domain of validity}
+     *       associated with the given CRS. Only geographic extents that are 
instances of
      *       {@link BoundingPolygon} associated to the given CRS are taken in 
account for this first step.</li>
      *   <li>If the above step did not found found any bounding polygon, then 
the
      *       {@linkplain #getGeographicBoundingBox(CoordinateReferenceSystem) 
geographic bounding boxes}
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/IdentifiedObjects.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/IdentifiedObjects.java
index 5a374cdaef..c8b2c0c321 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/IdentifiedObjects.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/IdentifiedObjects.java
@@ -22,18 +22,23 @@ import java.util.List;
 import java.util.LinkedHashSet;
 import java.util.Collection;
 import java.util.Locale;
+import java.util.Optional;
+import java.util.stream.Stream;
 import org.opengis.util.NameSpace;
 import org.opengis.util.GenericName;
 import org.opengis.util.FactoryException;
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
+import org.opengis.metadata.extent.Extent;
+import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.crs.CompoundCRS;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.ConcatenatedOperation;
 import static org.apache.sis.util.Utilities.equalsIgnoreMetadata;
 import org.apache.sis.util.Static;
+import org.apache.sis.util.Emptiable;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.OptionalCandidate;
@@ -48,6 +53,7 @@ import org.apache.sis.metadata.privy.Identifiers;
 import org.apache.sis.metadata.privy.NameMeaning;
 import org.apache.sis.metadata.privy.NameToIdentifier;
 import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.metadata.iso.extent.Extents;
 import org.apache.sis.referencing.factory.IdentifiedObjectFinder;
 import org.apache.sis.referencing.factory.GeodeticAuthorityFactory;
 import org.apache.sis.referencing.factory.UnavailableFactoryException;
@@ -94,9 +100,9 @@ public final class IdentifiedObjects extends Static {
      *       <td>{@link IdentifiedObject#getDomains()}</td></tr>
      *   <tr><td>{@value 
org.opengis.referencing.IdentifiedObject#REMARKS_KEY}</td>
      *       <td>{@link IdentifiedObject#getRemarks()}</td></tr>
-     *   <tr><td>{@value 
org.opengis.referencing.ReferenceSystem#SCOPE_KEY}</td>
+     *   <tr><td>{@value org.opengis.referencing.ObjectDomain#SCOPE_KEY}</td>
      *       <td>{@link ObjectDomain#getScope()}</td></tr>
-     *   <tr><td>{@value 
org.opengis.referencing.ReferenceSystem#DOMAIN_OF_VALIDITY_KEY}</td>
+     *   <tr><td>{@value 
org.opengis.referencing.ObjectDomain#DOMAIN_OF_VALIDITY_KEY}</td>
      *       <td>{@link ObjectDomain#getDomainOfValidity()}</td></tr>
      *   <tr><td>{@value 
org.opengis.referencing.operation.CoordinateOperation#OPERATION_VERSION_KEY}</td>
      *       <td>{@link CoordinateOperation#getOperationVersion()}</td></tr>
@@ -433,6 +439,50 @@ public final class IdentifiedObjects extends Static {
         return name;
     }
 
+    /**
+     * Returns the domain of validity of the given object.
+     * If the object specifies more than one domain of validity,
+     * then this method computes their intersection (note that this is the 
opposite of
+     * {@link #getGeographicBoundingBox(IdentifiedObject)}, which computes the 
union).
+     * If there is no intersection, then the returned object implements {@link 
Emptiable}
+     * and the {@link Emptiable#isEmpty()} method returns {@code true}.
+     *
+     * @param  object  the object for which to get the domain of validity, or 
{@code null}.
+     * @return the domain of validity where the object is valid, or empty if 
unspecified.
+     *
+     * @since 1.5
+     */
+    public static Optional<Extent> getDomainOfValidity(final IdentifiedObject 
object) {
+        Extent domain = null;
+        if (object != null) {
+            for (ObjectDomain obj : object.getDomains()) {
+                domain = Extents.intersection(domain, 
obj.getDomainOfValidity());
+            }
+        }
+        return Optional.ofNullable(domain);
+    }
+
+    /**
+     * Returns the geographic bounding box computed from the domains of the 
given object.
+     * If the given object contains more than one domain, then this method 
computes their union.
+     * Note that this is the opposite of {@link 
#getDomainOfValidity(IdentifiedObject)},
+     * which computes the intersection.
+     *
+     * @param  object  the object for which to get the domain of validity, or 
{@code null}.
+     * @return the geographic area where the object is valid, or empty if 
unspecified.
+     *
+     * @see IdentifiedObject#getDomains()
+     * @see Extents#getGeographicBoundingBox(Stream)
+     *
+     * @since 1.5
+     */
+    public static Optional<GeographicBoundingBox> 
getGeographicBoundingBox(final IdentifiedObject object) {
+        if (object == null) {
+            return Optional.empty();
+        }
+        return 
Extents.getGeographicBoundingBox(object.getDomains().stream().map(ObjectDomain::getDomainOfValidity));
+    }
+
     /**
      * Looks up a URN, such as {@code "urn:ogc:def:crs:EPSG:9.1:4326"}, of the 
specified object.
      * This method searches in all {@linkplain 
org.apache.sis.referencing.factory.GeodeticAuthorityFactory geodetic
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/Properties.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/Properties.java
index ec0283dfeb..a52462666a 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/Properties.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/Properties.java
@@ -22,9 +22,7 @@ import java.util.Collection;
 import java.util.function.IntFunction;
 import java.io.Serializable;
 import org.opengis.util.GenericName;
-import org.opengis.referencing.ReferenceSystem;
 import org.opengis.referencing.IdentifiedObject;
-import org.opengis.referencing.datum.Datum;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.SingleOperation;
@@ -38,6 +36,8 @@ import org.opengis.referencing.ObjectDomain;
 
 // Specific to the geoapi-4.0 branch:
 import org.opengis.metadata.Identifier;
+import org.opengis.metadata.extent.Extent;
+import org.opengis.util.InternationalString;
 
 
 /**
@@ -66,8 +66,8 @@ final class Properties extends AbstractMap<String,Object> 
implements Serializabl
         /*[ 2]*/ IdentifiedObject        .ALIAS_KEY,
         /*[ 3]*/ IdentifiedObject        .DOMAINS_KEY,
         /*[ 4]*/ IdentifiedObject        .REMARKS_KEY,
-        /*[ 5]*/ CoordinateOperation     .SCOPE_KEY,                    // 
same in Datum and ReferenceSystem
-        /*[ 6]*/ CoordinateOperation     .DOMAIN_OF_VALIDITY_KEY,       // 
same in Datum and ReferenceSystem
+        /*[ 5]*/ ObjectDomain            .SCOPE_KEY,
+        /*[ 6]*/ ObjectDomain            .DOMAIN_OF_VALIDITY_KEY,
         /*[ 7]*/ CoordinateOperation     .OPERATION_VERSION_KEY,
         /*[ 8]*/ CoordinateOperation     .COORDINATE_OPERATION_ACCURACY_KEY,
         /*[ 9]*/ OperationMethod         .FORMULA_KEY,
@@ -109,7 +109,7 @@ final class Properties extends AbstractMap<String,Object> 
implements Serializabl
      * Creates new properties from the specified identified object.
      */
     Properties(final IdentifiedObject object, final String[] excludes) {
-        this.object = object;
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         int excludeMask = 0;
         for (final String exclude : excludes) {
             final Integer i = INDICES.get(exclude);
@@ -118,6 +118,7 @@ final class Properties extends AbstractMap<String,Object> 
implements Serializabl
             }
         }
         this.excludeMask = excludeMask;
+        this.object = object;
     }
 
     /**
@@ -135,22 +136,16 @@ final class Properties extends AbstractMap<String,Object> 
implements Serializabl
                 case 3: return toArray(object.getDomains(),   
ObjectDomain[]::new);     // DOMAINS_KEY
                 case 4: return         object.getRemarks();                    
         // REMARKS_KEY
                 case 5: {   // SCOPE_KEY
-                    if (object instanceof ReferenceSystem) {
-                        return ((ReferenceSystem) object).getScope();
-                    } else if (object instanceof Datum) {
-                        return ((Datum) object).getScope();
-                    } else if (object instanceof CoordinateOperation) {
-                        return ((CoordinateOperation) object).getScope();
+                    for (final ObjectDomain domain : object.getDomains()) {
+                        InternationalString scope = domain.getScope();
+                        if (scope != null) return scope;
                     }
                     break;
                 }
                 case 6: {   // DOMAIN_OF_VALIDITY_KEY
-                    if (object instanceof ReferenceSystem) {
-                        return ((ReferenceSystem) 
object).getDomainOfValidity();
-                    } else if (object instanceof Datum) {
-                        return ((Datum) object).getDomainOfValidity();
-                    } else if (object instanceof CoordinateOperation) {
-                        return ((CoordinateOperation) 
object).getDomainOfValidity();
+                    for (final ObjectDomain domain : object.getDomains()) {
+                        Extent extent = domain.getDomainOfValidity();
+                        if (extent != null) return extent;
                     }
                     break;
                 }
diff --git 
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
index c566cef765..f872175d90 100644
--- 
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
@@ -43,7 +43,6 @@ import static 
org.opengis.referencing.IdentifiedObject.NAME_KEY;
 import static org.opengis.referencing.IdentifiedObject.ALIAS_KEY;
 import static org.opengis.referencing.IdentifiedObject.REMARKS_KEY;
 import static org.opengis.referencing.IdentifiedObject.IDENTIFIERS_KEY;
-import static org.opengis.referencing.datum.Datum.DOMAIN_OF_VALIDITY_KEY;
 import org.apache.sis.util.SimpleInternationalString;
 import org.apache.sis.util.privy.Constants;
 import org.apache.sis.metadata.privy.AxisNames;
@@ -76,6 +75,7 @@ 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;
+import static org.opengis.referencing.ObjectDomain.DOMAIN_OF_VALIDITY_KEY;
 
 
 /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
index 32f34b8cdc..4900d62993 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
@@ -368,9 +368,8 @@ public class AbstractCRS extends AbstractReferenceSystem 
implements CoordinateRe
     /**
      * Compares this coordinate reference system with the specified object for 
equality.
      * If the {@code mode} argument value is {@link ComparisonMode#STRICT 
STRICT} or
-     * {@link ComparisonMode#BY_CONTRACT BY_CONTRACT}, then all available 
properties are
-     * compared including the {@linkplain #getDomainOfValidity() domain of 
validity} and
-     * the {@linkplain #getScope() scope}.
+     * {@link ComparisonMode#BY_CONTRACT BY_CONTRACT}, then all available 
properties
+     * are compared including the {@linkplain #getDomains() domains} and 
remarks.
      *
      * @param  object  the object to compare to {@code this}.
      * @param  mode    {@link ComparisonMode#STRICT STRICT} for performing a 
strict comparison, or
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
index 35027bd710..4da215ea62 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
@@ -211,9 +211,9 @@ public class DefaultDerivedCRS extends 
AbstractDerivedCRS<Conversion> implements
      *     <td>{@link org.opengis.metadata.Identifier} (optionally as 
array)</td>
      *     <td>{@code this.getIdentifiers()}</td>
      *   </tr><tr>
-     *     <td>{@value 
org.opengis.referencing.operation.CoordinateOperation#DOMAIN_OF_VALIDITY_KEY}</td>
+     *     <td>{@value 
org.opengis.referencing.ObjectDomain#DOMAIN_OF_VALIDITY_KEY}</td>
      *     <td>{@link org.opengis.metadata.extent.Extent}</td>
-     *     <td>{@code conversionFromBase.getDomainOfValidity()}</td>
+     *     <td>{@code domain.getDomainOfValidity()}</td>
      *   </tr>
      * </table>
      *
diff --git 
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
index e62924f482..36d9ba831f 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
@@ -47,6 +47,12 @@ import static 
org.apache.sis.util.collection.Containers.property;
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.metadata.Identifier;
 
+// Specific to the geoapi-4.0 branch:
+import org.opengis.annotation.UML;
+import static org.opengis.annotation.Obligation.*;
+import static org.opengis.annotation.Specification.*;
+import org.apache.sis.referencing.internal.Legacy;
+
 
 /**
  * Specifies the relationship of a {@linkplain 
org.apache.sis.referencing.cs.AbstractCS Coordinate System} to the earth.
@@ -168,11 +174,11 @@ public class AbstractDatum extends 
AbstractIdentifiedObject implements Datum {
         super(properties);
         anchorDefinition = Types.toInternationalString(properties, 
ANCHOR_DEFINITION_KEY);
         if (anchorDefinition == null) {
-            anchorDefinition = Types.toInternationalString(properties, 
ANCHOR_POINT_KEY);
+            anchorDefinition = Types.toInternationalString(properties, 
"anchorPoint");      // Legacy name.
         }
         anchorEpoch = property(properties, ANCHOR_EPOCH_KEY, Temporal.class);
         if (anchorEpoch == null) {
-            Date date = property(properties, REALIZATION_EPOCH_KEY, 
Date.class);
+            Date date = property(properties, "realizationEpoch", Date.class);  
             // Legacy name.
             if (date != null) {
                 anchorEpoch = date.toInstant();
             }
@@ -260,20 +266,6 @@ public class AbstractDatum extends 
AbstractIdentifiedObject implements Datum {
         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;
-    }
-
     /**
      * 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).
@@ -291,21 +283,6 @@ public class AbstractDatum extends 
AbstractIdentifiedObject implements Datum {
         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 Datum.super.getRealizationEpoch();
-    }
-
     /**
      * Returns {@code true} if either the {@linkplain #getName() primary name} 
or at least
      * one {@linkplain #getAlias() alias} matches the given string according 
heuristic rules.
@@ -470,6 +447,15 @@ public class AbstractDatum extends 
AbstractIdentifiedObject implements Datum {
         super(org.apache.sis.referencing.privy.NilReferencingObject.INSTANCE);
     }
 
+    /**
+     * Returns a description of the point(s) used to anchor the datum to the 
Earth.
+     */
+    @XmlElement(name = "anchorDefinition")
+    @UML(identifier="anchorPoint", obligation=OPTIONAL, 
specification=ISO_19111, version=2003)
+    private InternationalString getAnchorPoint() {
+        return getAnchorDefinition().orElse(null);
+    }
+
     /**
      * Invoked by JAXB only at unmarshalling time.
      *
@@ -483,6 +469,16 @@ public class AbstractDatum extends 
AbstractIdentifiedObject implements Datum {
         }
     }
 
+    /**
+     * The time after which this datum definition is valid.
+     */
+    @XmlSchemaType(name = "date")
+    @XmlElement(name = "realizationEpoch")
+    @UML(identifier="realizationEpoch", obligation=OPTIONAL, 
specification=ISO_19111, version=2007)
+    private Date getRealizationEpoch() {
+        return getAnchorEpoch().map(Legacy::toDate).orElse(null);
+    }
+
     /**
      * Invoked by JAXB only at unmarshalling time.
      *
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/BursaWolfParameters.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/BursaWolfParameters.java
index ed4ff0171f..42a36c2251 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/BursaWolfParameters.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/BursaWolfParameters.java
@@ -32,6 +32,7 @@ import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.io.wkt.FormattableObject;
 import org.apache.sis.io.wkt.Formatter;
 import org.apache.sis.util.Utilities;
+import org.apache.sis.util.OptionalCandidate;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.privy.DoubleDouble;
 import org.apache.sis.referencing.privy.WKTKeywords;
@@ -268,6 +269,7 @@ public class BursaWolfParameters extends FormattableObject 
implements Cloneable,
      *
      * @return the target datum for this set of parameters, or {@code null} if 
unknown.
      */
+    @OptionalCandidate
     public GeodeticDatum getTargetDatum() {
         return targetDatum;
     }
@@ -609,9 +611,10 @@ public class BursaWolfParameters extends FormattableObject 
implements Cloneable,
      *
      * @see org.apache.sis.metadata.iso.extent.DefaultExtent
      */
+    @OptionalCandidate
     public Extent getDomainOfValidity() {
         if (domainOfValidity == null && targetDatum != null) {
-            return targetDatum.getDomainOfValidity();
+            return 
IdentifiedObjects.getDomainOfValidity(targetDatum).orElse(null);
         }
         return domainOfValidity;
     }
diff --git 
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
index 0af6cb5ee8..c921e6edab 100644
--- 
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
@@ -134,11 +134,11 @@ import org.apache.sis.xml.XML;
  *     <td>{@link org.opengis.referencing.ObjectDomain} (optionally as 
array)</td>
  *     <td>{@link AbstractIdentifiedObject#getDomains()}</td>
  *   </tr><tr>
- *     <td>{@value 
org.opengis.referencing.ReferenceSystem#DOMAIN_OF_VALIDITY_KEY}</td>
+ *     <td>{@value 
org.opengis.referencing.ObjectDomain#DOMAIN_OF_VALIDITY_KEY}</td>
  *     <td>{@link Extent}</td>
  *     <td>{@link 
org.apache.sis.referencing.DefaultObjectDomain#getDomainOfValidity()}</td>
  *   </tr><tr>
- *     <td>{@value org.opengis.referencing.ReferenceSystem#SCOPE_KEY}</td>
+ *     <td>{@value org.opengis.referencing.ObjectDomain#SCOPE_KEY}</td>
  *     <td>{@link String} or {@link InternationalString}</td>
  *     <td>{@link DefaultObjectDomain#getScope()}</td>
  *   </tr><tr>
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
index 8f17efbc4d..44ef1d1933 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
@@ -124,6 +124,7 @@ import static 
org.apache.sis.referencing.internal.ServicesForMetadata.CONNECTION
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.metadata.Identifier;
+import org.opengis.referencing.ObjectDomain;
 
 
 /**
@@ -1219,9 +1220,9 @@ codes:  for (int i=0; i<codes.length; i++) {
         @SuppressWarnings("LocalVariableHidesMemberVariable")
         final Map<String,Object> properties = createProperties(table, name, 
code, remarks, deprecated);
         if (domainCode != null) {
-            properties.put(Datum.DOMAIN_OF_VALIDITY_KEY, 
owner.createExtent(domainCode));
+            properties.put(ObjectDomain.DOMAIN_OF_VALIDITY_KEY, 
owner.createExtent(domainCode));
         }
-        properties.put(Datum.SCOPE_KEY, scope);
+        properties.put(ObjectDomain.SCOPE_KEY, scope);
         return properties;
     }
 
@@ -1696,7 +1697,7 @@ codes:  for (int i=0; i<codes.length; i++) {
                         @SuppressWarnings("LocalVariableHidesMemberVariable")
                         final Calendar calendar = getCalendar();
                         calendar.set(year, month, day);
-                        properties.put(Datum.REALIZATION_EPOCH_KEY, 
calendar.getTime());
+                        properties.put(Datum.ANCHOR_EPOCH_KEY, 
calendar.getTime().toInstant());
                     }
                 } catch (NumberFormatException exception) {
                     unexpectedException("createDatum", exception);          // 
Not a fatal error.
diff --git 
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
index a5abfd686b..a0af157c4f 100644
--- 
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,6 +29,20 @@ import org.apache.sis.referencing.cs.DefaultCartesianCS;
 import org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis;
 import org.apache.sis.referencing.privy.ReferencingUtilities;
 
+// Specific to the geoapi-4.0 branch:
+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;
+
 
 /**
  * Utilities related to version 1 of Well Known Text format, or to ISO 
19111:2007.
@@ -109,4 +123,43 @@ public final class Legacy {
         }
         return cs;
     }
+
+    /**
+     * 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 --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
index 43f6c32c02..b75d81ee06 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
@@ -90,7 +90,7 @@ import org.opengis.coordinate.CoordinateSet;
  *       for interpolating.</li>
  *   <li>In {@linkplain DefaultConversion conversion} and {@linkplain 
DefaultTransformation transformation} subclasses,
  *       a description of the {@linkplain DefaultOperationMethod operation 
method} together with the parameter values.</li>
- *   <li>The {@linkplain #getDomainOfValidity() domain of validity}.</li>
+ *   <li>The {@linkplain 
org.apache.sis.referencing.DefaultObjectDomain#getDomainOfValidity() domain of 
validity}.</li>
  *   <li>An estimation of the {@linkplain #getCoordinateOperationAccuracy() 
operation accuracy}.</li>
  * </ul>
  *
@@ -822,8 +822,7 @@ check:      for (int isTarget=0; ; isTarget++) {        // 
0 == source check; 1
     /**
      * Compares this coordinate operation with the specified object for 
equality. If the {@code mode} argument
      * is {@link ComparisonMode#STRICT} or {@link ComparisonMode#BY_CONTRACT 
BY_CONTRACT}, then all available
-     * properties are compared including the {@linkplain 
#getDomainOfValidity() domain of validity} and the
-     * {@linkplain #getScope() scope}.
+     * properties are compared including the {@linkplain #getDomains() 
domains} and the accuracy.
      *
      * @param  object  the object to compare to {@code this}.
      * @param  mode    {@link ComparisonMode#STRICT STRICT} for performing a 
strict comparison, or
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractSingleOperation.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractSingleOperation.java
index 45d43fc48e..b6da3ac7f1 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractSingleOperation.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractSingleOperation.java
@@ -278,8 +278,7 @@ class AbstractSingleOperation extends 
AbstractCoordinateOperation implements Sin
     /**
      * Compares this coordinate operation with the specified object for 
equality. If the {@code mode} argument
      * is {@link ComparisonMode#STRICT} or {@link ComparisonMode#BY_CONTRACT 
BY_CONTRACT}, then all available
-     * properties are compared including the {@linkplain 
#getDomainOfValidity() domain of validity} and the
-     * {@linkplain #getScope() scope}.
+     * properties are compared including the {@linkplain #getDomains() 
domains} and the accuracy.
      *
      * @return {@inheritDoc}
      */
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
index c47f397e54..b6635b8178 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
@@ -85,8 +85,7 @@ import static 
org.apache.sis.util.Utilities.equalsIgnoreMetadata;
  *       The late-binding approach allows the authority to define better 
suited operations than what
  *       we would get if we were transforming everything from and to a pivot 
system (e.g. WGS84).
  *       In addition, this approach provides useful information like the 
coordinate operation
- *       {@linkplain AbstractCoordinateOperation#getScope() scope} and
- *       {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain 
of validity},
+ *       {@linkplain AbstractCoordinateOperation#getDomains() domain of 
validity} and
  *       {@linkplain 
AbstractCoordinateOperation#getCoordinateOperationAccuracy() accuracy}.</div>
  *   </li>
  *   <li>If the above authority factory does not know about the specified CRS, 
then this class tries to
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationSorter.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationSorter.java
index 0f5c903c07..b0af3e6239 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationSorter.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationSorter.java
@@ -54,8 +54,7 @@ final class CoordinateOperationSorter implements 
Comparable<CoordinateOperationS
      */
     private CoordinateOperationSorter(final CoordinateOperation operation, 
final GeographicBoundingBox areaOfInterest) {
         this.operation = operation;
-        area = -Extents.area(Extents.intersection(areaOfInterest,
-                             
Extents.getGeographicBoundingBox(operation.getDomainOfValidity())));
+        area = -Extents.area(Extents.intersection(areaOfInterest, 
CRS.getGeographicBoundingBox(operation)));
         accuracy = CRS.getLinearAccuracy(operation);
     }
 
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
index 332b45903c..d87f20598b 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
@@ -417,8 +417,7 @@ final class DefaultConcatenatedOperation extends 
AbstractCoordinateOperation imp
     /**
      * Compares this concatenated operation with the specified object for 
equality. If the {@code mode} argument
      * is {@link ComparisonMode#STRICT} or {@link ComparisonMode#BY_CONTRACT 
BY_CONTRACT}, then all available
-     * properties are compared including the {@linkplain 
#getDomainOfValidity() domain of validity} and the
-     * {@linkplain #getScope() scope}.
+     * properties are compared including the {@linkplain #getDomains() 
domains} and the accuracy.
      *
      * @return {@inheritDoc}
      */
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConversion.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConversion.java
index 3253da4159..0c5331ca99 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConversion.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConversion.java
@@ -113,9 +113,9 @@ public class DefaultConversion extends 
AbstractSingleOperation implements Conver
      *     <td>{@link org.opengis.metadata.Identifier} (optionally as 
array)</td>
      *     <td>{@link #getIdentifiers()}</td>
      *   </tr><tr>
-     *     <td>{@value 
org.opengis.referencing.operation.CoordinateOperation#DOMAIN_OF_VALIDITY_KEY}</td>
+     *     <td>{@value 
org.opengis.referencing.ObjectDomain#DOMAIN_OF_VALIDITY_KEY}</td>
      *     <td>{@link org.opengis.metadata.extent.Extent}</td>
-     *     <td>{@link #getDomainOfValidity()}</td>
+     *     <td>{@link 
org.apache.sis.referencing.DefaultObjectDomain#getDomainOfValidity()}</td>
      *   </tr>
      * </table>
      *
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
index e518b7de9f..b4f4c42b55 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
@@ -390,9 +390,9 @@ public class DefaultCoordinateOperationFactory extends 
AbstractFactory implement
      *     <td>{@link org.opengis.metadata.Identifier} (optionally as 
array)</td>
      *     <td>{@link DefaultConversion#getIdentifiers()}</td>
      *   </tr><tr>
-     *     <td>{@value 
org.opengis.referencing.operation.CoordinateOperation#DOMAIN_OF_VALIDITY_KEY}</td>
+     *     <td>{@value 
org.opengis.referencing.ObjectDomain#DOMAIN_OF_VALIDITY_KEY}</td>
      *     <td>{@link org.opengis.metadata.extent.Extent}</td>
-     *     <td>{@link DefaultConversion#getDomainOfValidity()}</td>
+     *     <td>{@link 
org.apache.sis.referencing.DefaultObjectDomain#getDomainOfValidity()}</td>
      *   </tr>
      * </table>
      *
@@ -480,9 +480,9 @@ next:   for (int i=components.size(); --i >= 0;) {
      *     <td>{@link org.opengis.metadata.Identifier} (optionally as 
array)</td>
      *     <td>{@link DefaultConversion#getIdentifiers()}</td>
      *   </tr><tr>
-     *     <td>{@value 
org.opengis.referencing.operation.CoordinateOperation#DOMAIN_OF_VALIDITY_KEY}</td>
+     *     <td>{@value 
org.opengis.referencing.ObjectDomain#DOMAIN_OF_VALIDITY_KEY}</td>
      *     <td>{@link org.opengis.metadata.extent.Extent}</td>
-     *     <td>{@link DefaultConversion#getDomainOfValidity()}</td>
+     *     <td>{@link 
org.apache.sis.referencing.DefaultObjectDomain#getDomainOfValidity()}</td>
      *   </tr>
      * </table>
      *
@@ -732,8 +732,9 @@ next:   for (int i=components.size(); --i >= 0;) {
     /**
      * Finds or creates an operation for conversion or transformation between 
two coordinate reference systems.
      * If an operation exists, it is returned. If more than one operation 
exists, then the operation having the
-     * widest intersection between its {@linkplain 
AbstractCoordinateOperation#getDomainOfValidity() domain of
-     * validity} and the {@linkplain 
CoordinateOperationContext#getAreaOfInterest() area of interest} is returned.
+     * widest intersection between its {@linkplain 
org.apache.sis.referencing.DefaultObjectDomain#getDomainOfValidity()
+     * domain of validity} and the {@linkplain 
CoordinateOperationContext#getAreaOfInterest() area of interest}
+     * is returned.
      *
      * <p>The default implementation performs the following steps:</p>
      * <ul>
@@ -798,8 +799,9 @@ next:   for (int i=components.size(); --i >= 0;) {
     /**
      * Finds or creates operations for conversions or transformations between 
two coordinate reference systems.
      * If at least one operation exists, they are returned in preference 
order: the operation having the widest
-     * intersection between its {@linkplain 
AbstractCoordinateOperation#getDomainOfValidity() domain of validity}
-     * and the {@linkplain CoordinateOperationContext#getAreaOfInterest() area 
of interest} is returned.
+     * intersection between its {@linkplain 
org.apache.sis.referencing.DefaultObjectDomain#getDomainOfValidity()
+     * domain of validity} and the {@linkplain 
CoordinateOperationContext#getAreaOfInterest() area of interest}
+     * is returned.
      *
      * <p>The default implementation performs the following steps:</p>
      * <ul>
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java
index ddc10eb54b..a444daff6a 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultPassThroughOperation.java
@@ -221,8 +221,7 @@ public class DefaultPassThroughOperation extends 
AbstractCoordinateOperation imp
     /**
      * Compares this concatenated operation with the specified object for 
equality. If the {@code mode} argument
      * is {@link ComparisonMode#STRICT} or {@link ComparisonMode#BY_CONTRACT 
BY_CONTRACT}, then all available
-     * properties are compared including the {@linkplain 
#getDomainOfValidity() domain of validity} and the
-     * {@linkplain #getScope() scope}.
+     * properties are compared including the {@linkplain #getDomains() 
domains} and the accuracy.
      *
      * @return {@inheritDoc}
      */
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultTransformation.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultTransformation.java
index e25994c584..d3bdca7358 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultTransformation.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultTransformation.java
@@ -87,9 +87,9 @@ public class DefaultTransformation extends 
AbstractSingleOperation implements Tr
      *     <td>{@link org.opengis.metadata.quality.PositionalAccuracy} 
(optionally as array)</td>
      *     <td>{@link #getCoordinateOperationAccuracy()}</td>
      *   </tr><tr>
-     *     <td>{@value 
org.opengis.referencing.operation.CoordinateOperation#DOMAIN_OF_VALIDITY_KEY}</td>
+     *     <td>{@value 
org.opengis.referencing.ObjectDomain#DOMAIN_OF_VALIDITY_KEY}</td>
      *     <td>{@link org.opengis.metadata.extent.Extent}</td>
-     *     <td>{@link #getDomainOfValidity()}</td>
+     *     <td>{@link 
org.apache.sis.referencing.DefaultObjectDomain#getDomainOfValidity()}</td>
      *   </tr>
      * </table>
      *
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/InverseOperationMethod.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/InverseOperationMethod.java
index 967e44a047..2ada34c583 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/InverseOperationMethod.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/InverseOperationMethod.java
@@ -40,6 +40,9 @@ import 
org.apache.sis.referencing.operation.provider.AbstractProvider;
 import org.apache.sis.util.Deprecable;
 import org.apache.sis.util.collection.Containers;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.referencing.ObjectDomain;
+
 
 /**
  * Description of the inverse of another method. This class should be used 
only when no operation is defined
@@ -135,7 +138,7 @@ final class InverseOperationMethod extends 
DefaultOperationMethod {
      * @param target  where to store the properties of the inverse operation.
      */
     static void properties(final SingleOperation source, final 
Map<String,Object> target) {
-        target.put(SingleOperation.DOMAIN_OF_VALIDITY_KEY, 
source.getDomainOfValidity());
+        target.put(SingleOperation.DOMAINS_KEY, 
source.getDomains().toArray(ObjectDomain[]::new));
         final Collection<PositionalAccuracy> accuracy = 
source.getCoordinateOperationAccuracy();
         if (!Containers.isNullOrEmpty(accuracy)) {
             target.put(SingleOperation.COORDINATE_OPERATION_ACCURACY_KEY,
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
index eca3d7d1ac..2076fb52ae 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
@@ -189,7 +189,7 @@ public abstract class AbstractMathTransform extends 
FormattableObject
      * @throws TransformException if the domain cannot be estimated.
      *
      * @see MathTransforms#getDomain(MathTransform)
-     * @see 
org.opengis.referencing.operation.CoordinateOperation#getDomainOfValidity()
+     * @see org.opengis.referencing.ObjectDomain#getDomainOfValidity()
      *
      * @since 1.3
      */
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DomainDefinition.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DomainDefinition.java
index 614fc12cbd..244f76b702 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DomainDefinition.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DomainDefinition.java
@@ -60,7 +60,7 @@ import org.apache.sis.geometry.GeneralEnvelope;
  *
  * @see MathTransforms#getDomain(MathTransform)
  * @see AbstractMathTransform#getDomain(DomainDefinition)
- * @see 
org.opengis.referencing.operation.CoordinateOperation#getDomainOfValidity()
+ * @see org.opengis.referencing.operation.CoordinateOperation#getDomains()
  *
  * @since 1.3
  */
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransforms.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransforms.java
index 1102802222..f1c375666a 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransforms.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransforms.java
@@ -737,7 +737,7 @@ public final class MathTransforms extends Static {
      * @throws TransformException if the domain cannot be estimated.
      *
      * @see AbstractMathTransform#getDomain(DomainDefinition)
-     * @see 
org.opengis.referencing.operation.CoordinateOperation#getDomainOfValidity()
+     * @see org.opengis.referencing.operation.CoordinateOperation#getDomains()
      *
      * @since 1.3
      */
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/EllipsoidalHeightCombiner.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/EllipsoidalHeightCombiner.java
index 9d0f450bf9..0780da7d33 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/EllipsoidalHeightCombiner.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/EllipsoidalHeightCombiner.java
@@ -40,6 +40,9 @@ import org.apache.sis.metadata.iso.extent.Extents;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ArraysExt;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.referencing.ObjectDomain;
+
 
 /**
  * A class in charges of combining two-dimensional geographic or projected CRS 
with an ellipsoidal height into a
@@ -217,11 +220,13 @@ public final class EllipsoidalHeightCombiner {
             ArgumentChecks.ensureNonNullElement("components", i, crs);
             if (i != 0) name.append(" + ");
             name.append(crs.getName().getCode());
-            domain = Extents.intersection(domain, crs.getDomainOfValidity());
+            for (ObjectDomain obj : crs.getDomains()) {
+                domain = Extents.intersection(domain, 
obj.getDomainOfValidity());
+            }
         }
-        final Map<String,Object> properties = new HashMap<>(2);
+        final var properties = new HashMap<String,Object>(4);
         properties.put(CoordinateReferenceSystem.NAME_KEY, name.toString());
-        properties.put(CoordinateReferenceSystem.DOMAIN_OF_VALIDITY_KEY, 
domain);
+        properties.put(ObjectDomain.DOMAIN_OF_VALIDITY_KEY, domain);
         return properties;
     }
 }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/GeodeticObjectBuilder.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/GeodeticObjectBuilder.java
index e6d699ce53..cf72daddfc 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/GeodeticObjectBuilder.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/GeodeticObjectBuilder.java
@@ -61,6 +61,9 @@ import org.apache.sis.referencing.cs.AxesConvention;
 import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.parameter.Parameters;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.referencing.ObjectDomain;
+
 
 /**
  * Helper methods for building Coordinate Reference Systems and related 
objects.
@@ -183,7 +186,7 @@ public class GeodeticObjectBuilder extends 
Builder<GeodeticObjectBuilder> {
         }
         if (description != null || bbox != null) {
             final DefaultExtent extent = new DefaultExtent(description, bbox, 
null, null);
-            properties.put(CoordinateReferenceSystem.DOMAIN_OF_VALIDITY_KEY, 
extent);
+            properties.put(ObjectDomain.DOMAIN_OF_VALIDITY_KEY, extent);
         }
         return this;
     }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/NilReferencingObject.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/NilReferencingObject.java
index 5d3ef762d9..24d4cb655e 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/NilReferencingObject.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/NilReferencingObject.java
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.referencing.privy;
 
-import org.opengis.util.InternationalString;
 import org.opengis.referencing.ReferenceSystem;
 import org.apache.sis.xml.NilReason;
 import org.apache.sis.xml.NilObject;
@@ -67,11 +66,11 @@ public final class NilReferencingObject implements 
NilObject, ReferenceSystem {
         return NilReason.TEMPLATE;
     }
 
-    /*
-     * Simple properties. Not all of them are optional, but SIS is tolerant to 
null values.
-     * Returning null for collection are okay in the particular case of SIS 
implementation,
-     * because the constructor will replace empty collections by null 
references anyway.
+    /**
+     * Returns the localized "unnamed" name because this property is mandatory.
      */
-    @Override public Identifier          getName()  {return UNNAMED;}
-    @Override public InternationalString getScope() {return null;}
+    @Override
+    public Identifier getName() {
+        return UNNAMED;
+    }
 }
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/AbstractReferenceSystemTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/AbstractReferenceSystemTest.java
index b4814290ef..5314c05016 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/AbstractReferenceSystemTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/AbstractReferenceSystemTest.java
@@ -19,7 +19,7 @@ package org.apache.sis.referencing;
 import java.util.Map;
 import java.util.HashMap;
 import java.util.Locale;
-import static org.opengis.referencing.ReferenceSystem.*;
+import org.opengis.util.InternationalString;
 import org.apache.sis.io.wkt.Convention;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.metadata.iso.extent.DefaultExtent;
@@ -27,12 +27,17 @@ import 
org.apache.sis.metadata.iso.extent.DefaultTemporalExtent;
 import org.apache.sis.metadata.iso.extent.DefaultVerticalExtent;
 import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import static org.opengis.referencing.IdentifiedObject.*;
+import static org.opengis.referencing.ObjectDomain.*;
+
 // Test dependencies
 import org.junit.jupiter.api.Test;
 import static org.junit.jupiter.api.Assertions.*;
 import org.opengis.test.Validators;
 import org.apache.sis.test.TestCase;
 import org.apache.sis.test.mock.VerticalCRSMock;
+import static org.apache.sis.test.TestUtilities.getSingleton;
 import static org.apache.sis.test.Assertions.assertSerializedEquals;
 import static org.apache.sis.referencing.Assertions.assertWktEquals;
 
@@ -64,9 +69,11 @@ public final class AbstractReferenceSystemTest extends 
TestCase {
         final var reference = new AbstractReferenceSystem(properties);
         Validators.validate(reference);
 
-        assertEquals("This is a name",         reference.getName()   
.getCode());
-        assertEquals("This is a scope",        reference.getScope()  
.toString(Locale.ROOT));
-        assertEquals("Valide dans ce domaine", reference.getScope()  
.toString(Locale.FRENCH));
+        final InternationalString scope = 
getSingleton(reference.getDomains()).getScope();
+
+        assertEquals("This is a name",         reference.getName().getCode());
+        assertEquals("This is a scope",        scope.toString(Locale.ROOT));
+        assertEquals("Valide dans ce domaine", scope.toString(Locale.FRENCH));
         assertEquals("There is remarks",       
reference.getRemarks().toString(Locale.ENGLISH));
         assertEquals("Voici des remarques",    
reference.getRemarks().toString(Locale.FRENCH));
     }
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CRSTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CRSTest.java
index a347e64488..ce31a2b664 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CRSTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CRSTest.java
@@ -37,6 +37,9 @@ import org.apache.sis.system.Loggers;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.Utilities;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.referencing.ObjectDomain;
+
 // Test dependencies
 import org.junit.jupiter.api.Test;
 import static org.junit.jupiter.api.Assertions.*;
@@ -243,7 +246,7 @@ public final class CRSTest extends TestCaseWithLogs {
                 default: throw new AssertionError(i);
             }
             properties.put(DefaultProjectedCRS.NAME_KEY, "CRS #" + i);
-            properties.put(DefaultProjectedCRS.DOMAIN_OF_VALIDITY_KEY, new 
DefaultExtent(
+            properties.put(ObjectDomain.DOMAIN_OF_VALIDITY_KEY, new 
DefaultExtent(
                     null, new DefaultGeographicBoundingBox(-1, +1, ymin, 
ymax), null, null));
             crs[i] = new DefaultProjectedCRS(properties, baseCRS.geographic(), 
HardCodedConversions.MERCATOR, cs);
         }
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/GeodeticObjectVerifier.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/GeodeticObjectVerifier.java
index 63c6dfb55a..0163c3330c 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/GeodeticObjectVerifier.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/GeodeticObjectVerifier.java
@@ -34,6 +34,10 @@ import org.opengis.referencing.crs.GeodeticCRS;
 import org.apache.sis.metadata.privy.AxisNames;
 import org.apache.sis.measure.Units;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.referencing.ObjectDomain;
+import org.opengis.referencing.IdentifiedObject;
+
 // Test dependencies
 import static org.junit.jupiter.api.Assertions.*;
 
@@ -54,8 +58,21 @@ public final class GeodeticObjectVerifier {
     }
 
     /**
-     * Asserts that all {@link GeographicBoundingBox}, if any,
-     * {@linkplain #assertIsWorld(GeographicBoundingBox) encompasses the 
world}.
+     * Asserts that the first geographic bounding box, if any, encompasses the 
world.
+     *
+     * @param  object       the object to verify, or {@code null} if none.
+     * @param  isMandatory  {@code true} if an absence of world extent is a 
failure.
+     */
+    private static void assertIsWorld(final IdentifiedObject object, boolean 
isMandatory) {
+        for (ObjectDomain domain : object.getDomains()) {
+            assertIsWorld(domain.getDomainOfValidity(), isMandatory);
+            isMandatory = false;
+        }
+        assertFalse(isMandatory, "Expected a world extent element.");
+    }
+
+    /**
+     * Asserts that the first geographic bounding box, if any, encompasses the 
world.
      *
      * <p><b>Note:</b> a future version of this method may accept other kinds 
of extent,
      * for example a polygon encompassing the world.</p>
@@ -72,9 +89,7 @@ public final class GeodeticObjectVerifier {
                 }
             }
         }
-        if (isMandatory) {
-            fail("Expected a world extent element.");
-        }
+        assertFalse(isMandatory, "Expected a world extent element.");
     }
 
     /**
@@ -191,7 +206,7 @@ public final class GeodeticObjectVerifier {
      * <tr><th>Property</th> <th>Expected value</th></tr>
      * <tr><td>{@linkplain Identifier#getCode() Code} of the {@linkplain 
GeodeticDatum#getName() name}</td>
      *     <td>{@code "World Geodetic System 1984"}</td></tr>
-     * <tr><td>{@linkplain GeodeticDatum#getDomainOfValidity() Domain of 
validity}</td>
+     * <tr><td>{@linkplain GeodeticDatum#getDomains() Domain of validity}</td>
      *     <td>{@linkplain #assertIsWorld(GeographicBoundingBox) Is world} or 
absent</td></tr>
      * <tr><td>{@linkplain GeodeticDatum#getPrimeMeridian() Prime 
meridian}</td>
      *     <td>{@linkplain #assertIsGreenwich(PrimeMeridian) Is 
Greenwich}</td></tr>
@@ -203,9 +218,9 @@ public final class GeodeticObjectVerifier {
      * @param  isExtentMandatory  {@code true} if the domain of validity is 
required to contain an
      *                            {@code Extent} element for the world, or 
{@code false} if optional.
      */
-    public static void assertIsWGS84(final GeodeticDatum datum, final boolean 
isExtentMandatory) {
+    public static void assertIsWGS84(final GeodeticDatum datum, boolean 
isExtentMandatory) {
         assertEquals("World Geodetic System 1984", datum.getName().getCode(), 
"name");
-        assertIsWorld    (datum.getDomainOfValidity(), isExtentMandatory);
+        assertIsWorld    (datum, isExtentMandatory);
         assertIsGreenwich(datum.getPrimeMeridian());
         assertIsWGS84    (datum.getEllipsoid());
     }
@@ -219,7 +234,7 @@ public final class GeodeticObjectVerifier {
      * <tr><th>Property</th> <th>Expected value</th></tr>
      * <tr><td>{@linkplain Identifier#getCode() Code} of the {@linkplain 
GeodeticCRS#getName() name}</td>
      *     <td>{@code "WGS 84"}</td></tr>
-     * <tr><td>{@linkplain GeodeticCRS#getDomainOfValidity() Domain of 
validity}</td>
+     * <tr><td>{@linkplain GeodeticCRS#getDomains() Domain of validity}</td>
      *     <td>{@linkplain #assertIsWorld(GeographicBoundingBox) Is world} or 
absent</td></tr>
      * <tr><td>{@linkplain GeodeticCRS#getDatum() Datum}</td>
      *     <td>{@linkplain #assertIsWGS84(GeodeticDatum, boolean) Is 
WGS84}</td></tr>
@@ -235,7 +250,7 @@ public final class GeodeticObjectVerifier {
      */
     public static void assertIsWGS84(final GeodeticCRS crs, final boolean 
isExtentMandatory, final boolean isRangeMandatory) {
         assertEquals("WGS 84", crs.getName().getCode(), "name");
-        assertIsWorld(crs.getDomainOfValidity(), isExtentMandatory);
+        assertIsWorld(crs, isExtentMandatory);
         assertIsWGS84(crs.getDatum(), isExtentMandatory);
         final CoordinateSystem cs = crs.getCoordinateSystem();
         assertInstanceOf(EllipsoidalCS.class, cs, "coordinateSystem");
@@ -251,7 +266,7 @@ public final class GeodeticObjectVerifier {
      * <tr><th>Property</th> <th>Expected value</th></tr>
      * <tr><td>{@linkplain Identifier#getCode() Code} of the {@linkplain 
GeodeticDatum#getName() name}</td>
      *     <td>{@code "Mean Sea Level"}</td></tr>
-     * <tr><td>{@linkplain GeodeticDatum#getDomainOfValidity() Domain of 
validity}</td>
+     * <tr><td>{@linkplain GeodeticDatum#getDomains() Domain of validity}</td>
      *     <td>{@linkplain #assertIsWorld(GeographicBoundingBox) Is world} or 
absent</td></tr>
      * </table>
      *
@@ -261,7 +276,7 @@ public final class GeodeticObjectVerifier {
      */
     public static void assertIsMeanSeaLevel(final VerticalDatum datum, final 
boolean isExtentMandatory) {
         assertEquals("Mean Sea Level", datum.getName().getCode());
-        assertIsWorld(datum.getDomainOfValidity(), isExtentMandatory);
+        assertIsWorld(datum, isExtentMandatory);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultGeodeticCRSTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultGeodeticCRSTest.java
index 50fe1a8848..b09030fcee 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultGeodeticCRSTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultGeodeticCRSTest.java
@@ -25,6 +25,7 @@ import org.junit.jupiter.api.Test;
 import static org.junit.jupiter.api.Assertions.*;
 import org.opengis.test.Validators;
 import org.apache.sis.xml.test.TestCase;
+import static org.apache.sis.test.TestUtilities.getScope;
 
 
 /**
@@ -65,7 +66,7 @@ public final class DefaultGeodeticCRSTest extends TestCase {
          * Values in the following tests are specific to our XML file.
          * The actual texts in the EPSG database are more descriptive.
          */
-        assertEquals("Horizontal component of 3D system.", 
crs.getScope().toString());
+        assertEquals("Horizontal component of 3D system.", getScope(crs));
         /*
          * Marshal and compare with the original file.
          */
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java
index 005ec47095..ba1329e3a4 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java
@@ -41,6 +41,7 @@ import static org.junit.jupiter.api.Assertions.*;
 import org.opengis.test.Validators;
 import org.apache.sis.xml.test.TestCase;
 import org.apache.sis.referencing.cs.HardCodedCS;
+import static org.apache.sis.test.TestUtilities.getScope;
 import static org.apache.sis.test.Assertions.assertMessageContains;
 import static org.apache.sis.referencing.Assertions.assertWktEquals;
 import static 
org.apache.sis.referencing.Assertions.assertEpsgNameAndIdentifierEqual;
@@ -462,7 +463,7 @@ public final class DefaultProjectedCRSTest extends 
TestCase.WithLogs {
         Validators.validate(crs);
         assertEpsgNameAndIdentifierEqual("NTF (Paris) / Lambert zone II", 
27572, crs);
         assertEpsgNameAndIdentifierEqual("NTF (Paris)", 4807, 
crs.getBaseCRS());
-        assertEquals("Large and medium scale topographic mapping and 
engineering survey.", crs.getScope().toString());
+        assertEquals("Large and medium scale topographic mapping and 
engineering survey.", getScope(crs));
         assertAxisDirectionsEqual(crs.getBaseCRS().getCoordinateSystem(), 
AxisDirection.NORTH, AxisDirection.EAST);
         assertAxisDirectionsEqual(crs.getCoordinateSystem(), 
AxisDirection.EAST, AxisDirection.NORTH);
 
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/HardCodedCRS.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/HardCodedCRS.java
index a1ab55ea24..b13e1cdc69 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/HardCodedCRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/HardCodedCRS.java
@@ -20,12 +20,14 @@ import java.util.Map;
 import java.util.HashMap;
 import org.opengis.referencing.datum.PixelInCell;
 import static org.opengis.referencing.IdentifiedObject.*;
-import static org.opengis.referencing.ReferenceSystem.DOMAIN_OF_VALIDITY_KEY;
 import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.metadata.iso.extent.Extents;
 import org.apache.sis.referencing.datum.GeodeticDatumMock;
 import static org.apache.sis.referencing.IdentifiedObjects.getProperties;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import static org.opengis.referencing.ObjectDomain.DOMAIN_OF_VALIDITY_KEY;
+
 // Test dependencies
 import org.apache.sis.referencing.cs.HardCodedCS;
 import org.apache.sis.referencing.datum.HardCodedDatum;
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java
index 6c07e02f35..96f373a1a1 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java
@@ -21,6 +21,7 @@ import java.util.Locale;
 import java.io.InputStream;
 import jakarta.xml.bind.JAXBException;
 import org.opengis.metadata.extent.Extent;
+import org.opengis.util.InternationalString;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.datum.GeodeticDatum;
 import org.apache.sis.measure.Units;
@@ -39,6 +40,8 @@ import static org.junit.jupiter.api.Assertions.*;
 import org.opengis.test.Validators;
 import org.apache.sis.test.TestStep;
 import org.apache.sis.xml.test.TestCase;
+import static org.apache.sis.test.TestUtilities.getScope;
+import static org.apache.sis.test.TestUtilities.getSingleton;
 import static org.apache.sis.test.Assertions.assertSerializedEquals;
 import static org.apache.sis.metadata.Assertions.assertXmlEquals;
 import static org.apache.sis.referencing.Assertions.assertWktEquals;
@@ -101,9 +104,10 @@ public final class DefaultGeodeticDatumTest extends 
TestCase {
      */
     private static void validate(final DefaultGeodeticDatum datum) {
         Validators.validate(datum);
-        assertEquals("This is a name",        datum.getName   ().getCode());
-        assertEquals("This is a scope",       datum.getScope  
().toString(Locale.ROOT));
-        assertEquals("Valide pour tel usage", datum.getScope  
().toString(Locale.FRENCH));
+        InternationalString scope = 
getSingleton(datum.getDomains()).getScope();
+        assertEquals("This is a name",        datum.getName().getCode());
+        assertEquals("This is a scope",       scope.toString(Locale.ROOT));
+        assertEquals("Valide pour tel usage", scope.toString(Locale.FRENCH));
         assertEquals("There is remarks",      
datum.getRemarks().toString(Locale.ROOT));
         assertEquals("Voici des remarques",   
datum.getRemarks().toString(Locale.FRENCH));
         assertEquals("注です。",                
datum.getRemarks().toString(Locale.JAPANESE));
@@ -300,7 +304,7 @@ public final class DefaultGeodeticDatumTest extends 
TestCase {
         assertEquals("No distinction between the original and subsequent WGS 
84 frames.",
                 datum.getRemarks().toString());
         assertEquals("Satellite navigation.",
-                datum.getScope().toString());
+                getScope(datum));
         assertEquals("Station coordinates changed by a few centimetres in 
1994, 1997, 2002 and 2012.",
                 datum.getAnchorDefinition().get().toString());
         assertEquals(xmlDate("1984-01-01 00:00:00").toInstant(),
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultTemporalDatumTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultTemporalDatumTest.java
index 058f1fcb67..887c1f8870 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultTemporalDatumTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultTemporalDatumTest.java
@@ -17,7 +17,6 @@
 package org.apache.sis.referencing.datum;
 
 import java.util.Date;
-import java.util.Map;
 import java.util.HashMap;
 import java.io.InputStream;
 import jakarta.xml.bind.JAXBException;
@@ -32,8 +31,11 @@ import org.apache.sis.xml.test.TestCase;
 import org.apache.sis.metadata.iso.citation.HardCodedCitations;
 import static org.apache.sis.referencing.Assertions.assertWktEquals;
 import static org.apache.sis.test.TestUtilities.getSingleton;
+import static org.apache.sis.test.TestUtilities.getScope;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import static org.opengis.referencing.ObjectDomain.*;
+import static org.opengis.referencing.IdentifiedObject.*;
 import static org.opengis.test.Assertions.assertIdentifierEquals;
 
 
@@ -68,12 +70,12 @@ public final class DefaultTemporalDatumTest extends 
TestCase {
      * Creates the temporal datum to use for testing purpose.
      */
     private static DefaultTemporalDatum create() {
-        final Map<String,Object> properties = new HashMap<>(4);
-        assertNull(properties.put(DefaultTemporalDatum.IDENTIFIERS_KEY,
+        final var properties = new HashMap<String,Object>(4);
+        assertNull(properties.put(IDENTIFIERS_KEY,
                 new ImmutableIdentifier(HardCodedCitations.SIS, "SIS", "MJ")));
-        assertNull(properties.put(DefaultTemporalDatum.NAME_KEY, "Modified 
Julian"));
-        assertNull(properties.put(DefaultTemporalDatum.SCOPE_KEY, "History."));
-        assertNull(properties.put(DefaultTemporalDatum.REMARKS_KEY,
+        assertNull(properties.put(NAME_KEY, "Modified Julian"));
+        assertNull(properties.put(SCOPE_KEY, "History."));
+        assertNull(properties.put(REMARKS_KEY,
                 "Time measured as days since November 17, 1858 at 00:00 
UTC."));
         return new DefaultTemporalDatum(properties, new Date(ORIGIN));
     }
@@ -125,7 +127,7 @@ public final class DefaultTemporalDatumTest extends 
TestCase {
                                getSingleton(datum.getIdentifiers()), 
"identifier");
         assertEquals("Modified Julian", datum.getName().getCode());
         assertEquals("Time measured as days since November 17, 1858 at 00:00 
UTC.", datum.getRemarks().toString());
-        assertEquals("History.", datum.getScope().toString());
+        assertEquals("History.", getScope(datum));
         assertEquals(new Date(ORIGIN), datum.getOrigin());
     }
 }
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultVerticalDatumTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultVerticalDatumTest.java
index 073dad5049..aba9df56ff 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultVerticalDatumTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultVerticalDatumTest.java
@@ -35,6 +35,7 @@ import static 
org.apache.sis.referencing.GeodeticObjectVerifier.*;
 import org.junit.jupiter.api.Test;
 import static org.junit.jupiter.api.Assertions.*;
 import org.apache.sis.xml.test.TestCase;
+import static org.apache.sis.test.TestUtilities.getScope;
 import static org.apache.sis.metadata.Assertions.assertXmlEquals;
 import static org.apache.sis.referencing.Assertions.assertWktEquals;
 
@@ -129,7 +130,7 @@ public final class DefaultVerticalDatumTest extends 
TestCase {
          * The actual texts in the EPSG database are more descriptive.
          */
         assertEquals("Approximates geoid.",             
datum.getRemarks().toString());
-        assertEquals("Hydrography.",                    
datum.getScope().toString());
+        assertEquals("Hydrography.",                    getScope(datum));
         assertEquals("Averaged over a 19-year period.", 
datum.getAnchorDefinition().get().toString());
         /*
          * Test marshalling and compare with the original file.
@@ -162,7 +163,7 @@ public final class DefaultVerticalDatumTest extends 
TestCase {
          * Below is all we have.
          */
         assertEquals("Approximates geoid.", datum.getRemarks().toString());
-        assertEquals("Hydrography.",        datum.getScope().toString());
+        assertEquals("Hydrography.",        getScope(datum));
         /*
          * Test marshalling. We cannot yet compare with the original XML file
          * because of all the information lost. This may be fixed in a future
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/HardCodedDatum.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/HardCodedDatum.java
index 9c3c6a0c0c..bd7f3702d2 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/HardCodedDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/HardCodedDatum.java
@@ -21,12 +21,15 @@ import java.util.Map;
 import java.util.HashMap;
 import org.opengis.referencing.datum.PixelInCell;
 import org.opengis.referencing.datum.VerticalDatumType;
-import static org.opengis.referencing.datum.Datum.*;
 import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.referencing.internal.VerticalDatumTypes;
 import org.apache.sis.measure.Units;
 import static 
org.apache.sis.util.privy.StandardDateFormat.MILLISECONDS_PER_DAY;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import static org.opengis.referencing.IdentifiedObject.*;
+import static org.opengis.referencing.ObjectDomain.*;
+
 // Test dependencies
 import org.apache.sis.metadata.iso.citation.HardCodedCitations;
 
@@ -76,7 +79,7 @@ public final class HardCodedDatum {
      * {@code 
org.apache.sis.referencing.operation.transform.EarthGravitationalModel}.
      */
     public static final DefaultGeodeticDatum WGS72 = new DefaultGeodeticDatum(
-            properties("World Geodetic System 1972", "6322", WGS84.getScope()),
+            properties("World Geodetic System 1972", "6322", getScope(WGS84)),
             new DefaultEllipsoid(GeodeticDatumMock.WGS84.getEllipsoid()), 
GREENWICH);
 
     /**
@@ -100,7 +103,7 @@ public final class HardCodedDatum {
      * This is useful for testing datum shift from {@link #TOKYO}.
      */
     public static final DefaultGeodeticDatum JGD2000 = new 
DefaultGeodeticDatum(
-            properties("Japanese Geodetic Datum 2000", "6612", 
TOKYO.getScope()),
+            properties("Japanese Geodetic Datum 2000", "6612", 
getScope(TOKYO)),
             DefaultEllipsoid.createFlattenedSphere(properties("GRS 1980", 
"7019", null),
                     6378137, 298.257222101, Units.METRE), GREENWICH);
 
@@ -116,7 +119,7 @@ public final class HardCodedDatum {
      * This is not a valid datum according ISO 19111, but is used by Apache 
SIS for internal calculation.
      */
     public static final DefaultVerticalDatum ELLIPSOID = new 
DefaultVerticalDatum(
-            properties("Ellipsoid", null, SPHERE.getScope()),
+            properties("Ellipsoid", null, getScope(SPHERE)),
             VerticalDatumTypes.ELLIPSOIDAL);
 
     /**
@@ -163,6 +166,10 @@ public final class HardCodedDatum {
 
     /**
      * Creates a map of properties for the given name and EPSG code.
+     *
+     * @param  name   the object primary name.
+     * @param  code   the object identifier code.
+     * @param  scope  the object scope, or {@code null} if none.
      */
     private static Map<String,?> properties(final String name, final String 
code, final CharSequence scope) {
         final Map<String,Object> properties = new HashMap<>(4);
@@ -176,6 +183,13 @@ public final class HardCodedDatum {
         return properties;
     }
 
+    /**
+     * Returns the scope of the given object.
+     */
+    private static CharSequence getScope(final AbstractDatum object) {
+        return object.getDomains().iterator().next().getScope();
+    }
+
     /**
      * Do not allow instantiation of this class.
      */
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/SingleOperationMarshallingTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/SingleOperationMarshallingTest.java
index acb9daa993..9ced366669 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/SingleOperationMarshallingTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/SingleOperationMarshallingTest.java
@@ -47,6 +47,8 @@ import org.opengis.test.Validators;
 import org.apache.sis.xml.bind.referencing.CC_OperationParameterGroupTest;
 import org.apache.sis.xml.test.TestCase;
 import static org.apache.sis.test.TestUtilities.getSingleton;
+import static org.apache.sis.test.TestUtilities.getScope;
+import static org.apache.sis.test.TestUtilities.getDomainOfValidity;
 import static org.apache.sis.metadata.Assertions.assertXmlEquals;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
@@ -153,10 +155,10 @@ public final class SingleOperationMarshallingTest extends 
TestCase.WithLogs {
         final DefaultConversion c = unmarshalFile(DefaultConversion.class, 
openTestFile(false));
         assertEquals("World Mercator", c.getName().getCode(), "name");
         assertEquals("3395", getSingleton(c.getIdentifiers()).getCode(), 
"identifier");
-        assertEquals("Very small scale mapping.", 
String.valueOf(c.getScope()), "scope");
+        assertEquals("Very small scale mapping.", getScope(c), "scope");
         assertNull  (c.getOperationVersion(), "operationVersion");
 
-        final var e = (GeographicBoundingBox) 
getSingleton(c.getDomainOfValidity().getGeographicElements());
+        final GeographicBoundingBox e = getDomainOfValidity(c);
         assertEquals(+180, e.getEastBoundLongitude(), "eastBoundLongitude");
         assertEquals(-180, e.getWestBoundLongitude(), "westBoundLongitude");
         assertEquals(  84, e.getNorthBoundLatitude(), "northBoundLatitude");
@@ -218,7 +220,7 @@ public final class SingleOperationMarshallingTest extends 
TestCase.WithLogs {
         final DefaultTransformation c = 
unmarshalFile(DefaultTransformation.class, openTestFile(true));
         assertEquals("NTF (Paris) to NTF (1)", c.getName().getCode(), "name");
         assertEquals("1763", getSingleton(c.getIdentifiers()).getCode(), 
"identifier");
-        assertEquals("Change of prime meridian.", 
String.valueOf(c.getScope()), "scope");
+        assertEquals("Change of prime meridian.", getScope(c), "scope");
         assertEquals("IGN-Fra", c.getOperationVersion(), "operationVersion");
 
         final OperationMethod method = c.getMethod();
@@ -244,13 +246,13 @@ public final class SingleOperationMarshallingTest extends 
TestCase.WithLogs {
         final CoordinateReferenceSystem sourceCRS = c.getSourceCRS();
         assertInstanceOf(GeodeticCRS.class, sourceCRS, "sourceCRS");
         assertEquals("NTF (Paris)", sourceCRS.getName().getCode(), 
"sourceCRS.name");
-        assertEquals("Geodetic survey.", sourceCRS.getScope().toString(), 
"sourceCRS.scope");
+        assertEquals("Geodetic survey.", getScope(sourceCRS), 
"sourceCRS.scope");
         assertEquals("4807", 
getSingleton(sourceCRS.getIdentifiers()).getCode(), "sourceCRS.identifier");
 
         final CoordinateReferenceSystem targetCRS = c.getTargetCRS();
         assertInstanceOf(GeodeticCRS.class,  targetCRS, "targetCRS");
         assertEquals("NTF", targetCRS.getName().getCode(), "targetCRS.name");
-        assertEquals("Geodetic survey.", targetCRS.getScope().toString(), 
"targetCRS.scope");
+        assertEquals("Geodetic survey.", getScope(targetCRS), 
"targetCRS.scope");
         assertEquals("4275", 
getSingleton(targetCRS.getIdentifiers()).getCode(), "targetCRS.identifier");
 
         final var tr = assertInstanceOf(LinearTransform.class, 
c.getMathTransform());
diff --git 
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
index f948473262..90fa599b20 100644
--- 
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,6 +71,7 @@ import org.apache.sis.xml.test.DocumentComparator;
 import org.apache.sis.xml.test.TestCase;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.referencing.ObjectDomain;
 import org.opengis.referencing.datum.RealizationMethod;
 
 
@@ -332,7 +333,7 @@ public final class MetadataTest extends TestCase.WithLogs {
         properties.put(DefaultVerticalDatum.NAME_KEY, new 
NamedIdentifier(null, name));
         properties.put(DefaultVerticalDatum.IDENTIFIERS_KEY, new 
NamedIdentifier(null, "test", identifier, null, null));
         if (scope != null) {
-            properties.put(DefaultVerticalDatum.SCOPE_KEY, scope);
+            properties.put(ObjectDomain.SCOPE_KEY, scope);
         }
         return properties;
     }
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataVerticalTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataVerticalTest.java
index e1fe872ceb..57d29028b3 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataVerticalTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataVerticalTest.java
@@ -44,6 +44,7 @@ import org.apache.sis.xml.NilReason;
 import org.junit.jupiter.api.Test;
 import static org.junit.jupiter.api.Assertions.*;
 import org.apache.sis.xml.test.TestCase;
+import static org.apache.sis.test.TestUtilities.getScope;
 import static org.apache.sis.test.TestUtilities.getSingleton;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
@@ -164,10 +165,10 @@ public final class MetadataVerticalTest extends 
TestCase.WithLogs {
         assertEquals(10000, ve.getMaximumValue());
         final VerticalCRS crs = ve.getVerticalCRS();
         verifyIdentifiers("test1", crs);
-        assertEquals("World", crs.getScope().toString());
+        assertEquals("World", getScope(crs));
         final VerticalDatum datum = crs.getDatum();
         verifyIdentifiers("test2", datum);
-        assertEquals("World", datum.getScope().toString());
+        assertEquals("World", getScope(datum));
         assertEquals(VerticalDatumType.DEPTH, datum.getVerticalDatumType());   
 // Inferred from the name.
         final VerticalCS cs = crs.getCoordinateSystem();
         verifyIdentifiers("test3", cs);
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
index 538df66e92..4c17c8e31d 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
@@ -519,8 +519,9 @@ public class MetadataBuilder {
     }
 
     /**
-     * Information about the events or source data used in constructing the 
data specified by the
-     * {@linkplain DefaultLineage#getScope() scope}.
+     * Information about the events or source data used in constructing the 
data specified by the scope.
+     *
+     * @see DefaultLineage#getScope()
      */
     private DefaultLineage lineage;
 
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ComparisonMode.java 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ComparisonMode.java
index b86e96b975..49860713e3 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ComparisonMode.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ComparisonMode.java
@@ -95,9 +95,9 @@ public enum ComparisonMode {
      *
      * <h4>Application to coordinate reference systems</h4>
      * If the objects being compared are {@link 
org.opengis.referencing.crs.CoordinateReferenceSystem} instances,
-     * then only the properties relevant to the coordinate localization shall 
be compared.
+     * then only the properties impacting coordinate values shall be compared.
      * Metadata like the {@linkplain 
org.apache.sis.referencing.crs.AbstractCRS#getIdentifiers() identifiers}
-     * or the {@linkplain 
org.apache.sis.referencing.crs.AbstractCRS#getDomainOfValidity() domain of 
validity},
+     * or the {@linkplain 
org.apache.sis.referencing.crs.AbstractCRS#getDomains() domain of validity},
      * which have no impact on the coordinates being calculated, shall be 
ignored.
      *
      * <h4>Application to coordinate operations</h4>
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/LenientComparable.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/LenientComparable.java
index 3d305158f1..b1539f6d71 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/LenientComparable.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/LenientComparable.java
@@ -51,8 +51,7 @@ package org.apache.sis.util;
  *       <li>{@link ComparisonMode#IGNORE_METADATA IGNORE_METADATA} – The
  *           {@linkplain 
org.apache.sis.referencing.crs.AbstractCRS#getIdentifiers() identifiers},
  *           {@linkplain org.apache.sis.referencing.crs.AbstractCRS#getAlias() 
aliases},
- *           {@linkplain org.apache.sis.referencing.crs.AbstractCRS#getScope() 
scope},
- *           {@linkplain 
org.apache.sis.referencing.crs.AbstractCRS#getDomainOfValidity() domain of 
validity} and
+ *           {@linkplain 
org.apache.sis.referencing.crs.AbstractCRS#getDomains() domains} and
  *           {@linkplain 
org.apache.sis.referencing.crs.AbstractCRS#getRemarks() remarks}
  *           are ignored because they have no incidence on the coordinate 
values to be computed by
  *           {@linkplain 
org.opengis.referencing.operation.ConcatenatedOperation coordinate operations}.
diff --git 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/TestUtilities.java 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/TestUtilities.java
index 9a75478ef5..d8e2de7ce1 100644
--- 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/TestUtilities.java
+++ 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/TestUtilities.java
@@ -36,6 +36,10 @@ import java.text.Format;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import org.opengis.util.InternationalString;
+import org.opengis.referencing.IdentifiedObject;
+import org.opengis.metadata.extent.GeographicExtent;
+import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.apache.sis.util.Debug;
 import org.apache.sis.util.Static;
 import org.apache.sis.util.CharSequences;
@@ -46,6 +50,9 @@ import org.apache.sis.util.collection.TreeTableFormat;
 import org.apache.sis.util.privy.X364;
 import static org.apache.sis.util.privy.StandardDateFormat.UTC;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.referencing.ObjectDomain;
+
 // Test dependencies
 import static org.junit.jupiter.api.Assertions.*;
 
@@ -351,6 +358,31 @@ public final class TestUtilities extends Static {
         return element;
     }
 
+    /**
+     * Returns the scope of the given object. Exactly one scope shall exist.
+     *
+     * @param  object  the object for which to get the scope.
+     * @return the single scope of the given object.
+     */
+    public static String getScope(final IdentifiedObject object) {
+        InternationalString scope = 
getSingleton(object.getDomains()).getScope();
+        assertNotNull(scope, "Missing scope.");
+        return scope.toString();
+    }
+
+    /**
+     * Returns the domain of validity of the given object. Exactly one domain 
shall exist,
+     * and that domain shall be a geographic bounding box.
+     *
+     * @param  object  the object for which to get the domain of validity.
+     * @return the single domain of validity of the given object.
+     */
+    public static GeographicBoundingBox getDomainOfValidity(final 
IdentifiedObject object) {
+        ObjectDomain domain = getSingleton(object.getDomains());
+        GeographicExtent extent = 
getSingleton(domain.getDomainOfValidity().getGeographicElements());
+        return assertInstanceOf(GeographicBoundingBox.class, extent);
+    }
+
     /**
      * Returns a copy of the given array with the last coordinate values 
dropped for each coordinates.
      *
diff --git 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/ClassesTest.java 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/ClassesTest.java
index 90397af80c..1564f4fa73 100644
--- a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/ClassesTest.java
+++ b/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/ClassesTest.java
@@ -51,8 +51,6 @@ import java.io.Serializable;
 import java.awt.geom.Point2D;
 import javax.print.attribute.standard.PrinterStateReason;
 import javax.print.attribute.standard.PrinterStateReasons;
-import org.opengis.util.InternationalString;
-import org.opengis.metadata.extent.Extent;
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.ReferenceSystem;
 import org.opengis.referencing.cs.EllipsoidalCS;
@@ -147,12 +145,7 @@ public final class ClassesTest extends TestCase {
     /**
      * Dummy class for {@link #testGetLeafInterfaces()}.
      */
-    @SuppressWarnings("deprecation")
-    private abstract static class T1 implements GeographicCRS {
-        @Override public InternationalString getScope() {return null;}
-        @Override public Extent getDomainOfValidity() {return null;}
-    }
-    @SuppressWarnings("deprecation")
+    private abstract static class T1 implements GeographicCRS {}
     private abstract static class T2 extends T1 implements SingleCRS, 
CoordinateOperation {}
     private abstract static class T3 extends T2 implements Transformation {}
 
diff --git a/geoapi/snapshot b/geoapi/snapshot
index 622eb1227c..ae7a832b6a 160000
--- a/geoapi/snapshot
+++ b/geoapi/snapshot
@@ -1 +1 @@
-Subproject commit 622eb1227c8c04cf243747f3426e66565453cbb9
+Subproject commit ae7a832b6ae7cfc073cc5596bde39481b5b905df
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/CRSChooser.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/CRSChooser.java
index e5265d2672..8ba3e2497e 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/CRSChooser.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/CRSChooser.java
@@ -45,7 +45,6 @@ import javafx.stage.Window;
 import javafx.util.Duration;
 import org.opengis.geometry.Envelope;
 import org.opengis.util.FactoryException;
-import org.opengis.metadata.extent.Extent;
 import org.opengis.referencing.crs.GeodeticCRS;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.GeocentricCRS;
@@ -71,6 +70,9 @@ import org.apache.sis.metadata.iso.extent.Extents;
 import org.apache.sis.util.Exceptions;
 import org.apache.sis.util.resources.Vocabulary;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.referencing.ObjectDomain;
+
 
 /**
  * A list of Coordinate Reference Systems (CRS) from which the user can select.
@@ -78,7 +80,7 @@ import org.apache.sis.util.resources.Vocabulary;
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.5
  * @since   1.1
  */
 public class CRSChooser extends Dialog<CoordinateReferenceSystem> {
@@ -317,7 +319,7 @@ public class CRSChooser extends 
Dialog<CoordinateReferenceSystem> {
                 final CoordinateReferenceSystem crs = getValue();
                 type.setTextFill(Styles.NORMAL_TEXT);
                 type.setText(typeOf(crs, source.locale));
-                setDomainOfValidity(crs.getDomainOfValidity(), source.locale);
+                setDomainOfValidity(crs, source.locale);
             }
 
             /** Invoked in JavaFX thread on cancellation. */
@@ -345,17 +347,21 @@ public class CRSChooser extends 
Dialog<CoordinateReferenceSystem> {
     /**
      * Sets the text that describes the domain of validity.
      */
-    private void setDomainOfValidity(final Extent domainOfValidity, final 
Locale locale) {
-        String text  = Extents.getDescription(domainOfValidity, locale);
-        String tip   = text;
+    private void setDomainOfValidity(CoordinateReferenceSystem crs, final 
Locale locale) {
+        String extent = null;
+        for (ObjectDomain c : crs.getDomains()) {
+            extent = Extents.getDescription(c.getDomainOfValidity(), locale);
+            if (extent != null) break;
+        }
+        String tip   = extent;
         Color  color = Styles.NORMAL_TEXT;
-        if (!Utils.intersects(areaOfInterest, domainOfValidity)) {
+        if (!Utils.intersects(areaOfInterest, crs)) {
             tip   = 
Resources.forLocale(locale).getString(Resources.Keys.DoesNotCoverAOI);
-            text  = Styles.WARNING_ICON + " " + (text != null ? text : tip);
+            extent  = Styles.WARNING_ICON + " " + (extent != null ? extent : 
tip);
             color = Styles.ERROR_TEXT;
         }
         domain.setTextFill(color);
-        domain.setText(text);
+        domain.setText(extent);
         domain.getTooltip().setText(tip);
     }
 
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java
index d12548cf88..952c9d2b67 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java
@@ -623,7 +623,7 @@ public class RecentReferenceSystems {
             systems = new ArrayList<>(Math.min(NUM_SHOWN_ITEMS, n) + 
NUM_OTHER_ITEMS);
             for (int i=0; i<n; i++) {
                 final ReferenceSystem system = (ReferenceSystem) 
systemsOrCodes.get(i);
-                if (i >= NUM_CORE_ITEMS && !Utils.intersects(domain, 
system.getDomainOfValidity())) {
+                if (i >= NUM_CORE_ITEMS && !Utils.intersects(domain, system)) {
                     continue;
                 }
                 if (Utils.isIgnoreable(system)) {       // Ignore "Computer 
display" CRS.
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/Utils.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/Utils.java
index 41d5c19be6..ecf7ceaf8e 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/Utils.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/Utils.java
@@ -18,7 +18,6 @@ package org.apache.sis.gui.referencing;
 
 import org.opengis.geometry.Envelope;
 import org.opengis.util.FactoryException;
-import org.opengis.metadata.extent.Extent;
 import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.referencing.ReferenceSystem;
 import org.opengis.referencing.crs.SingleCRS;
@@ -33,6 +32,9 @@ import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.CRS;
 import static org.apache.sis.gui.internal.LogHandler.LOGGER;
 
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.referencing.ObjectDomain;
+
 
 /**
  * Utility methods shared by classes in this package only.
@@ -76,19 +78,25 @@ final class Utils {
     }
 
     /**
-     * Returns {@code true} if the specified domain of validity (typically 
obtained from a CRS) intersects the
-     * area of interest. If any information is missing, then this method 
conservatively returns {@code true}.
+     * Returns {@code true} if the specified domain of object intersects the 
area of interest.
+     * If any information is missing, then this method conservatively returns 
{@code true}.
      * The reason for returning {@code true} is because it will usually result 
in no action from the caller,
      * while {@code false} results in warning emitted or CRS filtered out.
      */
-    static boolean intersects(final ImmutableEnvelope areaOfInterest, final 
Extent domainOfValidity) {
+    static boolean intersects(final ImmutableEnvelope areaOfInterest, final 
ReferenceSystem crs) {
+        boolean conservative = true;
         if (areaOfInterest != null) {
-            final GeographicBoundingBox bbox = 
Extents.getGeographicBoundingBox(domainOfValidity);
-            if (bbox != null) {
-                return areaOfInterest.intersects(new ImmutableEnvelope(bbox));
+            for (final ObjectDomain domain : crs.getDomains()) {
+                final GeographicBoundingBox bbox = 
Extents.getGeographicBoundingBox(domain.getDomainOfValidity());
+                if (bbox != null) {
+                    if (areaOfInterest.intersects(new 
ImmutableEnvelope(bbox))) {
+                        return true;
+                    }
+                    conservative = false;
+                }
             }
         }
-        return true;
+        return conservative;
     }
 
     /**

Reply via email to