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

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

commit 428919e44a91cd9c40080b2d1630132d0ad322d4
Merge: 1483fcf71b ff6542a3f7
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Mon Apr 22 15:55:59 2024 +0200

    Merge branch 'geoapi-3.1': reduce usage of `AxisDirection.OTHER` and 
`VerticalDatumType`.

 .../apache/sis/coverage/grid/GridExtentCRS.java    |   6 +-
 .../apache/sis/metadata/iso/extent/Extents.java    |  62 ++++-----
 .../sis/metadata/iso/extent/ExtentsTest.java       |   9 +-
 .../apache/sis/io/wkt/GeodeticObjectParser.java    |  22 +--
 .../main/org/apache/sis/referencing/CRS.java       |   4 +-
 .../main/org/apache/sis/referencing/CommonCRS.java |  24 ++--
 .../org/apache/sis/referencing/cs/AbstractCS.java  |   4 +-
 .../main/org/apache/sis/referencing/cs/Codes.java  |  24 ++--
 .../org/apache/sis/referencing/cs/Normalizer.java  |   4 +-
 .../referencing/datum/DefaultVerticalDatum.java    |  14 +-
 .../referencing/factory/sql/EPSGCodeFinder.java    |   7 -
 .../referencing/factory/sql/EPSGDataAccess.java    |  14 +-
 .../sis/referencing/factory/sql/TableInfo.java     |   1 -
 .../apache/sis/referencing/internal/Legacy.java    |   8 +-
 .../referencing/internal/VerticalDatumTypes.java   | 147 ++++++++++++---------
 .../operation/CoordinateOperationRegistry.java     |   2 +-
 .../sis/referencing/operation/matrix/Matrices.java |   2 +-
 .../sis/referencing/privy/AxisDirections.java      |  27 ++--
 .../privy/EllipsoidalHeightCombiner.java           |   3 +-
 .../referencing/privy/ReferencingUtilities.java    |   7 +-
 .../org/apache/sis/io/wkt/TransliteratorTest.java  |  13 +-
 .../org/apache/sis/referencing/CommonCRSTest.java  |  20 +--
 .../apache/sis/referencing/cs/HardCodedAxes.java   |   4 +-
 .../datum/DefaultVerticalDatumTest.java            |   4 +-
 .../sis/referencing/datum/HardCodedDatum.java      |   2 +-
 .../referencing/datum/VerticalDatum (GML 3.1).xml  |   2 +-
 .../internal/VerticalDatumTypesTest.java           |  32 +++--
 .../sis/referencing/privy/AxisDirectionsTest.java  |  21 +--
 .../org/apache/sis/storage/netcdf/base/Axis.java   |   2 +-
 29 files changed, 251 insertions(+), 240 deletions(-)

diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtentCRS.java
index ae28430fdb,95020e45e4..8d078fddfd
--- 
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
@@@ -296,7 -299,7 +296,7 @@@ final class GridExtentCRS 
                      abbreviation = "t"; direction = AxisDirection.FUTURE; 
