This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new 8ac2e436ae Fix more test failures relative to the WGS84 being a datum
ensemble since EPSG version 10. Most of the remaining test failures are about
new operation types not yet supported.
8ac2e436ae is described below
commit 8ac2e436aee211df28ecda5991b8e57b4953198a
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Tue Sep 2 13:56:31 2025 +0200
Fix more test failures relative to the WGS84 being a datum ensemble since
EPSG version 10.
Most of the remaining test failures are about new operation types not yet
supported.
---
.../apache/sis/console/MetadataCommandTest.java | 3 +-
.../apache/sis/io/wkt/GeodeticObjectParser.java | 3 +-
.../main/org/apache/sis/referencing/CommonCRS.java | 30 +++---
.../sis/referencing/EPSGFactoryFallback.java | 5 +-
.../sis/referencing/datum/DatumOrEnsemble.java | 75 ++++++++++++++
.../referencing/datum/DefaultDatumEnsemble.java | 4 +-
.../referencing/factory/GeodeticObjectFactory.java | 110 ++++++++++++++++++++-
.../referencing/factory/sql/EPSGDataAccess.java | 36 ++-----
.../operation/CoordinateOperationFinder.java | 7 +-
.../org/apache/sis/referencing/Assertions.java | 18 ++++
.../test/org/apache/sis/referencing/CRSTest.java | 2 +
.../org/apache/sis/referencing/CommonCRSTest.java | 2 +-
.../sis/referencing/EPSGFactoryFallbackTest.java | 13 ++-
.../sis/referencing/datum/HardCodedDatum.java | 1 +
.../apache/sis/storage/netcdf/base/CRSBuilder.java | 5 +-
.../org/apache/sis/storage/CoverageSubsetTest.java | 4 +-
16 files changed, 253 insertions(+), 65 deletions(-)
diff --git
a/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/MetadataCommandTest.java
b/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/MetadataCommandTest.java
index 65c9b4725f..a2563cb880 100644
---
a/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/MetadataCommandTest.java
+++
b/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/MetadataCommandTest.java
@@ -78,7 +78,8 @@ public final class MetadataCommandTest extends
TestCaseWithLogs {
var test = new MetadataCommand(0, new String[] {CommandRunner.TEST,
url.toString(), "--format", "XML"});
test.run();
verifyNetCDF("<?xml", test.outputBuffer.toString());
- loggings.skipNextLogIfContains("EPSG:4019"); // Warning
about deprecated EPSG code.
+ loggings.skipNextLogIfContains("EPSG:6019"); // Warning about
deprecated EPSG code for datum.
+ loggings.skipNextLogIfContains("EPSG:4019"); // Warning about
deprecated EPSG code for CRS.
loggings.assertNoUnexpectedLog();
}
}
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 d60c174674..166abda4dd 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
@@ -2042,7 +2042,6 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
* In the latter case, the datum is null and we have instead
DerivingConversion element from a BaseParametricCRS.
*/
ParametricDatum datum = null;
- DatumEnsemble<ParametricDatum> datumEnsemble = null; // TODO
SingleCRS baseCRS = null;
Conversion fromBase = null;
if (!isBaseCRS) {
@@ -2073,7 +2072,7 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
if (baseCRS != null) {
return crsFactory.createDerivedCRS(properties, baseCRS,
fromBase, cs);
}
- return crsFactory.createParametricCRS(properties, datum,
datumEnsemble, (ParametricCS) cs);
+ return crsFactory.createParametricCRS(properties, datum,
(ParametricCS) cs);
}
} catch (FactoryException exception) {
throw element.parseFailed(exception);
diff --git
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
index 1d33123aca..12a11b590e 100644
---
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
@@ -502,7 +502,7 @@ public enum CommonCRS {
}
}
final Datum datum = single.getDatum();
- if (datum instanceof GeodeticDatum) {
+ if (datum == null || datum instanceof GeodeticDatum) {
final CommonCRS c = forDatum((GeodeticDatum) datum,
single.getDatumEnsemble());
if (c != null) return c;
}
@@ -524,8 +524,10 @@ public enum CommonCRS {
* database).
*/
int epsg = 0;
- final Identifier identifier = IdentifiedObjects.getIdentifier(datum,
Citations.EPSG);
- if (identifier != null) {
+ Identifier identifier;
+ if ((identifier = IdentifiedObjects.getIdentifier(datum,
Citations.EPSG)) != null ||
+ (identifier = IdentifiedObjects.getIdentifier(ensemble,
Citations.EPSG)) != null)
+ {
final String code = identifier.getCode();
if (code != null) try {
epsg = Integer.parseInt(code);
@@ -838,23 +840,26 @@ public enum CommonCRS {
* together with an enumeration value that can be used for fetching that
datum:
*
* <blockquote><table class="sis">
- * <caption>Commonly used geodetic reference frames</caption>
+ * <caption>Commonly used geodetic reference frames or datum
ensembles</caption>
* <tr><th>Name or alias</th>
<th>Enum</th> <th>EPSG</th></tr>
* <tr><td>European Datum 1950</td>
<td>{@link #ED50}</td> <td>6230</td></tr>
* <tr><td>European Terrestrial Reference System 1989</td>
<td>{@link #ETRS89}</td> <td>6258</td></tr>
* <tr><td>North American Datum 1927</td>
<td>{@link #NAD27}</td> <td>6267</td></tr>
* <tr><td>North American Datum 1983</td>
<td>{@link #NAD83}</td> <td>6269</td></tr>
* <tr><td>Not specified (based on GRS 1980 ellipsoid)</td>
<td>{@link #GRS1980}</td><td>6019</td></tr>
- * <tr><td>Not specified (based on GRS 1980 Authalic Sphere)</td>
<td>{@link #SPHERE}</td> <td>6047</td></tr>
+ * <tr><td>Not specified (based on GRS 1980 Authalic Sphere)</td>
<td>{@link #SPHERE}</td> <td><del>6047</del></td></tr>
* <tr><td>World Geodetic System 1972</td>
<td>{@link #WGS72}</td> <td>6322</td></tr>
* <tr><td>World Geodetic System 1984</td>
<td>{@link #WGS84}</td> <td>6326</td></tr>
* </table></blockquote>
*
+ * <h4>Datum ensemble</h4>
* Some rows in above table are actually defined as datum ensembles in
version 10 or later of the
- * <abbr>EPSG</abbr> geodetic dataset. These datum ensembles are listed in
{@link #datumEnsemble()}
+ * <abbr>EPSG</abbr> geodetic dataset. These rows are repeated in {@link
#datumEnsemble()} Javadoc
* and may be returned only if the {@code acceptEnsemble} argument is
{@code true}.
- * Note that whether a datum is a datum ensemble depends on whether Apache
<abbr>SIS</abbr>
- * is connected to an <abbr>EPSG</abbr> geodetic dataset and the version
of that dataset.
+ * In such case, the returned object is the ensemble viewed as if it was a
single geodetic datum.
+ *
+ * <p>Note that whether an object is a datum ensemble depends on whether
Apache <abbr>SIS</abbr>
+ * is connected to an <abbr>EPSG</abbr> geodetic dataset and the version
of that dataset.</p>
*
* @param acceptEnsemble whether to return datum ensemble as a
pseudo-datum.
* @return the datum or (optionally) datum ensemble associated to this
enum, or {@code null}
@@ -866,7 +871,7 @@ public enum CommonCRS {
* @since 1.5
*/
public synchronized GeodeticDatum datum(final boolean acceptEnsemble) {
- GeodeticDatum object = getDatumOrEnsemble(cached);
+ GeodeticDatum object = datumOrEnsemble(cached);
if (object == null) {
final GeodeticAuthorityFactory factory = factory();
if (factory != null) try {
@@ -879,7 +884,7 @@ public enum CommonCRS {
final var pm = primeMeridian();
cached = object = StandardDefinitions.createGeodeticDatum(datum,
ei, pm);
}
- if (!acceptEnsemble && object instanceof DatumEnsemble<?>) {
+ if (!acceptEnsemble && DatumOrEnsemble.asEnsemble(object).isPresent())
{
return null;
}
return object;
@@ -906,8 +911,7 @@ public enum CommonCRS {
* @since 1.5
*/
public DatumEnsemble<GeodeticDatum> datumEnsemble() {
- final GeodeticDatum object = datum(true);
- return (object instanceof DatumEnsemble<?>) ?
(DatumEnsemble<GeodeticDatum>) object : null;
+ return DatumOrEnsemble.asEnsemble(datum(true)).orElse(null);
}
/**
@@ -998,7 +1002,7 @@ public enum CommonCRS {
* because {@link org.apache.sis.referencing.datum.DefaultDatumEnsemble}
implements
* the {@link Datum} interface anyway in the Apache <abbr>SIS</abbr>
implementation.
*/
- private static GeodeticDatum getDatumOrEnsemble(final IdentifiedObject
object) {
+ private static GeodeticDatum datumOrEnsemble(final IdentifiedObject
object) {
if (object instanceof GeodeticDatum) {
return (GeodeticDatum) object;
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/EPSGFactoryFallback.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/EPSGFactoryFallback.java
index f34fe59f58..83fca7a59e 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/EPSGFactoryFallback.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/EPSGFactoryFallback.java
@@ -219,10 +219,11 @@ final class EPSGFactoryFallback extends
GeodeticAuthorityFactory
/**
* Returns a datum for the given EPSG code.
+ * For compatibility reason, it may be an ensemble viewed as a
pseudo-datum.
*/
@Override
public Datum createDatum(final String code) throws
NoSuchAuthorityCodeException {
- return (Datum) predefined(code, DATUM);
+ return (Datum) predefined(code, DATUM | ENSEMBLE);
}
/**
@@ -332,7 +333,7 @@ final class EPSGFactoryFallback extends
GeodeticAuthorityFactory
* ensured that there is no such collision - see
CommonCRSTest.ensureNoCodeCollision().
*/
if ((kind & ELLIPSOID) != 0 && n == crs.ellipsoid)
return crs.ellipsoid();
- if ((kind & DATUM) != 0 && n == crs.datum)
return crs.datum(false);
+ if ((kind & DATUM) != 0 && n == crs.datum)
return crs.datum((kind & ENSEMBLE) != 0);
if ((kind & ENSEMBLE) != 0 && n == crs.datum)
return crs.datumEnsemble();
if ((kind & CRS) != 0) {
if (n == crs.geographic) return crs.geographic();
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DatumOrEnsemble.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DatumOrEnsemble.java
index d08ce7f653..820ce1cfcc 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DatumOrEnsemble.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DatumOrEnsemble.java
@@ -382,6 +382,81 @@ public final class DatumOrEnsemble extends Static {
return false;
}
+ /**
+ * If the given object is a pseudo-datum for a geodetic ensemble, returns
that ensemble.
+ * This method is the converse of {@link #asDatum(GeodeticCRS)} and
recognizes only the
+ * pseudo-datum created by this class of by {@link DefaultDatumEnsemble}
static methods.
+ *
+ * @param datum the object which may be a pseudo-datum for an ensemble,
or {@code null}.
+ * @return the given object cast to a datum ensemble if the cast is valid.
+ */
+ public static Optional<DatumEnsemble<GeodeticDatum>> asEnsemble(final
GeodeticDatum datum) {
+ if (datum instanceof DefaultDatumEnsemble.Geodetic) {
+ return Optional.of((DefaultDatumEnsemble.Geodetic) datum);
+ }
+ return Optional.empty();
+ }
+
+ /**
+ * If the given object is a pseudo-datum for a vertical ensemble, returns
that ensemble.
+ * This method is the converse of {@link #asDatum(VerticalCRS)} and
recognizes only the
+ * pseudo-datum created by this class of by {@link DefaultDatumEnsemble}
static methods.
+ *
+ * @param datum the object which may be a pseudo-datum for an ensemble,
or {@code null}.
+ * @return the given object cast to a datum ensemble if the cast is valid.
+ */
+ public static Optional<DatumEnsemble<VerticalDatum>> asEnsemble(final
VerticalDatum datum) {
+ if (datum instanceof DefaultDatumEnsemble.Vertical) {
+ return Optional.of((DefaultDatumEnsemble.Vertical) datum);
+ }
+ return Optional.empty();
+ }
+
+ /**
+ * If the given object is a pseudo-datum for a temporal ensemble, returns
that ensemble.
+ * This method is the converse of {@link #asDatum(TemporalCRS)} and
recognizes only the
+ * pseudo-datum created by this class of by {@link DefaultDatumEnsemble}
static methods.
+ *
+ * @param datum the object which may be a pseudo-datum for an ensemble,
or {@code null}.
+ * @return the given object cast to a datum ensemble if the cast is valid.
+ */
+ public static Optional<DatumEnsemble<TemporalDatum>> asEnsemble(final
TemporalDatum datum) {
+ if (datum instanceof DefaultDatumEnsemble.Time) {
+ return Optional.of((DefaultDatumEnsemble.Time) datum);
+ }
+ return Optional.empty();
+ }
+
+ /**
+ * If the given object is a pseudo-datum for a parametric ensemble,
returns that ensemble.
+ * This method is the converse of {@link #asDatum(ParametricCRS)} and
recognizes only the
+ * pseudo-datum created by this class of by {@link DefaultDatumEnsemble}
static methods.
+ *
+ * @param datum the object which may be a pseudo-datum for an ensemble,
or {@code null}.
+ * @return the given object cast to a datum ensemble if the cast is valid.
+ */
+ public static Optional<DatumEnsemble<ParametricDatum>> asEnsemble(final
ParametricDatum datum) {
+ if (datum instanceof DefaultDatumEnsemble.Parametric) {
+ return Optional.of((DefaultDatumEnsemble.Parametric) datum);
+ }
+ return Optional.empty();
+ }
+
+ /**
+ * If the given object is a pseudo-datum for a engineering ensemble,
returns that ensemble.
+ * This method is the converse of {@link #asDatum(EngineeringCRS)} and
recognizes only the
+ * pseudo-datum created by this class of by {@link DefaultDatumEnsemble}
static methods.
+ *
+ * @param datum the object which may be a pseudo-datum for an ensemble,
or {@code null}.
+ * @return the given object cast to a datum ensemble if the cast is valid.
+ */
+ public static Optional<DatumEnsemble<EngineeringDatum>> asEnsemble(final
EngineeringDatum datum) {
+ if (datum instanceof DefaultDatumEnsemble.Engineering) {
+ return Optional.of((DefaultDatumEnsemble.Engineering) datum);
+ }
+ return Optional.empty();
+ }
+
/**
* Returns whether a legacy definition of a datum may be considered as
equivalent to the given datum ensemble.
* This is {@code true} if all reference frames (both the specified datum
and the ensemble members) have the
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java
index ab6976f313..4c3ebe3bc5 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java
@@ -322,7 +322,9 @@ public class DefaultDatumEnsemble<D extends Datum> extends
AbstractIdentifiedObj
* }
*
* It has been removed because, to be safe, it would require a `Class<D>`
argument in the static methods.
- * Even `? super D` is unsafe. See the comment in
`Factory.forMemberType(…)` method for more discussion.
+ * Even the use of `? super D` wildcard is potentially unsafe if members
implement two datum interfaces.
+ * See the comment inside `Factory.forMemberType(…)` method body for more
discussion.
+ * We could use `? extends Datum`, but its usefulness is uncertain.
*/
/**
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
index c6b18a1f62..989b346b35 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
@@ -555,7 +555,7 @@ public class GeodeticObjectFactory extends AbstractFactory
implements CRSFactory
* @param datum geodetic reference frame, or {@code null} if the
CRS is associated only to a datum ensemble.
* @param ensemble collection of reference frames which for low
accuracy requirements may be considered to be
* insignificantly different from each other, or
{@code null} if there is no such ensemble.
- * @param cs the two- or three-dimensional ellipsoidal
coordinate system for the created CRS.
+ * @param cs the two- or three-dimensional ellipsoidal
coordinate system for the created <abbr>CRS</abbr>.
* @throws FactoryException if the object creation failed.
*
* @see DefaultGeographicCRS#DefaultGeographicCRS(Map, GeodeticDatum,
DatumEnsemble, EllipsoidalCS)
@@ -579,6 +579,26 @@ public class GeodeticObjectFactory extends AbstractFactory
implements CRSFactory
return unique("createGeographicCRS", crs);
}
+ /**
+ * Creates a geographic <abbr>CRS</abbr> with a datum that may be a datum
ensemble.
+ * If the given {@code datum} argument is a {@linkplain
DefaultDatumEnsemble datum ensemble
+ * viewed as a pseudo-datum}, then it is used as the {@code ensemble}
argument of the above
+ * constructor.
+ *
+ * @param properties name and other properties to give to the new object.
+ * @param datum the geodetic reference frame or datum ensemble
viewed as a pseudo-datum.
+ * @param cs the two- or three-dimensional ellipsoidal
coordinate system for the created <abbr>CRS</abbr>.
+ * @throws FactoryException if the object creation failed.
+ */
+ @Override
+ public GeographicCRS createGeographicCRS(Map<String,?> properties,
GeodeticDatum datum, EllipsoidalCS cs)
+ throws FactoryException
+ {
+ DatumEnsemble<GeodeticDatum> ensemble =
DatumOrEnsemble.asEnsemble(datum).orElse(null);
+ if (ensemble != null) datum = null;
+ return createGeographicCRS(properties, datum, ensemble, cs);
+ }
+
/**
* Creates a datum ensemble from a collection of members and an ensemble
accuracy.
*
@@ -1002,7 +1022,7 @@ public class GeodeticObjectFactory extends
AbstractFactory implements CRSFactory
* @param datum vertical reference frame, or {@code null} if the
CRS is associated only to a datum ensemble.
* @param ensemble collection of reference frames which for low
accuracy requirements may be considered to be
* insignificantly different from each other, or
{@code null} if there is no such ensemble.
- * @param cs the vertical coordinate system for the created CRS.
+ * @param cs the vertical coordinate system for the created
<abbr>CRS</abbr>.
* @throws FactoryException if the object creation failed.
*
* @see DefaultVerticalCRS#DefaultVerticalCRS(Map, VerticalDatum,
DatumEnsemble, VerticalCS)
@@ -1026,6 +1046,26 @@ public class GeodeticObjectFactory extends
AbstractFactory implements CRSFactory
return unique("createVerticalCRS", crs);
}
+ /**
+ * Creates a vertical <abbr>CRS</abbr> with a datum that may be a datum
ensemble.
+ * If the given {@code datum} argument is a {@linkplain
DefaultDatumEnsemble datum ensemble
+ * viewed as a pseudo-datum}, then it is used as the {@code ensemble}
argument of the above
+ * constructor.
+ *
+ * @param properties name and other properties to give to the new object.
+ * @param datum the vertical reference frame or datum ensemble
viewed as a pseudo-datum.
+ * @param cs the vertical coordinate system for the created
<abbr>CRS</abbr>.
+ * @throws FactoryException if the object creation failed.
+ */
+ @Override
+ public VerticalCRS createVerticalCRS(Map<String,?> properties,
VerticalDatum datum, VerticalCS cs)
+ throws FactoryException
+ {
+ DatumEnsemble<VerticalDatum> ensemble =
DatumOrEnsemble.asEnsemble(datum).orElse(null);
+ if (ensemble != null) datum = null;
+ return createVerticalCRS(properties, datum, ensemble, cs);
+ }
+
/**
* Creates a static vertical datum from a realization method.
* The default implementation creates a {@link DefaultVerticalDatum}
instance.
@@ -1136,7 +1176,7 @@ public class GeodeticObjectFactory extends
AbstractFactory implements CRSFactory
* @param datum temporal datum, or {@code null} if the CRS is
associated only to a datum ensemble.
* @param ensemble collection of datum which for low accuracy
requirements may be considered to be
* insignificantly different from each other, or
{@code null} if there is no such ensemble.
- * @param cs the temporal coordinate system for the created CRS.
+ * @param cs the temporal coordinate system for the created
<abbr>CRS</abbr>.
* @throws FactoryException if the object creation failed.
*
* @see DefaultTemporalCRS#DefaultTemporalCRS(Map, TemporalDatum,
DatumEnsemble, TimeCS)
@@ -1159,6 +1199,26 @@ public class GeodeticObjectFactory extends
AbstractFactory implements CRSFactory
return unique("createTemporalCRS", crs);
}
+ /**
+ * Creates a temporal <abbr>CRS</abbr> with a datum that may be a datum
ensemble.
+ * If the given {@code datum} argument is a {@linkplain
DefaultDatumEnsemble datum ensemble
+ * viewed as a pseudo-datum}, then it is used as the {@code ensemble}
argument of the above
+ * constructor.
+ *
+ * @param properties name and other properties to give to the new object.
+ * @param datum the temporal datum or datum ensemble viewed as a
pseudo-datum.
+ * @param cs the temporal coordinate system for the created
<abbr>CRS</abbr>.
+ * @throws FactoryException if the object creation failed.
+ */
+ @Override
+ public TemporalCRS createTemporalCRS(Map<String,?> properties,
TemporalDatum datum, TimeCS cs)
+ throws FactoryException
+ {
+ DatumEnsemble<TemporalDatum> ensemble =
DatumOrEnsemble.asEnsemble(datum).orElse(null);
+ if (ensemble != null) datum = null;
+ return createTemporalCRS(properties, datum, ensemble, cs);
+ }
+
/**
* Creates a temporal datum from an enumerated type value.
* The default implementation creates a {@link DefaultTemporalDatum}
instance.
@@ -1238,7 +1298,7 @@ public class GeodeticObjectFactory extends
AbstractFactory implements CRSFactory
* @param datum parametric datum, or {@code null} if the CRS is
associated only to a datum ensemble.
* @param ensemble collection of datum which for low accuracy
requirements may be considered to be
* insignificantly different from each other, or
{@code null} if there is no such ensemble.
- * @param cs the parametric coordinate system for the created
CRS.
+ * @param cs the parametric coordinate system for the created
<abbr>CRS</abbr>.
* @throws FactoryException if the object creation failed.
*
* @see DefaultParametricCRS#DefaultParametricCRS(Map, ParametricDatum,
DatumEnsemble, ParametricCS)
@@ -1262,6 +1322,26 @@ public class GeodeticObjectFactory extends
AbstractFactory implements CRSFactory
return unique("createParametricCRS", crs);
}
+ /**
+ * Creates a parametric <abbr>CRS</abbr> with a datum that may be a datum
ensemble.
+ * If the given {@code datum} argument is a {@linkplain
DefaultDatumEnsemble datum ensemble
+ * viewed as a pseudo-datum}, then it is used as the {@code ensemble}
argument of the above
+ * constructor.
+ *
+ * @param properties name and other properties to give to the new object.
+ * @param datum the parametric datum or datum ensemble viewed as a
pseudo-datum.
+ * @param cs the parametric coordinate system for the created
<abbr>CRS</abbr>.
+ * @throws FactoryException if the object creation failed.
+ */
+ @Override
+ public ParametricCRS createParametricCRS(Map<String,?> properties,
ParametricDatum datum, ParametricCS cs)
+ throws FactoryException
+ {
+ DatumEnsemble<ParametricDatum> ensemble =
DatumOrEnsemble.asEnsemble(datum).orElse(null);
+ if (ensemble != null) datum = null;
+ return createParametricCRS(properties, datum, ensemble, cs);
+ }
+
/**
* Creates a parametric datum.
* The default implementation creates a {@link DefaultParametricDatum}
instance.
@@ -1412,7 +1492,7 @@ public class GeodeticObjectFactory extends
AbstractFactory implements CRSFactory
* @param datum engineering datum, or {@code null} if the CRS is
associated only to a datum ensemble.
* @param ensemble collection of datum which for low accuracy
requirements may be considered to be
* insignificantly different from each other, or
{@code null} if there is no such ensemble.
- * @param cs the coordinate system for the created CRS.
+ * @param cs the coordinate system for the created
<abbr>CRS</abbr>.
* @throws FactoryException if the object creation failed.
*
* @see DefaultEngineeringCRS#DefaultEngineeringCRS(Map, EngineeringDatum,
CoordinateSystem)
@@ -1436,6 +1516,26 @@ public class GeodeticObjectFactory extends
AbstractFactory implements CRSFactory
return unique("createEngineeringCRS", crs);
}
+ /**
+ * Creates a engineering <abbr>CRS</abbr> with a datum that may be a datum
ensemble.
+ * If the given {@code datum} argument is a {@linkplain
DefaultDatumEnsemble datum ensemble
+ * viewed as a pseudo-datum}, then it is used as the {@code ensemble}
argument of the above
+ * constructor.
+ *
+ * @param properties name and other properties to give to the new object.
+ * @param datum the engineering datum or datum ensemble viewed as a
pseudo-datum.
+ * @param cs the coordinate system for the created
<abbr>CRS</abbr>.
+ * @throws FactoryException if the object creation failed.
+ */
+ @Override
+ public EngineeringCRS createEngineeringCRS(Map<String,?> properties,
EngineeringDatum datum, CoordinateSystem cs)
+ throws FactoryException
+ {
+ DatumEnsemble<EngineeringDatum> ensemble =
DatumOrEnsemble.asEnsemble(datum).orElse(null);
+ if (ensemble != null) datum = null;
+ return createEngineeringCRS(properties, datum, ensemble, cs);
+ }
+
/**
* Creates an engineering datum.
* The default implementation creates a {@link DefaultEngineeringDatum}
instance.
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 d25d4afe10..9e4474feb5 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
@@ -75,6 +75,7 @@ import org.apache.sis.referencing.ImmutableIdentifier;
import org.apache.sis.referencing.DefaultObjectDomain;
import org.apache.sis.referencing.AbstractIdentifiedObject;
import org.apache.sis.referencing.cs.CoordinateSystems;
+import org.apache.sis.referencing.datum.DatumOrEnsemble;
import org.apache.sis.referencing.datum.DefaultDatumEnsemble;
import org.apache.sis.referencing.operation.DefaultOperationMethod;
import org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory;
@@ -1621,7 +1622,7 @@ search: try (ResultSet result =
executeMetadataQuery("Deprecation",
final String datumCode = getString(code, result, 9);
final CoordinateSystem cs =
owner.createCoordinateSystem(csCode); // Do not inline the `getString(…)`
calls.
final GeodeticDatum datumOrEnsemble =
owner.createGeodeticDatum(datumCode);
- final DatumEnsemble<GeodeticDatum> ensemble =
wasDatumEnsemble(datumOrEnsemble, GeodeticDatum.class);
+ final DatumEnsemble<GeodeticDatum> ensemble =
DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null);
final GeodeticDatum datum = (ensemble == null) ?
datumOrEnsemble : null;
if (cs instanceof CartesianCS) {
final var c = (CartesianCS) cs;
@@ -1653,7 +1654,7 @@ search: try (ResultSet result =
executeMetadataQuery("Deprecation",
csCode = replaceDeprecatedCS(csCode);
}
final EllipsoidalCS cs =
owner.createEllipsoidalCS(csCode.toString());
- final DatumEnsemble<GeodeticDatum> ensemble =
wasDatumEnsemble(datumOrEnsemble, GeodeticDatum.class);
+ final DatumEnsemble<GeodeticDatum> ensemble =
DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null);
final GeodeticDatum datum = (ensemble == null) ?
datumOrEnsemble : null;
constructor = (factory, metadata) ->
factory.createGeographicCRS(metadata, datum, ensemble, cs);
break;
@@ -1743,7 +1744,7 @@ search: try (ResultSet result =
executeMetadataQuery("Deprecation",
final String datumCode = getString(code, result, 9);
final VerticalCS cs = owner.createVerticalCS(csCode);
// Do not inline the `getString(…)` calls.
final VerticalDatum datumOrEnsemble =
owner.createVerticalDatum(datumCode);
- final DatumEnsemble<VerticalDatum> ensemble =
wasDatumEnsemble(datumOrEnsemble, VerticalDatum.class);
+ final DatumEnsemble<VerticalDatum> ensemble =
DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null);
final VerticalDatum datum = (ensemble == null) ?
datumOrEnsemble : null;
constructor = (factory, metadata) ->
factory.createVerticalCRS(metadata, datum, ensemble, cs);
break;
@@ -1760,7 +1761,7 @@ search: try (ResultSet result =
executeMetadataQuery("Deprecation",
final String datumCode = getString(code, result, 9);
final TimeCS cs = owner.createTimeCS(csCode); // Do
not inline the `getString(…)` calls.
final TemporalDatum datumOrEnsemble =
owner.createTemporalDatum(datumCode);
- final DatumEnsemble<TemporalDatum> ensemble =
wasDatumEnsemble(datumOrEnsemble, TemporalDatum.class);
+ final DatumEnsemble<TemporalDatum> ensemble =
DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null);
final TemporalDatum datum = (ensemble == null) ?
datumOrEnsemble : null;
constructor = (factory, metadata) ->
factory.createTemporalCRS(metadata, datum, ensemble, cs);
break;
@@ -1773,7 +1774,7 @@ search: try (ResultSet result =
executeMetadataQuery("Deprecation",
final String datumCode = getString(code, result, 9);
final CoordinateSystem cs =
owner.createCoordinateSystem(csCode); // Do not inline the `getString(…)`
calls.
final EngineeringDatum datumOrEnsemble =
owner.createEngineeringDatum(datumCode);
- final DatumEnsemble<EngineeringDatum> ensemble =
wasDatumEnsemble(datumOrEnsemble, EngineeringDatum.class);
+ final DatumEnsemble<EngineeringDatum> ensemble =
DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null);
final EngineeringDatum datum = (ensemble == null) ?
datumOrEnsemble : null;
constructor = (factory, metadata) ->
factory.createEngineeringCRS(metadata, datum, ensemble, cs);
break;
@@ -1786,7 +1787,7 @@ search: try (ResultSet result =
executeMetadataQuery("Deprecation",
final String datumCode = getString(code, result, 9);
final ParametricCS cs =
owner.createParametricCS(csCode); // Do not inline the `getString(…)` calls.
final ParametricDatum datumOrEnsemble =
owner.createParametricDatum(datumCode);
- final DatumEnsemble<ParametricDatum> ensemble =
wasDatumEnsemble(datumOrEnsemble, ParametricDatum.class);
+ final DatumEnsemble<ParametricDatum> ensemble =
DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null);
final ParametricDatum datum = (ensemble == null) ?
datumOrEnsemble : null;
constructor = (factory, metadata) ->
factory.createParametricCRS(metadata, datum, ensemble, cs);
break;
@@ -1836,29 +1837,6 @@ search: try (ResultSet result =
executeMetadataQuery("Deprecation",
return returnValue;
}
- /**
- * Returns the given datum as a datum ensemble if it should be considered
as such.
- * This method exists because the datum and datum ensemble are stored in
the same table,
- * and Apache <abbr>SIS</abbr> creates those two kinds of objects with the
same method.
- * The real type is resolved by inspection of the {@link
#createDatum(String)} return value.
- *
- * <h4>Design restriction</h4>
- * We cannot resolve the type with a private field which would be set by
{@link #createDatumEnsemble(String)}
- * because that method will not be invoked if the datum is fetched from
the cache.
- *
- * @param <D> compile-time value of {@code memberType}.
- * @param datum the datum to check if it is a datum ensemble.
- * @param memberType the expected type of datum members.
- * @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> wasDatumEnsemble(final D
datum, final Class<D> memberType) {
- if (datum instanceof DatumEnsemble<?>) {
- return DefaultDatumEnsemble.castOrCopy((DatumEnsemble<?>)
datum).cast(memberType);
- }
- return null;
- }
-
/**
* Creates an arbitrary datum from a code. The returned object will
typically be an
* instance of {@link GeodeticDatum}, {@link VerticalDatum} or {@link
TemporalDatum}.
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
index 9f977bc288..ec8bc9e40a 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
@@ -627,8 +627,11 @@ public class CoordinateOperationFinder extends
CoordinateOperationRegistry {
if (!(interpolationCS instanceof EllipsoidalCS)) {
final EllipsoidalCS cs =
CommonCRS.WGS84.geographic3D().getCoordinateSystem();
if (!Utilities.equalsIgnoreMetadata(interpolationCS, cs)) {
- final GeographicCRS stepCRS = factorySIS.crsFactory
- .createGeographicCRS(derivedFrom(sourceCRS),
sourceCRS.getDatum(), sourceCRS.getDatumEnsemble(), cs);
+ final GeographicCRS stepCRS =
factorySIS.crsFactory.createGeographicCRS(
+ derivedFrom(sourceCRS),
+ sourceCRS.getDatum(),
+ sourceCRS.getDatumEnsemble(),
+ cs);
step1 = createOperation(sourceCRS,
toAuthorityDefinition(GeographicCRS.class, stepCRS));
interpolationCRS = step1.getTargetCRS();
interpolationCS = interpolationCRS.getCoordinateSystem();
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/Assertions.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/Assertions.java
index 629f83ef94..84497a619b 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/Assertions.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/Assertions.java
@@ -38,7 +38,10 @@ import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.cs.RangeMeaning;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.apache.sis.util.Static;
+import org.apache.sis.util.Utilities;
+import org.apache.sis.util.ComparisonMode;
import org.apache.sis.io.wkt.Symbols;
import org.apache.sis.io.wkt.WKTFormat;
import org.apache.sis.io.wkt.Convention;
@@ -94,6 +97,21 @@ public final class Assertions extends Static {
private Assertions() {
}
+ /**
+ * Asserts that the two given coordinate references are equivalent.
+ * This method is tolerance to differences regarding whether a datum
versus datum ensemble.
+ *
+ * @param expected the expected object.
+ * @param actual the actual object.
+ *
+ * @see org.apache.sis.test.Assertions#assertEqualsIgnoreMetadata(Object,
Object)
+ */
+ public static void assertEquivalent(final CoordinateReferenceSystem
expected, final CoordinateReferenceSystem actual) {
+ assertTrue(Utilities.deepEquals(expected, actual,
ComparisonMode.DEBUG), "Shall be approximately equal.");
+ assertTrue(Utilities.deepEquals(expected, actual,
ComparisonMode.APPROXIMATE), "DEBUG inconsistent with APPROXIMATE.");
+ assertTrue(CRS.equivalent(expected, actual), "CRS shall be
equivalent.");
+ }
+
/**
* Asserts that the given identifier has the expected code and the {@code
"OGC"} code space.
* The authority is expected to be {@link Citations#OGC}. We expect the
exact same authority
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CRSTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CRSTest.java
index c03e0ad1c1..94dcc1f456 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CRSTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CRSTest.java
@@ -116,6 +116,7 @@ public final class CRSTest extends TestCaseWithLogs {
verifyForCode(CommonCRS.Vertical.MEAN_SEA_LEVEL.crs(), "EPSG:5714");
verifyForCode(CommonCRS.Vertical.DEPTH.crs(), "EPSG:5715");
+ loggings.skipNextLogIfContains("EPSG:6047");
loggings.skipNextLogIfContains("EPSG:4047"); // No longer supported
by EPSG.
loggings.assertNoUnexpectedLog();
}
@@ -258,6 +259,7 @@ public final class CRSTest extends TestCaseWithLogs {
null, new DefaultGeographicBoundingBox(-1, +1, ymin,
ymax), null, null));
crs[i] = new DefaultProjectedCRS(properties, baseCRS.geographic(),
HardCodedConversions.MERCATOR, cs);
}
+ loggings.skipNextLogIfContains("EPSG:6047"); //
Datum of EPSG:4047.
loggings.skipNextLogIfContains("EPSG:4047"); //
No longer supported by EPSG.
final ProjectedCRS[] overlappingCRS = Arrays.copyOf(crs, 3); //
Exclude the last CRS only.
/*
diff --git
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
index da24ead89f..7551ac1fe6 100644
---
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
@@ -198,7 +198,7 @@ public final class CommonCRSTest extends
EPSGDependentTestCase {
Validators.validate(crs);
assertEquals ("ETRS89", crs.getName().getCode());
assertSame (CommonCRS.ETRS89.geographic().getDatum(),
crs.getDatum());
- assertNotSame(CommonCRS.WGS84 .geographic().getDatum(),
crs.getDatum());
+ assertNotSame(CommonCRS.WGS84 .datum(true), crs.getDatum());
final CoordinateSystem cs = crs.getCoordinateSystem();
final String name = cs.getName().getCode();
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/EPSGFactoryFallbackTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/EPSGFactoryFallbackTest.java
index ed618cbfaa..191bb02450 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/EPSGFactoryFallbackTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/EPSGFactoryFallbackTest.java
@@ -145,6 +145,7 @@ public final class EPSGFactoryFallbackTest extends
TestCaseWithLogs {
verifyCreateDatum(CommonCRS.NAD27 .datum(true), "6267");
verifyCreateDatum(CommonCRS.ED50 .datum(true), "6230");
verifyCreateDatum(CommonCRS.SPHERE.datum(true), "6047");
+ loggings.skipNextLogIfContains("EPSG:6047"); // Deprecated EPSG
entry for datum.
loggings.assertNoUnexpectedLog();
}
@@ -213,7 +214,7 @@ public final class EPSGFactoryFallbackTest extends
TestCaseWithLogs {
* Asserts that the result of {@link
EPSGFactoryFallback#createObject(String)} is the given datum.
*/
private static void verifyCreateDatum(final Datum expected, final String
code) throws FactoryException {
- assertSame(expected, EPSGFactoryFallback.INSTANCE.createDatum(code),
code);
+ assertSame(expected, EPSGFactoryFallback.INSTANCE.createDatum (code),
code);
assertSame(expected, EPSGFactoryFallback.INSTANCE.createObject(code),
code);
}
@@ -271,9 +272,13 @@ public final class EPSGFactoryFallbackTest extends
TestCaseWithLogs {
} finally {
setEPSGFactory(EPSG);
}
- loggings.skipNextLogIfContains("EPSG:4047");
- loggings.skipNextLogIfContains("EPSG:4019"); // Deprecated EPSG
entry.
- loggings.skipNextLogIfContains("EPSG:4047"); // Repeated
because order may vary.
+ boolean repeat = false;
+ do {
+ loggings.skipNextLogIfContains("EPSG:6047"); // Deprecated
EPSG entry for datum.
+ loggings.skipNextLogIfContains("EPSG:4047"); // Deprecated
EPSG entry for CRS.
+ loggings.skipNextLogIfContains("EPSG:6019"); // Deprecated
EPSG entry for datum.
+ loggings.skipNextLogIfContains("EPSG:4019"); // Deprecated
EPSG entry for CRS.
+ } while ((repeat = !repeat) == true); // Repeated
because order may vary.
loggings.assertNoUnexpectedLog();
}
}
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/HardCodedDatum.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/HardCodedDatum.java
index 3edb04e959..aef537a003 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/HardCodedDatum.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/HardCodedDatum.java
@@ -108,6 +108,7 @@ public final class HardCodedDatum {
/**
* Spherical datum based on GRS 1980 Authalic Sphere (EPSG:6047). Prime
meridian is Greenwich.
+ * Note that this entry has been deprecated in recent <abbr>EPSG</abbr>
versions.
*/
public static final DefaultGeodeticDatum SPHERE = new DefaultGeodeticDatum(
properties("Not specified (based on GRS 1980 Authalic Sphere)",
"6047", "Not a valid datum."),
diff --git
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/CRSBuilder.java
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/CRSBuilder.java
index 50c3e33691..a9c3ebde88 100644
---
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/CRSBuilder.java
+++
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/CRSBuilder.java
@@ -1007,10 +1007,9 @@ previous: for (int i = components.size(); --i >= 0;) {
@Override void createCRS(CRSFactory factory, Map<String,?> properties)
throws FactoryException {
properties =
properties(getFirstAxis().coordinates.getUnitsString());
if (datum != null) {
- referenceSystem = factory.createTemporalCRS(properties,
datum, datumEnsemble, coordinateSystem);
+ referenceSystem = factory.createTemporalCRS(properties, datum,
datumEnsemble, coordinateSystem);
} else {
- referenceSystem = factory.createEngineeringCRS(properties,
- CommonCRS.Engineering.TIME.datum(), coordinateSystem);
+ referenceSystem = factory.createEngineeringCRS(properties,
CommonCRS.Engineering.TIME.datum(), coordinateSystem);
}
}
}
diff --git
a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageSubsetTest.java
b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageSubsetTest.java
index 8c3fa3e71b..833577cd04 100644
---
a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageSubsetTest.java
+++
b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageSubsetTest.java
@@ -36,7 +36,7 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import org.apache.sis.test.TestCase;
import org.apache.sis.referencing.crs.HardCodedCRS;
-import static org.apache.sis.test.Assertions.assertEqualsIgnoreMetadata;
+import static org.apache.sis.referencing.Assertions.assertEquivalent;
/**
@@ -114,7 +114,7 @@ public final class CoverageSubsetTest extends TestCase {
{
final GridGeometry domain = reduced.getGridGeometry();
assertEquals(dimension, domain.getDimension());
- assertEqualsIgnoreMetadata(crs, domain.getCoordinateReferenceSystem());
+ assertEquivalent(crs, domain.getCoordinateReferenceSystem());
final GridCoverage loaded = reduced.read(null);
assertEquals(domain, loaded.getGridGeometry());