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 c08fea432c Supports the `ENSEMBLE` element at WKT parsing and
formatting time.
c08fea432c is described below
commit c08fea432cbadbce85dd8748e3de942a74a851ef
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Sat Sep 6 18:52:54 2025 +0200
Supports the `ENSEMBLE` element at WKT parsing and formatting time.
---
.../org/apache/sis/console/CRSCommandTest.java | 6 +-
.../sis/metadata/iso/citation/Citations.java | 2 +-
.../sis/metadata/iso/citation/CitationsTest.java | 2 +-
.../main/org/apache/sis/io/wkt/AbstractParser.java | 9 +-
.../apache/sis/io/wkt/GeodeticObjectParser.java | 201 +++++++++++++++------
.../apache/sis/referencing/crs/AbstractCRS.java | 79 +++++---
.../sis/referencing/crs/AbstractDerivedCRS.java | 14 ++
.../sis/referencing/crs/DefaultCompoundCRS.java | 9 -
.../sis/referencing/crs/DefaultDerivedCRS.java | 38 ----
.../sis/referencing/crs/DefaultEngineeringCRS.java | 18 +-
.../sis/referencing/crs/DefaultGeodeticCRS.java | 27 ++-
.../sis/referencing/crs/DefaultParametricCRS.java | 18 +-
.../sis/referencing/crs/DefaultProjectedCRS.java | 10 -
.../sis/referencing/crs/DefaultTemporalCRS.java | 18 +-
.../sis/referencing/crs/DefaultVerticalCRS.java | 18 +-
.../sis/referencing/datum/AbstractDatum.java | 33 +++-
.../referencing/datum/DefaultDatumEnsemble.java | 74 ++++++--
.../referencing/datum/DefaultEngineeringDatum.java | 16 +-
.../referencing/datum/DefaultGeodeticDatum.java | 7 +-
.../sis/referencing/datum/DefaultImageDatum.java | 21 ++-
.../referencing/datum/DefaultParametricDatum.java | 16 +-
.../referencing/datum/DefaultTemporalDatum.java | 14 +-
.../referencing/datum/DefaultVerticalDatum.java | 9 +-
.../referencing/factory/GeodeticObjectFactory.java | 2 +-
.../internal/PositionalAccuracyConstant.java | 58 +++---
.../operation/AbstractCoordinateOperation.java | 10 +-
.../provider/MercatorAuxiliarySphere.java | 3 +-
.../referencing/operation/provider/Mollweide.java | 3 +-
.../provider/ObliqueMercatorTwoPoints.java | 5 +-
.../apache/sis/referencing/privy/WKTKeywords.java | 28 +--
.../apache/sis/referencing/privy/WKTUtilities.java | 18 ++
.../sis/io/wkt/GeodeticObjectParserTest.java | 35 +++-
.../operation/HardCodedConversions.java | 5 +-
.../main/org/apache/sis/setup/GeometryLibrary.java | 3 +-
.../main/org/apache/sis/util/privy/Constants.java | 5 +
35 files changed, 534 insertions(+), 300 deletions(-)
diff --git
a/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/CRSCommandTest.java
b/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/CRSCommandTest.java
index 380b0b0c71..ac42465ab6 100644
---
a/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/CRSCommandTest.java
+++
b/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/CRSCommandTest.java
@@ -44,8 +44,10 @@ public final class CRSCommandTest extends TestCase {
final String name = "\"WGS\\E\\s?(?:19)?\\Q84\"";
// Accept "WGS 84" or "WGS 1984".
WGS84 = "(?m)\\Q" +
// Multilines.
"GeodeticCRS[" + name + ",\n" +
- " Datum[\"World Geodetic System 1984\\E\\s?\\w*\\Q\",\n" +
// End with "ensemble" in EPSG 10+.
- " Ellipsoid[" + name + ", 6378137.0, 298.257223563]],\n" +
+ " Ensemble[\"World Geodetic System 1984\\E\\s?\\w*\\Q\",\n" +
// Ignore any suffix in the name.
+ "\\E(?: Member\\[\".+\"\\],\n)+\\Q" +
// At least one MEMBER[…].
+ " Ellipsoid[" + name + ", 6378137.0, 298.257223563],\n" +
+ " EnsembleAccuracy[2.0]],\n" +
" CS[ellipsoidal, 2],\n" +
" Axis[\"Latitude (B)\", north],\n" +
" Axis[\"Longitude (L)\", east],\n" +
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/Citations.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/Citations.java
index 972fe9ba19..bd805c8be8 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/Citations.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/Citations.java
@@ -294,7 +294,7 @@ public final class Citations extends Static {
*
* @since 0.4
*/
- public static final IdentifierSpace<String> ESRI = new
CitationConstant.Authority<>("ArcGIS", "ESRI");
+ public static final IdentifierSpace<String> ESRI = new
CitationConstant.Authority<>("ArcGIS", Constants.ESRI);
/**
* The authority for identifiers of objects defined by the World
Meteorological Organization (<abbr>WMO</abbr>).
diff --git
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/citation/CitationsTest.java
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/citation/CitationsTest.java
index 1e15401bc4..c7f066ea78 100644
---
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/citation/CitationsTest.java
+++
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/citation/CitationsTest.java
@@ -90,7 +90,7 @@ public final class CitationsTest extends TestCase {
assertSame(EPSG, fromName(Constants.EPSG)); // Success of
this test is important for remaining of SIS.
assertSame(IOGP, fromName(Constants.IOGP));
assertSame(IOGP, fromName("OGP"));
- assertSame(ESRI, fromName("ESRI")); // Handled in
a way very similar to "OGC".
+ assertSame(ESRI, fromName(Constants.ESRI)); // Handled in
a way very similar to "OGC".
assertSame(NETCDF, fromName(Constants.NETCDF));
assertSame(GEOTIFF, fromName(Constants.GEOTIFF));
assertSame(PROJ4, fromName("Proj.4"));
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/AbstractParser.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/AbstractParser.java
index d6abe3c310..4e70bf62f5 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/AbstractParser.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/AbstractParser.java
@@ -425,17 +425,18 @@ abstract class AbstractParser implements Parser {
*
* @param parent the element from which to pull a child element.
* @param key name of the element to pull.
- * @return the value, or {@code null} if none.
+ * @param mode {@link #MANDATORY} or {@link #OPTIONAL}.
+ * @return the value, or {@code Double.NaN} if none.
* @throws ParseException if an element cannot be parsed.
*/
- final Double pullElementAsDouble(final Element parent, final String key)
throws ParseException {
- Element element = parent.pullElement(OPTIONAL, key);
+ final double pullElementAsDouble(final Element parent, final String key,
final int mode) throws ParseException {
+ Element element = parent.pullElement(mode, key);
if (element != null) {
double value = element.pullDouble(key);
element.close(ignoredElements);
return value;
}
- return null;
+ return Double.NaN;
}
/**
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 d64fc1d548..2fda55c79c 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
@@ -304,27 +304,22 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
*/
@Override
final Object buildFromTree(final Element element) throws ParseException {
- Object value = parseCoordinateReferenceSystem(element, false);
- if (value != null) {
- return value;
- }
- value = parseMathTransform(element, false);
- if (value != null) {
- return value;
- }
Object object;
- if ((object = parseAxis (FIRST, element, null,
Units.METRE )) == null &&
- (object = parsePrimeMeridian (FIRST, element, false,
Units.DEGREE)) == null &&
- (object = parseDatum (FIRST, element, null )) == null &&
- (object = parseEllipsoid (FIRST, element )) == null &&
- (object = parseToWGS84 (FIRST, element )) == null &&
- (object = parseVerticalDatum (FIRST, element, false)) == null &&
- (object = parseTimeDatum (FIRST, element )) == null &&
- (object = parseParametricDatum (FIRST, element )) == null &&
- (object = parseEngineeringDatum (FIRST, element, false)) == null &&
- (object = parseImageDatum (FIRST, element )) == null &&
- (object = parseOperation (FIRST, element)) == null &&
- (object = parseGeogTranslation (FIRST, element)) == null)
+ if (null == (object = parseCoordinateReferenceSystem(element,
false))
+ && null == (object = parseMathTransform (element,
false))
+ && null == (object = parseAxis (FIRST, element, null,
Units.METRE ))
+ && null == (object = parsePrimeMeridian (FIRST, element,
false, Units.DEGREE))
+ && null == (object = parseEnsemble (FIRST, element,
Datum.class, greenwich()))
+ && null == (object = parseDatum (FIRST, element,
greenwich()))
+ && null == (object = parseEllipsoid (FIRST, element))
+ && null == (object = parseToWGS84 (FIRST, element))
+ && null == (object = parseVerticalDatum (FIRST, element,
false))
+ && null == (object = parseTimeDatum (FIRST, element))
+ && null == (object = parseParametricDatum (FIRST, element))
+ && null == (object = parseEngineeringDatum (FIRST, element,
false))
+ && null == (object = parseImageDatum (FIRST, element))
+ && null == (object = parseOperation (FIRST, element))
+ && null == (object = parseGeogTranslation (FIRST, element)))
{
throw element.missingOrUnknownComponent(WKTKeywords.GeodeticCRS);
}
@@ -1111,12 +1106,12 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
* If present, we will store that value for processing by the
`parseCoordinateSystem(…)` method.
*/
final Integer order = pullElementAsInteger(element,
WKTKeywords.Order);
- final Double minimum = pullElementAsDouble (element,
WKTKeywords.AxisMinValue);
- final Double maximum = pullElementAsDouble (element,
WKTKeywords.AxisMaxValue);
+ final double minimum = pullElementAsDouble (element,
WKTKeywords.AxisMinValue, OPTIONAL);
+ final double maximum = pullElementAsDouble (element,
WKTKeywords.AxisMaxValue, OPTIONAL);
final String meaning = pullElementAsEnum (element,
WKTKeywords.RangeMeaning);
final Map<String, Object> properties = parseMetadataAndClose(element,
name, null);
- properties.put(DefaultCoordinateSystemAxis.MINIMUM_VALUE_KEY, minimum);
- properties.put(DefaultCoordinateSystemAxis.MAXIMUM_VALUE_KEY, maximum);
+ if (Double.isFinite(minimum))
properties.put(DefaultCoordinateSystemAxis.MINIMUM_VALUE_KEY, minimum);
+ if (Double.isFinite(maximum))
properties.put(DefaultCoordinateSystemAxis.MAXIMUM_VALUE_KEY, maximum);
properties.put(DefaultCoordinateSystemAxis.RANGE_MEANING_KEY,
Types.forCodeName(RangeMeaning.class, meaning,
RangeMeaning::valueOf));
/*
@@ -1414,6 +1409,75 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
}
}
+ /**
+ * Parses an {@code "Ensemble"} (WKT 2) element.
+ *
+ * @param mode {@link #FIRST}, {@link #OPTIONAL} or {@link
#MANDATORY}.
+ * @param parent the parent element.
+ * @param datumType GeoAPI interface of the type of datum to create.
+ * @param meridian the prime meridian, or {@code null} if the ensemble
is not geodetic.
+ * @return the {@code "Ensemble"} element as a {@link DatumEnsemble}
object.
+ * @throws ParseException if the {@code "Ensemble"} element cannot be
parsed.
+ *
+ * @see
org.apache.sis.referencing.datum.DefaultDatumEnsemble#formatTo(Formatter)
+ */
+ private <D extends Datum> DatumEnsemble<D> parseEnsemble(final int mode,
final Element parent,
+ final Class<D> datumType, final PrimeMeridian meridian) throws
ParseException
+ {
+ final Element ensemble = parent.pullElement(mode,
WKTKeywords.Ensemble);
+ if (ensemble == null) {
+ return null;
+ }
+ final String ensembleName = ensemble.pullString("name");
+ final Ellipsoid ellipsoid;
+ final boolean vertical;
+ if (datumType == GeodeticDatum.class) {
+ ellipsoid = parseEllipsoid(MANDATORY, ensemble);
+ vertical = false;
+ } else if (datumType == Datum.class) {
+ // Unspecified datum type, use the presence of `ELLIPSOID` for
detecting the geodetic case.
+ ellipsoid = parseEllipsoid(OPTIONAL, ensemble);
+ vertical = (ellipsoid == null);
+ } else {
+ ellipsoid = null;
+ vertical = (datumType == VerticalDatum.class);
+ }
+ final DatumFactory datumFactory = factories.getDatumFactory();
+ final var members = new ArrayList<D>();
+ try {
+ Element element = ensemble.pullElement(MANDATORY,
WKTKeywords.Member);
+ do {
+ final Datum member;
+ try {
+ final String name = element.pullString("name");
+ final Map<String,Object> properties =
parseAnchorAndClose(element, name);
+ if (ellipsoid != null) { // `memberType` may be `Datum`
or `GeodeticDatum`
+ member = datumFactory.createGeodeticDatum(properties,
ellipsoid, meridian);
+ } else if (vertical) {
+ member = datumFactory.createVerticalDatum(properties,
null);
+ } else if (datumType == TemporalDatum.class) {
+ member = datumFactory.createTemporalDatum(properties,
null);
+ } else if (datumType == ParametricDatum.class) {
+ member =
datumFactory.createParametricDatum(properties);
+ } else if (datumType == EngineeringDatum.class) {
+ member =
datumFactory.createEngineeringDatum(properties);
+ } else {
+ // Should never happen because this method is private
and we checked all calls.
+ throw new AssertionError(datumType);
+ }
+ } catch (FactoryException exception) {
+ throw element.parseFailed(exception);
+ }
+ members.add(datumType.cast(member));
+ element = ensemble.pullElement(OPTIONAL, WKTKeywords.Member);
+ } while (element != null);
+ var accuracy =
PositionalAccuracyConstant.ensemble(pullElementAsDouble(ensemble,
WKTKeywords.EnsembleAccuracy, MANDATORY));
+ return
datumFactory.createDatumEnsemble(parseAnchorAndClose(ensemble, ensembleName),
members, accuracy);
+ } catch (FactoryException exception) {
+ throw ensemble.parseFailed(exception);
+ }
+ }
+
/**
* Parses a {@code "Datum"} (WKT 2) element.
*
@@ -1425,13 +1489,13 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
*
* @param mode {@link #FIRST}, {@link #OPTIONAL} or {@link
#MANDATORY}.
* @param parent the parent element.
- * @param meridian the prime meridian, or {@code null} for Greenwich.
+ * @param meridian the prime meridian.
* @return the {@code "Datum"} element as a {@link GeodeticDatum} object.
* @throws ParseException if the {@code "Datum"} element cannot be parsed.
*
* @see
org.apache.sis.referencing.datum.DefaultGeodeticDatum#formatTo(Formatter)
*/
- private GeodeticDatum parseDatum(final int mode, final Element parent,
PrimeMeridian meridian) throws ParseException {
+ private GeodeticDatum parseDatum(final int mode, final Element parent,
final PrimeMeridian meridian) throws ParseException {
final Element element = parent.pullElement(mode, WKTKeywords.Datum,
WKTKeywords.GeodeticDatum);
if (element == null) {
return null;
@@ -1440,9 +1504,6 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
final Ellipsoid ellipsoid = parseEllipsoid(MANDATORY,
element);
final Object toWGS84 = parseToWGS84(OPTIONAL, element);
final Map<String,Object> properties = parseAnchorAndClose(element,
name);
- if (meridian == null) {
- meridian = CommonCRS.WGS84.primeMeridian();
- }
if (toWGS84 != null) {
properties.put(DefaultGeodeticDatum.BURSA_WOLF_KEY, toWGS84);
}
@@ -1639,6 +1700,7 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
* An EngineeringCRS can be either a "normal" one (with a non-null
datum), or a DerivedCRS.
* In the latter case, the datum is null and we have instead
DerivingConversion element from a base CRS.
*/
+ DatumEnsemble<EngineeringDatum> ensemble = null;
EngineeringDatum datum = null;
SingleCRS baseCRS = null;
Conversion fromBase = null;
@@ -1669,18 +1731,20 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
}
}
}
- if (baseCRS == null) {
// The most usual case.
- datum = parseEngineeringDatum(MANDATORY, element, isWKT1);
+ if (baseCRS == null) { // The most usual case.
+ ensemble = parseEnsemble(OPTIONAL, element,
EngineeringDatum.class, null);
+ datum = parseEngineeringDatum(ensemble == null ? MANDATORY :
OPTIONAL, element, isWKT1);
}
+ final IdentifiedObject datumOrEnsemble = (datum != null) ? datum :
ensemble;
final CRSFactory crsFactory = factories.getCRSFactory();
try {
final CoordinateSystem cs = parseCoordinateSystem(element, null,
1, isWKT1, unit, false, null);
- final Map<String,Object> properties =
parseMetadataAndClose(element, name, datum);
+ final Map<String,Object> properties =
parseMetadataAndClose(element, name, datumOrEnsemble);
if (baseCRS != null) {
properties.put(Legacy.DERIVED_TYPE_KEY, EngineeringCRS.class);
return crsFactory.createDerivedCRS(properties, baseCRS,
fromBase, cs);
}
- return crsFactory.createEngineeringCRS(properties, datum, cs);
+ return crsFactory.createEngineeringCRS(properties, datum,
ensemble, cs);
} catch (FactoryException exception) {
throw element.parseFailed(exception);
}
@@ -1874,19 +1938,23 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
warning(element, WKTKeywords.AngleUnit,
Errors.formatInternational(
Errors.Keys.InconsistentUnitsForCS_1, angularUnit),
null);
}
- final PrimeMeridian meridian = parsePrimeMeridian(OPTIONAL,
element, isWKT1, longitudeUnit);
- final GeodeticDatum datum = parseDatum(MANDATORY, element,
meridian);
- final DatumEnsemble<GeodeticDatum> datumEnsemble = null; // TODO
- final Map<String,?> properties = parseMetadataAndClose(element,
name, datum);
+ PrimeMeridian meridian = parsePrimeMeridian(OPTIONAL, element,
isWKT1, longitudeUnit);
+ if (meridian == null) {
+ meridian = greenwich();
+ }
+ final DatumEnsemble<GeodeticDatum> ensemble =
parseEnsemble(OPTIONAL, element, GeodeticDatum.class, meridian);
+ final GeodeticDatum datum = parseDatum(ensemble == null ?
MANDATORY : OPTIONAL, element, meridian);
+ final IdentifiedObject datumOrEnsemble = (datum != null) ? datum :
ensemble;
+ final Map<String,?> properties = parseMetadataAndClose(element,
name, datumOrEnsemble);
if (cs instanceof EllipsoidalCS) {
// By far the most frequent case.
- return crsFactory.createGeographicCRS(properties, datum,
datumEnsemble, (EllipsoidalCS) cs);
+ return crsFactory.createGeographicCRS(properties, datum,
ensemble, (EllipsoidalCS) cs);
}
if (cs instanceof CartesianCS) {
// The second most frequent case.
- return crsFactory.createGeodeticCRS(properties, datum,
datumEnsemble,
+ return crsFactory.createGeodeticCRS(properties, datum,
ensemble,
Legacy.forGeocentricCRS((CartesianCS) cs, false));
}
if (cs instanceof SphericalCS) {
// Not very common case.
- return crsFactory.createGeodeticCRS(properties, datum,
datumEnsemble, (SphericalCS) cs);
+ return crsFactory.createGeodeticCRS(properties, datum,
ensemble, (SphericalCS) cs);
}
} catch (FactoryException exception) {
throw element.parseFailed(exception);
@@ -1927,6 +1995,7 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
* A VerticalCRS can be either a "normal" one (with a non-null datum),
or a DerivedCRS of kind VerticalCRS.
* In the latter case, the datum is null and we have instead
DerivingConversion element from a BaseVertCRS.
*/
+ DatumEnsemble<VerticalDatum> ensemble = null;
VerticalDatum datum = null;
SingleCRS baseCRS = null;
Conversion fromBase = null;
@@ -1946,13 +2015,17 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
baseCRS = parseVerticalCRS(MANDATORY, element, true);
}
}
- if (baseCRS == null) {
// The most usual case.
- datum = parseVerticalDatum(MANDATORY, element, isWKT1);
+ if (baseCRS == null) { // The most usual case.
+ ensemble = parseEnsemble(OPTIONAL, element, VerticalDatum.class,
null);
+ datum = parseVerticalDatum(ensemble == null ? MANDATORY :
OPTIONAL, element, isWKT1);
}
+ final IdentifiedObject datumOrEnsemble = (datum != null) ? datum :
ensemble;
final CoordinateSystem cs;
try {
- cs = parseCoordinateSystem(element, WKTKeywords.vertical, 1,
isWKT1, unit, false, datum.getRealizationMethod().orElse(null));
- final Map<String,?> properties = parseMetadataAndClose(element,
name, datum);
+ final RealizationMethod method = (datumOrEnsemble instanceof
VerticalDatum)
+ ? ((VerticalDatum)
datumOrEnsemble).getRealizationMethod().orElse(null) : null;
+ cs = parseCoordinateSystem(element, WKTKeywords.vertical, 1,
isWKT1, unit, false, method);
+ final Map<String,?> properties = parseMetadataAndClose(element,
name, datumOrEnsemble);
if (cs instanceof VerticalCS) {
final CRSFactory crsFactory = factories.getCRSFactory();
if (baseCRS != null) {
@@ -1963,14 +2036,14 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
* But sometimes the axis (which was not available when we
created the datum) provides
* more information. Verify if we can have a better type now,
and if so rebuild the datum.
*/
- if (datum.getRealizationMethod().isEmpty()) {
+ if (method == null && datum != null) {
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);
}
}
- verticalCRS = crsFactory.createVerticalCRS(properties, datum,
(VerticalCS) cs);
+ verticalCRS = crsFactory.createVerticalCRS(properties, datum,
ensemble, (VerticalCS) cs);
/*
* Some DefaultVerticalExtent objects may be waiting for the
VerticalCRS before to complete
* their construction. If this is the case, try to complete
them now.
@@ -2008,6 +2081,7 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
* A TemporalCRS can be either a "normal" one (with a non-null datum),
or a DerivedCRS of kind TemporalCRS.
* In the latter case, the datum is null and we have instead
DerivingConversion element from a BaseTimeCRS.
*/
+ DatumEnsemble<TemporalDatum> ensemble = null;
TemporalDatum datum = null;
SingleCRS baseCRS = null;
Conversion fromBase = null;
@@ -2027,19 +2101,21 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
baseCRS = parseTimeCRS(MANDATORY, element, true);
}
}
- if (baseCRS == null) {
// The most usual case.
- datum = parseTimeDatum(MANDATORY, element);
+ if (baseCRS == null) { // The most usual case.
+ ensemble = parseEnsemble(OPTIONAL, element, TemporalDatum.class,
null);
+ datum = parseTimeDatum(ensemble == null ? MANDATORY : OPTIONAL,
element);
}
+ final IdentifiedObject datumOrEnsemble = (datum != null) ? datum :
ensemble;
final CoordinateSystem cs;
try {
cs = parseCoordinateSystem(element, WKTKeywords.temporal, 1,
false, unit, false, null);
- final Map<String,?> properties = parseMetadataAndClose(element,
name, datum);
+ final Map<String,?> properties = parseMetadataAndClose(element,
name, datumOrEnsemble);
if (cs instanceof TimeCS) {
final CRSFactory crsFactory = factories.getCRSFactory();
if (baseCRS != null) {
return crsFactory.createDerivedCRS(properties, baseCRS,
fromBase, cs);
}
- return crsFactory.createTemporalCRS(properties, datum,
(TimeCS) cs);
+ return crsFactory.createTemporalCRS(properties, datum,
ensemble, (TimeCS) cs);
}
} catch (FactoryException exception) {
throw element.parseFailed(exception);
@@ -2069,6 +2145,7 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
* A ParametricCRS can be either a "normal" one (with a non-null
datum), or a DerivedCRS of kind ParametricCRS.
* In the latter case, the datum is null and we have instead
DerivingConversion element from a BaseParametricCRS.
*/
+ DatumEnsemble<ParametricDatum> ensemble = null;
ParametricDatum datum = null;
SingleCRS baseCRS = null;
Conversion fromBase = null;
@@ -2088,19 +2165,21 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
baseCRS = parseParametricCRS(MANDATORY, element, true);
}
}
- if (baseCRS == null) {
// The most usual case.
- datum = parseParametricDatum(MANDATORY, element);
+ if (baseCRS == null) { // The most usual case.
+ ensemble = parseEnsemble(OPTIONAL, element, ParametricDatum.class,
null);
+ datum = parseParametricDatum(ensemble == null ? MANDATORY :
OPTIONAL, element);
}
+ final IdentifiedObject datumOrEnsemble = (datum != null) ? datum :
ensemble;
final CoordinateSystem cs;
try {
cs = parseCoordinateSystem(element, WKTKeywords.parametric, 1,
false, unit, false, null);
- final Map<String,?> properties = parseMetadataAndClose(element,
name, datum);
+ final Map<String,?> properties = parseMetadataAndClose(element,
name, datumOrEnsemble);
if (cs instanceof ParametricCS) {
final CRSFactory crsFactory = factories.getCRSFactory();
if (baseCRS != null) {
return crsFactory.createDerivedCRS(properties, baseCRS,
fromBase, cs);
}
- return crsFactory.createParametricCRS(properties, datum,
(ParametricCS) cs);
+ return crsFactory.createParametricCRS(properties, datum,
ensemble, (ParametricCS) cs);
}
} catch (FactoryException exception) {
throw element.parseFailed(exception);
@@ -2329,12 +2408,11 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
final CoordinateReferenceSystem targetCRS =
parseCoordinateReferenceSystem(element, MANDATORY, WKTKeywords.TargetCRS);
final CoordinateReferenceSystem interpolationCRS =
parseCoordinateReferenceSystem(element, OPTIONAL,
WKTKeywords.InterpolationCRS);
final OperationMethod method =
parseMethod(element, WKTKeywords.Method);
- final Element accuracy =
element.pullElement(OPTIONAL, WKTKeywords.OperationAccuracy);
+ final double accuracy =
pullElementAsDouble(element, WKTKeywords.OperationAccuracy, OPTIONAL);
final Map<String,Object> properties =
parseParametersAndClose(element, name, method);
- if (accuracy != null) {
+ if (Double.isFinite(accuracy)) {
properties.put(CoordinateOperation.COORDINATE_OPERATION_ACCURACY_KEY,
-
PositionalAccuracyConstant.transformation(accuracy.pullDouble("accuracy")));
- accuracy.close(ignoredElements);
+
PositionalAccuracyConstant.transformation(accuracy));
}
try {
final DefaultCoordinateOperationFactory df = getOperationFactory();
@@ -2376,4 +2454,11 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
return DefaultCoordinateOperationFactory.provider();
}
}
+
+ /**
+ * Returns the prime meridian to use by default when none is specified.
+ */
+ private static PrimeMeridian greenwich() {
+ return CommonCRS.WGS84.primeMeridian();
+ }
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
index 184d2b5ae7..a30da11b1c 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractCRS.java
@@ -19,6 +19,7 @@ package org.apache.sis.referencing.crs;
import java.util.Map;
import java.util.EnumMap;
import java.util.Objects;
+import java.util.function.Function;
import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlSeeAlso;
@@ -34,8 +35,10 @@ import org.apache.sis.referencing.cs.AbstractCS;
import org.apache.sis.referencing.cs.AxesConvention;
import org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis;
import org.apache.sis.referencing.datum.AbstractDatum;
+import org.apache.sis.referencing.datum.DefaultDatumEnsemble;
import org.apache.sis.referencing.privy.ReferencingUtilities;
import org.apache.sis.metadata.privy.ImplementationHelper;
+import org.apache.sis.io.wkt.FormattableObject;
import org.apache.sis.io.wkt.Convention;
import org.apache.sis.io.wkt.Formatter;
import org.apache.sis.util.Utilities;
@@ -44,6 +47,7 @@ import org.apache.sis.util.resources.Errors;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
import org.opengis.metadata.Identifier;
+import org.opengis.referencing.datum.DatumEnsemble;
// Specific to the geoapi-4.0 branch:
import org.opengis.referencing.crs.DerivedCRS;
@@ -281,34 +285,6 @@ public class AbstractCRS extends AbstractReferenceSystem
implements CoordinateRe
return CoordinateReferenceSystem.class;
}
- /**
- * Returns the datum or a view of the ensemble as a datum, or {@code null}
if none.
- * The {@code legacy} argument is usually {@code false}, except when
formatting in a legacy <abbr>WKT</abbr> format.
- *
- * @param legacy whether to allow a view of the ensemble as a datum for
interoperability with legacy standards.
- * @return the datum, or {@code null} if none.
- */
- Datum getDatumOrEnsemble(final boolean legacy) {
- /*
- * User could provide his own CRS implementation outside this SIS
package, so we have
- * to check for SingleCRS interface. But all SIS classes override this
implementation.
- */
- if (this instanceof SingleCRS) {
- final var crs = (SingleCRS) this;
- final Datum datum = crs.getDatum();
- if (datum != null) {
- return datum;
- }
- if (legacy) {
- final var ensemble = crs.getDatumEnsemble();
- if (ensemble instanceof Datum) {
- return (Datum) ensemble;
- }
- }
- }
- return null;
- }
-
/**
* Returns the coordinate system.
*
@@ -468,7 +444,7 @@ public class AbstractCRS extends AbstractReferenceSystem
implements CoordinateRe
protected String formatTo(final Formatter formatter) {
final String keyword = super.formatTo(formatter);
formatter.newLine();
- formatter.append(AbstractDatum.castOrCopy(getDatumOrEnsemble(true)));
// For the conversion of ensemble to datum.
+ formatDatum(formatter);
formatter.newLine();
final Convention convention = formatter.getConvention();
final boolean isWKT1 = convention.majorVersion() == 1;
@@ -479,6 +455,51 @@ public class AbstractCRS extends AbstractReferenceSystem
implements CoordinateRe
return keyword;
}
+ /**
+ * Formats the datum or a view of the ensemble as a datum.
+ * Subclasses should override for invoking the static {@code
formatDatum(…)} with more specifiy types.
+ */
+ void formatDatum(final Formatter formatter) {
+ /*
+ * User could provide his own CRS implementation outside this SIS
package, so we have
+ * to check for SingleCRS interface. But all SIS classes override this
implementation.
+ */
+ if (this instanceof SingleCRS) {
+ final var sc = (SingleCRS) this;
+ formatDatum(formatter, sc, sc.getDatum(),
AbstractDatum::castOrCopy, (crs) -> {
+ final DatumEnsemble<?> ensemble = crs.getDatumEnsemble();
+ return (ensemble instanceof Datum) ? (Datum) ensemble : null;
+ });
+ }
+ }
+
+ /**
+ * Formats the datum or a view of the ensemble as a datum.
+ *
+ * @param <D> the type of datum or ensemble members.
+ * @param formatter the formatter where to write the datum.
+ * @param crs the coordinate reference system.
+ * @param datum the datum to format, or {@code null} if none.
+ * @param toFormattable the function to invoke for converting the datum
to a formattable object.
+ * @param asDatum the function to invoke for getting an ensemble
viewed as a datum.
+ */
+ static <C extends SingleCRS, D extends Datum> void formatDatum(
+ final Formatter formatter,
+ final C crs,
+ final D datum,
+ final Function<D, FormattableObject> toFormattable,
+ final Function<C, D> asDatum)
+ {
+ if (datum != null) {
+ formatter.appendFormattable(datum, toFormattable);
+ } else if (formatter.getConvention().supports(Convention.WKT2_2019)) {
+ formatter.appendFormattable(crs.getDatumEnsemble(),
DefaultDatumEnsemble::castOrCopy);
+ } else {
+ // Apply `toFormattable` unconditionally for forcing a conversion
of ensemble to datum.
+ formatter.append(toFormattable.apply(asDatum.apply(crs)));
+ }
+ }
+
/**
* Returns {@code true} if the given formatter is in the process of
formatting the base CRS of an
* {@link AbstractDerivedCRS}. In such case, the coordinate system axes
shall not be formatted.
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
index cabb6fd81c..dba0e2c4c1 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/AbstractDerivedCRS.java
@@ -37,6 +37,7 @@ import
org.apache.sis.referencing.privy.ReferencingFactoryContainer;
import org.apache.sis.xml.bind.referencing.CC_Conversion;
import org.apache.sis.metadata.privy.ImplementationHelper;
import org.apache.sis.metadata.privy.Identifiers;
+import org.apache.sis.io.wkt.Formatter;
import org.apache.sis.system.Semaphores;
import org.apache.sis.util.Utilities;
import org.apache.sis.util.ArgumentChecks;
@@ -186,6 +187,19 @@ abstract class AbstractDerivedCRS extends AbstractCRS
implements DerivedCRS {
return conversionFromBase;
}
+ /**
+ * Formats the datum or a view of the ensemble as a datum.
+ */
+ @Override
+ final void formatDatum(final Formatter formatter) {
+ final SingleCRS baseCRS = getBaseCRS();
+ if (baseCRS instanceof AbstractCRS) {
+ ((AbstractCRS) baseCRS).formatDatum(formatter);
+ } else {
+ super.formatDatum(formatter);
+ }
+ }
+
/**
* Compares this coordinate reference system with the specified object for
equality.
*
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
index d6abe1b8be..fb2ba4b411 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultCompoundCRS.java
@@ -27,7 +27,6 @@ import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-import org.opengis.referencing.datum.Datum;
import org.opengis.referencing.crs.SingleCRS;
import org.opengis.referencing.crs.CompoundCRS;
import org.opengis.referencing.crs.GeodeticCRS;
@@ -309,14 +308,6 @@ public class DefaultCompoundCRS extends AbstractCRS
implements CompoundCRS {
return CompoundCRS.class;
}
- /**
- * Compound CRS do not have datum.
- */
- @Override
- final Datum getDatumOrEnsemble(final boolean legacy) {
- return null;
- }
-
/**
* Returns the ordered list of coordinate reference systems.
* This is the list of CRS given at construction time.
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
index 7973e5ed0d..72119d0ec0 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
@@ -53,7 +53,6 @@ import
org.apache.sis.xml.bind.referencing.CS_CoordinateSystem;
import org.apache.sis.referencing.privy.ReferencingUtilities;
import org.apache.sis.referencing.privy.WKTUtilities;
import org.apache.sis.referencing.privy.WKTKeywords;
-import org.apache.sis.referencing.datum.DatumOrEnsemble;
import static org.apache.sis.referencing.internal.Legacy.DERIVED_TYPE_KEY;
import org.apache.sis.io.wkt.Convention;
import org.apache.sis.io.wkt.Formatter;
@@ -425,18 +424,6 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS
implements DerivedCRS
return getBaseCRS().getDatumEnsemble();
}
- /**
- * Returns the datum or a view of the ensemble as a datum.
- */
- @Override
- Datum getDatumOrEnsemble(final boolean legacy) {
- final SingleCRS baseCRS = getBaseCRS();
- if (baseCRS instanceof AbstractCRS) {
- return ((AbstractCRS) baseCRS).getDatumOrEnsemble(legacy);
- }
- return super.getDatumOrEnsemble(legacy);
- }
-
/**
* Returns the CRS on which the conversion is applied.
* This CRS defines the {@linkplain #getDatum() datum} of this CRS and (at
least implicitly)
@@ -686,11 +673,6 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS
implements DerivedCRS
return ((GeodeticCRS) getBaseCRS()).getDatumEnsemble();
}
- /** Returns the datum or a view of the ensemble as a datum. */
- @Override GeodeticDatum getDatumOrEnsemble(final boolean legacy) {
- return legacy ? DatumOrEnsemble.asDatum((GeodeticCRS)
getBaseCRS()) : getDatum();
- }
-
/** Returns a coordinate reference system of the same type as this CRS
but with different axes. */
@Override AbstractCRS createSameType(final AbstractCS derivedCS) {
return new Geodetic(this, derivedCS);
@@ -747,11 +729,6 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS
implements DerivedCRS
return ((VerticalCRS) getBaseCRS()).getDatumEnsemble();
}
- /** Returns the datum or a view of the ensemble as a datum. */
- @Override VerticalDatum getDatumOrEnsemble(final boolean legacy) {
- return legacy ? DatumOrEnsemble.asDatum((VerticalCRS)
getBaseCRS()) : getDatum();
- }
-
/** Returns the coordinate system given at construction time. */
@Override public VerticalCS getCoordinateSystem() {
return (VerticalCS) super.getCoordinateSystem();
@@ -813,11 +790,6 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS
implements DerivedCRS
return ((TemporalCRS) getBaseCRS()).getDatumEnsemble();
}
- /** Returns the datum or a view of the ensemble as a datum. */
- @Override TemporalDatum getDatumOrEnsemble(final boolean legacy) {
- return legacy ? DatumOrEnsemble.asDatum((TemporalCRS)
getBaseCRS()) : getDatum();
- }
-
/** Returns the coordinate system given at construction time. */
@Override public TimeCS getCoordinateSystem() {
return (TimeCS) super.getCoordinateSystem();
@@ -879,11 +851,6 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS
implements DerivedCRS
return ((ParametricCRS) getBaseCRS()).getDatumEnsemble();
}
- /** Returns the datum or a view of the ensemble as a datum. */
- @Override ParametricDatum getDatumOrEnsemble(final boolean legacy) {
- return legacy ? DatumOrEnsemble.asDatum((ParametricCRS)
getBaseCRS()) : getDatum();
- }
-
/** Returns the coordinate system given at construction time. */
@Override public ParametricCS getCoordinateSystem() {
return (ParametricCS) super.getCoordinateSystem();
@@ -948,11 +915,6 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS
implements DerivedCRS
return ((EngineeringCRS) getBaseCRS()).getDatumEnsemble();
}
- /** Returns the datum or a view of the ensemble as a datum. */
- @Override EngineeringDatum getDatumOrEnsemble(final boolean legacy) {
- return legacy ? DatumOrEnsemble.asDatum((EngineeringCRS)
getBaseCRS()) : getDatum();
- }
-
/** Returns a coordinate reference system of the same type as this CRS
but with different axes. */
@Override AbstractCRS createSameType(final AbstractCS derivedCS) {
return new Engineering(this, derivedCS);
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java
index 95c51219cc..a20f930a20 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultEngineeringCRS.java
@@ -27,6 +27,7 @@ import org.opengis.referencing.datum.EngineeringDatum;
import org.apache.sis.referencing.AbstractReferenceSystem;
import org.apache.sis.referencing.cs.*;
import org.apache.sis.referencing.datum.DatumOrEnsemble;
+import org.apache.sis.referencing.datum.DefaultEngineeringDatum;
import org.apache.sis.referencing.privy.WKTKeywords;
import org.apache.sis.xml.bind.referencing.CS_CoordinateSystem;
import org.apache.sis.io.wkt.Formatter;
@@ -236,15 +237,6 @@ public class DefaultEngineeringCRS extends
AbstractSingleCRS<EngineeringDatum> i
return super.getDatumEnsemble();
}
- /**
- * Returns the datum or a view of the ensemble as a datum.
- * The {@code legacy} argument tells whether this method is invoked for
formatting in a legacy <abbr>WKT</abbr> format.
- */
- @Override
- final EngineeringDatum getDatumOrEnsemble(final boolean legacy) {
- return legacy ? DatumOrEnsemble.asDatum(this) : getDatum();
- }
-
/**
* {@inheritDoc}
*
@@ -279,6 +271,14 @@ public class DefaultEngineeringCRS extends
AbstractSingleCRS<EngineeringDatum> i
: formatter.shortOrLong(WKTKeywords.EngCRS,
WKTKeywords.EngineeringCRS);
}
+ /**
+ * Formats the datum or a view of the ensemble as a datum.
+ */
+ @Override
+ final void formatDatum(final Formatter formatter) {
+ formatDatum(formatter, this, getDatum(),
DefaultEngineeringDatum::castOrCopy, DatumOrEnsemble::asDatum);
+ }
+
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
index 93844e7a95..bbc1e2e742 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
@@ -44,7 +44,6 @@ import org.apache.sis.referencing.privy.ReferencingUtilities;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.io.wkt.Convention;
import org.apache.sis.io.wkt.Formatter;
-import org.apache.sis.measure.Units;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
import org.opengis.referencing.datum.DatumEnsemble;
@@ -161,15 +160,6 @@ class DefaultGeodeticCRS extends
AbstractSingleCRS<GeodeticDatum> implements Geo
return super.getDatum();
}
- /**
- * Returns the datum or a view of the ensemble as a datum.
- * The {@code legacy} argument tells whether this method is invoked for
formatting in a legacy <abbr>WKT</abbr> format.
- */
- @Override
- final GeodeticDatum getDatumOrEnsemble(final boolean legacy) {
- return legacy ? DatumOrEnsemble.asDatum(this) : getDatum();
- }
-
/**
* Returns a coordinate reference system of the same type as this CRS but
with different axes.
* This method shall be overridden by all {@code DefaultGeodeticCRS}
subclasses in this package.
@@ -221,16 +211,13 @@ class DefaultGeodeticCRS extends
AbstractSingleCRS<GeodeticDatum> implements Geo
* The prime meridian is part of datum according ISO 19111, but is
formatted
* as a sibling (rather than a child) element in WKT for historical
reasons.
*/
- @SuppressWarnings("LocalVariableHidesMemberVariable")
- final GeodeticDatum datum = getDatumOrEnsemble(true);
formatter.newLine();
- formatter.append(DefaultGeodeticDatum.castOrCopy(datum)); // For the
conversion of ensemble to datum.
+ formatDatum(formatter);
formatter.newLine();
final Unit<Angle> angularUnit = AxisDirections.getAngularUnit(cs,
null);
DatumOrEnsemble.getPrimeMeridian(this).ifPresent((PrimeMeridian pm) ->
{
- if (convention != Convention.WKT2_SIMPLIFIED || // Really this
specific enum, not Convention.isSimplified().
- ReferencingUtilities.getGreenwichLongitude(pm,
Units.DEGREE) != 0)
- {
+ // Really this specific enum, not Convention.isSimplified().
+ if (convention != Convention.WKT2_SIMPLIFIED ||
pm.getGreenwichLongitude() != 0) {
final Unit<Angle> oldUnit =
formatter.addContextualUnit(angularUnit);
formatter.indent(1);
formatter.appendFormattable(pm,
DefaultPrimeMeridian::castOrCopy);
@@ -291,6 +278,14 @@ class DefaultGeodeticCRS extends
AbstractSingleCRS<GeodeticDatum> implements Geo
}
}
+ /**
+ * Formats the datum or a view of the ensemble as a datum.
+ */
+ @Override
+ final void formatDatum(final Formatter formatter) {
+ formatDatum(formatter, this, getDatum(),
DefaultGeodeticDatum::castOrCopy, DatumOrEnsemble::asDatum);
+ }
+
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultParametricCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultParametricCRS.java
index e0334e0404..285fc6cb3e 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultParametricCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultParametricCRS.java
@@ -24,6 +24,7 @@ import org.apache.sis.referencing.privy.WKTKeywords;
import org.apache.sis.referencing.cs.AxesConvention;
import org.apache.sis.referencing.cs.AbstractCS;
import org.apache.sis.referencing.datum.DatumOrEnsemble;
+import org.apache.sis.referencing.datum.DefaultParametricDatum;
import org.apache.sis.io.wkt.Formatter;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
@@ -219,15 +220,6 @@ public class DefaultParametricCRS extends
AbstractSingleCRS<ParametricDatum> imp
return super.getDatumEnsemble();
}
- /**
- * Returns the datum or a view of the ensemble as a datum.
- * The {@code legacy} argument tells whether this method is invoked for
formatting in a legacy <abbr>WKT</abbr> format.
- */
- @Override
- final ParametricDatum getDatumOrEnsemble(final boolean legacy) {
- return legacy ? DatumOrEnsemble.asDatum(this) : getDatum();
- }
-
/**
* Returns the coordinate system.
*
@@ -278,6 +270,14 @@ public class DefaultParametricCRS extends
AbstractSingleCRS<ParametricDatum> imp
return isBaseCRS(formatter) ? WKTKeywords.BaseParamCRS :
WKTKeywords.ParametricCRS;
}
+ /**
+ * Formats the datum or a view of the ensemble as a datum.
+ */
+ @Override
+ final void formatDatum(final Formatter formatter) {
+ formatDatum(formatter, this, getDatum(),
DefaultParametricDatum::castOrCopy, DatumOrEnsemble::asDatum);
+ }
+
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
index 25ad210d3d..bc289ee30f 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
@@ -30,7 +30,6 @@ import org.opengis.referencing.datum.GeodeticDatum;
import org.opengis.referencing.operation.Conversion;
import org.apache.sis.referencing.cs.AxesConvention;
import org.apache.sis.referencing.cs.AbstractCS;
-import org.apache.sis.referencing.datum.DatumOrEnsemble;
import org.apache.sis.referencing.privy.ReferencingUtilities;
import org.apache.sis.referencing.privy.AxisDirections;
import org.apache.sis.referencing.privy.WKTKeywords;
@@ -238,15 +237,6 @@ public class DefaultProjectedCRS extends
AbstractDerivedCRS implements Projected
return getBaseCRS().getDatumEnsemble();
}
- /**
- * Returns the datum or a view of the ensemble as a datum.
- * The {@code legacy} argument tells whether this method is invoked for
formatting in a legacy <abbr>WKT</abbr> format.
- */
- @Override
- final GeodeticDatum getDatumOrEnsemble(final boolean legacy) {
- return legacy ? DatumOrEnsemble.asDatum(getBaseCRS()) : getDatum();
- }
-
/**
* Returns the geographic CRS on which the map projection is applied.
* This CRS defines the {@linkplain #getDatum() datum} of this CRS and (at
least implicitly)
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
index 11f109ec18..b9c063073e 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
@@ -38,6 +38,7 @@ import org.apache.sis.referencing.AbstractReferenceSystem;
import org.apache.sis.referencing.cs.AxesConvention;
import org.apache.sis.referencing.cs.AbstractCS;
import org.apache.sis.referencing.datum.DatumOrEnsemble;
+import org.apache.sis.referencing.datum.DefaultTemporalDatum;
import org.apache.sis.referencing.privy.WKTKeywords;
import org.apache.sis.io.wkt.Formatter;
import org.apache.sis.measure.Units;
@@ -291,15 +292,6 @@ public class DefaultTemporalCRS extends
AbstractSingleCRS<TemporalDatum> impleme
return super.getDatumEnsemble();
}
- /**
- * Returns the datum or a view of the ensemble as a datum.
- * The {@code legacy} argument tells whether this method is invoked for
formatting in a legacy <abbr>WKT</abbr> format.
- */
- @Override
- final TemporalDatum getDatumOrEnsemble(final boolean legacy) {
- return legacy ? DatumOrEnsemble.asDatum(this) : getDatum();
- }
-
/**
* Returns the coordinate system.
*
@@ -518,6 +510,14 @@ public class DefaultTemporalCRS extends
AbstractSingleCRS<TemporalDatum> impleme
return isBaseCRS(formatter) ? WKTKeywords.BaseTimeCRS :
WKTKeywords.TimeCRS;
}
+ /**
+ * Formats the datum or a view of the ensemble as a datum.
+ */
+ @Override
+ final void formatDatum(final Formatter formatter) {
+ formatDatum(formatter, this, getDatum(),
DefaultTemporalDatum::castOrCopy, DatumOrEnsemble::asDatum);
+ }
+
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultVerticalCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultVerticalCRS.java
index 7fe47b27fa..75f7420703 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultVerticalCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultVerticalCRS.java
@@ -27,6 +27,7 @@ import org.apache.sis.referencing.AbstractReferenceSystem;
import org.apache.sis.referencing.cs.AxesConvention;
import org.apache.sis.referencing.cs.AbstractCS;
import org.apache.sis.referencing.datum.DatumOrEnsemble;
+import org.apache.sis.referencing.datum.DefaultVerticalDatum;
import org.apache.sis.referencing.privy.WKTKeywords;
import org.apache.sis.io.wkt.Formatter;
@@ -220,15 +221,6 @@ public class DefaultVerticalCRS extends
AbstractSingleCRS<VerticalDatum> impleme
return super.getDatumEnsemble();
}
- /**
- * Returns the datum or a view of the ensemble as a datum.
- * The {@code legacy} argument tells whether this method is invoked for
formatting in a legacy <abbr>WKT</abbr> format.
- */
- @Override
- final VerticalDatum getDatumOrEnsemble(final boolean legacy) {
- return legacy ? DatumOrEnsemble.asDatum(this) : getDatum();
- }
-
/**
* Returns the coordinate system.
*
@@ -271,6 +263,14 @@ public class DefaultVerticalCRS extends
AbstractSingleCRS<VerticalDatum> impleme
: formatter.shortOrLong(WKTKeywords.VertCRS,
WKTKeywords.VerticalCRS);
}
+ /**
+ * Formats the datum or a view of the ensemble as a datum.
+ */
+ @Override
+ final void formatDatum(final Formatter formatter) {
+ formatDatum(formatter, this, getDatum(),
DefaultVerticalDatum::castOrCopy, DatumOrEnsemble::asDatum);
+ }
+
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
index f9d86b2e79..93fa957ec0 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
@@ -33,9 +33,13 @@ import org.opengis.referencing.IdentifiedObject;
import org.opengis.referencing.datum.Datum;
import org.apache.sis.referencing.AbstractIdentifiedObject;
import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.privy.WKTKeywords;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.iso.Types;
+import org.apache.sis.util.privy.Constants;
+import org.apache.sis.util.collection.Containers;
+import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.temporal.TemporalDate;
import org.apache.sis.metadata.privy.Identifiers;
import org.apache.sis.metadata.privy.NameToIdentifier;
@@ -44,10 +48,10 @@ import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.io.wkt.ElementKind;
import org.apache.sis.io.wkt.Formatter;
import static org.apache.sis.util.Utilities.deepEquals;
-import static org.apache.sis.util.collection.Containers.property;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
import org.opengis.metadata.Identifier;
+import org.opengis.referencing.datum.DatumEnsemble;
import org.opengis.referencing.datum.DynamicReferenceFrame;
// Specific to the geoapi-4.0 branch:
@@ -201,15 +205,15 @@ public class AbstractDatum extends
AbstractIdentifiedObject implements Datum {
if (anchorDefinition == null) {
anchorDefinition = Types.toInternationalString(properties,
"anchorPoint"); // Legacy name.
}
- anchorEpoch = property(properties, ANCHOR_EPOCH_KEY, Temporal.class);
+ anchorEpoch = Containers.property(properties, ANCHOR_EPOCH_KEY,
Temporal.class);
if (anchorEpoch == null) {
- Date date = property(properties, "realizationEpoch", Date.class);
// Legacy name.
+ Date date = Containers.property(properties, "realizationEpoch",
Date.class); // Legacy name.
if (date != null) {
anchorEpoch = date.toInstant();
}
}
- publicationDate = property(properties, PUBLICATION_DATE_KEY,
Temporal.class);
- conventionalRS = property(properties, CONVENTIONAL_RS_KEY,
IdentifiedObject.class);
+ publicationDate = Containers.property(properties,
PUBLICATION_DATE_KEY, Temporal.class);
+ conventionalRS = Containers.property(properties, CONVENTIONAL_RS_KEY,
IdentifiedObject.class);
}
/**
@@ -500,6 +504,10 @@ public class AbstractDatum extends
AbstractIdentifiedObject implements Datum {
* Formats the inner part of the <i>Well Known Text</i> (WKT)
representation for this datum.
* See {@link AbstractIdentifiedObject#formatTo(Formatter)} for more
information.
*
+ * <h4>Default implementation</h4>
+ * The default implementation appends the datum name and returns {@code
"Member"} if this datum
+ * is formatted inside a {@code ENSEMBLE} <abbr>WKT</abbr> element, or
{@code null} otherwise.
+ *
* @param formatter the formatter where to format the inner content of
this WKT element.
* @return the {@linkplain org.apache.sis.io.wkt.KeywordCase#CAMEL_CASE
CamelCase} keyword
* for the WKT element, or {@code null} if unknown.
@@ -511,13 +519,20 @@ public class AbstractDatum extends
AbstractIdentifiedObject implements Datum {
if (name == null) {
name = IdentifiedObjects.getName(this, null);
if (name == null) { // Should
never happen, but be safe.
- return super.formatTo(formatter);
- }
- if ("ESRI".equalsIgnoreCase(Citations.toCodeSpace(authority)) &&
!name.startsWith(Simplifier.ESRI_DATUM_PREFIX)) {
- name = Simplifier.ESRI_DATUM_PREFIX + name;
+ name =
Vocabulary.forLocale(formatter.getLocale()).getString(Vocabulary.Keys.Unnamed);
+ } else if
(Constants.ESRI.equalsIgnoreCase(Citations.toCodeSpace(authority))) {
+ /*
+ * ESRI specific convention: datum names start with the "D_"
suffix.
+ */
+ if (!name.startsWith(Simplifier.ESRI_DATUM_PREFIX)) {
+ name = Simplifier.ESRI_DATUM_PREFIX + name;
+ }
}
}
formatter.append(name, ElementKind.DATUM);
+ if (formatter.getEnclosingElement(1) instanceof DatumEnsemble<?>) {
+ return WKTKeywords.Member;
+ }
return null;
}
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 4c3ebe3bc5..6a216fc196 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
@@ -43,12 +43,15 @@ import org.apache.sis.referencing.GeodeticException;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.internal.Resources;
import org.apache.sis.referencing.privy.WKTKeywords;
+import org.apache.sis.referencing.privy.WKTUtilities;
+import org.apache.sis.referencing.internal.PositionalAccuracyConstant;
import org.apache.sis.metadata.privy.SecondaryTrait;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.Classes;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.Utilities;
import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.privy.CollectionsExt;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
import java.util.Optional;
@@ -150,7 +153,7 @@ public class DefaultDatumEnsemble<D extends Datum> extends
AbstractIdentifiedObj
* @throws IllegalArgumentException if a member is an instance of {@link
DatumEnsemble}, of if at least two
* different {@linkplain AbstractDatum#getConventionalRS()
conventional reference systems} are found.
*
- * @see #create(Map, Collection, PositionalAccuracy)
+ * @see #create(Map, Class, Collection, PositionalAccuracy)
*/
protected DefaultDatumEnsemble(final Map<String,?> properties,
final Collection<? extends D> members,
@@ -223,8 +226,9 @@ public class DefaultDatumEnsemble<D extends Datum> extends
AbstractIdentifiedObj
* The returned ensemble may implement the {@link GeodeticDatum}, {@link
VerticalDatum}, {@link TemporalDatum},
* {@link ParametricDatum} or {@link EngineeringDatum} interface if all
members are instances of the same interface.
*
- * @param <D> the type of datum members contained in this
ensemble.
+ * @param <D> the type of datum members contained in the ensemble
to create.
* @param properties the properties to be given to the identified object.
+ * @param memberType type of members, or {@code null} for automatic.
* @param members datum or reference frames which are members of this
ensemble.
* @param accuracy inaccuracy introduced through use of this ensemble
(mandatory).
* @return the datum ensemble.
@@ -233,10 +237,13 @@ public class DefaultDatumEnsemble<D extends Datum>
extends AbstractIdentifiedObj
*/
public static <D extends Datum> DefaultDatumEnsemble<D> create(
final Map<String,?> properties,
+ final Class<D> memberType,
final Collection<? extends D> members,
final PositionalAccuracy accuracy)
{
- return Factory.forMemberType(Datum.class, null, properties,
List.copyOf(members), accuracy);
+ return Factory.forMemberType(
+ memberType != null ? memberType : Datum.class,
+ null, properties, List.copyOf(members), accuracy);
}
/**
@@ -349,6 +356,19 @@ public class DefaultDatumEnsemble<D extends Datum> extends
AbstractIdentifiedObj
return ensembleAccuracy;
}
+ /**
+ * Returns an estimation of positional accuracy in metres, or {@code NaN}
if unknown.
+ * If at least one {@linkplain
org.apache.sis.metadata.iso.quality.DefaultQuantitativeResult quantitative
+ * result} is found with a linear unit, then returns the largest result
value converted to metres.
+ *
+ * @return the accuracy estimation (always in meters), or NaN if unknown.
+ *
+ * @see
org.apache.sis.referencing.CRS#getLinearAccuracy(CoordinateOperation)
+ */
+ public double getLinearAccuracy() {
+ return
PositionalAccuracyConstant.getLinearAccuracy(CollectionsExt.singletonOrEmpty(getEnsembleAccuracy()));
+ }
+
/**
* Returns an anchor definition which is common to all members of the
datum ensemble.
* If the value is not the same for all members, or if at least one member
returned
@@ -499,16 +519,32 @@ check: if (it.hasNext()) {
@Override
protected String formatTo(final Formatter formatter) {
super.formatTo(formatter);
- if (Convention.WKT2_2015.compareTo(formatter.getConvention()) >= 0) {
+ for (final Datum member : getMembers()) {
+ formatter.newLine();
+ formatter.appendFormattable(member, AbstractDatum::castOrCopy);
+ }
+ complete(formatter);
+ formatter.newLine();
+ WKTUtilities.appendElementIfPositive(WKTKeywords.EnsembleAccuracy,
getLinearAccuracy(), formatter);
+ formatter.newLine();
+ if (!formatter.getConvention().supports(Convention.WKT2_2019)) {
formatter.setInvalidWKT(this, null);
}
return WKTKeywords.Ensemble;
}
+ /**
+ * Completes the <abbr>WKT</abbr> formatting with elements to insert after
members and before accuracy.
+ *
+ * @param formatter the formatter where to format the inner content of
this WKT element.
+ */
+ void complete(final Formatter formatter) {
+ }
+
/**
* An ensemble viewed as a low-accuracy geodetic datum.
*
- * @see #create(Map, Collection, PositionalAccuracy)
+ * @see #create(Map, Class, Collection, PositionalAccuracy)
* @see #castOrCopy(DatumEnsemble)
* @see DatumOrEnsemble#of(GeodeticCRS)
* @see DatumOrEnsemble#asTargetDatum(GeodeticCRS, GeodeticCRS)
@@ -558,12 +594,26 @@ check: if (it.hasNext()) {
public PrimeMeridian getPrimeMeridian() {
return getCommonMandatoryValue(GeodeticDatum::getPrimeMeridian);
}
+
+ /**
+ * Completes the <abbr>WKT</abbr> formatting with elements to insert
after members and before accuracy.
+ * It includes the ellipsoid, but not the prime meridian which is
formatted outside the ensemble.
+ */
+ @Override
+ void complete(final Formatter formatter) {
+ formatter.newLine();
+ try {
+ formatter.appendFormattable(getEllipsoid(),
DefaultEllipsoid::castOrCopy);
+ } catch (GeodeticException e) {
+ formatter.setInvalidWKT(this, e);
+ }
+ }
}
/**
* An ensemble viewed as a low-accuracy vertical datum.
*
- * @see #create(Map, Collection, PositionalAccuracy)
+ * @see #create(Map, Class, Collection, PositionalAccuracy)
* @see #castOrCopy(DatumEnsemble)
* @see DatumOrEnsemble#of(VerticalCRS)
* @see DatumOrEnsemble#asTargetDatum(VerticalCRS, VerticalCRS)
@@ -604,7 +654,7 @@ check: if (it.hasNext()) {
/**
* An ensemble viewed as a low-accuracy temporal datum.
*
- * @see #create(Map, Collection, PositionalAccuracy)
+ * @see #create(Map, Class, Collection, PositionalAccuracy)
* @see #castOrCopy(DatumEnsemble)
* @see DatumOrEnsemble#of(TemporalCRS)
* @see DatumOrEnsemble#asTargetDatum(TemporalCRS, TemporalCRS)
@@ -646,7 +696,7 @@ check: if (it.hasNext()) {
/**
* An ensemble viewed as a low-accuracy parametric datum.
*
- * @see #create(Map, Collection, PositionalAccuracy)
+ * @see #create(Map, Class, Collection, PositionalAccuracy)
* @see #castOrCopy(DatumEnsemble)
* @see DatumOrEnsemble#of(ParametricCRS)
* @see DatumOrEnsemble#asTargetDatum(ParametricCRS, ParametricCRS)
@@ -675,7 +725,7 @@ check: if (it.hasNext()) {
/**
* An ensemble viewed as a low-accuracy engineering datum.
*
- * @see #create(Map, Collection, PositionalAccuracy)
+ * @see #create(Map, Class, Collection, PositionalAccuracy)
* @see #castOrCopy(DatumEnsemble)
* @see DatumOrEnsemble#of(EngineeringCRS)
* @see DatumOrEnsemble#asTargetDatum(EngineeringCRS, EngineeringCRS)
@@ -709,7 +759,7 @@ check: if (it.hasNext()) {
*
* @param <D> base type of all members in the ensembles constructed by
this factory instance.
*
- * @see #create(Map, Collection, PositionalAccuracy)
+ * @see #create(Map, Class, Collection, PositionalAccuracy)
* @see #castOrCopy(DatumEnsemble)
*/
private static abstract class Factory<D extends Datum> {
@@ -784,7 +834,7 @@ nextType: for (final Factory<?> factory : FACTORIES) {
}
}
}
- throw new
ClassCastException(Errors.format(Errors.Keys.IllegalClass_2, Datum.class,
Classes.getClass(illegal)));
+ throw new
ClassCastException(Errors.format(Errors.Keys.IllegalClass_2, memberType,
Classes.getClass(illegal)));
}
/**
@@ -797,7 +847,7 @@ nextType: for (final Factory<?> factory : FACTORIES) {
* @throws IllegalArgumentException if a member is an instance of
{@link DatumEnsemble}, of if at least two
* different {@linkplain AbstractDatum#getConventionalRS()
conventional reference systems} are found.
*
- * @see #create(Map, Collection, PositionalAccuracy)
+ * @see #create(Map, Class, Collection, PositionalAccuracy)
*/
abstract DefaultDatumEnsemble<D> create(Map<String,?> properties,
List<? extends D> members, PositionalAccuracy accuracy);
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultEngineeringDatum.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultEngineeringDatum.java
index d16159f328..d0a5d1f080 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultEngineeringDatum.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultEngineeringDatum.java
@@ -41,7 +41,7 @@ import org.opengis.metadata.Identifier;
* components were created using only SIS factories and static constants.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.crs.DefaultEngineeringCRS
* @see
org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createEngineeringDatum(String)
@@ -155,11 +155,21 @@ public class DefaultEngineeringDatum extends
AbstractDatum implements Engineerin
/**
* Formats this datum as a <i>Well Known Text</i> {@code
EngineeringDatum[…]} element.
*
- * @return {@code "EngineeringDatum"} (WKT 2) or {@code "Local_Datum"}
(WKT 1).
+ * <h4>Compatibility note</h4>
+ * Apache <abbr>SIS</abbr> accepts this type as members of datum ensembles,
+ * but this is not valid <abbr>WKT</abbr> according <abbr>ISO</abbr>
19162:2019.
+ *
+ * @return {@code "EDatum"} or {@code "EngineeringDatum"} (WKT 2), or
{@code "Local_Datum"} (WKT 1).
+ * May also be {@code "Member"} if this datum is inside a
<abbr>WKT</abbr> {@code Ensemble[…]} element.
*/
@Override
protected String formatTo(final Formatter formatter) {
- super.formatTo(formatter);
+ final String name = super.formatTo(formatter);
+ if (name != null) {
+ // Member of a datum ensemble, but ISO 19162:2019 allows that for
geodetic and vertical datum only.
+ formatter.setInvalidWKT(this, null);
+ return name;
+ }
if (formatter.getConvention().majorVersion() == 1) {
/*
* Datum type was provided for all kind of datum in the legacy OGC
01-009 specification.
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
index 3e00f7e85c..7f5a051171 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
@@ -740,10 +740,15 @@ public class DefaultGeodeticDatum extends AbstractDatum
implements GeodeticDatum
* as a separated element after the geodetic reference frame (for
compatibility with WKT 1).
*
* @return {@code "Datum"} or {@code "GeodeticDatum"}.
+ * May also be {@code "Member"} if this datum is inside a
<abbr>WKT</abbr> {@code Ensemble[…]} element.
*/
@Override
protected String formatTo(final Formatter formatter) {
- super.formatTo(formatter);
+ final String name = super.formatTo(formatter);
+ if (name != null) {
+ // Member of a datum ensemble.
+ return name;
+ }
formatter.newLine();
formatter.appendFormattable(getEllipsoid(),
DefaultEllipsoid::castOrCopy);
final boolean isWKT1 = formatter.getConvention().majorVersion() == 1;
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultImageDatum.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultImageDatum.java
index 97c61996f2..5118816d1b 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultImageDatum.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultImageDatum.java
@@ -26,7 +26,6 @@ import org.opengis.util.InternationalString;
import org.apache.sis.referencing.privy.WKTKeywords;
import org.apache.sis.metadata.privy.ImplementationHelper;
import org.apache.sis.io.wkt.Formatter;
-import org.apache.sis.io.wkt.Convention;
import org.apache.sis.util.ComparisonMode;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
@@ -178,18 +177,24 @@ public final class DefaultImageDatum extends
AbstractDatum {
* Formats this datum as a <i>Well Known Text</i> {@code ImageDatum[…]}
element.
*
* <h4>Compatibility note</h4>
- * {@code ImageDatum} is defined in the WKT 2 specification only.
+ * {@code ImageDatum} is defined only in the first edition of the
+ * <abbr>WKT</abbr> 2 specification (<abbr>ISO</abbr> 19162:2015).
*
- * @return {@code "ImageDatum"}.
+ * @return {@code "IDatum"} or {@code "ImageDatum"}.
*/
@Override
protected String formatTo(final Formatter formatter) {
- super.formatTo(formatter);
- final Convention convention = formatter.getConvention();
- if (convention == Convention.INTERNAL) {
- formatter.append(getPixelInCell(), ElementKind.CODE_LIST); //
This is an extension compared to ISO 19162.
- } else if (convention.majorVersion() == 1) {
+ final String name = super.formatTo(formatter);
+ if (name != null) {
+ // Member of a datum ensemble, but ISO 19162:2019 allows that for
geodetic and vertical datum only.
formatter.setInvalidWKT(this, null);
+ return name;
+ }
+ switch (formatter.getConvention()) {
+ // `PixelInCell` is an extension compared to ISO 19162.
+ case INTERNAL: formatter.append(getPixelInCell(),
ElementKind.CODE_LIST); break;
+ case WKT2_2015: break; // The only standard where this
element is defined.
+ default: formatter.setInvalidWKT(this, null); break;
}
return formatter.shortOrLong(WKTKeywords.IDatum,
WKTKeywords.ImageDatum);
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultParametricDatum.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultParametricDatum.java
index 0f4272d196..e0efe9b6f9 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultParametricDatum.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultParametricDatum.java
@@ -48,7 +48,7 @@ import org.opengis.referencing.datum.ParametricDatum;
* all components were created using only SIS factories and static constants.
*
* @author Johann Sorel (Geomatys)
- * @version 1.4
+ * @version 1.5
*
* @see org.apache.sis.referencing.cs.DefaultParametricCS
* @see org.apache.sis.referencing.crs.DefaultParametricCRS
@@ -164,13 +164,21 @@ public class DefaultParametricDatum extends AbstractDatum
implements ParametricD
* Formats this datum as a <i>Well Known Text</i> {@code
ParametricDatum[…]} element.
*
* <h4>Compatibility note</h4>
- * {@code ParametricDatum} is defined in the WKT 2 specification only.
+ * {@code ParametricDatum} is defined in the <abbr>WKT</abbr> 2
specification only.
+ * Apache <abbr>SIS</abbr> accepts this type as members of datum ensembles,
+ * but this is not valid <abbr>WKT</abbr> according <abbr>ISO</abbr>
19162:2019.
*
- * @return {@code "ParametricDatum"}.
+ * @return {@code "PDatum"} or {@code "ParametricDatum"}.
+ * May also be {@code "Member"} if this datum is inside a
<abbr>WKT</abbr> {@code Ensemble[…]} element.
*/
@Override
protected String formatTo(final Formatter formatter) {
- super.formatTo(formatter);
+ final String name = super.formatTo(formatter);
+ if (name != null) {
+ // Member of a datum ensemble, but ISO 19162:2019 allows that for
geodetic and vertical datum only.
+ formatter.setInvalidWKT(this, null);
+ return name;
+ }
if (formatter.getConvention().majorVersion() == 1) {
formatter.setInvalidWKT(this, null);
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultTemporalDatum.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultTemporalDatum.java
index 52fffaee63..f851aa3604 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultTemporalDatum.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultTemporalDatum.java
@@ -257,13 +257,21 @@ public class DefaultTemporalDatum extends AbstractDatum
implements TemporalDatum
* Formats this datum as a <i>Well Known Text</i> {@code TimeDatum[…]}
element.
*
* <h4>Compatibility note</h4>
- * {@code TimeDatum} is defined in the WKT 2 specification only.
+ * {@code TimeDatum} is defined in the <abbr>WKT</abbr> 2 specification
only.
+ * Apache <abbr>SIS</abbr> accepts this type as members of datum ensembles,
+ * but this is not valid <abbr>WKT</abbr> according <abbr>ISO</abbr>
19162:2019.
*
- * @return {@code "TimeDatum"}.
+ * @return {@code "TDatum"} or {@code "TimeDatum"}.
+ * May also be {@code "Member"} if this datum is inside a
<abbr>WKT</abbr> {@code Ensemble[…]} element.
*/
@Override
protected String formatTo(final Formatter formatter) {
- super.formatTo(formatter);
+ final String name = super.formatTo(formatter);
+ if (name != null) {
+ // Member of a datum ensemble, but ISO 19162:2019 allows that for
geodetic and vertical datum only.
+ formatter.setInvalidWKT(this, null);
+ return name;
+ }
formatter.append(new Origin(getOrigin()));
if (formatter.getConvention().majorVersion() == 1) {
formatter.setInvalidWKT(this, null);
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 3063f0d003..e34d5b2ad9 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
@@ -376,11 +376,16 @@ public class DefaultVerticalDatum extends AbstractDatum
implements VerticalDatum
* 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.
*
- * @return {@code "VerticalDatum"} (WKT 2) or {@code "Vert_Datum"} (WKT 1).
+ * @return {@code "VDatum"} or {@code "VerticalDatum"} (WKT 2), or {@code
"Vert_Datum"} (WKT 1).
+ * May also be {@code "Member"} if this datum is inside a
<abbr>WKT</abbr> {@code Ensemble[…]} element.
*/
@Override
protected String formatTo(final Formatter formatter) {
- super.formatTo(formatter);
+ final String name = super.formatTo(formatter);
+ if (name != null) {
+ // Member of a datum ensemble.
+ return name;
+ }
if (formatter.getConvention().majorVersion() == 1) {
formatter.append(VerticalDatumTypes.toLegacyCode(getOrGuessMethod(formatter.getEnclosingElement(1))));
return WKTKeywords.Vert_Datum;
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 373dd67588..ff3f7e2713 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
@@ -620,7 +620,7 @@ public class GeodeticObjectFactory extends AbstractFactory
implements CRSFactory
{
final DefaultDatumEnsemble<D> ensemble;
try {
- ensemble = DefaultDatumEnsemble.create(complete(properties),
members, accuracy);
+ ensemble = DefaultDatumEnsemble.create(complete(properties), null,
members, accuracy);
} catch (IllegalArgumentException exception) {
throw new InvalidGeodeticParameterException(exception);
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/PositionalAccuracyConstant.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/PositionalAccuracyConstant.java
index 22a60b2a89..bacab75f14 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/PositionalAccuracyConstant.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/PositionalAccuracyConstant.java
@@ -240,33 +240,15 @@ public final class PositionalAccuracyConstant extends
DefaultAbsoluteExternalPos
}
/**
- * Convenience method returning the accuracy in meters for the specified
operation.
- * This method tries each of the following procedures and returns the
first successful one:
+ * Extracts the accuracy in meters from the given metadata.
+ * If at least one {@link QuantitativeResult} is found with a linear unit,
then the largest
+ * accuracy estimate is converted to {@linkplain Units#METRE metres} and
returned.
*
- * <ul>
- * <li>If at least one {@link QuantitativeResult} is found with a linear
unit, then the largest
- * accuracy estimate is converted to {@linkplain Units#METRE metres}
and returned.</li>
- * <li>Otherwise, if the operation is a {@link Conversion}, then returns
0 since a conversion
- * is by definition accurate up to rounding errors.</li>
- * <li>Otherwise, if the operation is a {@link Transformation}, then
checks if the datum shift
- * were applied with the help of Bursa-Wolf parameters. This
procedure looks for SIS-specific
- * {@link #DATUM_SHIFT_APPLIED} and {@link #DATUM_SHIFT_OMITTED
DATUM_SHIFT_OMITTED} constants.</li>
- * <li>Otherwise, if the operation is a {@link ConcatenatedOperation},
returns the sum of the accuracy
- * of all components. This is a conservative scenario where we
assume that errors cumulate linearly.
- * Note that this is not necessarily the "worst case" scenario since
the accuracy could be worst
- * if the math transforms are highly non-linear.</li>
- * </ul>
- *
- * If the above is modified, please update {@code
AbstractCoordinateOperation.getLinearAccuracy()} javadoc.
- *
- * @param operation the operation to inspect for accuracy.
+ * @param accuracies the metadata to inspect for accuracy.
* @return the accuracy estimate (always in meters), or NaN if unknown.
- *
- * @see
org.apache.sis.referencing.operation.AbstractCoordinateOperation#getLinearAccuracy()
*/
- public static double getLinearAccuracy(final CoordinateOperation
operation) {
+ public static double getLinearAccuracy(final Iterable<PositionalAccuracy>
accuracies) {
double accuracy = Double.NaN;
- final Collection<PositionalAccuracy> accuracies =
operation.getCoordinateOperationAccuracy();
for (final PositionalAccuracy metadata : accuracies) {
for (final Result result : metadata.getResults()) {
if (result instanceof QuantitativeResult) {
@@ -292,6 +274,36 @@ public final class PositionalAccuracyConstant extends
DefaultAbsoluteExternalPos
}
}
}
+ return accuracy;
+ }
+
+ /**
+ * Extracts the accuracy in meters from the specified operation.
+ * This method tries each of the following procedures and returns the
first successful one:
+ *
+ * <ul>
+ * <li>If at least one {@link QuantitativeResult} is found with a linear
unit, then the largest
+ * accuracy estimate is converted to {@linkplain Units#METRE metres}
and returned.</li>
+ * <li>Otherwise, if the operation is a {@link Conversion}, then returns
0 since a conversion
+ * is by definition accurate up to rounding errors.</li>
+ * <li>Otherwise, if the operation is a {@link Transformation}, then
checks if the datum shift
+ * were applied with the help of Bursa-Wolf parameters. This
procedure looks for SIS-specific
+ * {@link #DATUM_SHIFT_APPLIED} and {@link #DATUM_SHIFT_OMITTED
DATUM_SHIFT_OMITTED} constants.</li>
+ * <li>Otherwise, if the operation is a {@link ConcatenatedOperation},
returns the sum of the accuracy
+ * of all components. This is a conservative scenario where we
assume that errors cumulate linearly.
+ * Note that this is not necessarily the "worst case" scenario since
the accuracy could be worst
+ * if the math transforms are highly non-linear.</li>
+ * </ul>
+ *
+ * If the above is modified, please update {@code
AbstractCoordinateOperation.getLinearAccuracy()} javadoc.
+ *
+ * @param operation the operation to inspect for accuracy.
+ * @return the accuracy estimate (always in meters), or NaN if unknown.
+ *
+ * @see
org.apache.sis.referencing.operation.AbstractCoordinateOperation#getLinearAccuracy()
+ */
+ public static double getLinearAccuracy(final CoordinateOperation
operation) {
+ double accuracy =
getLinearAccuracy(operation.getCoordinateOperationAccuracy());
if (Double.isNaN(accuracy)) {
/*
* No quantitative (linear) accuracy were found. If the coordinate
operation is actually
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
index c96d0cb1ed..7ba89eed2b 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
@@ -1026,15 +1026,7 @@ check: for (int isTarget=0; ; isTarget++) {
// 0 == source check; 1
*/
if (!isSubOperation && !isGeogTran && !(this instanceof
ConcatenatedOperation)) {
append(formatter, getInterpolationCRS().orElse(null),
WKTKeywords.InterpolationCRS);
- final double accuracy = getLinearAccuracy();
- if (accuracy > 0) {
- formatter.append(new FormattableObject() {
- @Override protected String formatTo(final Formatter
formatter) {
- formatter.append(accuracy);
- return WKTKeywords.OperationAccuracy;
- }
- });
- }
+
WKTUtilities.appendElementIfPositive(WKTKeywords.OperationAccuracy,
getLinearAccuracy(), formatter);
}
/*
* Verifies if what we wrote is allowed by the standard.
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/MercatorAuxiliarySphere.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/MercatorAuxiliarySphere.java
index 87129c0d00..b8345c2318 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/MercatorAuxiliarySphere.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/MercatorAuxiliarySphere.java
@@ -21,6 +21,7 @@ import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.apache.sis.parameter.ParameterBuilder;
import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.util.privy.Constants;
/**
@@ -65,7 +66,7 @@ public final class MercatorAuxiliarySphere extends
AbstractMercator {
*/
private static final ParameterDescriptorGroup PARAMETERS;
static {
- final ParameterBuilder builder =
builder().setCodeSpace(Citations.ESRI, "ESRI");
+ final ParameterBuilder builder =
builder().setCodeSpace(Citations.ESRI, Constants.ESRI);
AUXILIARY_SPHERE_TYPE =
builder.addName("Auxiliary_Sphere_Type").createBounded(0, 3, 0);
final ParameterDescriptor<?>[] descriptors =
toArray(Mercator2SP.PARAMETERS.descriptors(), 1);
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mollweide.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mollweide.java
index 9214a12e32..5a7ba1f070 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mollweide.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mollweide.java
@@ -22,6 +22,7 @@ import org.opengis.parameter.ParameterDescriptorGroup;
import org.apache.sis.parameter.Parameters;
import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.referencing.operation.projection.NormalizedProjection;
+import org.apache.sis.util.privy.Constants;
/**
@@ -92,7 +93,7 @@ public final class Mollweide extends MapProjection {
*/
private static final ParameterDescriptorGroup PARAMETERS;
static {
- PARAMETERS = builder().setCodeSpace(Citations.ESRI, "ESRI")
+ PARAMETERS = builder().setCodeSpace(Citations.ESRI, Constants.ESRI)
.addName("Mollweide")
.addName(null, "Homalographic")
.addName(null, "Homolographic")
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ObliqueMercatorTwoPoints.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ObliqueMercatorTwoPoints.java
index 4f4af29d81..d668e5700d 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ObliqueMercatorTwoPoints.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ObliqueMercatorTwoPoints.java
@@ -24,6 +24,7 @@ import org.apache.sis.measure.MeasurementRange;
import org.apache.sis.measure.Longitude;
import org.apache.sis.measure.Latitude;
import org.apache.sis.measure.Units;
+import org.apache.sis.util.privy.Constants;
/**
@@ -48,7 +49,7 @@ public class ObliqueMercatorTwoPoints extends ObliqueMercator
{
LAT_OF_2ND_POINT,
LONG_OF_2ND_POINT;
static {
- final ParameterBuilder builder =
builder().setCodeSpace(Citations.ESRI, "ESRI");
+ final ParameterBuilder builder =
builder().setCodeSpace(Citations.ESRI, Constants.ESRI);
LAT_OF_1ST_POINT = create(builder.addName("Latitude_Of_1st_Point"),
Latitude.MIN_VALUE, Latitude.MAX_VALUE);
LAT_OF_2ND_POINT = create(builder.addName("Latitude_Of_2nd_Point"),
Latitude.MIN_VALUE, Latitude.MAX_VALUE);
LONG_OF_1ST_POINT = create(builder.addName("Longitude_Of_1st_Point"),
Longitude.MIN_VALUE, Longitude.MAX_VALUE);
@@ -77,7 +78,7 @@ public class ObliqueMercatorTwoPoints extends ObliqueMercator
{
final ParameterDescriptor<Double> easting,
final ParameterDescriptor<Double> northing)
{
- super(builder().setCodeSpace(Citations.ESRI, "ESRI").addName(name)
+ super(builder().setCodeSpace(Citations.ESRI,
Constants.ESRI).addName(name)
.createGroupForMapProjection(
LAT_OF_1ST_POINT, LONG_OF_1ST_POINT,
LAT_OF_2ND_POINT, LONG_OF_2ND_POINT,
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTKeywords.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTKeywords.java
index 80ad11133c..c2fe067df1 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTKeywords.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTKeywords.java
@@ -78,19 +78,21 @@ public final class WKTKeywords extends Static {
* and {@link org.apache.sis.referencing.datum.AbstractDatum}.
*/
public static final String
- CS = "CS",
- Axis = "Axis",
- AxisMinValue = "AxisMinValue",
- AxisMaxValue = "AxisMaxValue",
- RangeMeaning = "RangeMeaning",
- Order = "Order",
- Meridian = "Meridian",
- PrimeMeridian = "PrimeMeridian",
- PrimeM = "PrimeM",
- Ellipsoid = "Ellipsoid",
- Spheroid = "Spheroid",
- Ensemble = "Ensemble",
- ToWGS84 = "ToWGS84";
+ CS = "CS",
+ Axis = "Axis",
+ AxisMinValue = "AxisMinValue",
+ AxisMaxValue = "AxisMaxValue",
+ RangeMeaning = "RangeMeaning",
+ Order = "Order",
+ Meridian = "Meridian",
+ PrimeMeridian = "PrimeMeridian",
+ PrimeM = "PrimeM",
+ Ellipsoid = "Ellipsoid",
+ Spheroid = "Spheroid",
+ Ensemble = "Ensemble",
+ Member = "Member",
+ EnsembleAccuracy = "EnsembleAccuracy",
+ ToWGS84 = "ToWGS84";
/**
* Related to {@link org.apache.sis.referencing.crs.DefaultGeocentricCRS}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTUtilities.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTUtilities.java
index 7f118cc5f7..71e7ed7df4 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTUtilities.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTUtilities.java
@@ -192,6 +192,24 @@ public final class WKTUtilities extends Static {
formatter.append(name, (type != null) ? type : ElementKind.NAME);
}
+ /**
+ * Appends an element containing only a {@code double} value if that value
is strictly greater than zero.
+ *
+ * @param name name of the element to add.
+ * @param value value to add.
+ * @param formatter formatter where to add the value.
+ */
+ public static void appendElementIfPositive(final String name, final double
value, final Formatter formatter) {
+ if (value > 0) {
+ formatter.append(new FormattableObject() {
+ @Override protected String formatTo(final Formatter formatter)
{
+ formatter.append(value);
+ return name;
+ }
+ });
+ }
+ }
+
/**
* Appends a {@linkplain ParameterValueGroup group of parameters} in a
{@code Param_MT[…]} element.
*
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
index 074b3c4774..54790bb884 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
@@ -39,6 +39,7 @@ import org.apache.sis.measure.Longitude;
import org.apache.sis.metadata.privy.AxisNames;
import org.apache.sis.referencing.privy.ReferencingFactoryContainer;
import org.apache.sis.referencing.cs.CoordinateSystems;
+import org.apache.sis.referencing.datum.DatumOrEnsemble;
import org.apache.sis.referencing.datum.BursaWolfParameters;
import org.apache.sis.referencing.datum.DefaultGeodeticDatum;
import org.apache.sis.referencing.factory.GeodeticObjectFactory;
@@ -496,6 +497,38 @@ public final class GeodeticObjectParserTest extends
EPSGDependentTestCase {
assertAxisEquals(AxisNames.GEODETIC_LONGITUDE, "λ",
AxisDirection.EAST, -180, +180, Units.DEGREE, RangeMeaning.WRAPAROUND,
cs.getAxis(1));
}
+ /**
+ * Tests the parsing of a geographic CRS with datum ensemble.
+ *
+ * @throws ParseException if the parsing failed.
+ */
+ @Test
+ public void testGeographicCRSWithEnsemble() throws ParseException {
+ final GeographicCRS crs = parse(GeographicCRS.class,
+ "GeodeticCRS[“WGS 84”,\n" +
+ " Ensemble[“World Geodetic System 1984”,\n" +
+ " Member[“World Geodetic System 1984 (Transit)”],\n" +
+ " Member[“World Geodetic System 1984 (G730)”],\n" +
+ " Member[“World Geodetic System 1984 (G873)”],\n" +
+ " Ellipsoid[“WGS84”, 6378137.0, 298.257223563],\n" +
+ " EnsembleAccuracy[2.0]],\n" +
+ " PrimeMeridian[“Greenwich”, 0],\n" +
+ " CS[ellipsoidal, 2],\n" +
+ " Axis[“Geodetic longitude (Lon)”, east],\n" +
+ " Axis[“Geodetic latitude (Lat)”, north],\n" +
+ " Unit[“degree”, 0.017453292519943295],\n" +
+ " Usage[\n" +
+ " Scope[“Horizontal component of 3D system.”],\n" +
+ " BBox[-90.00, -180.00, 90.00, 180.00]]]");
+ verifyGeographicCRS(0, crs);
+ assertNull(crs.getDatum());
+ final Iterator<GeodeticDatum> members =
crs.getDatumEnsemble().getMembers().iterator();
+ assertNameAndIdentifierEqual("World Geodetic System 1984 (Transit)",
0, members.next());
+ assertNameAndIdentifierEqual("World Geodetic System 1984 (G730)",
0, members.next());
+ assertNameAndIdentifierEqual("World Geodetic System 1984 (G873)",
0, members.next());
+ assertFalse(members.hasNext());
+ }
+
/**
* Implementation of {@link #testGeographicCRS()} and related test methods.
* This test expects no {@code AUTHORITY} element on any component.
@@ -506,7 +539,7 @@ public final class GeodeticObjectParserTest extends
EPSGDependentTestCase {
private void verifyGeographicCRS(final int swap, final GeographicCRS crs)
throws ParseException {
assertNameAndIdentifierEqual("WGS 84", 0, crs);
- final GeodeticDatum datum = crs.getDatum();
+ final GeodeticDatum datum = DatumOrEnsemble.asDatum(crs);
assertNameAndIdentifierEqual("World Geodetic System 1984", 0, datum);
assertNameAndIdentifierEqual("Greenwich", 0, datum.getPrimeMeridian());
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/HardCodedConversions.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/HardCodedConversions.java
index f7720d31a2..2aa9f19ce0 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/HardCodedConversions.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/HardCodedConversions.java
@@ -22,13 +22,14 @@ import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.operation.OperationMethod;
import org.apache.sis.referencing.ImmutableIdentifier;
+import org.apache.sis.referencing.crs.DefaultProjectedCRS;
import org.apache.sis.referencing.operation.provider.Mercator1SP;
import org.apache.sis.referencing.operation.provider.TransverseMercator;
import org.apache.sis.referencing.operation.provider.LambertConformal1SP;
import org.apache.sis.referencing.operation.provider.LambertConformal2SP;
import org.apache.sis.referencing.operation.provider.PolarStereographicB;
import org.apache.sis.metadata.iso.citation.Citations;
-import org.apache.sis.referencing.crs.DefaultProjectedCRS;
+import org.apache.sis.util.privy.Constants;
// Test dependencies
import org.apache.sis.referencing.crs.HardCodedCRS;
@@ -177,7 +178,7 @@ public final class HardCodedConversions {
pg.parameter("Easting at false origin") .setValue( 700000);
pg.parameter("Northing at false origin").setValue(6600000);
final DefaultConversion c = create("Lambert Conic Conformal", method,
pg);
- final ImmutableIdentifier id = new ImmutableIdentifier(Citations.ESRI,
"ESRI", "102110");
+ final ImmutableIdentifier id = new ImmutableIdentifier(Citations.ESRI,
Constants.ESRI, "102110");
return new DefaultProjectedCRS(
Map.of(ProjectedCRS.NAME_KEY, "RGF 1993 Lambert",
ProjectedCRS.IDENTIFIERS_KEY, id),
diff --git
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/GeometryLibrary.java
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/GeometryLibrary.java
index 2af321afa8..1f06b907e5 100644
---
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/GeometryLibrary.java
+++
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/GeometryLibrary.java
@@ -16,6 +16,7 @@
*/
package org.apache.sis.setup;
+import org.apache.sis.util.privy.Constants;
import org.opengis.metadata.acquisition.GeometryType;
@@ -70,7 +71,7 @@ public enum GeometryLibrary {
*
* @see <a href="https://github.com/Esri/geometry-api-java/wiki">API wiki
page</a>
*/
- ESRI("ESRI"),
+ ESRI(Constants.ESRI),
/**
* The Java Topology Suite (JTS) library. This open source library
provides an object model
diff --git
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/Constants.java
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/Constants.java
index d04ca9a625..bc47d7a9be 100644
---
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/Constants.java
+++
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/Constants.java
@@ -112,6 +112,11 @@ public final class Constants extends Static {
*/
public static final String UCUM = "UCUM";
+ /**
+ * The {@value} code space.
+ */
+ public static final String ESRI = "ESRI";
+
/**
* The {@value} code space.
*/