This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/sis.git
commit f9759678243294344be5460f8c52bd48907099c2 Merge: f3170bc4ec bb738fc51c Author: Martin Desruisseaux <[email protected]> AuthorDate: Tue Sep 2 17:37:07 2025 +0200 Merge branch 'geoapi-3.1'. .../apache/sis/console/MetadataCommandTest.java | 3 +- .../apache/sis/io/wkt/GeodeticObjectParser.java | 18 ++-- .../pending/geoapi/referencing/MissingMethods.java | 69 +++++++++++++ .../main/org/apache/sis/referencing/CommonCRS.java | 107 +++++++++++++++------ .../sis/referencing/EPSGFactoryFallback.java | 32 ++++-- .../sis/referencing/StandardDefinitions.java | 18 ++-- .../sis/referencing/datum/DatumOrEnsemble.java | 60 ++++++++++++ .../referencing/datum/DefaultDatumEnsemble.java | 4 +- .../referencing/datum/DefaultGeodeticDatum.java | 4 +- .../factory/GeodeticAuthorityFactory.java | 2 +- .../referencing/factory/GeodeticObjectFactory.java | 81 +++++++++------- .../referencing/factory/sql/EPSGDataAccess.java | 36 ++----- .../referencing/internal/ServicesForMetadata.java | 75 --------------- .../operation/CoordinateOperationFinder.java | 6 +- .../org/apache/sis/referencing/Assertions.java | 20 +++- .../test/org/apache/sis/referencing/CRSTest.java | 2 + .../org/apache/sis/referencing/CommonCRSTest.java | 8 +- .../sis/referencing/EPSGFactoryFallbackTest.java | 25 +++-- .../sis/referencing/GeodeticObjectVerifier.java | 7 +- .../sis/referencing/StandardDefinitionsTest.java | 2 +- .../sis/referencing/datum/HardCodedDatum.java | 1 + .../sis/storage/geotiff/reader/CRSBuilder.java | 2 +- .../apache/sis/storage/netcdf/base/CRSBuilder.java | 3 +- .../apache/sis/storage/netcdf/base/Convention.java | 2 +- .../sis/storage/netcdf/base/GridMapping.java | 2 +- .../org/apache/sis/storage/CoverageSubsetTest.java | 4 +- 26 files changed, 365 insertions(+), 228 deletions(-) diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java index 8631f90798,2f364380b5..1291af32e8 --- 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 @@@ -87,11 -87,8 +87,13 @@@ import org.apache.sis.util.iso.Types // Specific to the main and geoapi-3.1 branches: import org.opengis.referencing.ReferenceIdentifier; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.referencing.ObjectDomain; +// Specific to the main branch: +import org.opengis.referencing.ReferenceSystem; - import org.apache.sis.referencing.internal.ServicesForMetadata; ++import org.apache.sis.pending.geoapi.referencing.MissingMethods; ++import org.apache.sis.referencing.cs.DefaultParametricCS; ++import org.apache.sis.referencing.datum.DefaultParametricDatum; +import org.apache.sis.referencing.factory.GeodeticObjectFactory; +import org.apache.sis.temporal.TemporalDate; /** @@@ -983,7 -969,7 +985,7 @@@ class GeodeticObjectParser extends Math } case WKTKeywords.parametric: { if (axes.length != (dimension = 1)) break; - return ServicesForMetadata.createParametricCS(csProperties, axes[0], csFactory); - return csFactory.createParametricCS(csProperties, axes[0]); ++ return MissingMethods.createParametricCS(csProperties, axes[0], csFactory); } default: { warning(parent, WKTKeywords.CS, Errors.formatInternational(Errors.Keys.UnknownType_1, type), null); @@@ -1513,10 -1498,10 +1515,10 @@@ * * @param mode {@link #FIRST}, {@link #OPTIONAL} or {@link #MANDATORY}. * @param parent the parent element. - * @return the {@code "ParametricDatum"} element as a {@link ParametricDatum} object. + * @return the {@code "ParametricDatum"} element as a {@code ParametricDatum} object. * @throws ParseException if the {@code "ParametricDatum"} element cannot be parsed. */ - private Datum parseParametricDatum(final int mode, final Element parent) throws ParseException { - private ParametricDatum parseParametricDatum(final int mode, final Element parent) throws ParseException { ++ private DefaultParametricDatum parseParametricDatum(final int mode, final Element parent) throws ParseException { final Element element = parent.pullElement(mode, WKTKeywords.ParametricDatum, WKTKeywords.PDatum); if (element == null) { return null; @@@ -1524,7 -1509,7 +1526,7 @@@ final String name = element.pullString("name"); final DatumFactory datumFactory = factories.getDatumFactory(); try { - return ServicesForMetadata.createParametricDatum(parseAnchorAndClose(element, name), datumFactory); - return datumFactory.createParametricDatum(parseAnchorAndClose(element, name)); ++ return MissingMethods.createParametricDatum(parseAnchorAndClose(element, name), datumFactory); } catch (FactoryException exception) { throw element.parseFailed(exception); } @@@ -2058,7 -2046,7 +2060,7 @@@ * 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. */ - Datum datum = null; - ParametricDatum datum = null; ++ DefaultParametricDatum datum = null; SingleCRS baseCRS = null; Conversion fromBase = null; if (!isBaseCRS) { @@@ -2084,12 -2072,12 +2086,12 @@@ try { cs = parseCoordinateSystem(element, WKTKeywords.parametric, 1, false, unit, false, null); final Map<String,?> properties = parseMetadataAndClose(element, name, datum); - if (cs != null) { - if (cs instanceof ParametricCS) { ++ if (cs instanceof DefaultParametricCS) { final CRSFactory crsFactory = factories.getCRSFactory(); if (baseCRS != null) { return crsFactory.createDerivedCRS(properties, baseCRS, fromBase, cs); } - return ServicesForMetadata.createParametricCRS(properties, datum, cs, crsFactory); - return crsFactory.createParametricCRS(properties, datum, (ParametricCS) cs); ++ return MissingMethods.createParametricCRS(properties, datum, (DefaultParametricCS) cs, crsFactory); } } catch (FactoryException exception) { throw element.parseFailed(exception); diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/pending/geoapi/referencing/MissingMethods.java index a84e462276,0000000000..091edd126e mode 100644,000000..100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/pending/geoapi/referencing/MissingMethods.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/pending/geoapi/referencing/MissingMethods.java @@@ -1,96 -1,0 +1,165 @@@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sis.pending.geoapi.referencing; + ++import java.util.Map; +import java.util.function.Function; ++import org.opengis.util.FactoryException; +import org.opengis.referencing.crs.*; +import org.opengis.referencing.datum.*; ++import org.opengis.referencing.cs.CSFactory; ++import org.opengis.referencing.cs.CoordinateSystemAxis; +import org.apache.sis.referencing.crs.DefaultVerticalCRS; +import org.apache.sis.referencing.crs.DefaultTemporalCRS; +import org.apache.sis.referencing.crs.DefaultEngineeringCRS; ++import org.apache.sis.referencing.cs.DefaultParametricCS; +import org.apache.sis.referencing.datum.DefaultDatumEnsemble; ++import org.apache.sis.referencing.datum.DefaultParametricDatum; ++import org.apache.sis.referencing.factory.GeodeticObjectFactory; ++import org.apache.sis.referencing.factory.InvalidGeodeticParameterException; + + +/** + * Placeholder for methods missing in the GeoAPI 3.0 interface. + */ +public final class MissingMethods { + /** + * To be set by static {@code AbstractCRS} initializer. + */ + public static volatile Function<CoordinateReferenceSystem, DefaultDatumEnsemble<?>> datumEnsemble; + + /** + * To be set by static {@code DefaultGeodeticCRS} initializer. + */ + public static volatile Function<GeodeticCRS, DefaultDatumEnsemble<GeodeticDatum>> geodeticDatumEnsemble; + + private MissingMethods() { + } + + /** + * Returns the datum ensemble of an arbitrary CRS. + * + * @param datum the CRS from which to get a datum ensemble, or {@code null} if none. + * @return the datum ensemble, or {@code null} if none. + */ + public static DefaultDatumEnsemble<?> getDatumEnsemble(final CoordinateReferenceSystem crs) { + final var m = datumEnsemble; + return (m != null) ? m.apply(crs) : null; + } + + /** + * Returns the datum ensemble of an arbitrary geodetic CRS. + * + * @param datum the CRS from which to get a datum ensemble, or {@code null} if none. + * @return the datum ensemble, or {@code null} if none. + */ + public static DefaultDatumEnsemble<GeodeticDatum> getDatumEnsemble(final GeodeticCRS crs) { + final var m = geodeticDatumEnsemble; + return (m != null) ? m.apply(crs) : null; + } + + /** + * Returns the datum ensemble of an arbitrary vertical CRS. + * + * @param datum the CRS from which to get a datum ensemble, or {@code null} if none. + * @return the datum ensemble, or {@code null} if none. + */ + public static DefaultDatumEnsemble<VerticalDatum> getDatumEnsemble(final VerticalCRS crs) { + return (crs instanceof DefaultVerticalCRS) ? ((DefaultVerticalCRS) crs).getDatumEnsemble() : null; + } + + /** + * Returns the datum ensemble of an arbitrary temporal CRS. + * + * @param datum the CRS from which to get a datum ensemble, or {@code null} if none. + * @return the datum ensemble, or {@code null} if none. + */ + public static DefaultDatumEnsemble<TemporalDatum> getDatumEnsemble(final TemporalCRS crs) { + return (crs instanceof DefaultTemporalCRS) ? ((DefaultTemporalCRS) crs).getDatumEnsemble() : null; + } + + /** + * Returns the datum ensemble of an arbitrary engineering CRS. + * + * @param datum the CRS from which to get a datum ensemble, or {@code null} if none. + * @return the datum ensemble, or {@code null} if none. + */ + public static DefaultDatumEnsemble<EngineeringDatum> getDatumEnsemble(final EngineeringCRS crs) { + return (crs instanceof DefaultEngineeringCRS) ? ((DefaultEngineeringCRS) crs).getDatumEnsemble() : null; + } ++ ++ /** ++ * Creates a parametric CS. This method requires the <abbr>SIS</abbr> factory ++ * since parametric CRS were not available in GeoAPI 3.0. ++ * ++ * @param properties the coordinate system name, and optionally other properties. ++ * @param axis the axis of the parametric coordinate system. ++ * @param factory the factory to use for creating the coordinate system. ++ * @return a parametric coordinate system using the given axes. ++ * @throws FactoryException if the parametric object creation failed. ++ */ ++ public static DefaultParametricCS createParametricCS(final Map<String,?> properties, final CoordinateSystemAxis axis, ++ CSFactory factory) throws FactoryException ++ { ++ if (!(factory instanceof GeodeticObjectFactory)) { ++ factory = GeodeticObjectFactory.provider(); ++ } ++ return ((GeodeticObjectFactory) factory).createParametricCS(properties, axis); ++ } ++ ++ /** ++ * Creates a parametric datum. This method requires the <abbr>SIS</abbr> factory ++ * since parametric <abbr>CRS</abbr> were not available in GeoAPI 3.0. ++ * ++ * @param properties the datum name, and optionally other properties. ++ * @param factory the factory to use for creating the datum. ++ * @return a parametric datum using the given name. ++ * @throws FactoryException if the parametric object creation failed. ++ */ ++ public static DefaultParametricDatum createParametricDatum(final Map<String,?> properties, DatumFactory factory) ++ throws FactoryException ++ { ++ if (!(factory instanceof GeodeticObjectFactory)) { ++ factory = GeodeticObjectFactory.provider(); ++ } ++ return ((GeodeticObjectFactory) factory).createParametricDatum(properties); ++ } ++ ++ /** ++ * Creates a parametric <abbr>CRS</abbr>. This method requires the <abbr>SIS</abbr> factory ++ * since parametric <abbr>CRS</abbr> were not available in GeoAPI 3.0. ++ * ++ * @param properties the coordinate reference system name, and optionally other properties. ++ * @param datum the parametric datum. ++ * @param cs the parametric coordinate system. ++ * @param factory the factory to use for creating the coordinate reference system. ++ * @return a parametric coordinate system using the given axes. ++ * @throws FactoryException if the parametric object creation failed. ++ */ ++ public static SingleCRS createParametricCRS(final Map<String,?> properties, final DefaultParametricDatum datum, ++ final DefaultParametricCS cs, CRSFactory factory) throws FactoryException ++ { ++ if (!(factory instanceof GeodeticObjectFactory)) { ++ factory = GeodeticObjectFactory.provider(); ++ } ++ try { ++ return ((GeodeticObjectFactory) factory).createParametricCRS(properties, datum, cs); ++ } catch (ClassCastException e) { ++ throw new InvalidGeodeticParameterException(e.toString(), e); ++ } ++ } +} diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java index 0248507b48,12a11b590e..b2eec3b12e --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java @@@ -503,8 -502,8 +504,8 @@@ public enum CommonCRS } } final Datum datum = single.getDatum(); - if (datum instanceof GeodeticDatum) { + if (datum == null || datum instanceof GeodeticDatum) { - final CommonCRS c = forDatum((GeodeticDatum) datum, single.getDatumEnsemble()); + final CommonCRS c = forDatum((GeodeticDatum) datum, getDatumEnsemble(single)); if (c != null) return c; } throw new IllegalArgumentException(Errors.format( @@@ -881,8 -910,8 +920,8 @@@ * * @since 1.5 */ - public DatumEnsemble<GeodeticDatum> datumEnsemble() { + public DefaultDatumEnsemble<GeodeticDatum> datumEnsemble() { - return getDatumEnsemble(geographic()); + return DatumOrEnsemble.asEnsemble(datum(true)).orElse(null); } /** diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/EPSGFactoryFallback.java index 2a7f97c27c,4ab57382bd..d75d81c095 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/EPSGFactoryFallback.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/EPSGFactoryFallback.java @@@ -52,6 -52,6 +52,9 @@@ import org.apache.sis.setup.Installatio import org.apache.sis.measure.Latitude; import org.apache.sis.measure.Units; ++// Specific to the main branch: ++import org.apache.sis.referencing.datum.DefaultDatumEnsemble; ++ // Specific to the main and geoapi-3.1 branches: import org.opengis.referencing.crs.GeocentricCRS; @@@ -218,7 -224,15 +223,15 @@@ final class EPSGFactoryFallback extend */ @Override public Datum createDatum(final String code) throws NoSuchAuthorityCodeException { - return (Datum) predefined(code, DATUM); + return (Datum) predefined(code, DATUM | ENSEMBLE); + } + + /** + * Returns a datum ensemble for the given EPSG code. + */ + @Override - public DatumEnsemble<?> createDatumEnsemble(final String code) throws NoSuchAuthorityCodeException { - return (DatumEnsemble<?>) predefined(code, ENSEMBLE); ++ public DefaultDatumEnsemble<?> createDatumEnsemble(final String code) throws NoSuchAuthorityCodeException { ++ return (DefaultDatumEnsemble<?>) predefined(code, ENSEMBLE); } /** @@@ -418,6 -435,7 +433,7 @@@ switch (kind) { case CRS: return CoordinateReferenceSystem.class; case DATUM: return Datum.class; - case ENSEMBLE: return DatumEnsemble.class; ++ case ENSEMBLE: return DefaultDatumEnsemble.class; case ELLIPSOID: return Ellipsoid.class; case PRIME_MERIDIAN: return PrimeMeridian.class; case UNIT: return Unit.class; diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/StandardDefinitions.java index 19e6daa6b7,c1691e4fe1..fc062eace9 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/StandardDefinitions.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/StandardDefinitions.java @@@ -76,9 -76,12 +76,10 @@@ import org.apache.sis.measure.Latitude import org.apache.sis.measure.Units; import static org.apache.sis.metadata.privy.ReferencingServices.AUTHALIC_RADIUS; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.referencing.datum.DatumEnsemble; -import static org.opengis.referencing.ObjectDomain.DOMAIN_OF_VALIDITY_KEY; - -// Specific to the geoapi-3.1 branch: -import org.opengis.referencing.datum.RealizationMethod; +// Specific to the main branch: +import org.opengis.referencing.datum.VerticalDatumType; +import static org.opengis.referencing.datum.Datum.DOMAIN_OF_VALIDITY_KEY; ++import org.apache.sis.referencing.datum.DefaultDatumEnsemble; /** @@@ -233,14 -236,17 +234,17 @@@ final class StandardDefinitions } /** - * Creates a geodetic CRS from hard-coded values for the given code. + * Creates a geodetic <abbr>CRS</abbr> from hard-coded values for the given code. * - * @param code the EPSG code. - * @param datum the geodetic reference frame. - * @param cs the coordinate system. - * @return the geographic CRS for the given code. + * @param code the EPSG code. + * @param datum the geodetic reference frame, or {@code null} if a datum ensemble is used instead. + * @param ensemble the datum ensemble, or {@code null} if none. + * @param cs the coordinate system. + * @return the geographic <abbr>CRS</abbr> for the given code. */ - static GeographicCRS createGeographicCRS(final short code, final GeodeticDatum datum, final EllipsoidalCS cs) { + static GeographicCRS createGeographicCRS(final short code, final GeodeticDatum datum, - final DatumEnsemble<GeodeticDatum> ensemble, final EllipsoidalCS cs) ++ final DefaultDatumEnsemble<GeodeticDatum> ensemble, final EllipsoidalCS cs) + { final String name; boolean world = false; switch (code) { diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DatumOrEnsemble.java index ce78a4c244,820ce1cfcc..5243d12f90 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DatumOrEnsemble.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DatumOrEnsemble.java @@@ -372,6 -382,81 +372,66 @@@ public final class DatumOrEnsemble exte return false; } + /** + * If the given object is a pseudo-datum for a geodetic ensemble, returns that ensemble. + * This method is the converse of {@link #asDatum(GeodeticCRS)} and recognizes only the + * pseudo-datum created by this class of by {@link DefaultDatumEnsemble} static methods. + * + * @param datum the object which may be a pseudo-datum for an ensemble, or {@code null}. + * @return the given object cast to a datum ensemble if the cast is valid. + */ - public static Optional<DatumEnsemble<GeodeticDatum>> asEnsemble(final GeodeticDatum datum) { ++ public static Optional<DefaultDatumEnsemble<GeodeticDatum>> asEnsemble(final GeodeticDatum datum) { + if (datum instanceof DefaultDatumEnsemble.Geodetic) { + return Optional.of((DefaultDatumEnsemble.Geodetic) datum); + } + return Optional.empty(); + } + + /** + * If the given object is a pseudo-datum for a vertical ensemble, returns that ensemble. + * This method is the converse of {@link #asDatum(VerticalCRS)} and recognizes only the + * pseudo-datum created by this class of by {@link DefaultDatumEnsemble} static methods. + * + * @param datum the object which may be a pseudo-datum for an ensemble, or {@code null}. + * @return the given object cast to a datum ensemble if the cast is valid. + */ - public static Optional<DatumEnsemble<VerticalDatum>> asEnsemble(final VerticalDatum datum) { ++ public static Optional<DefaultDatumEnsemble<VerticalDatum>> asEnsemble(final VerticalDatum datum) { + if (datum instanceof DefaultDatumEnsemble.Vertical) { + return Optional.of((DefaultDatumEnsemble.Vertical) datum); + } + return Optional.empty(); + } + + /** + * If the given object is a pseudo-datum for a temporal ensemble, returns that ensemble. + * This method is the converse of {@link #asDatum(TemporalCRS)} and recognizes only the + * pseudo-datum created by this class of by {@link DefaultDatumEnsemble} static methods. + * + * @param datum the object which may be a pseudo-datum for an ensemble, or {@code null}. + * @return the given object cast to a datum ensemble if the cast is valid. + */ - public static Optional<DatumEnsemble<TemporalDatum>> asEnsemble(final TemporalDatum datum) { ++ public static Optional<DefaultDatumEnsemble<TemporalDatum>> asEnsemble(final TemporalDatum datum) { + if (datum instanceof DefaultDatumEnsemble.Time) { + return Optional.of((DefaultDatumEnsemble.Time) datum); + } + return Optional.empty(); + } + - /** - * If the given object is a pseudo-datum for a parametric ensemble, returns that ensemble. - * This method is the converse of {@link #asDatum(ParametricCRS)} and recognizes only the - * pseudo-datum created by this class of by {@link DefaultDatumEnsemble} static methods. - * - * @param datum the object which may be a pseudo-datum for an ensemble, or {@code null}. - * @return the given object cast to a datum ensemble if the cast is valid. - */ - public static Optional<DatumEnsemble<ParametricDatum>> asEnsemble(final ParametricDatum datum) { - if (datum instanceof DefaultDatumEnsemble.Parametric) { - return Optional.of((DefaultDatumEnsemble.Parametric) datum); - } - return Optional.empty(); - } - + /** + * If the given object is a pseudo-datum for a engineering ensemble, returns that ensemble. + * This method is the converse of {@link #asDatum(EngineeringCRS)} and recognizes only the + * pseudo-datum created by this class of by {@link DefaultDatumEnsemble} static methods. + * + * @param datum the object which may be a pseudo-datum for an ensemble, or {@code null}. + * @return the given object cast to a datum ensemble if the cast is valid. + */ - public static Optional<DatumEnsemble<EngineeringDatum>> asEnsemble(final EngineeringDatum datum) { ++ public static Optional<DefaultDatumEnsemble<EngineeringDatum>> asEnsemble(final EngineeringDatum datum) { + if (datum instanceof DefaultDatumEnsemble.Engineering) { + return Optional.of((DefaultDatumEnsemble.Engineering) datum); + } + return Optional.empty(); + } + /** * Returns whether a legacy definition of a datum may be considered as equivalent to the given datum ensemble. * This is {@code true} if all reference frames (both the specified datum and the ensemble members) have the diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java index 0797fabecc,01e51591b7..c647333610 --- 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 @@@ -612,10 -605,10 +612,10 @@@ public class GeodeticObjectFactory exte * @param datum geodetic reference frame, or {@code null} if the CRS is associated only to a datum ensemble. * @param ensemble collection of reference frames which for low accuracy requirements may be considered to be * insignificantly different from each other, or {@code null} if there is no such ensemble. - * @param cs the two- or three-dimensional ellipsoidal coordinate system for the created CRS. + * @param cs the two- or three-dimensional ellipsoidal coordinate system for the created <abbr>CRS</abbr>. * @throws FactoryException if the object creation failed. * - * @see DefaultGeographicCRS#DefaultGeographicCRS(Map, GeodeticDatum, DatumEnsemble, EllipsoidalCS) + * @see DefaultGeographicCRS#DefaultGeographicCRS(Map, GeodeticDatum, DefaultDatumEnsemble, EllipsoidalCS) * @see GeodeticAuthorityFactory#createGeographicCRS(String) * * @since 1.5 @@@ -636,22 -630,23 +636,24 @@@ } /** - * Creates a geographic <abbr>CRS</abbr> from a reference frame. - * This is a shortcut for the {@linkplain #createGeographicCRS(Map, GeodeticDatum, DefaultDatumEnsemble, EllipsoidalCS) - * more generic method} without datum ensemble. + * Creates a geographic <abbr>CRS</abbr> with a datum that may be a datum ensemble. + * If the given {@code datum} argument is a {@linkplain DefaultDatumEnsemble datum ensemble + * viewed as a pseudo-datum}, then it is used as the {@code ensemble} argument of the above + * constructor. * * @param properties name and other properties to give to the new object. - * Available properties are {@linkplain ObjectFactory listed there}. - * @param datum geodetic reference frame to use in created CRS. - * @param cs the ellipsoidal coordinate system for the created CRS. + * @param datum the geodetic reference frame or datum ensemble viewed as a pseudo-datum. + * @param cs the two- or three-dimensional ellipsoidal coordinate system for the created <abbr>CRS</abbr>. + * @return the coordinate reference system for the given properties. * @throws FactoryException if the object creation failed. */ @Override - public GeographicCRS createGeographicCRS(Map<String, ?> properties, GeodeticDatum datum, EllipsoidalCS cs) + public GeographicCRS createGeographicCRS(Map<String,?> properties, GeodeticDatum datum, EllipsoidalCS cs) throws FactoryException { - return createGeographicCRS(properties, datum, null, cs); - DatumEnsemble<GeodeticDatum> ensemble = DatumOrEnsemble.asEnsemble(datum).orElse(null); ++ DefaultDatumEnsemble<GeodeticDatum> ensemble = DatumOrEnsemble.asEnsemble(datum).orElse(null); + if (ensemble != null) datum = null; + return createGeographicCRS(properties, datum, ensemble, cs); } /** @@@ -1078,10 -1072,10 +1080,10 @@@ * @param datum vertical reference frame, or {@code null} if the CRS is associated only to a datum ensemble. * @param ensemble collection of reference frames which for low accuracy requirements may be considered to be * insignificantly different from each other, or {@code null} if there is no such ensemble. - * @param cs the vertical coordinate system for the created CRS. + * @param cs the vertical coordinate system for the created <abbr>CRS</abbr>. * @throws FactoryException if the object creation failed. * - * @see DefaultVerticalCRS#DefaultVerticalCRS(Map, VerticalDatum, DatumEnsemble, VerticalCS) + * @see DefaultVerticalCRS#DefaultVerticalCRS(Map, VerticalDatum, DefaultDatumEnsemble, VerticalCS) * @see GeodeticAuthorityFactory#createVerticalCRS(String) * * @since 1.5 @@@ -1102,23 -1097,52 +1104,26 @@@ } /** - * Creates a static vertical datum from a realization method. - * The default implementation creates a {@link DefaultVerticalDatum} instance. + * Creates a vertical <abbr>CRS</abbr> with a datum that may be a datum ensemble. + * If the given {@code datum} argument is a {@linkplain DefaultDatumEnsemble datum ensemble + * viewed as a pseudo-datum}, then it is used as the {@code ensemble} argument of the above + * constructor. * * @param properties name and other properties to give to the new object. - * Available properties are {@linkplain ObjectFactory listed there}. - * @param datum vertical datum to use in created CRS. - * @param cs the vertical coordinate system for the created CRS. + * @param datum the vertical reference frame or datum ensemble viewed as a pseudo-datum. + * @param cs the vertical coordinate system for the created <abbr>CRS</abbr>. + * @return the coordinate reference system for the given properties. * @throws FactoryException if the object creation failed. */ @Override - public VerticalCRS createVerticalCRS(Map<String, ?> properties, VerticalDatum datum, VerticalCS cs) + public VerticalCRS createVerticalCRS(Map<String,?> properties, VerticalDatum datum, VerticalCS cs) throws FactoryException { - return createVerticalCRS(properties, datum, null, cs); - DatumEnsemble<VerticalDatum> ensemble = DatumOrEnsemble.asEnsemble(datum).orElse(null); ++ DefaultDatumEnsemble<VerticalDatum> ensemble = DatumOrEnsemble.asEnsemble(datum).orElse(null); + if (ensemble != null) datum = null; + return createVerticalCRS(properties, datum, ensemble, cs); } - /** - * Creates a static vertical datum from a realization method. - * The default implementation creates a {@link DefaultVerticalDatum} instance. - * - * @param properties name and other properties to give to the new object. - * @param method the realization method of the vertical datum, or {@code null} if none. - * @throws FactoryException if the object creation failed. - * - * @see DefaultVerticalDatum#DefaultVerticalDatum(Map, RealizationMethod) - * @see GeodeticAuthorityFactory#createVerticalDatum(String) - * - * @since 2.0 (temporary version number until this branch is released) - */ - @Override - public VerticalDatum createVerticalDatum(final Map<String,?> properties, - final RealizationMethod method) - throws FactoryException - { - final DefaultVerticalDatum datum; - try { - datum = new DefaultVerticalDatum(complete(properties), method); - } catch (IllegalArgumentException exception) { - throw new InvalidGeodeticParameterException(exception); - } - return unique("createVerticalDatum", datum); - } - /** * Creates a vertical datum from an enumerated type value. * The default implementation creates a {@link DefaultVerticalDatum} instance. @@@ -1224,10 -1285,10 +1229,10 @@@ * @param datum temporal datum, or {@code null} if the CRS is associated only to a datum ensemble. * @param ensemble collection of datum which for low accuracy requirements may be considered to be * insignificantly different from each other, or {@code null} if there is no such ensemble. - * @param cs the temporal coordinate system for the created CRS. + * @param cs the temporal coordinate system for the created <abbr>CRS</abbr>. * @throws FactoryException if the object creation failed. * - * @see DefaultTemporalCRS#DefaultTemporalCRS(Map, TemporalDatum, DatumEnsemble, TimeCS) + * @see DefaultTemporalCRS#DefaultTemporalCRS(Map, TemporalDatum, DefaultDatumEnsemble, TimeCS) * @see GeodeticAuthorityFactory#createTemporalCRS(String) * * @since 1.5 @@@ -1247,22 -1309,23 +1252,24 @@@ } /** - * Creates a temporal <abbr>CRS</abbr> from a datum. - * This is a shortcut for the {@linkplain #createTemporalCRS(Map, TemporalDatum, DefaultDatumEnsemble, TimeCS) - * more generic method} without datum ensemble. + * Creates a temporal <abbr>CRS</abbr> with a datum that may be a datum ensemble. + * If the given {@code datum} argument is a {@linkplain DefaultDatumEnsemble datum ensemble + * viewed as a pseudo-datum}, then it is used as the {@code ensemble} argument of the above + * constructor. * * @param properties name and other properties to give to the new object. - * Available properties are {@linkplain ObjectFactory listed there}. - * @param datum temporal datum to use in created CRS. - * @param cs the temporal coordinate system for the created CRS. + * @param datum the temporal datum or datum ensemble viewed as a pseudo-datum. + * @param cs the temporal coordinate system for the created <abbr>CRS</abbr>. + * @return the coordinate reference system for the given properties. * @throws FactoryException if the object creation failed. */ @Override - public TemporalCRS createTemporalCRS(Map<String, ?> properties, TemporalDatum datum, TimeCS cs) + public TemporalCRS createTemporalCRS(Map<String,?> properties, TemporalDatum datum, TimeCS cs) throws FactoryException { - return createTemporalCRS(properties, datum, null, cs); - DatumEnsemble<TemporalDatum> ensemble = DatumOrEnsemble.asEnsemble(datum).orElse(null); ++ DefaultDatumEnsemble<TemporalDatum> ensemble = DatumOrEnsemble.asEnsemble(datum).orElse(null); + if (ensemble != null) datum = null; + return createTemporalCRS(properties, datum, ensemble, cs); } /** @@@ -1349,10 -1407,10 +1356,10 @@@ * @param datum parametric datum, or {@code null} if the CRS is associated only to a datum ensemble. * @param ensemble collection of datum which for low accuracy requirements may be considered to be * insignificantly different from each other, or {@code null} if there is no such ensemble. - * @param cs the parametric coordinate system for the created CRS. + * @param cs the parametric coordinate system for the created <abbr>CRS</abbr>. * @throws FactoryException if the object creation failed. * - * @see DefaultParametricCRS#DefaultParametricCRS(Map, ParametricDatum, DatumEnsemble, ParametricCS) + * @see DefaultParametricCRS#DefaultParametricCRS(Map, DefaultParametricDatum, DefaultDatumEnsemble, ParametricCS) * @see GeodeticAuthorityFactory#createParametricCRS(String) * * @since 1.5 @@@ -1627,22 -1683,23 +1634,24 @@@ } /** - * Creates a engineering <abbr>CRS</abbr> from a datum. - * This is a shortcut for the {@linkplain #createEngineeringCRS(Map, EngineeringDatum, DefaultDatumEnsemble, CoordinateSystem) - * more generic method} without datum ensemble. + * Creates a engineering <abbr>CRS</abbr> with a datum that may be a datum ensemble. + * If the given {@code datum} argument is a {@linkplain DefaultDatumEnsemble datum ensemble + * viewed as a pseudo-datum}, then it is used as the {@code ensemble} argument of the above + * constructor. * * @param properties name and other properties to give to the new object. - * Available properties are {@linkplain ObjectFactory listed there}. - * @param datum engineering datum to use in created CRS. - * @param cs the coordinate system for the created CRS. + * @param datum the engineering datum or datum ensemble viewed as a pseudo-datum. + * @param cs the coordinate system for the created <abbr>CRS</abbr>. + * @return the coordinate reference system for the given properties. * @throws FactoryException if the object creation failed. */ @Override - public EngineeringCRS createEngineeringCRS(Map<String, ?> properties, EngineeringDatum datum, CoordinateSystem cs) + public EngineeringCRS createEngineeringCRS(Map<String,?> properties, EngineeringDatum datum, CoordinateSystem cs) throws FactoryException { - return createEngineeringCRS(properties, datum, null, cs); - DatumEnsemble<EngineeringDatum> ensemble = DatumOrEnsemble.asEnsemble(datum).orElse(null); ++ DefaultDatumEnsemble<EngineeringDatum> ensemble = DatumOrEnsemble.asEnsemble(datum).orElse(null); + if (ensemble != null) datum = null; + return createEngineeringCRS(properties, datum, ensemble, cs); } /** diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java index 3f8fab53f4,c3b772b488..8bccebf8da --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java @@@ -1635,7 -1623,7 +1636,7 @@@ search: try (ResultSet result = execute final String datumCode = getString(code, result, 9); final CoordinateSystem cs = owner.createCoordinateSystem(csCode); // Do not inline the `getString(…)` calls. final GeodeticDatum datumOrEnsemble = owner.createGeodeticDatum(datumCode); - final DefaultDatumEnsemble<GeodeticDatum> ensemble = wasDatumEnsemble(datumOrEnsemble, GeodeticDatum.class); - final DatumEnsemble<GeodeticDatum> ensemble = DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null); ++ final DefaultDatumEnsemble<GeodeticDatum> ensemble = DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null); final GeodeticDatum datum = (ensemble == null) ? datumOrEnsemble : null; if (cs instanceof CartesianCS) { final var c = (CartesianCS) cs; @@@ -1671,11 -1655,9 +1672,11 @@@ csCode = replaceDeprecatedCS(csCode); } final EllipsoidalCS cs = owner.createEllipsoidalCS(csCode.toString()); - final DefaultDatumEnsemble<GeodeticDatum> ensemble = wasDatumEnsemble(datumOrEnsemble, GeodeticDatum.class); - final DatumEnsemble<GeodeticDatum> ensemble = DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null); ++ final DefaultDatumEnsemble<GeodeticDatum> ensemble = DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null); final GeodeticDatum datum = (ensemble == null) ? datumOrEnsemble : null; - constructor = (factory, metadata) -> factory.createGeographicCRS(metadata, datum, ensemble, cs); + constructor = (factory, metadata) -> + (ensemble != null) ? extended(factory).createGeographicCRS(metadata, datum, ensemble, cs) + : factory.createGeographicCRS(metadata, datum, cs); break; } /* ────────────────────────────────────────────────────────────────────── @@@ -1763,11 -1745,9 +1764,11 @@@ final String datumCode = getString(code, result, 9); final VerticalCS cs = owner.createVerticalCS(csCode); // Do not inline the `getString(…)` calls. final VerticalDatum datumOrEnsemble = owner.createVerticalDatum(datumCode); - final DefaultDatumEnsemble<VerticalDatum> ensemble = wasDatumEnsemble(datumOrEnsemble, VerticalDatum.class); - final DatumEnsemble<VerticalDatum> ensemble = DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null); ++ final DefaultDatumEnsemble<VerticalDatum> ensemble = DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null); final VerticalDatum datum = (ensemble == null) ? datumOrEnsemble : null; - constructor = (factory, metadata) -> factory.createVerticalCRS(metadata, datum, ensemble, cs); + constructor = (factory, metadata) -> + (ensemble != null) ? extended(factory).createVerticalCRS(metadata, datum, ensemble, cs) + : factory.createVerticalCRS(metadata, datum, cs); break; } /* ────────────────────────────────────────────────────────────────────── @@@ -1782,11 -1762,9 +1783,11 @@@ final String datumCode = getString(code, result, 9); final TimeCS cs = owner.createTimeCS(csCode); // Do not inline the `getString(…)` calls. final TemporalDatum datumOrEnsemble = owner.createTemporalDatum(datumCode); - final DefaultDatumEnsemble<TemporalDatum> ensemble = wasDatumEnsemble(datumOrEnsemble, TemporalDatum.class); - final DatumEnsemble<TemporalDatum> ensemble = DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null); ++ final DefaultDatumEnsemble<TemporalDatum> ensemble = DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null); final TemporalDatum datum = (ensemble == null) ? datumOrEnsemble : null; - constructor = (factory, metadata) -> factory.createTemporalCRS(metadata, datum, ensemble, cs); + constructor = (factory, metadata) -> + (ensemble != null) ? extended(factory).createTemporalCRS(metadata, datum, ensemble, cs) + : factory.createTemporalCRS(metadata, datum, cs); break; } /* ────────────────────────────────────────────────────────────────────── @@@ -1797,11 -1775,9 +1798,11 @@@ final String datumCode = getString(code, result, 9); final CoordinateSystem cs = owner.createCoordinateSystem(csCode); // Do not inline the `getString(…)` calls. final EngineeringDatum datumOrEnsemble = owner.createEngineeringDatum(datumCode); - final DefaultDatumEnsemble<EngineeringDatum> ensemble = wasDatumEnsemble(datumOrEnsemble, EngineeringDatum.class); - final DatumEnsemble<EngineeringDatum> ensemble = DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null); ++ final DefaultDatumEnsemble<EngineeringDatum> ensemble = DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null); final EngineeringDatum datum = (ensemble == null) ? datumOrEnsemble : null; - constructor = (factory, metadata) -> factory.createEngineeringCRS(metadata, datum, ensemble, cs); + constructor = (factory, metadata) -> + (ensemble != null) ? extended(factory).createEngineeringCRS(metadata, datum, ensemble, cs) + : factory.createEngineeringCRS(metadata, datum, cs); break; } /* ────────────────────────────────────────────────────────────────────── @@@ -1810,11 -1786,11 +1811,11 @@@ case "parametric": { final String csCode = getString(code, result, 8); final String datumCode = getString(code, result, 9); - final ParametricCS cs = owner.createParametricCS(csCode); // Do not inline the `getString(…)` calls. - final ParametricDatum datumOrEnsemble = owner.createParametricDatum(datumCode); - final DatumEnsemble<ParametricDatum> ensemble = DatumOrEnsemble.asEnsemble(datumOrEnsemble).orElse(null); - final ParametricDatum datum = (ensemble == null) ? datumOrEnsemble : null; - constructor = (factory, metadata) -> factory.createParametricCRS(metadata, datum, ensemble, cs); + final DefaultParametricCS cs = owner.createParametricCS(csCode); // Do not inline the `getString(…)` calls. + final DefaultParametricDatum datumOrEnsemble = owner.createParametricDatum(datumCode); - final DefaultDatumEnsemble<DefaultParametricDatum> ensemble = wasDatumEnsemble(datumOrEnsemble, DefaultParametricDatum.class); ++ final DefaultDatumEnsemble<DefaultParametricDatum> ensemble = null; // TODO: not yet implemented. + final DefaultParametricDatum datum = (ensemble == null) ? datumOrEnsemble : null; + constructor = (factory, metadata) -> extended(factory).createParametricCRS(metadata, datum, ensemble, cs); break; } /* ────────────────────────────────────────────────────────────────────── diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ServicesForMetadata.java index 15366f34aa,8c6fc20090..9c7e99fead --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ServicesForMetadata.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ServicesForMetadata.java @@@ -568,7 -473,7 +494,6 @@@ public final class ServicesForMetadata return new CoordinateFormat(locale, timezone); } -- /** * Returns transform between a pair of vertical CRS. * diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java index f06bb790fb,2fc63352b1..611d3b2e35 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java @@@ -630,8 -634,11 +630,10 @@@ public class CoordinateOperationFinder if (!(interpolationCS instanceof EllipsoidalCS)) { final EllipsoidalCS cs = CommonCRS.WGS84.geographic3D().getCoordinateSystem(); if (!Utilities.equalsIgnoreMetadata(interpolationCS, cs)) { - final GeographicCRS stepCRS = factorySIS.crsFactory - .createGeographicCRS(derivedFrom(sourceCRS), DatumOrEnsemble.asDatum(sourceCRS), cs); + final GeographicCRS stepCRS = factorySIS.crsFactory.createGeographicCRS( + derivedFrom(sourceCRS), - sourceCRS.getDatum(), - sourceCRS.getDatumEnsemble(), ++ DatumOrEnsemble.asDatum(sourceCRS), + cs); step1 = createOperation(sourceCRS, toAuthorityDefinition(GeographicCRS.class, stepCRS)); interpolationCRS = step1.getTargetCRS(); interpolationCS = interpolationCRS.getCoordinateSystem(); diff --cc endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/CRSBuilder.java index bfcaeb984f,a9c3ebde88..ee0dae34e9 --- a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/CRSBuilder.java +++ b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/CRSBuilder.java @@@ -1000,10 -1007,9 +1000,9 @@@ previous: for (int i = components.siz @Override void createCRS(CRSFactory factory, Map<String,?> properties) throws FactoryException { properties = properties(getFirstAxis().coordinates.getUnitsString()); if (datum != null) { - referenceSystem = factory.createTemporalCRS(properties, datum, datumEnsemble, coordinateSystem); + referenceSystem = factory.createTemporalCRS(properties, datum, coordinateSystem); } else { - referenceSystem = factory.createEngineeringCRS(properties, - CommonCRS.Engineering.TIME.datum(), coordinateSystem); + referenceSystem = factory.createEngineeringCRS(properties, CommonCRS.Engineering.TIME.datum(), coordinateSystem); } } }