hasTime = true;
                  } else {
                      abbreviation = abbreviation(target);
-                     direction = AxisDirection.OTHER;
 -                    direction = AxisDirection.UNSPECIFIED;
++                    direction = AxisDirections.UNSPECIFIED;
                      hasOther = true;
                  }
                  /*
@@@ -308,7 -311,7 +308,7 @@@
                      final CoordinateSystemAxis previous = axes[k];
                      if (previous != null) {
                          if 
(direction.equals(AxisDirections.absolute(previous.getDirection()))) {
-                             direction = AxisDirection.OTHER;
 -                            direction = AxisDirection.UNSPECIFIED;
++                            direction = AxisDirections.UNSPECIFIED;
                              hasOther = true;
                          }
                          if (abbreviation.equals(previous.getAbbreviation())) {
@@@ -331,7 -334,7 +331,7 @@@
              if (axes[j] == null) {
                  final String name = 
Vocabulary.forLocale(locale).getString(Vocabulary.Keys.Dimension_1, j);
                  final String abbreviation = abbreviation(j);
-                 axes[j] = axis(csFactory, name, abbreviation, 
AxisDirection.OTHER);
 -                axes[j] = axis(csFactory, name, abbreviation, 
AxisDirection.UNSPECIFIED);
++                axes[j] = axis(csFactory, name, abbreviation, 
AxisDirections.UNSPECIFIED);
              }
          }
          /*
diff --cc 
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/Extents.java
index 360b50cc81,2fda0bf211..b4ec7fc882
--- 
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
@@@ -371,16 -362,15 +365,15 @@@ public final class Extents extends Stat
       * performs a choice based on the vertical datum and the unit of 
measurement:
       *
       * <ul class="verbose">
-      *   <li><p><b>Choice based on vertical datum</b><br>
+      *   <li><p><b>Choice based on realization method</b><br>
 -     *   Only the extents associated (indirectly, through their CRS) to the 
same non-null {@link RealizationMethod}
 +     *   Only the extents associated (indirectly, through their CRS) to the 
same non-null {@link VerticalDatumType}
-      *   will be taken in account. If all datum types are null, then this 
method conservatively uses only the first
-      *   vertical extent. Otherwise the datum type used for filtering the 
vertical extents is:</p>
+      *   will be taken in account. If all realization methods are absent, 
then this method conservatively uses only
+      *   the first vertical extent. Otherwise the realization method used for 
filtering the vertical extents is:</p>
       *
       *   <ul>
-      *     <li>{@link VerticalDatumType#GEOIDAL} or {@link 
VerticalDatumType#DEPTH DEPTH} if at least one extent
-      *         uses those datum types. For this method, {@code DEPTH} is 
considered as equivalent to {@code GEOIDAL}
-      *         except for the axis direction.</li>
-      *     <li>Otherwise, the first non-null datum type found in iteration 
order.</li>
 -     *     <li>{@link RealizationMethod#GEOID} if at least one extent uses 
this realization method.</li>
 -     *     <li>Otherwise, {@link RealizationMethod#TIDAL} if at least one 
extent uses this realization method.</li>
++     *     <li>{@link VerticalDatumType#GEOIDAL} if at least one extent uses 
this realization method.</li>
++     *     <li>Otherwise, {@link VerticalDatumType#DEPTH} if at least one 
extent uses this realization method.</li>
+      *     <li>Otherwise, the first non-null realization type found in 
iteration order.</li>
       *   </ul>
       *
       *   <div class="note"><b>Rational:</b> like {@linkplain 
#getGeographicBoundingBox(Extent) geographic bounding box},
@@@ -420,23 -409,21 +412,20 @@@
       * @since 0.4
       */
      @OptionalCandidate
 -    @SuppressWarnings("deprecation")
      public static MeasurementRange<Double> getVerticalRange(final Extent 
extent) {
          MeasurementRange<Double> range = null;
-         VerticalDatumType selectedType = null;
 -        RealizationMethod selectedMethod = null;
++        VerticalDatumType selectedMethod = null;
          if (extent != null) {
              for (final VerticalExtent element : 
nonNull(extent.getVerticalElements())) {
                  double min = element.getMinimumValue();
                  double max = element.getMaximumValue();
                  final VerticalCRS crs = element.getVerticalCRS();
-                 VerticalDatumType type = null;
 -                RealizationMethod method = null;
++                VerticalDatumType method = null;
                  Unit<?> unit = null;
                  if (crs != null) {
                      final VerticalDatum datum = crs.getDatum();
                      if (datum != null) {
-                         type = datum.getVerticalDatumType();
-                         if (type == VerticalDatumType.DEPTH) {
-                             type = VerticalDatumType.GEOIDAL;
-                         }
 -                        method = datum.getRealizationMethod().orElse(method);
++                        method = datum.getVerticalDatumType();
                      }
                      final CoordinateSystemAxis axis = 
crs.getCoordinateSystem().getAxis(0);
                      unit = axis.getUnit();
@@@ -456,14 -443,17 +445,17 @@@
                      }
                      /*
                       * If the new range is not measured relative to the same 
kind of surface than the previous range,
-                      * then we do not know how to combine those ranges. Do 
nothing, unless the new range is a Mean Sea
-                      * Level Height in which case we forget all previous 
ranges and use the new one instead.
+                      * then we do not know how to combine those ranges. Do 
nothing, unless the new range is a geoidal
+                      * height in which case we forget all previous ranges and 
use the new one instead.
                       */
-                     if (!type.equals(selectedType)) {
-                         if (!type.equals(VerticalDatumType.GEOIDAL)) {
+                     if (method != selectedMethod) {
 -                        if (selectedMethod == RealizationMethod.GEOID ||
 -                                   (method != RealizationMethod.GEOID &&
 -                                    method != RealizationMethod.TIDAL))
++                        if (selectedMethod == VerticalDatumType.GEOIDAL ||
++                                   (method != VerticalDatumType.GEOIDAL &&
++                                    method != VerticalDatumType.DEPTH))
+                         {
                              continue;
                          }
-                     } else if (selectedType != null) {
+                     } else if (selectedMethod != null) {
                          /*
                           * If previous range did not specify any unit, then 
unconditionally replace it by
                           * the new range since it provides more information. 
If both ranges specify units,
diff --cc 
endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/extent/ExtentsTest.java
index 71f0b919df,848979dc2f..f562dd5a60
--- 
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/extent/ExtentsTest.java
+++ 
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/extent/ExtentsTest.java
@@@ -31,6 -31,9 +31,9 @@@ import org.apache.sis.measure.Units
  import org.apache.sis.measure.MeasurementRange;
  import static org.apache.sis.metadata.privy.ReferencingServices.NAUTICAL_MILE;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.referencing.datum.RealizationMethod;
++// Specific to the main branch:
++import org.opengis.referencing.datum.VerticalDatumType;
+ 
  // Test dependencies
  import org.junit.jupiter.api.Test;
  import static org.junit.jupiter.api.Assertions.*;
@@@ -82,7 -85,7 +85,7 @@@ public final class ExtentsTest extends 
          Unit<?> unit = null;
          for (final DefaultVerticalExtent e : extents) {
              unit = 
e.getVerticalCRS().getCoordinateSystem().getAxis(0).getUnit();
-             if (Units.isLinear(unit)) break;
 -            if 
(e.getVerticalCRS().getDatum().getRealizationMethod().orElse(null) == 
RealizationMethod.GEOID) break;
++            if (e.getVerticalCRS().getDatum().getVerticalDatumType() == 
VerticalDatumType.GEOIDAL) break;
          }
          final UnitConverter c = unit.getConverterToAny(Units.METRE);
          /*
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
index 09d1ba92d7,643d8ceb56..af7f934d23
--- 
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
@@@ -875,7 -865,7 +875,7 @@@ class GeodeticObjectParser extends Math
                      if (defaultUnit == null) {
                          throw 
parent.missingComponent(WKTKeywords.ParametricUnit);
                      }
-                     direction = AxisDirection.OTHER;
 -                    direction = AxisDirection.UNSPECIFIED;
++                    direction = AxisDirections.UNSPECIFIED;
                      nz = "Parametric";
                      z = "p";
                      break;
@@@ -1461,12 -1446,13 +1461,12 @@@
              return null;
          }
          final String name = element.pullString("name");
-         VerticalDatumType type = null;
 -        @SuppressWarnings("deprecation")
 -        RealizationMethod method = null;
++        VerticalDatumType method = null;
          if (isWKT1) {
-             type = 
VerticalDatumTypes.fromLegacy(element.pullInteger("datum"));
+             method = 
VerticalDatumTypes.fromLegacy(element.pullInteger("datum"));
          }
-         if (type == null) {
-             type = VerticalDatumTypes.guess(name, null, null);
+         if (method == null) {
+             method = VerticalDatumTypes.guess(name, null, null);
          }
          final DatumFactory datumFactory = factories.getDatumFactory();
          try {
@@@ -2258,7 -2247,7 +2258,7 @@@
                  buffer.append(number);
                  axes[i] = csFactory.createCoordinateSystemAxis(
                          singletonMap(CoordinateSystemAxis.NAME_KEY, 
buffer.toString()),
-                         number, AxisDirection.OTHER, Units.UNITY);
 -                        number, AxisDirection.UNSPECIFIED, Units.UNITY);
++                        number, AxisDirections.UNSPECIFIED, Units.UNITY);
              }
              final Map<String,Object> properties = 
parseMetadataAndClose(element, name, baseCRS);
              final Map<String,Object> axisName = 
singletonMap(CoordinateSystem.NAME_KEY, AxisDirections.appendTo(new 
StringBuilder("CS"), axes));
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
index 8873622ad1,7c012a1e8e..fc312dda24
--- 
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
@@@ -945,8 -992,8 +945,8 @@@ public final class CRS extends Static 
       * of the domain of validity of all components.
       *
       * <h4>Ellipsoidal height</h4>
-      * If a two-dimensional geographic or projected CRS if followed or 
preceded by a vertical CRS with ellipsoidal
-      * {@linkplain 
org.apache.sis.referencing.datum.DefaultVerticalDatum#getVerticalDatumType() 
datum type}, then
+      * If a two-dimensional geographic or projected CRS is followed or 
preceded by a vertical CRS with ellipsoidal
 -     * {@linkplain 
org.apache.sis.referencing.datum.DefaultVerticalDatum#getRealizationMethod() 
realization method},
++     * {@linkplain 
org.apache.sis.referencing.datum.DefaultVerticalDatum#getVerticalDatumType() 
datum type},
       * this method combines them in a single three-dimensional geographic or 
projected CRS.  Note that standalone
       * ellipsoidal heights are not allowed according ISO 19111. But if such 
situation is nevertheless found, then
       * the action described here fixes the issue. This is the reverse of 
<code>{@linkplain #getVerticalComponent
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
index 622d9c2836,8abad5348b..3ff72a19f8
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
@@@ -48,9 -47,9 +48,9 @@@ import org.opengis.referencing.datum.Da
  import org.opengis.referencing.datum.Ellipsoid;
  import org.opengis.referencing.datum.GeodeticDatum;
  import org.opengis.referencing.datum.PrimeMeridian;
+ import org.opengis.referencing.datum.TemporalDatum;
  import org.opengis.referencing.datum.VerticalDatum;
 -import org.opengis.referencing.datum.RealizationMethod;
 +import org.opengis.referencing.datum.VerticalDatumType;
- import org.opengis.referencing.datum.TemporalDatum;
  import org.opengis.referencing.datum.EngineeringDatum;
  import org.opengis.metadata.extent.GeographicBoundingBox;
  import static org.opengis.referencing.IdentifiedObject.NAME_KEY;
@@@ -1259,8 -1247,8 +1256,6 @@@ public enum CommonCRS 
           *   <tr><th>Direction:</th>            <td>{@link 
AxisDirection#UP}</td></tr>
           *   <tr><th>Unit:</th>                 <td>{@link 
Units#METRE}</td></tr>
           * </table></blockquote>
--         *
-          * @see VerticalDatumType#GEOIDAL
 -         * @see RealizationMethod#TIDAL
           */
          MEAN_SEA_LEVEL(true, (short) 5714, (short) 5100),
  
@@@ -1274,8 -1262,8 +1269,6 @@@
           *   <tr><th>Direction:</th>            <td>{@link 
AxisDirection#DOWN}</td></tr>
           *   <tr><th>Unit:</th>                 <td>{@link 
Units#METRE}</td></tr>
           * </table></blockquote>
--         *
-          * @see VerticalDatumType#GEOIDAL
 -         * @see RealizationMethod#TIDAL
           */
          DEPTH(true, (short) 5715, (short) 5100),
  
@@@ -1343,9 -1332,8 +1337,8 @@@
           * Creates a new enumeration value of the given name.
           *
           * <h4>API design note</h4>
-          * This constructor does not expect {@link VerticalDatumType} 
constant in order to avoid too
-          * early class initialization. In particular, we do not want early 
dependency to the SIS-specific
-          * {@code VerticalDatumTypes.ELLIPSOIDAL} constant.
 -         * This constructor does not expect {@link RealizationMethod} 
constant in order to avoid
++         * This constructor does not expect {@link VerticalDatumType} 
constant in order to avoid
+          * the creation of non-standard code list value before they are 
actually needed.
           */
          private Vertical(final boolean isEPSG, final short crs, final short 
datum) {
              this.isEPSG = isEPSG;
@@@ -1481,7 -1467,16 +1472,12 @@@
                          if (isEPSG) {
                              object = 
StandardDefinitions.createVerticalDatum(datum);
                          } else {
+                             /*
+                              * All cases where the first constructor argument 
is `false`, currently BAROMETRIC and
+                              * ELLIPSOIDAL. The way to construct the 
ellipsoidal pseudo-method shall be equivalent
+                              * to a call to 
`VerticalDatumTypes.ellipsoidal()`.
+                              */
 -                            RealizationMethod method = null;
 -                            if (this != OTHER_SURFACE) {
 -                                method = RealizationMethod.valueOf(name());
 -                            }
 -                            object = new 
DefaultVerticalDatum(properties(datum), method);
 +                            object = new 
DefaultVerticalDatum(properties(datum), VerticalDatumType.valueOf(name()));
                          }
                          cached = object;
                      }
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AbstractCS.java
index 4a03d9f291,1625e20723..a43be5bf76
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AbstractCS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/cs/AbstractCS.java
@@@ -228,7 -229,7 +228,7 @@@ public class AbstractCS extends Abstrac
               * more than one time axis. Such case happen in meteorological 
models.
               */
              final AxisDirection dir = AxisDirections.absolute(direction);
-             if (!dir.equals(AxisDirection.OTHER)) {
 -            if (dir != AxisDirection.UNSPECIFIED && dir != 
AxisDirection.OTHER) {
++            if (dir != AxisDirections.UNSPECIFIED && dir != 
AxisDirection.OTHER) {
                  for (int j=i; --j>=0;) {
                      final AxisDirection other = axes[j].getDirection();
                      final AxisDirection abs = AxisDirections.absolute(other);
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultVerticalDatum.java
index 4f911e51e5,776b9d95dd..6b29262c9d
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultVerticalDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultVerticalDatum.java
@@@ -198,26 -223,15 +198,25 @@@ public class DefaultVerticalDatum exten
      }
  
      /**
 -     * Returns the method through which this vertical reference frame is 
realized.
 +     * Returns the type of this datum, or infers the type from the datum name 
if no type were specified.
 +     * The latter case occurs after unmarshalling, since GML 3.2 does not 
contain any attribute for the datum type.
 +     * It may also happen if the datum were created using reflection.
 +     *
-      * <p>This method uses heuristic rules and may be changed in any future 
SIS version. If the type cannot be
-      * determined, default on the ellipsoidal type since it will usually 
implies no additional calculation.</p>
++     * <p>This method uses heuristic rules and may be changed in any future 
SIS version.</p>
       *
 -     * @return method through which this vertical reference frame is realized.
 +     * <p>No synchronization needed; this is not a problem if this value is 
computed twice.
 +     * This method returns only existing immutable instances.</p>
       *
 -     * @since 2.0
 +     * @see #getVerticalDatumType()
 +     * @see #getTypeElement()
       */
 -    @Override
 -    public Optional<RealizationMethod> getRealizationMethod() {
 -        return Optional.ofNullable(method);
 +    private VerticalDatumType type() {
 +        VerticalDatumType t = type;
 +        if (t == null) {
 +            final ReferenceIdentifier name = super.getName();
 +            type = t = VerticalDatumTypes.guess(name != null ? name.getCode() 
: null, super.getAlias(), null);
 +        }
 +        return t;
      }
  
      /**
@@@ -264,10 -283,9 +263,9 @@@
              }
              default: {
                  /*
 -                 * RealizationMethod is considered as metadata because it is 
related to the anchor definition,
 +                 * VerticalDatumType is considered as metadata because it is 
related to the anchor definition,
                   * which is itself considered as metadata. Furthermore, 
GeodeticObjectParser and EPSGDataAccess
-                  * do not always set this property to the same value: the 
former uses the information provided
-                  * by the coordinate system axis while the other does not.
+                  * do not always set this property to the same value, because 
of historical changes in the WKT.
                   */
                  return true;
              }
@@@ -290,10 -308,10 +288,10 @@@
       * Formats this datum as a <i>Well Known Text</i> {@code 
VerticalDatum[…]} element.
       *
       * <h4>Compatibility note</h4>
-      * OGC 01-009 defined numerical codes for various vertical datum types, 
for example 2005 for geoidal height
-      * and 2002 for ellipsoidal height. Such codes were formatted for all 
{@code Datum} subtypes in WKT 1.
-      * Datum types became provided only for vertical datum in the ISO 
19111:2003 specification, then removed
-      * completely in ISO 19111:2007.
+      * OGC 01-009 defined numerical codes for various vertical datum types, 
for example 2005 for geoidal height.
+      * Such codes were formatted for all {@code Datum} subtypes in WKT 1. 
Datum types became specified only for
+      * vertical datum in the ISO 19111:2003 standard, then removed completely 
in the ISO 19111:2007 standard.
 -     * They were reintroduced in a different form ({@link RealizationMethod}) 
in the ISO 19111:2019 standard.
++     * They were reintroduced in a different form ({@code RealizationMethod}) 
in the ISO 19111:2019 standard.
       *
       * @return {@code "VerticalDatum"} (WKT 2) or {@code "Vert_Datum"} (WKT 
1).
       *
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
index 3b89bbf16c,a05d123ee6..e8f36e5fb3
--- 
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
@@@ -1719,14 -1712,8 +1713,8 @@@ codes:  for (int i=0; i<codes.length; i
                          datum = datumFactory.createGeodeticDatum(properties, 
ellipsoid, meridian);
                          break;
                      }
-                     /*
-                      * Vertical datum type is hard-coded to geoidal. It would 
be possible to infer other
-                      * types by looking at the coordinate system, but it 
could result in different datum
-                      * associated to the same EPSG code.  Since vertical 
datum type is no longer part of
-                      * ISO 19111:2007, it is probably not worth to handle 
such cases.
-                      */
                      case "vertical": {
-                         datum = datumFactory.createVerticalDatum(properties, 
VERTICAL_DATUM_TYPE);
 -                        datum = datumFactory.createVerticalDatum(properties, 
(RealizationMethod) null);
++                        datum = datumFactory.createVerticalDatum(properties, 
VerticalDatumType.GEOIDAL);
                          break;
                      }
                      /*
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Legacy.java
index eba35c1897,ca37336531..ff134ec0fa
--- 
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
@@@ -90,7 -63,8 +90,7 @@@ public final class Legacy 
       * the ISO 19111's ones (ISO names are "Geocentric X", "Geocentric Y" and 
"Geocentric Z"). This constant uses
       * the invalid names and directions for WKT 1 parsing/formatting purposes.
       */
-     private static final CartesianCS LEGACY = new 
DefaultCartesianCS(Map.of(NAME_KEY, "Legacy geocentric"),
 -    @SuppressWarnings("deprecation")
+     private static final CartesianCS GEOCENTRIC = new 
DefaultCartesianCS(Map.of(NAME_KEY, "Legacy geocentric"),
              new DefaultCoordinateSystemAxis(Map.of(NAME_KEY, "X"), "X", 
AxisDirection.OTHER, Units.METRE),
              new DefaultCoordinateSystemAxis(Map.of(NAME_KEY, "Y"), "Y", 
AxisDirection.EAST,  Units.METRE),
              new DefaultCoordinateSystemAxis(Map.of(NAME_KEY, "Z"), "Z", 
AxisDirection.NORTH, Units.METRE));
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/VerticalDatumTypes.java
index b6de9fa530,11f58d1e6d..6ccaa8d0c4
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/VerticalDatumTypes.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/VerticalDatumTypes.java
@@@ -16,11 -16,11 +16,12 @@@
   */
  package org.apache.sis.referencing.internal;
  
+ import java.util.Locale;
  import java.util.Collection;
 +import java.util.function.Predicate;
  import javax.measure.Unit;
 +import org.opengis.util.CodeList;
  import org.opengis.util.GenericName;
 -import org.opengis.referencing.datum.RealizationMethod;
  import org.opengis.referencing.datum.VerticalDatumType;
  import org.opengis.referencing.cs.CoordinateSystemAxis;
  import org.opengis.referencing.cs.AxisDirection;
@@@ -36,71 -35,93 +37,90 @@@ import org.apache.sis.measure.Units
   * Those constants are not in public API because they were intentionally 
omitted from ISO 19111,
   * and the ISO experts said that they should really not be public.
   *
 + * <p>This class implements {@link Predicate} for opportunist reasons.
 + * This implementation convenience may change in any future SIS version.</p>
 + *
   * @author  Martin Desruisseaux (IRD, Geomatys)
   */
 -public final class VerticalDatumTypes {
 +public final class VerticalDatumTypes implements Predicate<CodeList<?>> {
      /**
-      * A vertical datum for ellipsoidal heights that are measured along the
-      * normal to the ellipsoid used in the definition of horizontal datum.
+      * A pseudo-realization method for ellipsoidal heights that are measured 
along
+      * the normal to the ellipsoid used in the definition of horizontal datum.
+      * <strong>The use of this method is deprecated</strong> as ellipsoidal 
height
+      * should never be separated from the horizontal components according ISO 
19111.
       *
-      * <p>Identifier: {@code CS_DatumType.CS_VD_Ellipsoidal}</p>
+      * <h4>Legacy</h4>
+      * This type was associated to code 2000 in the {@code Vert_Datum} 
element of the legacy WKT 1 format.
+      * The UML identifier was {@code CS_DatumType.CS_VD_Ellipsoidal}.
+      *
+      * @see org.apache.sis.referencing.CommonCRS.Vertical#ELLIPSOIDAL
       */
-     public static final VerticalDatumType ELLIPSOIDAL = 
VerticalDatumType.valueOf("ELLIPSOIDAL");
+     static final String ELLIPSOIDAL = "ELLIPSOIDAL";
  
      /**
-      * A vertical datum for orthometric heights that are measured along the 
plumb line.
+      * A vertical datum type for orthometric heights that are measured along 
the plumb line.
       *
-      * <p>Identifier: {@code CS_DatumType.CS_VD_Orthometric}</p>
+      * <h4>Legacy</h4>
+      * This type was associated to code 2001 in the {@code Vert_Datum} 
element of the legacy WKT 1 format.
+      * The UML identifier was {@code CS_DatumType.CS_VD_Orthometric}.
       */
-     public static final VerticalDatumType ORTHOMETRIC = 
VerticalDatumType.valueOf("ORTHOMETRIC");
+     private static final String ORTHOMETRIC = "ORTHOMETRIC";
  
      /**
-      * Mapping from the numeric values used in legacy specification (OGC 
01-009) to {@link VerticalDatumType}.
-      * Indices in this array are the legacy codes minus 2000.
+      * A vertical datum type for origin of the vertical axis based on 
atmospheric pressure.
+      *
+      * <h4>Legacy</h4>
+      * This type was associated to code 2003 in the {@code Vert_Datum} 
element of the legacy WKT 1 format.
+      * The UML identifier was {@code CS_DatumType.CS_VD_AltitudeBarometric}.
       *
-      * <strong>This array shall not be fill before the above static 
constants.</strong>
+      * @see org.apache.sis.referencing.CommonCRS.Vertical#BAROMETRIC
       */
-     private static final VerticalDatumType[] TYPES;
+     static final String BAROMETRIC = "BAROMETRIC";
  
 -    /**
 -     * Do not allow instantiation of this class.
 -     */
 -    private VerticalDatumTypes() {
 -    }
 -
      /**
-      * Mapping from {@link VerticalDatumType} to the numeric values used in 
legacy specification (OGC 01-009).
+      * Returns a pseudo-realization method for ellipsoidal heights.
+      * <strong>The use of this method is deprecated</strong> as ellipsoidal 
height
+      * should never be separated from the horizontal components according ISO 
19111.
+      *
+      * <h4>Maintenance note</h4>
 -     * If the implementation of this method is modified, search for {@code 
RealizationMethod.valueOf}
++     * If the implementation of this method is modified, search for {@code 
VerticalDatumType.valueOf}
+      * at least in {@link 
org.apache.sis.referencing.CommonCRS.Vertical#datum()} and make sure that
+      * the code is equivalent.
+      *
+      * @return the ellipsoidal pseudo-realization method.
       */
-     private static final short[] LEGACY_CODES;
-     static {
-         TYPES = new VerticalDatumType[7];
-         LEGACY_CODES = new short[Math.max(ELLIPSOIDAL.ordinal(), 
ORTHOMETRIC.ordinal()) + 1];
-         for (short code = 2000; code <= 2006; code++) {
-             final VerticalDatumType type;
-             switch (code) {
-                 case 2000: type = VerticalDatumType .OTHER_SURFACE; break;  
// CS_VD_Other
-                 case 2001: type = VerticalDatumTypes.ORTHOMETRIC;   break;  
// CS_VD_Orthometric
-                 case 2002: type = VerticalDatumTypes.ELLIPSOIDAL;   break;  
// CS_VD_Ellipsoidal
-                 case 2003: type = VerticalDatumType .BAROMETRIC;    break;  
// CS_VD_AltitudeBarometric
-                 case 2005: type = VerticalDatumType .GEOIDAL;       break;  
// CS_VD_GeoidModelDerived
-                 case 2006: type = VerticalDatumType .DEPTH;         break;  
// CS_VD_Depth
-                 default:   continue;
-             }
-             TYPES[code - 2000] = type;
-             LEGACY_CODES[type.ordinal()] = code;
-         }
 -    public static RealizationMethod ellipsoidal() {
 -        return RealizationMethod.valueOf(ELLIPSOIDAL);
++    public static VerticalDatumType ellipsoidal() {
++        return VerticalDatumType.valueOf(ELLIPSOIDAL);
+     }
+ 
+     /**
+      * Returns {@code true} if the given value is the ellipsoidal 
pseudo-realization method.
+      *
+      * @param  method  the method to test, or {@code null}.
+      * @return whether the given method is the ellipsoidal pseudo-realization 
method.
+      */
 -    public static boolean ellipsoidal(final RealizationMethod method) {
++    public static boolean ellipsoidal(final VerticalDatumType method) {
+         return (method != null) && 
ELLIPSOIDAL.equalsIgnoreCase(method.name());
      }
  
      /**
       * Returns the vertical datum type from a legacy code. The legacy codes 
were defined in
-      * <a href="https://www.ogc.org/standards/ct";>OGC 01-009</a>
-      * (<cite>Coordinate Transformation Services)</cite>, which also defined 
the version 1 of
-      * <a 
href="http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/doc-files/WKT.html";><cite>Well
-      * Known Text</cite></a> format (WKT 1). This method is used for WKT 1 
parsing.
+      * OGC 01-009 (<cite>Coordinate Transformation Services)</cite>, which 
also defined the version 1
+      * of <cite>Well Known Text</cite></a> format (WKT 1). This method is 
used for WKT 1 parsing.
       *
       * @param  code  the legacy vertical datum code.
-      * @return the vertical datum type, or {@code null} if the code is 
unrecognized.
+      * @return the vertical datum type, or {@code null} if none.
       */
-     public static VerticalDatumType fromLegacy(int code) {
-         code -= 2000;
-         return (code >= 0 && code < TYPES.length) ? TYPES[code] : null;
 -    public static RealizationMethod fromLegacy(final int code) {
++    public static VerticalDatumType fromLegacy(final int code) {
+         switch (code) {
+         //  case 2000: return null;                                     // 
CS_VD_Other
 -            case 2001: return RealizationMethod.valueOf(ORTHOMETRIC);   // 
CS_VD_Orthometric
++            case 2001: return VerticalDatumType.valueOf(ORTHOMETRIC);   // 
CS_VD_Orthometric
+             case 2002: return ellipsoidal();                            // 
CS_VD_Ellipsoidal
 -            case 2003: return RealizationMethod.valueOf(BAROMETRIC);    // 
CS_VD_AltitudeBarometric
 -            case 2005: return RealizationMethod.GEOID;                  // 
CS_VD_GeoidModelDerived
 -            case 2006: return RealizationMethod.TIDAL;                  // 
CS_VD_Depth
++            case 2003: return VerticalDatumType.BAROMETRIC;             // 
CS_VD_AltitudeBarometric
++            case 2005: return VerticalDatumType.GEOIDAL;                // 
CS_VD_GeoidModelDerived
++            case 2006: return VerticalDatumType.DEPTH;                  // 
CS_VD_Depth
+             default:   return null;
+         }
      }
  
      /**
@@@ -110,35 -131,76 +130,38 @@@
       * @param  type  the vertical datum type, or {@code null} if unknown.
       * @return the legacy code for the given datum type, or 0 if unknown.
       */
+     @SuppressWarnings("deprecation")
      public static int toLegacy(final VerticalDatumType type) {
          if (type != null) {
-             final int ordinal = type.ordinal();
-             if (ordinal >= 0 && ordinal < LEGACY_CODES.length) {
-                 return LEGACY_CODES[ordinal];
+             switch (type.name().toUpperCase(Locale.US)) {
+                 case ORTHOMETRIC: return 2001;      // CS_VD_Orthometric
+                 case ELLIPSOIDAL: return 2002;      // CS_VD_Ellipsoidal
+                 case BAROMETRIC:  return 2003;      // 
CS_VD_AltitudeBarometric
+                 case "GEOIDAL":   return 2005;      // CS_VD_GeoidModelDerived
+                 case "DEPTH":     return 2006;      // CS_VD_Depth
              }
          }
-         return 0;
+         return 2000;
      }
  
 -    /**
 -     * Returns the vertical datum type from a realization method.
 -     * If the given method cannot be mapped to a legacy type, then this 
method returns "other surface".
 -     * This is because the vertical datum type was a mandatory property in 
legacy OGC/ISO standards.
 -     * This method is used for writing GML documents older than GML 3.2.
 -     *
 -     * @param  method  the realization method, or {@code null}.
 -     * @return the vertical datum type (never null).
 -     */
 -    @SuppressWarnings("deprecation")
 -    public static VerticalDatumType fromMethod(final RealizationMethod 
method) {
 -        if (method == RealizationMethod.GEOID) return 
VerticalDatumType.GEOIDAL;
 -        if (method == RealizationMethod.TIDAL) return VerticalDatumType.DEPTH;
 -        if (method != null) {
 -            return 
VerticalDatumType.valueOf(method.name().toUpperCase(Locale.US));
 -        }
 -        return VerticalDatumType.OTHER_SURFACE;
 -    }
 -
 -    /**
 -     * Returns the realization method from a vertical datum type.
 -     * This method is used for reading GML documents older than GML 3.2.
 -     *
 -     * @param  type  the vertical datum type, or {@code null}.
 -     * @return the realization method, or {@code null} if none.
 -     */
 -    @SuppressWarnings("deprecation")
 -    public static RealizationMethod toMethod(final VerticalDatumType type) {
 -        if (type != null) {
 -            if (type == VerticalDatumType.GEOIDAL)         return 
RealizationMethod.GEOID;
 -            if (type == VerticalDatumType.DEPTH)           return 
RealizationMethod.TIDAL;
 -            if (type == VerticalDatumType.BAROMETRIC)      return 
RealizationMethod.valueOf(BAROMETRIC);
 -            if (ORTHOMETRIC.equalsIgnoreCase(type.name())) return 
RealizationMethod.valueOf(ORTHOMETRIC);
 -            if (ELLIPSOIDAL.equalsIgnoreCase(type.name())) return 
ellipsoidal();
 -        }
 -        return null;
 -    }
 -
      /**
-      * Guesses the type of a datum from its name, aliases or a given vertical 
axis. This is sometimes needed
-      * after XML unmarshalling or WKT parsing, since GML 3.2 and ISO 19162 do 
not contain any attribute for
-      * the datum type.
+      * Guesses the realization method of a datum from its name, aliases or a 
given vertical axis.
+      * This is sometimes needed after XML unmarshalling or WKT parsing, 
because GML 3.2 and ISO 19162
+      * do not contain any attribute for the datum type.
       *
-      * <p>This method uses heuristic rules and may be changed in any future 
SIS version.
-      * If the type cannot be determined, defaults to {@link 
VerticalDatumType#OTHER_SURFACE}.</p>
+      * <p>This method uses heuristic rules and may be changed in any future 
SIS version.</p>
       *
       * @param  name     the name of the datum for which to guess a type, or 
{@code null} if unknown.
       * @param  aliases  the aliases of the datum for which to guess a type, 
or {@code null} if unknown.
       * @param  axis     the vertical axis for which to guess a type, or 
{@code null} if unknown.
 -     * @return a datum type, or {@code null} if none can be guessed.
 +     * @return a datum type, or {@link VerticalDatumType#OTHER_SURFACE} if 
none can be guessed.
       */
 -    public static RealizationMethod guess(final String name, final 
Collection<? extends GenericName> aliases,
 +    public static VerticalDatumType guess(final String name, final 
Collection<? extends GenericName> aliases,
              final CoordinateSystemAxis axis)
      {
-         VerticalDatumType type = guess(name);
-         if (type != null) {
-             return type;
 -        RealizationMethod method = guess(name);
++        VerticalDatumType method = guess(name);
+         if (method != null) {
+             return method;
          }
          if (aliases != null) {
              for (final GenericName alias : aliases) {
@@@ -155,13 -217,13 +178,13 @@@
                  if (abbreviation.length() == 1) {
                      AxisDirection dir = AxisDirection.UP;               // 
Expected direction for accepting the type.
                      switch (abbreviation.charAt(0)) {
-                         case 'h': type = ELLIPSOIDAL; break;
-                         case 'H': type = VerticalDatumType.GEOIDAL; break;
-                         case 'D': type = VerticalDatumType.DEPTH; dir = 
AxisDirection.DOWN; break;
+                         case 'h': method = ellipsoidal(); break;
 -                        case 'H': method = RealizationMethod.GEOID; break;
 -                        case 'D': method = RealizationMethod.TIDAL; dir = 
AxisDirection.DOWN; break;
 -                        default:  return null;
++                        case 'H': method = VerticalDatumType.GEOIDAL; break;
++                        case 'D': method = VerticalDatumType.DEPTH; dir = 
AxisDirection.DOWN; break;
 +                        default:  return VerticalDatumType.OTHER_SURFACE;
                      }
                      if (dir.equals(axis.getDirection())) {
-                         return type;
+                         return method;
                      }
                  }
              } else if (Units.isPressure(unit)) {
@@@ -172,23 -234,19 +195,23 @@@
      }
  
      /**
-      * Guesses the type of a datum of the given name. This method attempts to 
guess only if the given name
-      * contains at least one letter. If the type cannot be determined, 
returns {@code null}.
+      * Guesses the realization method of a datum of the given name. This 
method attempts to guess only if
+      * the given name contains at least one letter. If the type cannot be 
determined, returns {@code null}.
       *
-      * @param  name  name of the datum for which to guess a type, or {@code 
null}.
-      * @return a datum type, or {@code null} if none can be guessed.
+      * @param  name  name of the datum for which to guess a realization 
method, or {@code null}.
+      * @return a realization method, or {@code null} if none can be guessed.
       */
 -    private static RealizationMethod guess(final String name) {
 +    private static VerticalDatumType guess(final String name) {
          if (name != null) {
              if (CharSequences.equalsFiltered("Mean Sea Level", name, 
Characters.Filter.LETTERS_AND_DIGITS, true)) {
 -                return RealizationMethod.TIDAL;
 +                return VerticalDatumType.GEOIDAL;
              }
 -            if (name.contains("geoid")) {
 -                return RealizationMethod.GEOID;
 +            for (int i=0; i<name.length();) {
 +                final int c = name.codePointAt(i);
 +                if (Character.isLetter(c)) {
 +                    return CodeLists.find(VerticalDatumType.class, new 
VerticalDatumTypes(name));
 +                }
 +                i += Character.charCount(c);
              }
          }
          return null;
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/AxisDirections.java
index 96a6d5e2ad,4671df63a3..3826d39454
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/AxisDirections.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/AxisDirections.java
@@@ -35,11 -35,6 +35,11 @@@ import org.apache.sis.util.iso.Types
  import org.apache.sis.measure.Units;
  import static org.apache.sis.util.CharSequences.*;
  
 +// Specific to the main branch:
 +import org.opengis.annotation.UML;
 +import static org.opengis.annotation.Obligation.CONDITIONAL;
- import static org.opengis.annotation.Specification.UNSPECIFIED;
++import static org.opengis.annotation.Specification.ISO_19111;
 +
  
  /**
   * Utilities methods related to {@link AxisDirection}.
@@@ -71,53 -66,8 +71,59 @@@ public final class AxisDirections exten
       *
       * @see #isUserDefined(AxisDirection)
       */
 -    private static final int LAST_ORDINAL = UNSPECIFIED.ordinal();
 +    private static final int LAST_ORDINAL = DISPLAY_DOWN.ordinal();
 +
 +    /**
 +     * Forward direction.
 +     * For an observer at the centre of the object this is will be towards 
its front, bow or nose.
 +     * Added in ISO 19111:2019 (was not in ISO 19111:2007).
 +     */
-     @UML(identifier="forward", obligation=CONDITIONAL, 
specification=UNSPECIFIED)
++    @UML(identifier="forward", obligation=CONDITIONAL, 
specification=ISO_19111)
 +    public static final AxisDirection FORWARD = 
AxisDirection.valueOf("FORWARD");
 +
 +    /**
 +     * Starboard direction.
 +     * For an observer at the centre of the object this will be towards its 
right.
 +     * Added in ISO 19111:2019 (was not in ISO 19111:2007).
 +     */
-     @UML(identifier="starboard", obligation=CONDITIONAL, 
specification=UNSPECIFIED)
++    @UML(identifier="starboard", obligation=CONDITIONAL, 
specification=ISO_19111)
 +    public static final AxisDirection STARBOARD = 
AxisDirection.valueOf("STARBOARD");
 +
 +    /**
 +     * Port direction.
 +     * For an observer at the centre of the object this will be towards its 
left.
 +     * Added in ISO 19111:2019 (was not in ISO 19111:2007).
 +     */
-     @UML(identifier="port", obligation=CONDITIONAL, specification=UNSPECIFIED)
++    @UML(identifier="port", obligation=CONDITIONAL, specification=ISO_19111)
 +    public static final AxisDirection PORT = AxisDirection.valueOf("PORT");
 +
 +    /**
 +     * Direction of geographic angles (bearing).
 +     * Added in ISO 19111:2019 (was not in ISO 19111:2007).
 +     */
-     @UML(identifier="clockwise", obligation=CONDITIONAL, 
specification=UNSPECIFIED)
++    @UML(identifier="clockwise", obligation=CONDITIONAL, 
specification=ISO_19111)
 +    public static final AxisDirection CLOCKWISE = 
AxisDirection.valueOf("CLOCKWISE");
 +
 +    /**
 +     * Direction of arithmetic angles. Used in polar coordinate systems.
 +     * Added in ISO 19111:2019 (was not in ISO 19111:2007).
 +     */
-     @UML(identifier="counterClockwise", obligation=CONDITIONAL, 
specification=UNSPECIFIED)
++    @UML(identifier="counterClockwise", obligation=CONDITIONAL, 
specification=ISO_19111)
 +    public static final AxisDirection COUNTER_CLOCKWISE = 
AxisDirection.valueOf("COUNTER_CLOCKWISE");
 +
 +    /**
 +     * Distance from the origin in a polar coordinate system.
 +     * Added in ISO 19111:2019 (was not in ISO 19111:2007).
 +     */
-     @UML(identifier="awayFrom", obligation=CONDITIONAL, 
specification=UNSPECIFIED)
++    @UML(identifier="awayFrom", obligation=CONDITIONAL, 
specification=ISO_19111)
 +    public static final AxisDirection AWAY_FROM = 
AxisDirection.valueOf("AWAY_FROM");
 +
++    /**
++     * Axis positive direction is unspecified.
++     */
++    @UML(identifier="unspecified", obligation=CONDITIONAL, 
specification=ISO_19111)
++    public static final AxisDirection UNSPECIFIED = 
AxisDirection.valueOf("UNSPECIFIED");
+ 
      /**
       * For each direction, the opposite direction.
       * This map shall be immutable after construction.
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/ReferencingUtilities.java
index a1a8eb1a5c,65b6d458f0..9fc219d785
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/ReferencingUtilities.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/ReferencingUtilities.java
@@@ -272,10 -220,7 +272,7 @@@ public final class ReferencingUtilitie
       */
      public static boolean isEllipsoidalHeight(final VerticalDatum datum) {
          if (datum != null) {
-             final VerticalDatumType type = datum.getVerticalDatumType();
-             if (type != null) {
-                 return "ELLIPSOIDAL".equalsIgnoreCase(type.name());
-             }
 -            return 
datum.getRealizationMethod().map(VerticalDatumTypes::ellipsoidal).orElse(false);
++            return 
VerticalDatumTypes.ellipsoidal(datum.getVerticalDatumType());
          }
          return false;
      }
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/TransliteratorTest.java
index 31c0786c52,3ba62d844f..0e4ad77061
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/TransliteratorTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/TransliteratorTest.java
@@@ -21,6 -21,6 +21,7 @@@ import org.opengis.referencing.cs.Spher
  import org.opengis.referencing.cs.EllipsoidalCS;
  import org.opengis.referencing.cs.CoordinateSystem;
  import org.apache.sis.metadata.privy.AxisNames;
++import org.apache.sis.referencing.privy.AxisDirections;
  
  // Test dependencies
  import org.junit.jupiter.api.Test;
@@@ -98,12 -98,12 +99,12 @@@ public final class TransliteratorTest e
      @Test
      public void testToUnicodeAbbreviation() {
          final Transliterator t = Transliterator.DEFAULT;
-         assertEquals("φ",  t.toUnicodeAbbreviation("ellipsoidal", 
AxisDirection.NORTH, "P"), "P");
-         assertEquals("φ",  t.toUnicodeAbbreviation("ellipsoidal", 
AxisDirection.NORTH, "B"), "B");
-         assertEquals("λ",  t.toUnicodeAbbreviation("ellipsoidal", 
AxisDirection.EAST,  "L"), "L");
-         assertEquals("θ",  t.toUnicodeAbbreviation("polar",       
AxisDirection.OTHER, "U"), "U");
-         assertEquals("Ω",  t.toUnicodeAbbreviation("spherical",   
AxisDirection.NORTH, "U"), "U");
-         assertEquals("θ",  t.toUnicodeAbbreviation("spherical",   
AxisDirection.EAST,  "V"), "V");
+         assertEquals("φ",  t.toUnicodeAbbreviation("ellipsoidal", 
AxisDirection.NORTH,     "P"), "P");
+         assertEquals("φ",  t.toUnicodeAbbreviation("ellipsoidal", 
AxisDirection.NORTH,     "B"), "B");
+         assertEquals("λ",  t.toUnicodeAbbreviation("ellipsoidal", 
AxisDirection.EAST,      "L"), "L");
 -        assertEquals("θ",  t.toUnicodeAbbreviation("polar",       
AxisDirection.CLOCKWISE, "U"), "U");
++        assertEquals("θ",  t.toUnicodeAbbreviation("polar",       
AxisDirections.CLOCKWISE,"U"), "U");
+         assertEquals("Ω",  t.toUnicodeAbbreviation("spherical",   
AxisDirection.NORTH,     "U"), "U");
+         assertEquals("θ",  t.toUnicodeAbbreviation("spherical",   
AxisDirection.EAST,      "V"), "V");
      }
  
      /**
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java
index b2560e43fb,c109be58ca..80f6689c5d
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java
@@@ -214,34 -214,37 +214,34 @@@ public final class CommonCRSTest extend
       * Verifies the vertical datum enumeration.
       */
      @Test
 -    @SuppressWarnings("deprecation")
      public void testVertical() {
          for (final CommonCRS.Vertical e : CommonCRS.Vertical.values()) {
-             final VerticalDatumType datumType;
 -            final RealizationMethod method;
++            final VerticalDatumType method;
              final String axisName, datumName;
              switch (e) {
-                 case NAVD88:         axisName = 
AxisNames.GRAVITY_RELATED_HEIGHT; datumName = "North American Vertical Datum 
1988"; datumType = VerticalDatumType. GEOIDAL;       break;
-                 case BAROMETRIC:     axisName = "Barometric altitude";        
    datumName = "Constant pressure surface";          datumType = 
VerticalDatumType. BAROMETRIC;    break;
-                 case MEAN_SEA_LEVEL: axisName = 
AxisNames.GRAVITY_RELATED_HEIGHT; datumName = "Mean Sea Level";                 
    datumType = VerticalDatumType. GEOIDAL;       break;
-                 case DEPTH:          axisName = AxisNames.DEPTH;              
    datumName = "Mean Sea Level";                     datumType = 
VerticalDatumType. GEOIDAL;       break;
-                 case ELLIPSOIDAL:    axisName = AxisNames.ELLIPSOIDAL_HEIGHT; 
    datumName = "Ellipsoid";                          datumType = 
VerticalDatumTypes.ELLIPSOIDAL;   break;
-                 case OTHER_SURFACE:  axisName = "Height";                     
    datumName = "Other surface";                      datumType = 
VerticalDatumType. OTHER_SURFACE; break;
 -                case NAVD88:         axisName = 
AxisNames.GRAVITY_RELATED_HEIGHT; datumName = "North American Vertical Datum 
1988"; method = RealizationMethod. GEOID; break;
 -                case BAROMETRIC:     axisName = "Barometric altitude";        
    datumName = "Constant pressure surface";          method = 
RealizationMethod.valueOf("BAROMETRIC"); break;
 -                case MEAN_SEA_LEVEL: axisName = 
AxisNames.GRAVITY_RELATED_HEIGHT; datumName = "Mean Sea Level";                 
    method = RealizationMethod. TIDAL; break;
 -                case DEPTH:          axisName = AxisNames.DEPTH;              
    datumName = "Mean Sea Level";                     method = 
RealizationMethod. TIDAL; break;
++                case NAVD88:         axisName = 
AxisNames.GRAVITY_RELATED_HEIGHT; datumName = "North American Vertical Datum 
1988"; method = VerticalDatumType. GEOIDAL;       break;
++                case BAROMETRIC:     axisName = "Barometric altitude";        
    datumName = "Constant pressure surface";          method = 
VerticalDatumType. BAROMETRIC;    break;
++                case MEAN_SEA_LEVEL: axisName = 
AxisNames.GRAVITY_RELATED_HEIGHT; datumName = "Mean Sea Level";                 
    method = VerticalDatumType. GEOIDAL;       break;
++                case DEPTH:          axisName = AxisNames.DEPTH;              
    datumName = "Mean Sea Level";                     method = 
VerticalDatumType. GEOIDAL;       break;
+                 case ELLIPSOIDAL:    axisName = AxisNames.ELLIPSOIDAL_HEIGHT; 
    datumName = "Ellipsoid";                          method = 
VerticalDatumTypes.ellipsoidal(); break;
 -                case OTHER_SURFACE:  axisName = "Height";                     
    datumName = "Other surface";                      method = null; break;
++                case OTHER_SURFACE:  axisName = "Height";                     
    datumName = "Other surface";                      method = 
VerticalDatumType. OTHER_SURFACE; break;
                  default: throw new AssertionError(e);
              }
              final String        name  = e.name();
              final VerticalDatum datum = e.datum();
              final VerticalCRS   crs   = e.crs();
 -            if (e.isEPSG) {
 +            if (e.isEPSG && !name.startsWith("NAV")) {
                  /*
-                  * BAROMETRIC, ELLIPSOIDAL and OTHER_SURFACE uses an axis 
named "Height", which is not
-                  * a valid axis name according ISO 19111. We skip the 
validation test for those enums.
+                  * BAROMETRIC and ELLIPSOIDAL uses an axis named "Height", 
which is not a valid
+                  * axis name according ISO 19111. We skip the validation test 
for those enums.
                   */
                  Validators.validate(crs);
              }
              assertSame(datum, e.datum(), name);                         // 
Datum before CRS creation.
              assertSame(crs.getDatum(), e.datum(), name);                // 
Datum after CRS creation.
              assertEquals(datumName, datum.getName().getCode(), name);
-             assertEquals(datumType, datum.getVerticalDatumType(), name);
++            assertEquals(method, datum.getVerticalDatumType(), name);
              assertEquals(axisName,  
crs.getCoordinateSystem().getAxis(0).getName().getCode(), name);
 -            if (!e.isEPSG) {  // Because the information is not in EPSG 
database 9.x.
 -                assertEquals(method, 
datum.getRealizationMethod().orElse(null), name);
 -            }
          }
      }
  
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/HardCodedAxes.java
index 48ac69bb32,b7b43a955b..bffb391065
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/HardCodedAxes.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/cs/HardCodedAxes.java
@@@ -471,8 -468,8 +471,8 @@@ public final class HardCodedAxes 
       * and the unit is dimensionless. This constant is sometimes used as a 
placeholder
       * for axes that were not properly defined.
       */
-     public static final DefaultCoordinateSystemAxis UNDEFINED = 
create("Undefined", "z",
-             AxisDirection.OTHER, Units.UNITY, Double.NEGATIVE_INFINITY, 
Double.POSITIVE_INFINITY, null);
+     public static final DefaultCoordinateSystemAxis UNDEFINED = 
create("Undefined", "m",
 -            AxisDirection.UNSPECIFIED, Units.UNITY, Double.NEGATIVE_INFINITY, 
Double.POSITIVE_INFINITY, null);
++            AxisDirections.UNSPECIFIED, Units.UNITY, 
Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, null);
  
      /**
       * Creates a new axis of the given name, abbreviation, direction and unit.
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultVerticalDatumTest.java
index 81fb6a38bd,9de1a8749b..fe792940f1
--- 
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
@@@ -65,34 -65,6 +65,34 @@@ public final class DefaultVerticalDatum
                         : "VerticalDatum.xml");
      }
  
 +    /**
 +     * Tests the {@link DefaultVerticalDatum#getVerticalDatumType()} method 
in a state
 +     * simulating unmarshalling of GML 3.2 document.
 +     *
 +     * @throws NoSuchFieldException   Should never happen.
 +     * @throws IllegalAccessException Should never happen.
 +     */
 +    @Test
 +    public void testAfterUnmarshal() throws NoSuchFieldException, 
IllegalAccessException {
 +        final Field typeField = 
DefaultVerticalDatum.class.getDeclaredField("type");
 +        typeField.setAccessible(true);
 +        assertEquals(VerticalDatumType .GEOIDAL,       typeForName(typeField, 
"Geoidal height"));
 +        assertEquals(VerticalDatumType .DEPTH,         typeForName(typeField, 
"Some depth measurement"));
-         assertEquals(VerticalDatumTypes.ELLIPSOIDAL,   typeForName(typeField, 
"Ellipsoidal height"));
++        assertEquals(VerticalDatumTypes.ellipsoidal(), typeForName(typeField, 
"Ellipsoidal height"));
 +        assertEquals(VerticalDatumType .OTHER_SURFACE, typeForName(typeField, 
"NotADepth"));
 +    }
 +
 +    /**
 +     * Returns the vertical datum type inferred by {@link 
DefaultVerticalDatum} for the given name.
 +     */
 +    private static VerticalDatumType typeForName(final Field typeField, final 
String name) throws IllegalAccessException {
 +        final var datum = new DefaultVerticalDatum(
 +                Map.of(DefaultVerticalDatum.NAME_KEY, name),
 +                VerticalDatumType.OTHER_SURFACE);
 +        typeField.set(datum, null);
 +        return datum.getVerticalDatumType();
 +    }
 +
      /**
       * Tests {@link DefaultVerticalDatum#toWKT()}.
       */
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/VerticalDatumTypesTest.java
index 950f9f7f82,2b846e8736..7a19958814
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/VerticalDatumTypesTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/VerticalDatumTypesTest.java
@@@ -16,7 -16,9 +16,8 @@@
   */
  package org.apache.sis.referencing.internal;
  
 -import org.opengis.referencing.datum.RealizationMethod;
  import org.opengis.referencing.datum.VerticalDatumType;
+ import org.apache.sis.referencing.CommonCRS;
  import org.apache.sis.util.ArraysExt;
  
  // Test dependencies
@@@ -37,14 -40,25 +38,25 @@@ public final class VerticalDatumTypesTe
      public VerticalDatumTypesTest() {
      }
  
+     /**
+      * Verifies name constraint with values defined in {@link 
org.apache.sis.referencing.CommonCRS.Vertical}.
+      * Some enumeration values must have the same names as the constants 
defined in {@link VerticalDatumTypes},
 -     * because the realization method is obtained by a call to {@link 
RealizationMethod#valueOf(String)}.
++     * because the realization method is obtained by a call to {@link 
VerticalDatumType#valueOf(String)}.
+      */
+     @Test
+     public void verifyNameConstraint() {
+         assertEquals(VerticalDatumTypes.ELLIPSOIDAL, 
CommonCRS.Vertical.ELLIPSOIDAL.name());
+         assertEquals(VerticalDatumTypes.BAROMETRIC,  
CommonCRS.Vertical.BAROMETRIC.name());
+     }
+ 
      /**
       * Tests the {@link VerticalDatumTypes#fromLegacy(int)} method.
       */
      @Test
      public void testFromLegacy() {
-         assertEquals(VerticalDatumTypes.ELLIPSOIDAL, 
VerticalDatumTypes.fromLegacy(2002));
-         assertEquals(VerticalDatumType .GEOIDAL,     
VerticalDatumTypes.fromLegacy(2005));
-         assertEquals(VerticalDatumType .DEPTH,       
VerticalDatumTypes.fromLegacy(2006));
+         assertEquals(VerticalDatumTypes.ellipsoidal(), 
VerticalDatumTypes.fromLegacy(2002));
 -        assertEquals(RealizationMethod .GEOID,         
VerticalDatumTypes.fromLegacy(2005));
 -        assertEquals(RealizationMethod .TIDAL,         
VerticalDatumTypes.fromLegacy(2006));
++        assertEquals(VerticalDatumType .GEOIDAL,       
VerticalDatumTypes.fromLegacy(2005));
++        assertEquals(VerticalDatumType .DEPTH,         
VerticalDatumTypes.fromLegacy(2006));
      }
  
      /**
@@@ -58,13 -72,13 +70,13 @@@
      }
  
      /**
-      * Tests the list of vertical datum types. Note that {@link 
#testFromLegacy()} must be executed
-      * first for ensuring {@link VerticalDatumTypes} class initialization 
prior this test.
+      * Verifies the list of realization methods.
       */
      @Test
-     public void testVerticalDatumTypes() {
+     public void verifyCodeList() {
 -        final RealizationMethod expected = VerticalDatumTypes.ellipsoidal();  
  // Must be first.
 -        final RealizationMethod[] types = RealizationMethod.values();
 -        assertEquals(RealizationMethod.LEVELLING, types[0]);
++        final VerticalDatumType expected = VerticalDatumTypes.ellipsoidal();  
  // Must be first.
 +        final VerticalDatumType[] types = VerticalDatumType.values();
 +        assertEquals(VerticalDatumType.OTHER_SURFACE, types[0]);
-         assertTrue(ArraysExt.contains(types, VerticalDatumTypes.ELLIPSOIDAL));
+         assertTrue(ArraysExt.contains(types, expected));
      }
  }
diff --cc 
endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/privy/AxisDirectionsTest.java
index 528027e9ca,b926d08d7c..f50eb7f5f9
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/privy/AxisDirectionsTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/privy/AxisDirectionsTest.java
@@@ -32,11 -32,6 +32,12 @@@ import org.apache.sis.referencing.cs.Ha
  import org.apache.sis.referencing.cs.HardCodedCS;
  import org.apache.sis.test.TestCase;
  
 +// Specific to the main branch:
 +import static org.apache.sis.referencing.privy.AxisDirections.AWAY_FROM;
 +import static org.apache.sis.referencing.privy.AxisDirections.CLOCKWISE;
 +import static 
org.apache.sis.referencing.privy.AxisDirections.COUNTER_CLOCKWISE;
++import static org.apache.sis.referencing.privy.AxisDirections.UNSPECIFIED;
 +
  
  /**
   * Tests the {@link AxisDirections} class.
diff --cc 
endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java
index 5784bbf8e5,8bff2968de..9ca1fbd600
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java
@@@ -630,7 -630,7 +630,7 @@@ public final class Axis extends NamedEl
              } else switch (order) {
                  case 0:  dir = AxisDirection.COLUMN_POSITIVE; break;
                  case 1:  dir = AxisDirection.ROW_POSITIVE;    break;
-                 default: dir = AxisDirection.OTHER;           break;
 -                default: dir = AxisDirection.UNSPECIFIED;     break;
++                default: dir = AxisDirections.UNSPECIFIED;    break;
              }
          }
          final String abbr;

Reply via email to