You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2025/07/24 17:53:22 UTC
(sis) 01/04: Support the `REALIZATION_METHOD_CODE` column of the "Datum" table of EPSG version 10+.
This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
commit 058a84cae16e41f7c10922a9703957d19ba05e25
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Thu Jul 24 12:09:15 2025 +0200
Support the `REALIZATION_METHOD_CODE` column of the "Datum" table of EPSG version 10+.
---
.../apache/sis/io/wkt/GeodeticObjectParser.java | 6 +-
.../referencing/datum/DefaultVerticalDatum.java | 8 +-
.../referencing/factory/sql/EPSGDataAccess.java | 87 ++++++++++++++++------
.../sis/referencing/factory/sql/SQLTranslator.java | 24 ++++--
.../org/apache/sis/referencing/internal/Epoch.java | 2 -
.../referencing/internal/VerticalDatumTypes.java | 57 ++++++++++----
.../internal/VerticalDatumTypesTest.java | 33 +++++---
7 files changed, 155 insertions(+), 62 deletions(-)
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 2b969c5339..fcc952c75c 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
@@ -1447,10 +1447,10 @@ class GeodeticObjectParser extends MathTransformParser implements Comparator<Coo
@SuppressWarnings("deprecation")
RealizationMethod method = null;
if (isWKT1) {
- method = VerticalDatumTypes.fromLegacy(element.pullInteger("datum"));
+ method = VerticalDatumTypes.fromLegacyCode(element.pullInteger("datum"));
}
if (method == null) {
- method = VerticalDatumTypes.guess(name, null, null);
+ method = VerticalDatumTypes.fromDatum(name, null, null);
}
final DatumFactory datumFactory = factories.getDatumFactory();
try {
@@ -1936,7 +1936,7 @@ class GeodeticObjectParser extends MathTransformParser implements Comparator<Coo
* more information. Verify if we can have a better type now, and if so rebuild the datum.
*/
if (datum.getRealizationMethod().isEmpty()) {
- var type = VerticalDatumTypes.guess(datum.getName().getCode(), datum.getAlias(), cs.getAxis(0));
+ var type = VerticalDatumTypes.fromDatum(datum.getName().getCode(), datum.getAlias(), cs.getAxis(0));
if (type != null) {
final DatumFactory datumFactory = factories.getDatumFactory();
datum = datumFactory.createVerticalDatum(IdentifiedObjects.getProperties(datum), type);
diff --git 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
index c7ac53c321..4a097c0eed 100644
--- 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
@@ -98,6 +98,8 @@ public class DefaultVerticalDatum extends AbstractDatum implements VerticalDatum
/**
* The realization method (geoid, tidal, <i>etc.</i>), or {@code null} if unspecified.
+ *
+ * @see #getRealizationMethod()
*/
private RealizationMethod method;
@@ -366,7 +368,7 @@ public class DefaultVerticalDatum extends AbstractDatum implements VerticalDatum
protected String formatTo(final Formatter formatter) {
super.formatTo(formatter);
if (formatter.getConvention().majorVersion() == 1) {
- formatter.append(VerticalDatumTypes.toLegacy(method));
+ formatter.append(VerticalDatumTypes.toLegacyCode(method));
return WKTKeywords.Vert_Datum;
}
return formatter.shortOrLong(WKTKeywords.VDatum, WKTKeywords.VerticalDatum);
@@ -408,7 +410,7 @@ public class DefaultVerticalDatum extends AbstractDatum implements VerticalDatum
if (Context.isGMLVersion(Context.current(), LegacyNamespaces.VERSION_3_2)) {
return null;
}
- return VerticalDatumTypes.toName(method);
+ return VerticalDatumTypes.toLegacyName(method);
}
/**
@@ -416,7 +418,7 @@ public class DefaultVerticalDatum extends AbstractDatum implements VerticalDatum
*/
private void setTypeElement(final String type) {
if (method == null) {
- method = VerticalDatumTypes.fromName(type);
+ method = VerticalDatumTypes.fromLegacyName(type);
} else {
ImplementationHelper.propertyAlreadySet(DefaultVerticalDatum.class, "setType", "verticalDatumType");
}
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 0b3b995688..e2cef4ba6a 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
@@ -88,6 +88,7 @@ import org.apache.sis.referencing.internal.EPSGParameterDomain;
import org.apache.sis.referencing.internal.ParameterizedTransformBuilder;
import org.apache.sis.referencing.internal.PositionalAccuracyConstant;
import org.apache.sis.referencing.internal.SignReversalComment;
+import org.apache.sis.referencing.internal.VerticalDatumTypes;
import org.apache.sis.referencing.internal.Resources;
import org.apache.sis.referencing.internal.ServicesForMetadata;
import org.apache.sis.parameter.DefaultParameterDescriptor;
@@ -239,7 +240,7 @@ public class EPSGDataAccess extends GeodeticAuthorityFactory implements CRSAutho
* A pool of prepared statements. Keys are {@link String} objects related to their originating method
* (for example "Ellipsoid" for {@link #createEllipsoid(String)}).
*/
- private final Map<String,PreparedStatement> statements = new HashMap<>();
+ private final Map<String, PreparedStatement> statements = new HashMap<>();
/**
* The set of authority codes for different types. This map is used by the {@link #getAuthorityCodes(Class)}
@@ -265,7 +266,15 @@ public class EPSGDataAccess extends GeodeticAuthorityFactory implements CRSAutho
*
* @see #getAxisName(Integer)
*/
- private final Map<Integer,AxisName> axisNames = new HashMap<>();
+ private final Map<Integer, AxisName> axisNames = new HashMap<>();
+
+ /**
+ * Cache for realization methods. This service is not provided by {@code ConcurrentAuthorityFactory}
+ * because the realization method table is specific to the <abbr>EPSG</abbr> authority factory.
+ *
+ * @see #getRealizationMethod(Integer)
+ */
+ private final Map<Integer, RealizationMethod> realizationMethods = new HashMap<>();
/**
* Cache of naming systems other than EPSG. There is usually few of them (at most 15).
@@ -273,13 +282,13 @@ public class EPSGDataAccess extends GeodeticAuthorityFactory implements CRSAutho
*
* @see #createProperties(String, Integer, String, CharSequence, String, String, CharSequence, boolean)
*/
- private final Map<String,NameSpace> namingSystems = new HashMap<>();
+ private final Map<String, NameSpace> namingSystems = new HashMap<>();
/**
* The properties to be given the objects to construct.
* Reused every time {@code createProperties(…)} is invoked.
*/
- private final Map<String,Object> properties = new HashMap<>();
+ private final Map<String, Object> properties = new HashMap<>();
/**
* A safety guard for preventing never-ending loops in recursive calls to some {@code createFoo(String)} methods.
@@ -293,7 +302,7 @@ public class EPSGDataAccess extends GeodeticAuthorityFactory implements CRSAutho
*
* Keys are EPSG codes and values are the type of object being constructed (but those values are not yet used).
*/
- private final Map<Integer,Class<?>> safetyGuard = new HashMap<>();
+ private final Map<Integer, Class<?>> safetyGuard = new HashMap<>();
/**
* {@code true} for disabling the logging of warnings when this factory creates deprecated objects.
@@ -1396,7 +1405,7 @@ codes: for (int i=0; i<codes.length; i++) {
endOfRecursion(GeographicCRS.class, epsg);
}
}
- DatumEnsemble<GeodeticDatum> ensemble = tryAsEnsemble(datum, GeodeticDatum.class);
+ DatumEnsemble<GeodeticDatum> ensemble = wasDatumEnsemble(datum, GeodeticDatum.class);
if (ensemble != null) datum = null;
crs = crsFactory.createGeographicCRS(createProperties("Coordinate Reference System",
epsg, name, null, area, scope, remarks, deprecated), datum, ensemble, cs);
@@ -1493,7 +1502,7 @@ codes: for (int i=0; i<codes.length; i++) {
case "vertical": {
VerticalCS cs = owner.createVerticalCS (getString(code, result, 8));
VerticalDatum datum = owner.createVerticalDatum(getString(code, result, 9));
- DatumEnsemble<VerticalDatum> ensemble = tryAsEnsemble(datum, VerticalDatum.class);
+ DatumEnsemble<VerticalDatum> ensemble = wasDatumEnsemble(datum, VerticalDatum.class);
if (ensemble != null) datum = null;
crs = crsFactory.createVerticalCRS(createProperties("Coordinate Reference System",
epsg, name, null, area, scope, remarks, deprecated), datum, ensemble, cs);
@@ -1509,7 +1518,7 @@ codes: for (int i=0; i<codes.length; i++) {
case "temporal": {
TimeCS cs = owner.createTimeCS (getString(code, result, 8));
TemporalDatum datum = owner.createTemporalDatum(getString(code, result, 9));
- DatumEnsemble<TemporalDatum> ensemble = tryAsEnsemble(datum, TemporalDatum.class);
+ DatumEnsemble<TemporalDatum> ensemble = wasDatumEnsemble(datum, TemporalDatum.class);
if (ensemble != null) datum = null;
crs = crsFactory.createTemporalCRS(createProperties("Coordinate Reference System",
epsg, name, null, area, scope, remarks, deprecated), datum, ensemble, cs);
@@ -1544,7 +1553,7 @@ codes: for (int i=0; i<codes.length; i++) {
case "geocentric": {
CoordinateSystem cs = owner.createCoordinateSystem(getString(code, result, 8));
GeodeticDatum datum = owner.createGeodeticDatum (getString(code, result, 9));
- DatumEnsemble<GeodeticDatum> ensemble = tryAsEnsemble(datum, GeodeticDatum.class);
+ DatumEnsemble<GeodeticDatum> ensemble = wasDatumEnsemble(datum, GeodeticDatum.class);
if (ensemble != null) datum = null;
@SuppressWarnings("LocalVariableHidesMemberVariable")
final Map<String,Object> properties = createProperties("Coordinate Reference System",
@@ -1565,7 +1574,7 @@ codes: for (int i=0; i<codes.length; i++) {
case "engineering": {
CoordinateSystem cs = owner.createCoordinateSystem(getString(code, result, 8));
EngineeringDatum datum = owner.createEngineeringDatum(getString(code, result, 9));
- DatumEnsemble<EngineeringDatum> ensemble = tryAsEnsemble(datum, EngineeringDatum.class);
+ DatumEnsemble<EngineeringDatum> ensemble = wasDatumEnsemble(datum, EngineeringDatum.class);
if (ensemble != null) datum = null;
crs = crsFactory.createEngineeringCRS(createProperties("Coordinate Reference System",
epsg, name, null, area, scope, remarks, deprecated), datum, ensemble, cs);
@@ -1577,7 +1586,7 @@ codes: for (int i=0; i<codes.length; i++) {
case "parametric": {
ParametricCS cs = owner.createParametricCS (getString(code, result, 8));
ParametricDatum datum = owner.createParametricDatum(getString(code, result, 9));
- DatumEnsemble<ParametricDatum> ensemble = tryAsEnsemble(datum, ParametricDatum.class);
+ DatumEnsemble<ParametricDatum> ensemble = wasDatumEnsemble(datum, ParametricDatum.class);
if (ensemble != null) datum = null;
crs = crsFactory.createParametricCRS(createProperties("Coordinate Reference System",
epsg, name, null, area, scope, remarks, deprecated), datum, ensemble, cs);
@@ -1622,7 +1631,7 @@ codes: for (int i=0; i<codes.length; i++) {
* @return the given datum as an ensemble if it should be considered as such, or {@code null} otherwise.
* @throws ClassCastException if at least one member is not an instance of the specified type.
*/
- private static <D extends Datum> DatumEnsemble<D> tryAsEnsemble(final D datum, final Class<D> memberType) {
+ private static <D extends Datum> DatumEnsemble<D> wasDatumEnsemble(final D datum, final Class<D> memberType) {
if (datum instanceof DatumEnsemble<?>) {
return DefaultDatumEnsemble.castOrCopy((DatumEnsemble<?>) datum).cast(memberType);
}
@@ -1656,17 +1665,18 @@ codes: for (int i=0; i<codes.length; i++) {
ArgumentChecks.ensureNonNull("code", code);
Datum returnValue = null;
try (ResultSet result = executeQuery("Datum", "DATUM_CODE", "DATUM_NAME",
- "SELECT DATUM_CODE," +
- " DATUM_NAME," +
- " DATUM_TYPE," +
- " ORIGIN_DESCRIPTION," +
- " REALIZATION_EPOCH," +
- " AREA_OF_USE_CODE," + // Deprecated since EPSG version 10 (always null)
- " DATUM_SCOPE," +
- " REMARKS," +
- " DEPRECATED," +
- " ELLIPSOID_CODE," + // Only for geodetic type
- " PRIME_MERIDIAN_CODE" + // Only for geodetic type
+ "SELECT DATUM_CODE," + // [ 1]
+ " DATUM_NAME," + // [ 2]
+ " DATUM_TYPE," + // [ 3]
+ " ORIGIN_DESCRIPTION," + // [ 4]
+ " REALIZATION_EPOCH," + // [ 5]
+ " AREA_OF_USE_CODE," + // [ 6] — Deprecated since EPSG version 10 (always null)
+ " DATUM_SCOPE," + // [ 7]
+ " REMARKS," + // [ 8]
+ " DEPRECATED," + // [ 9]
+ " ELLIPSOID_CODE," + // [10] — Only for geodetic type
+ " PRIME_MERIDIAN_CODE," + // [11] — Only for geodetic type
+ " REALIZATION_METHOD_CODE" + // [12] — Only for vertical type
" FROM \"Datum\"" +
" WHERE DATUM_CODE = ?", code))
{
@@ -1736,7 +1746,8 @@ codes: for (int i=0; i<codes.length; i++) {
break;
}
case "vertical": {
- datum = datumFactory.createVerticalDatum(properties, null);
+ final RealizationMethod method = getRealizationMethod(getOptionalInteger(result, 12));
+ datum = datumFactory.createVerticalDatum(properties, method);
break;
}
/*
@@ -2459,6 +2470,34 @@ codes: for (int i=0; i<codes.length; i++) {
return returnValue;
}
+ /**
+ * Returns the realization method for the specified code.
+ *
+ * @param code code of the realization method, or {@code null} if none.
+ * @return realization method, or {@code null} if the given code was null.
+ */
+ private RealizationMethod getRealizationMethod(final Integer code) throws FactoryException, SQLException {
+ assert Thread.holdsLock(this);
+ RealizationMethod returnValue = realizationMethods.get(code);
+ if (returnValue == null && code != null) {
+ try (ResultSet result = executeQuery("DatumRealizationMethod",
+ "SELECT REALIZATION_METHOD_NAME" +
+ " FROM \"DatumRealizationMethod\"" +
+ " WHERE REALIZATION_METHOD_CODE = ?", code))
+ {
+ while (result.next()) {
+ final String name = getString(code, result, 1);
+ returnValue = ensureSingleton(VerticalDatumTypes.fromMethod(name), returnValue, code);
+ }
+ }
+ if (returnValue == null) {
+ throw noSuchAuthorityCode(RealizationMethod.class, String.valueOf(code));
+ }
+ realizationMethods.put(code, returnValue);
+ }
+ return returnValue;
+ }
+
/**
* Creates an unit of measurement from a code.
* Current implementation first checks if {@link Units#valueOfEPSG(int)} can provide a hard-coded unit
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/SQLTranslator.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/SQLTranslator.java
index d3c836baf9..83a6998c9d 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/SQLTranslator.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/SQLTranslator.java
@@ -366,9 +366,11 @@ public class SQLTranslator implements Function<String,String> {
/*
* A column named "BASE_CRS_CODE" in EPSG version 9 has been renamed "SOURCE_GEOGCRS_CODE" in version 10.
* Detects which name is used, with precedence to latest database version if the two columns are found.
+ * Opportunistically use this detection for generating empty columns for fields that did not existed in
+ * the "Datum" table of EPSG version 9.
*/
+ boolean isOldSchema = false;
skip: try (ResultSet result = md.getColumns(catalog, schemaPattern, toActualTableName("Coordinate Reference System"), baseCRS)) {
- boolean isOldSchema = false;
while (result.next()) {
final String column = result.getString(Reflection.COLUMN_NAME);
if ("BASE_CRS_CODE".equalsIgnoreCase(column)) {
@@ -378,11 +380,12 @@ skip: try (ResultSet result = md.getColumns(catalog, schemaPattern, toActualTa
isOldSchema = "SOURCE_GEOGCRS_CODE".equalsIgnoreCase(column);
}
}
- if (isOldSchema) {
- columnRenaming = new HashMap<>(columnRenaming);
- columnRenaming.put("BASE_CRS_CODE", "SOURCE_GEOGCRS_CODE");
- columnRenaming = Map.copyOf(columnRenaming);
- }
+ }
+ if (isOldSchema) {
+ columnRenaming = new HashMap<>(columnRenaming);
+ columnRenaming.put("BASE_CRS_CODE", "SOURCE_GEOGCRS_CODE"); // In table "Coordinate Reference System".
+ addMissingColumn("REALIZATION_METHOD_CODE", "INTEGER"); // In table "Datum".
+ columnRenaming = Map.copyOf(columnRenaming);
}
/*
* Detect if the database uses boolean types where applicable.
@@ -420,6 +423,15 @@ skip: try (ResultSet result = md.getColumns(catalog, schemaPattern, toActualTa
&& !useBoolean;
}
+ /**
+ * Declares that the column of the given name shall be replaced by a placeholder.
+ * This method is invoked for columns added in <abbr>EPSG</abbr> version 10 or later
+ * when we detected that the schema in use is <abbr>EPSG</abbr> version 8 or before;
+ */
+ private void addMissingColumn(final String column, final String type) {
+ columnRenaming.put(column, "CAST(NULL AS " + type + ") AS " + column);
+ }
+
/**
* Returns the catalog that contains the EPSG schema. This is the catalog specified at construction time
* if it was non-null, or the catalog discovered by the constructor otherwise.
diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Epoch.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Epoch.java
index 5be71863b9..de6020319d 100644
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Epoch.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Epoch.java
@@ -35,8 +35,6 @@ import org.apache.sis.util.privy.Constants;
* This is a temporary object used for Well-Known Text formatting.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.5
- * @since 1.5
*/
public final class Epoch extends FormattableObject {
/**
diff --git 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
index 58a22e5fb3..ecea0315c6 100644
--- 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
@@ -24,6 +24,7 @@ import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.cs.AxisDirection;
import org.apache.sis.util.Characters;
import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.privy.CodeLists;
import org.apache.sis.measure.Units;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
@@ -31,11 +32,15 @@ import org.opengis.referencing.datum.RealizationMethod;
/**
- * Extensions to the standard set of {@link RealizationEpoch}.
+ * Extensions to the standard set of {@link RealizationMethod}.
* Some of those constants are derived from a legacy {@code VerticalDatumType} code list.
* 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.
*
+ * <h2>Note on class naming</h2>
+ * {@code RealizationMethods} could have been a more appropriate name.
+ * For now we keep {@code VerticalDatumTypes} as a way to remind that this is currently only about vertical datum.
+ *
* @author Martin Desruisseaux (IRD, Geomatys)
*/
public final class VerticalDatumTypes {
@@ -73,6 +78,11 @@ public final class VerticalDatumTypes {
*/
static final String BAROMETRIC = "BAROMETRIC";
+ /**
+ * A value used in the <abbr>EPSG</abbr> database.
+ */
+ static final String LOCAL = "LOCAL";
+
/**
* Do not allow instantiation of this class.
*/
@@ -113,7 +123,7 @@ public final class VerticalDatumTypes {
* @param code the legacy vertical datum code.
* @return the vertical datum type, or {@code null} if none.
*/
- public static RealizationMethod fromLegacy(final int code) {
+ public static RealizationMethod fromLegacyCode(final int code) {
switch (code) {
// case 2000: return null; // CS_VD_Other
case 2001: return RealizationMethod.valueOf(ORTHOMETRIC); // CS_VD_Orthometric
@@ -132,7 +142,7 @@ public final class VerticalDatumTypes {
* @param method the realization method, or {@code null} if unknown.
* @return the legacy code for the given datum type, or 0 if unknown.
*/
- public static int toLegacy(final RealizationMethod method) {
+ public static int toLegacyCode(final RealizationMethod method) {
if (method != null) {
switch (method.name().toUpperCase(Locale.US)) {
case ORTHOMETRIC: return 2001; // CS_VD_Orthometric
@@ -154,7 +164,7 @@ public final class VerticalDatumTypes {
* @param method the realization method, or {@code null}.
* @return the vertical datum type name (never null).
*/
- public static String toName(final RealizationMethod method) {
+ public static String toLegacyName(final RealizationMethod method) {
if (method == RealizationMethod.GEOID) return "geoidal";
if (method == RealizationMethod.TIDAL) return "depth";
if (method != null) {
@@ -170,15 +180,36 @@ public final class VerticalDatumTypes {
* @param type the vertical datum type, or {@code null}.
* @return the realization method, or {@code null} if none.
*/
- public static RealizationMethod fromName(final String type) {
- if ("GEOIDAL" .equalsIgnoreCase(type)) return RealizationMethod.GEOID;
- if ("DEPTH" .equalsIgnoreCase(type)) return RealizationMethod.TIDAL;
+ public static RealizationMethod fromLegacyName(final String type) {
+ if ("geoidal" .equalsIgnoreCase(type)) return RealizationMethod.GEOID;
+ if ("depth" .equalsIgnoreCase(type)) return RealizationMethod.TIDAL;
+ if (LOCAL .equalsIgnoreCase(type)) return RealizationMethod.valueOf(LOCAL);
if (BAROMETRIC .equalsIgnoreCase(type)) return RealizationMethod.valueOf(BAROMETRIC);
if (ORTHOMETRIC.equalsIgnoreCase(type)) return RealizationMethod.valueOf(ORTHOMETRIC);
if (ELLIPSOIDAL.equalsIgnoreCase(type)) return ellipsoidal();
return null;
}
+ /**
+ * Returns the realization method from heuristic rules applied on the name.
+ *
+ * @param name the realization method name, or {@code null}.
+ * @return the realization method, or {@code null} if the given name was null.
+ */
+ public static RealizationMethod fromMethod(final String name) {
+ RealizationMethod method = fromLegacyName(name);
+ if (method == null && name != null && !name.isBlank()) {
+ final int s = name.lastIndexOf('-');
+ if (s >= 0 && name.substring(s+1).strip().equalsIgnoreCase("based")) {
+ method = CodeLists.forCodeName(RealizationMethod.class, name.substring(0, s));
+ }
+ if (method == null) {
+ method = RealizationMethod.valueOf(name);
+ }
+ }
+ return method;
+ }
+
/**
* 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
@@ -191,16 +222,16 @@ public final class VerticalDatumTypes {
* @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.
*/
- public static RealizationMethod guess(final String name, final Collection<? extends GenericName> aliases,
+ public static RealizationMethod fromDatum(final String name, final Collection<? extends GenericName> aliases,
final CoordinateSystemAxis axis)
{
- RealizationMethod method = guess(name);
+ RealizationMethod method = fromDatum(name);
if (method != null) {
return method;
}
if (aliases != null) {
for (final GenericName alias : aliases) {
- method = guess(alias.tip().toString());
+ method = fromDatum(alias.tip().toString());
if (method != null) {
return method;
}
@@ -230,13 +261,13 @@ public final class VerticalDatumTypes {
}
/**
- * 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}.
+ * Guesses the realization method of a datum of the given name.
+ * If the realization method cannot be determined, returns {@code null}.
*
* @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 RealizationMethod fromDatum(final String name) {
if (name != null) {
if (CharSequences.equalsFiltered("Mean Sea Level", name, Characters.Filter.LETTERS_AND_DIGITS, true)) {
return RealizationMethod.TIDAL;
diff --git 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
index 28f4e0ca9f..b5fe441aec 100644
--- 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
@@ -33,7 +33,6 @@ import org.opengis.referencing.datum.RealizationMethod;
*
* @author Martin Desruisseaux (Geomatys)
*/
-@SuppressWarnings("deprecation")
public final class VerticalDatumTypesTest extends TestCase {
/**
* Creates a new test case.
@@ -53,23 +52,35 @@ public final class VerticalDatumTypesTest extends TestCase {
}
/**
- * Tests the {@link VerticalDatumTypes#fromLegacy(int)} method.
+ * Tests the {@link VerticalDatumTypes#fromLegacyCode(int)} method.
*/
@Test
- public void testFromLegacy() {
- assertEquals(VerticalDatumTypes.ellipsoidal(), VerticalDatumTypes.fromLegacy(2002));
- assertEquals(RealizationMethod .GEOID, VerticalDatumTypes.fromLegacy(2005));
- assertEquals(RealizationMethod .TIDAL, VerticalDatumTypes.fromLegacy(2006));
+ public void testFromLegacyCode() {
+ assertEquals(VerticalDatumTypes.ellipsoidal(), VerticalDatumTypes.fromLegacyCode(2002));
+ assertEquals(RealizationMethod .GEOID, VerticalDatumTypes.fromLegacyCode(2005));
+ assertEquals(RealizationMethod .TIDAL, VerticalDatumTypes.fromLegacyCode(2006));
}
/**
- * Tests the {@link VerticalDatumTypes#toLegacy(RealizationMethod)} method.
+ * Tests the {@link VerticalDatumTypes#toLegacyCode(RealizationMethod)} method.
*/
@Test
- public void testToLegacy() {
- assertEquals(2002, VerticalDatumTypes.toLegacy(VerticalDatumTypes.ellipsoidal()));
- assertEquals(2005, VerticalDatumTypes.toLegacy(RealizationMethod .GEOID));
- assertEquals(2006, VerticalDatumTypes.toLegacy(RealizationMethod .TIDAL));
+ public void testToLegacyCode() {
+ assertEquals(2002, VerticalDatumTypes.toLegacyCode(VerticalDatumTypes.ellipsoidal()));
+ assertEquals(2005, VerticalDatumTypes.toLegacyCode(RealizationMethod .GEOID));
+ assertEquals(2006, VerticalDatumTypes.toLegacyCode(RealizationMethod .TIDAL));
+ }
+
+ /**
+ * Tests the {@link VerticalDatumTypes#fromMethod(String)} method
+ * with names from the <abbr>EPSG</abbr> database.
+ */
+ @Test
+ public void testFromMethod() {
+ assertEquals(RealizationMethod .LEVELLING, VerticalDatumTypes.fromMethod("Levelling-based"));
+ assertEquals(RealizationMethod .GEOID, VerticalDatumTypes.fromMethod("Geoid-based"));
+ assertEquals(RealizationMethod .TIDAL, VerticalDatumTypes.fromMethod("Tidal"));
+ assertEquals(VerticalDatumTypes.LOCAL, VerticalDatumTypes.fromMethod("Local").name());
}
/**