This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-3.1 in repository https://gitbox.apache.org/repos/asf/sis.git
commit 3bb55654d2758254dd9dda8a4c956118bc2436fb Merge: d8e3bc5a7f e79df9c2d3 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Tue Aug 5 15:29:44 2025 +0200 Merge branch 'geoapi-4.0' into geoapi-3.1: Update the EPSG geodetic dataset from version 9.9.1 to version 12.013. This merge addresses only the code that read an existing database. Update of the code installing the database will be in a separated merge. Noticeable changes: * Removed tables: Area. * Added tables: ConventionalRS, DatumEnsemble, DatumEnsembleMember, DatumRealizationMethod, DefiningOperation, Extent, Scope, Usage. * The `SOURCE_GEOGCRS_CODE` column has been renamed `BASE_CRS_CODE`. The merge contains also work on GeoTIFF and on the geometry module (incubator). .../sis/buildtools/coding/ReorganizeImports.java | 7 +- .../org.apache.sis.feature/main/module-info.java | 3 + .../main/org/apache/sis/coverage/CategoryList.java | 2 +- .../org/apache/sis/coverage/SampleDimension.java | 27 +- .../coverage/grid/CoordinateOperationFinder.java | 43 +- .../apache/sis/coverage/grid/GridDerivation.java | 53 +- .../org/apache/sis/coverage/grid/GridExtent.java | 9 +- .../apache/sis/coverage/grid/SliceGeometry.java | 2 +- .../main/org/apache/sis/coverage/package-info.java | 2 +- .../org/apache/sis/feature/DefaultFeatureType.java | 2 +- .../main/org/apache/sis/feature/Features.java | 4 +- .../main/org/apache/sis/filter/Optimization.java | 6 +- .../main/org/apache/sis/filter/PropertyValue.java | 2 +- .../main/org/apache/sis/filter/TemporalFilter.java | 2 +- .../main/org/apache/sis/image/PixelIterator.java | 2 +- .../main/org/apache/sis/image/TransferType.java | 6 +- .../main/org/apache/sis/image/Transferer.java | 2 +- .../sis/coverage/grid/GridDerivationTest.java | 49 + .../org/apache/sis/feature/FeatureTestCase.java | 6 +- .../sis/filter/privy/ValueReferenceMock.java | 2 +- .../org/apache/sis/metadata/MetadataStandard.java | 2 +- .../org/apache/sis/metadata/MetadataVisitor.java | 2 +- .../org/apache/sis/metadata/TreeTableView.java | 2 +- .../sis/metadata/internal/CitationConstant.java | 2 +- .../sis/metadata/iso/citation/Citations.java | 2 +- .../metadata/iso/extent/DefaultVerticalExtent.java | 18 +- .../apache/sis/metadata/iso/extent/Extents.java | 14 +- .../DefaultRepresentativeFraction.java | 4 +- .../iso/maintenance/DefaultScopeDescription.java | 6 +- .../org/apache/sis/metadata/sql/Dispatcher.java | 2 +- .../org/apache/sis/temporal/LenientDateFormat.java | 4 +- .../apache/sis/util/iso/DefaultNameFactory.java | 6 +- .../main/org/apache/sis/util/iso/Types.java | 2 +- .../apache/sis/temporal/LenientDateFormatTest.java | 4 + .../apache/sis/profile/japan/netcdf/GCOM_C.java | 4 +- .../sis/geometry/AbstractDirectPosition.java | 2 +- .../org/apache/sis/geometry/AbstractEnvelope.java | 2 +- .../main/org/apache/sis/geometry/Envelopes.java | 102 +- .../apache/sis/geometry/WraparoundInEnvelope.java | 171 +- .../main/org/apache/sis/io/wkt/Formatter.java | 2 +- .../apache/sis/io/wkt/GeodeticObjectParser.java | 11 +- .../sis/parameter/DefaultParameterDescriptor.java | 2 + .../sis/parameter/DefaultParameterValue.java | 4 +- .../main/org/apache/sis/parameter/Parameters.java | 4 +- .../main/org/apache/sis/parameter/Verifier.java | 81 +- .../sis/referencing/AbstractIdentifiedObject.java | 2 +- .../main/org/apache/sis/referencing/Builder.java | 2 +- .../main/org/apache/sis/referencing/CRS.java | 22 +- .../apache/sis/referencing/NamedIdentifier.java | 2 +- .../sis/referencing/crs/DefaultGeodeticCRS.java | 24 +- .../referencing/datum/DefaultDatumEnsemble.java | 122 +- .../referencing/datum/DefaultGeodeticDatum.java | 16 +- .../referencing/datum/DefaultVerticalDatum.java | 6 +- .../referencing/factory/AuthorityFactoryProxy.java | 11 + .../factory/ConcurrentAuthorityFactory.java | 28 +- .../factory/GeodeticAuthorityFactory.java | 143 +- .../referencing/factory/GeodeticObjectFactory.java | 3 - .../factory/IdentifiedObjectFinder.java | 2 +- .../referencing/factory/IdentifiedObjectSet.java | 77 +- .../referencing/factory/sql/AuthorityCodes.java | 6 +- .../sis/referencing/factory/sql/AxisName.java | 18 +- .../sis/referencing/factory/sql/BursaWolfInfo.java | 210 -- .../factory/sql/CoordinateOperationSet.java | 21 +- .../referencing/factory/sql/EPSGCodeFinder.java | 20 +- .../referencing/factory/sql/EPSGDataAccess.java | 2601 +++++++++++--------- .../sis/referencing/factory/sql/EPSGFactory.java | 4 +- .../sis/referencing/factory/sql/EPSG_Finish.sql | 2 +- .../sis/referencing/factory/sql/EPSG_Prepare.sql | 18 +- .../referencing/factory/sql/ObjectPertinence.java | 154 ++ .../sis/referencing/factory/sql/SQLTranslator.java | 424 ++-- .../sis/referencing/factory/sql/TableInfo.java | 61 +- .../org/apache/sis/referencing/internal/Epoch.java | 2 - .../internal/ParameterizedTransformBuilder.java | 9 + .../internal/PositionalAccuracyConstant.java | 40 +- .../referencing/internal/VerticalDatumTypes.java | 80 +- .../operation/CoordinateOperationContext.java | 28 +- .../operation/CoordinateOperationFinder.java | 27 +- .../operation/CoordinateOperationRegistry.java | 2 +- .../DefaultCoordinateOperationFactory.java | 31 +- .../referencing/operation/SubOperationInfo.java | 13 +- .../referencing/operation/gridded/LoadedGrid.java | 2 +- .../operation/matrix/AffineTransforms2D.java | 6 +- .../sis/referencing/operation/matrix/Matrix1.java | 2 +- .../sis/referencing/operation/matrix/Matrix2.java | 2 +- .../sis/referencing/operation/matrix/Matrix3.java | 2 +- .../sis/referencing/operation/matrix/Matrix4.java | 2 +- .../referencing/operation/matrix/MatrixSIS.java | 2 +- .../referencing/operation/provider/Wraparound.java | 2 +- .../operation/transform/MolodenskyTransform.java | 2 +- .../operation/transform/WraparoundTransform.java | 4 +- .../referencing/privy/CoordinateOperations.java | 5 - .../org/apache/sis/geometry/EnvelopesTest.java | 12 +- .../datum/DefaultGeodeticDatumTest.java | 2 +- .../referencing/factory/sql/EPSGFactoryTest.java | 36 +- .../sis/referencing/factory/sql/TableInfoTest.java | 10 +- .../internal/VerticalDatumTypesTest.java | 33 +- .../InterpolatedGeocentricTransformTest.java | 2 +- .../storage/landsat/LandsatStoreProviderTest.java | 2 +- .../apache/sis/storage/geotiff/GeoTiffStore.java | 4 +- .../org/apache/sis/storage/geotiff/Reader.java | 2 +- .../org/apache/sis/storage/geotiff/writer/ZIP.java | 28 +- .../org/apache/sis/storage/geotiff/WriterTest.java | 41 +- .../apache/sis/storage/netcdf/base/Convention.java | 30 +- .../sis/storage/netcdf/base/GridMapping.java | 135 +- .../org/apache/sis/storage/netcdf/base/Node.java | 4 +- .../apache/sis/io/stream/HyperRectangleWriter.java | 54 +- .../sis/io/stream/SubsampledRectangleWriter.java | 26 +- .../org/apache/sis/io/stream/UpdatableWrite.java | 2 +- .../org/apache/sis/storage/StorageConnector.java | 8 +- .../aggregate/BandAggregateGridResource.java | 2 +- .../aggregate/ConcatenatedGridResource.java | 2 +- .../sis/storage/aggregate/CoverageAggregator.java | 2 +- .../sis/storage/base/MemoryGridResource.java | 29 +- .../storage/image/WritableSingleImageStore.java | 2 +- .../org/apache/sis/storage/CoverageSubsetTest.java | 2 +- .../aggregate/BandAggregateGridResourceTest.java | 2 +- .../sis/storage/aggregate/OpaqueGridResource.java | 2 +- .../sis/storage/base/MemoryGridResourceTest.java | 2 +- .../apache/sis/storage/csv/StoreProviderTest.java | 2 +- .../sis/storage/esri/AsciiGridStoreTest.java | 2 +- .../sis/storage/image/WorldFileStoreTest.java | 2 +- .../apache/sis/storage/wkt/StoreProviderTest.java | 2 +- .../test/org/apache/sis/storage/wkt/StoreTest.java | 2 +- .../apache/sis/storage/xml/StoreProviderTest.java | 2 +- .../test/org/apache/sis/storage/xml/StoreTest.java | 2 +- .../main/org/apache/sis/math/ArrayVector.java | 4 +- .../main/org/apache/sis/math/DecimalFunctions.java | 2 +- .../main/org/apache/sis/math/Vector.java | 6 +- .../main/org/apache/sis/measure/DerivedScalar.java | 4 +- .../org/apache/sis/measure/MeasurementRange.java | 6 +- .../main/org/apache/sis/measure/NumberRange.java | 14 +- .../main/org/apache/sis/measure/Scalar.java | 10 +- .../main/org/apache/sis/setup/GeometryLibrary.java | 18 + .../main/org/apache/sis/system/Semaphores.java | 2 +- .../main/org/apache/sis/util/ArgumentChecks.java | 2 +- .../main/org/apache/sis/util/ArraysExt.java | 20 +- .../main/org/apache/sis/util/Numbers.java | 6 +- .../main/org/apache/sis/util/collection/Cache.java | 11 +- .../org/apache/sis/util/collection/Containers.java | 8 +- .../sis/util/collection/DefaultTreeTable.java | 2 +- .../main/org/apache/sis/util/privy/Constants.java | 10 +- .../main/org/apache/sis/util/privy/Numerics.java | 2 +- .../org/apache/sis/util/resources/Vocabulary.java | 5 + .../sis/util/resources/Vocabulary.properties | 1 + .../sis/util/resources/Vocabulary_fr.properties | 1 + .../test/org/apache/sis/math/VectorTest.java | 2 +- .../org/apache/sis/measure/SystemUnitTest.java | 2 +- .../geometries/{Polygon.java => CurvePolygon.java} | 25 +- .../org/apache/sis/geometries/GeometryFactory.java | 160 +- .../org/apache/sis/geometries/MultiPolygon.java | 2 +- .../main/org/apache/sis/geometries/Polygon.java | 9 +- .../main/org/apache/sis/geometries/Triangle.java | 2 +- .../main/org/apache/sis/geometries/Wrapper.java | 469 ++++ .../org/apache/sis/geometries/math/Matrix2D.java | 2 +- .../org/apache/sis/geometries/math/Matrix3D.java | 2 +- .../org/apache/sis/geometries/math/Matrix4D.java | 2 +- .../main/org/apache/sis/geometries/math/Tuple.java | 8 +- .../org/apache/sis/geometries/math/TupleArray.java | 20 +- .../sis/geometries/privy/DefaultPolygon.java | 8 +- .../processor/spatialedition/Transform.java | 8 +- .../processor/spatialrelations2d/Contains.java | 11 +- .../sis/geometries/triangulate/EarClipping.java | 14 +- .../coveragejson/CoverageJsonStoreTest.java | 2 +- .../apache/sis/gui/coverage/CoverageCanvas.java | 10 +- .../referencing/factory/sql/epsg/DebugTools.sql | 2 +- .../sis/referencing/factory/sql/epsg/README.md | 1 + 166 files changed, 4142 insertions(+), 2191 deletions(-) diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java index 9e61cd69a9,c3237e3320..f6653ddeee --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java @@@ -215,29 -203,28 +215,30 @@@ public class DefaultScopeDescription ex } /** - * Returns the given value casted to a {@code Set} of elements of the given type. - * Returns the given value cast to a {@code Set<CharSequence>}. ++ * Returns the given value cast to a {@code Set} of elements of the given type. + * It is caller responsibility to ensure that the cast is valid, as element type + * is verified only when assertions are enabled. */ @SuppressWarnings("unchecked") - private static Set<CharSequence> cast(final Object value) { + private static <E> Set<E> cast(final Object value, final Class<E> type) { assert !(value instanceof CheckedContainer<?>) || - ((CheckedContainer<?>) value).getElementType() == CharSequence.class; - return (Set<CharSequence>) value; + ((CheckedContainer<?>) value).getElementType() == type; + return (Set<E>) value; } /** * Returns the set of properties identified by the {@code code} argument, * or an unmodifiable empty set if another value is defined. */ - private Set<CharSequence> getProperty(final byte code) { + private <E> Set<E> getProperty(final Class<E> type, final byte code) { + @SuppressWarnings("LocalVariableHidesMemberVariable") final Object value = this.value; if (value != null) { if (property == code) { - return cast(value); + return cast(value, type); } else if (!(value instanceof Set) || !((Set<?>) value).isEmpty()) { return Semaphores.query(Semaphores.NULL_COLLECTION) - ? null : new ExcludedSet<E>(NAMES[code-1], NAMES[property-1]); + ? null : new ExcludedSet<>(NAMES[code-1], NAMES[property-1]); } } /* @@@ -562,6 -509,6 +563,7 @@@ * * @since 1.0 */ ++ @SuppressWarnings("deprecation") public void setLevelDescription(final ScopeCode level, final Set<? extends CharSequence> newValues) { if (level == ScopeCode.DATASET) { String description = null; diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java index ab1f8c95bf,796b7abe65..e473ae0c0f --- 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 @@@ -1443,12 -1445,13 +1444,12 @@@ class GeodeticObjectParser extends Math return null; } final String name = element.pullString("name"); - @SuppressWarnings("deprecation") RealizationMethod method = null; if (isWKT1) { - method = VerticalDatumTypes.fromLegacy(element.pullInteger("datum")); + method = VerticalDatumTypes.fromLegacyCode(element.pullInteger("datum")); } if (method == null) { - method = VerticalDatumTypes.guess(name, null, null); + method = VerticalDatumTypes.fromDatum(name, null, null); } final DatumFactory datumFactory = factories.getDatumFactory(); try { diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultVerticalDatum.java index d5da02669e,0d27307af2..8ba7eb177d --- 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 @@@ -428,7 -368,7 +430,7 @@@ public class DefaultVerticalDatum exten protected String formatTo(final Formatter formatter) { super.formatTo(formatter); if (formatter.getConvention().majorVersion() == 1) { - formatter.append(VerticalDatumTypes.toLegacy(getVerticalDatumType())); - formatter.append(VerticalDatumTypes.toLegacyCode(method)); ++ formatter.append(VerticalDatumTypes.toLegacyCode(getVerticalDatumType())); return WKTKeywords.Vert_Datum; } return formatter.shortOrLong(WKTKeywords.VDatum, WKTKeywords.VerticalDatum); diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java index e1eeacb925,5f8fd800ea..955389f63f --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java @@@ -1115,35 -1092,34 +1115,61 @@@ public abstract class ConcurrentAuthori return create(AuthorityFactoryProxy.ENGINEERING_CRS, code); } + /** + * Returns a 2-dimensional engineering coordinate reference system applied to locations in images. + * The default implementation performs the following steps: + * <ul> + * <li>Return the cached instance for the given code if such instance already exists.</li> + * <li>Otherwise if the Data Access Object (DAO) overrides the {@code createImageCRS(String)} + * method, invoke that method and cache the result for future use.</li> + * <li>Otherwise delegate to the {@link GeodeticAuthorityFactory#createImageCRS(String)} + * method in the parent class. This allows to check if the more generic + * {@link #createCoordinateReferenceSystem(String)} method cached a value before to try that method.</li> + * </ul> + * + * @return the coordinate reference system for the given code. + * @throws FactoryException if the object creation failed. + * + * @deprecated The {@code ImageCRS} class has been removed in ISO 19111:2019. + * It is replaced by {@code EngineeringCRS}. + */ + @Override + @Deprecated(since = "1.5") + public ImageCRS createImageCRS(final String code) throws FactoryException { + if (isDefault(ImageCRS.class)) { + return super.createImageCRS(code); + } + return create(AuthorityFactoryProxy.IMAGE_CRS, code); + } + /** - * Returns an arbitrary datum from a code. The returned object will typically be an + * Returns an arbitrary datum ensemble from a code. + * The default implementation performs the following steps: + * <ul> + * <li>Return the cached instance for the given code if such instance already exists.</li> + * <li>Otherwise if the Data Access Object (DAO) overrides the {@code createDatumEnsemble(String)} + * method, invoke that method and cache the result for future use.</li> + * <li>Otherwise delegate to the {@link GeodeticAuthorityFactory#createDatumEnsemble(String)} + * method in the parent class. This allows to check if the more generic + * {@link #createObject(String)} method cached a value before to try that method.</li> + * </ul> + * + * @return the datum for the given code. + * @throws FactoryException if the object creation failed. + * + * @since 1.5 + */ + @Override + public DatumEnsemble<?> createDatumEnsemble(final String code) throws FactoryException { + if (isDefault(DatumEnsemble.class)) { + return super.createDatumEnsemble(code); + } + return create(AuthorityFactoryProxy.ENSEMBLE, code); + } + + /** + * Returns an arbitrary datum from a code. The returned object will typically be a + * {@link GeodeticDatum}, {@link VerticalDatum}, {@link TemporalDatum} or {@link EngineeringDatum}. * The default implementation performs the following steps: * <ul> * <li>Return the cached instance for the given code if such instance already exists.</li> diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java index 8185386ed5,09cd80a83e..c684889ab8 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java @@@ -541,30 -526,46 +543,70 @@@ public abstract class GeodeticAuthority return cast(EngineeringCRS.class, createCoordinateReferenceSystem(code), code); } + /** + * Creates a 2-dimensional engineering coordinate reference system applied to locations in images. + * Image coordinate reference systems are treated as a separate sub-type because a separate + * user community exists for images with its own terms of reference. + * + * <h4>Default implementation</h4> + * The default implementation delegates to {@link #createCoordinateReferenceSystem(String)} and casts the result. - * If the result cannot be casted, then a {@link NoSuchAuthorityCodeException} is thrown. ++ * If the result cannot be cast, then a {@link NoSuchAuthorityCodeException} is thrown. + * + * @param code value allocated by authority. + * @return the coordinate reference system for the given code. + * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found. + * @throws FactoryException if the object creation failed for some other reason. + * + * @see org.apache.sis.referencing.crs.DefaultImageCRS + * + * @deprecated The {@code ImageCRS} class has been removed in ISO 19111:2019. + * It is replaced by {@code EngineeringCRS}. + */ + @Deprecated(since = "1.5") + public ImageCRS createImageCRS(final String code) throws NoSuchAuthorityCodeException, FactoryException { + return cast(ImageCRS.class, createCoordinateReferenceSystem(code), code); + } + + /** + * Creates an arbitrary datum ensemble from a code. + * A datum ensemble is a collection of datums which for low accuracy requirements + * may be considered to be insignificantly different from each other. + * + * <h4>Examples</h4> + * The {@linkplain #getAuthorityCodes(Class) set of available codes} depends on the defining + * {@linkplain #getAuthority() authority} and the {@code GeodeticAuthorityFactory} subclass in use. + * A frequently used authority is "EPSG", which includes the following codes: + * + * <table class="sis"> + * <caption>Authority codes examples</caption> + * <tr><th>Code</th> <th>Description</th></tr> + * <tr><td>EPSG:6326</td> <td>World Geodetic System 1984</td></tr> + * <tr><td>EPSG:6258</td> <td>European Terrestrial Reference System 1989</td></tr> + * </table> + * + * <h4>Default implementation</h4> + * The default implementation delegates to {@link #createDatum(String)} and casts the result. + * If the result cannot be cast, then a {@link NoSuchAuthorityCodeException} is thrown. + * This approach assumes that the datum ensemble implements also the {@link Datum} interface. + * It is the case of the {@link org.apache.sis.referencing.datum.DefaultDatumEnsemble} class. + * + * <p>This default implementation is unusual, but is convenient for the implementation strategy + * of Apache <abbr>SIS</abbr> and for the structure of the <abbr>EPSG</abbr> geodetic dataset, + * which uses the same {@code "Datum"} table for storing the properties of the two kinds of object.</p> + * + * @param code value allocated by authority. + * @return the datum ensemble for the given code. + * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found. + * @throws FactoryException if the object creation failed for some other reason. + * + * @see org.apache.sis.referencing.datum.DefaultDatumEnsemble + * + * @since 1.5 + */ + public DatumEnsemble<?> createDatumEnsemble(final String code) throws NoSuchAuthorityCodeException, FactoryException { + return cast(DatumEnsemble.class, createDatum(code), code); + } + /** * Creates an arbitrary datum from a code. The returned object will typically be an * instance of {@link GeodeticDatum}, {@link VerticalDatum} or {@link TemporalDatum}. diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/CoordinateOperationSet.java index a67aad7de8,f289b0f33e..be28e30680 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/CoordinateOperationSet.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/CoordinateOperationSet.java @@@ -109,10 -110,9 +110,10 @@@ final class CoordinateOperationSet exte } /** - * Creates a coordinate operation for the specified EPSG code. + * Creates a coordinate operation for the specified <abbr>EPSG</abbr> code. */ @Override + @SuppressWarnings("deprecation") protected CoordinateOperation createObject(final String code) throws FactoryException { final Integer base = projections.get(code); if (base != null) { diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGCodeFinder.java index 55553fc50f,47975c6b37..f250ecf703 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGCodeFinder.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGCodeFinder.java @@@ -318,8 -319,8 +319,8 @@@ crs: if (isInstance(CoordinateRefere * ORDER BY COORD_REF_SYS_CODE */ final Condition filter; - if (object instanceof DerivedCRS) { // No need to use isInstance(Class, Object) from here. - filter = dependencies("BASE_CRS_CODE", SingleCRS.class, ((DerivedCRS) object).getBaseCRS(), true); + if (object instanceof GeneralDerivedCRS) { // No need to use isInstance(Class, Object) from here. - filter = dependencies("SOURCE_GEOGCRS_CODE", CoordinateReferenceSystem.class, ((GeneralDerivedCRS) object).getBaseCRS(), true); ++ filter = dependencies("BASE_CRS_CODE", CoordinateReferenceSystem.class, ((GeneralDerivedCRS) object).getBaseCRS(), true); } else if (object instanceof GeodeticCRS) { filter = dependencies("DATUM_CODE", GeodeticDatum.class, ((GeodeticCRS) object).getDatum(), true); } else if (object instanceof VerticalCRS) { diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java index 34ca685020,59997d0496..cf8ecff2c0 --- 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 @@@ -1477,47 -1714,74 +1715,74 @@@ search: try (ResultSet result = execute * We need to check if EPSG database 10+ has more specific information. * See https://issues.apache.org/jira/browse/SIS-518 */ - @SuppressWarnings("LocalVariableHidesMemberVariable") - final Map<String,Object> properties = createProperties("Coordinate Reference System", - name, epsg, area, scope, remarks, deprecated); - if (baseCRS instanceof GeodeticCRS) { - return factory.createProjectedCRS(metadata, (GeodeticCRS) baseCRS, fromBase, cs); + if (baseCRS instanceof GeographicCRS) { - crs = crsFactory.createProjectedCRS(properties, (GeographicCRS) baseCRS, op, cs); ++ return factory.createProjectedCRS(metadata, (GeographicCRS) baseCRS, fromBase, cs); } else { - crs = crsFactory.createDerivedCRS(properties, baseCRS, op, cs); + return factory.createDerivedCRS(metadata, baseCRS, fromBase, cs); } } finally { - Semaphores.clear(Semaphores.SUSPEND_PARAMETER_CHECK, suspendParamChecks); + Semaphores.clearIfFalse(Semaphores.SUSPEND_PARAMETER_CHECK, old); } - } finally { - endOfRecursion(ProjectedCRS.class, epsg); - } + }; break; } - /* ---------------------------------------------------------------------- + /* ────────────────────────────────────────────────────────────────────── * VERTICAL CRS - * ---------------------------------------------------------------------- */ + * ────────────────────────────────────────────────────────────────────── */ case "vertical": { - final VerticalCS cs = owner.createVerticalCS (getString(code, result, 8)); - final VerticalDatum datum = owner.createVerticalDatum(getString(code, result, 9)); - crs = crsFactory.createVerticalCRS(createProperties("Coordinate Reference System", - name, epsg, area, scope, remarks, deprecated), datum, cs); + final String csCode = getString(code, result, 8); + final String datumCode = getString(code, result, 9); + final VerticalCS cs = owner.createVerticalCS(csCode); // Do not inline the `getString(…)` calls. + final VerticalDatum datumOrEnsemble = owner.createVerticalDatum(datumCode); + final DatumEnsemble<VerticalDatum> ensemble = wasDatumEnsemble(datumOrEnsemble, VerticalDatum.class); + final VerticalDatum datum = (ensemble == null) ? datumOrEnsemble : null; + constructor = (factory, metadata) -> factory.createVerticalCRS(metadata, datum, ensemble, cs); break; } - /* ---------------------------------------------------------------------- + /* ────────────────────────────────────────────────────────────────────── * TEMPORAL CRS * - * NOTE : The original EPSG database does not define any temporal CRS. - * This block is a SIS-specific extension. - * ---------------------------------------------------------------------- */ + * NOTE : As of version 12, the EPSG database does not define temporal CRS. + * This block is a SIS─specific extension. + * ────────────────────────────────────────────────────────────────────── */ case "time": case "temporal": { - final TimeCS cs = owner.createTimeCS (getString(code, result, 8)); - final TemporalDatum datum = owner.createTemporalDatum(getString(code, result, 9)); - crs = crsFactory.createTemporalCRS(createProperties("Coordinate Reference System", - name, epsg, area, scope, remarks, deprecated), datum, cs); + final String csCode = getString(code, result, 8); + final String datumCode = getString(code, result, 9); + final TimeCS cs = owner.createTimeCS(csCode); // Do not inline the `getString(…)` calls. + final TemporalDatum datumOrEnsemble = owner.createTemporalDatum(datumCode); + final DatumEnsemble<TemporalDatum> ensemble = wasDatumEnsemble(datumOrEnsemble, TemporalDatum.class); + final TemporalDatum datum = (ensemble == null) ? datumOrEnsemble : null; + constructor = (factory, metadata) -> factory.createTemporalCRS(metadata, datum, ensemble, cs); + break; + } + /* ────────────────────────────────────────────────────────────────────── + * ENGINEERING CRS + * ────────────────────────────────────────────────────────────────────── */ + case "engineering": { + final String csCode = getString(code, result, 8); + final String datumCode = getString(code, result, 9); + final CoordinateSystem cs = owner.createCoordinateSystem(csCode); // Do not inline the `getString(…)` calls. + final EngineeringDatum datumOrEnsemble = owner.createEngineeringDatum(datumCode); + final DatumEnsemble<EngineeringDatum> ensemble = wasDatumEnsemble(datumOrEnsemble, EngineeringDatum.class); + final EngineeringDatum datum = (ensemble == null) ? datumOrEnsemble : null; + constructor = (factory, metadata) -> factory.createEngineeringCRS(metadata, datum, ensemble, cs); break; } - /* ---------------------------------------------------------------------- + /* ────────────────────────────────────────────────────────────────────── + * PARAMETRIC CRS + * ────────────────────────────────────────────────────────────────────── */ + 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 = wasDatumEnsemble(datumOrEnsemble, ParametricDatum.class); + final ParametricDatum datum = (ensemble == null) ? datumOrEnsemble : null; + constructor = (factory, metadata) -> factory.createParametricCRS(metadata, datum, ensemble, cs); + break; + } + /* ────────────────────────────────────────────────────────────────────── * COMPOUND CRS * * NOTE: This method invokes itself recursively. diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/VerticalDatumTypes.java index b28513be42,ecea0315c6..8eef7854ae --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/VerticalDatumTypes.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/VerticalDatumTypes.java @@@ -24,18 -24,16 +24,19 @@@ import org.opengis.referencing.cs.Coord import org.opengis.referencing.cs.AxisDirection; import org.apache.sis.util.Characters; import org.apache.sis.util.CharSequences; + import org.apache.sis.util.privy.CodeLists; import org.apache.sis.measure.Units; +// Specific to the main and geoapi-3.1 branches: +import org.opengis.referencing.datum.VerticalDatumType; + // Specific to the geoapi-3.1 and geoapi-4.0 branches: import org.opengis.referencing.datum.RealizationMethod; /** - * Extensions to the standard set of {@link RealizationEpoch}. + * Extensions to the standard set of {@link RealizationMethod}. - * Some of those constants are derived from a legacy {@code VerticalDatumType} code list. + * Some of those constants are derived from a legacy {@link VerticalDatumType} code list. * Those constants are not in public API because they were intentionally omitted from ISO 19111, * and the ISO experts said that they should really not be public. * @@@ -132,13 -139,12 +138,13 @@@ public final class VerticalDatumTypes * Returns the legacy code for the datum type, or 2000 (other surface) if unknown. * This method is used for WKT 1 formatting. * - * @param type the vertical datum type, or {@code null} if unknown. - * @param method the realization method, or {@code null} if unknown. ++ * @param method the vertical datum type, or {@code null} if unknown. * @return the legacy code for the given datum type, or 0 if unknown. */ - public static int toLegacyCode(final RealizationMethod method) { + @SuppressWarnings("deprecation") - public static int toLegacy(final VerticalDatumType type) { - if (type != null) { - switch (type.name().toUpperCase(Locale.US)) { ++ public static int toLegacyCode(final VerticalDatumType method) { + if (method != null) { + switch (method.name().toUpperCase(Locale.US)) { case ORTHOMETRIC: return 2001; // CS_VD_Orthometric case ELLIPSOIDAL: return 2002; // CS_VD_Ellipsoidal case BAROMETRIC: return 2003; // CS_VD_AltitudeBarometric @@@ -155,38 -161,55 +161,74 @@@ * This is because the vertical datum type was a mandatory property in legacy OGC/ISO standards. * This method is used for writing GML documents older than GML 3.2. * ++ * <p>Note: this is renamed {@code toLegacyName(RealizationMethod)} on the GeoAPI 4.0 branch.</p> ++ * * @param method the realization method, or {@code null}. - * @return the vertical datum type name (never null). + * @return the vertical datum type (never null). */ - public static String toLegacyName(final RealizationMethod method) { - if (method == RealizationMethod.GEOID) return "geoidal"; - if (method == RealizationMethod.TIDAL) return "depth"; + @SuppressWarnings("deprecation") + public static VerticalDatumType fromMethod(final RealizationMethod method) { + if (method == RealizationMethod.GEOID) return VerticalDatumType.GEOIDAL; + if (method == RealizationMethod.TIDAL) return VerticalDatumType.DEPTH; if (method != null) { - return method.name().toLowerCase(Locale.US); + return VerticalDatumType.valueOf(method.name().toUpperCase(Locale.US)); } - return "other surface"; + return VerticalDatumType.OTHER_SURFACE; + } + + /** + * Returns the realization method from a vertical datum type. + * This method is used for reading GML documents older than GML 3.2. + * ++ * <p>Note: this is renamed {@code fromLegacyName(String)} on the GeoAPI 4.0 branch.</p> ++ * + * @param type the vertical datum type, or {@code null}. + * @return the realization method, or {@code null} if none. + */ + @SuppressWarnings("deprecation") + public static RealizationMethod toMethod(final VerticalDatumType type) { - if (type != null) { - if (type == VerticalDatumType.GEOIDAL) return RealizationMethod.GEOID; - if (type == VerticalDatumType.DEPTH) return RealizationMethod.TIDAL; - if (type == VerticalDatumType.BAROMETRIC) return RealizationMethod.valueOf(BAROMETRIC); - if (ORTHOMETRIC.equalsIgnoreCase(type.name())) return RealizationMethod.valueOf(ORTHOMETRIC); - if (ELLIPSOIDAL.equalsIgnoreCase(type.name())) return ellipsoidal(); - } ++ return (type != null) ? fromLegacyName(type.name()) : null; + } + + /** + * Returns the realization method from a vertical datum type. + * This method is used for reading GML documents older than GML 3.2. + * + * @param type the vertical datum type, or {@code null}. + * @return the realization method, or {@code null} if none. + */ + public static RealizationMethod fromLegacyName(final String type) { + if ("geoidal" .equalsIgnoreCase(type)) return RealizationMethod.GEOID; + if ("depth" .equalsIgnoreCase(type)) return RealizationMethod.TIDAL; + if (LOCAL .equalsIgnoreCase(type)) return RealizationMethod.valueOf(LOCAL); + if (BAROMETRIC .equalsIgnoreCase(type)) return RealizationMethod.valueOf(BAROMETRIC); + if (ORTHOMETRIC.equalsIgnoreCase(type)) return RealizationMethod.valueOf(ORTHOMETRIC); + if (ELLIPSOIDAL.equalsIgnoreCase(type)) return ellipsoidal(); return null; } + /** + * Returns the realization method from heuristic rules applied on the name. + * ++ * <p>Note: this is {@code fromMethod(String)} on the GeoAPI 4.0 branch.</p> ++ * + * @param name the realization method name, or {@code null}. + * @return the realization method, or {@code null} if the given name was null. + */ + public static RealizationMethod fromMethod(final String name) { + RealizationMethod method = fromLegacyName(name); + if (method == null && name != null && !name.isBlank()) { + final int s = name.lastIndexOf('-'); + if (s >= 0 && name.substring(s+1).strip().equalsIgnoreCase("based")) { + method = CodeLists.forCodeName(RealizationMethod.class, name.substring(0, s)); + } + if (method == null) { + method = RealizationMethod.valueOf(name); + } + } + return method; + } + /** * Guesses the realization method of a datum from its name, aliases or a given vertical axis. * This is sometimes needed after XML unmarshalling or WKT parsing, because GML 3.2 and ISO 19162 diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java index 2d6ae5666e,e127c1d49f..1bd5e387f4 --- 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 @@@ -1193,8 -1182,15 +1206,16 @@@ public class CoordinateOperationFinder * @param crs the CRS having a conversion that cannot be inverted. * @return a default error message. */ - private String canNotInvert(final DerivedCRS crs) { + @SuppressWarnings("deprecation") + private String canNotInvert(final GeneralDerivedCRS crs) { return resources().getString(Resources.Keys.NonInvertibleOperation_1, label(crs.getConversionFromBase())); } + + /** + * Returns whether the operation can be cached. This is {@code false} if + * the operation depends on parameters that may vary between two executions. + */ + final boolean canStoreInCache() { + return canStoreInCache; + } } diff --cc endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/VerticalDatumTypesTest.java index a9be269f6a,b5fe441aec..0a167b5be6 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/VerticalDatumTypesTest.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/VerticalDatumTypesTest.java @@@ -66,13 -62,25 +66,26 @@@ public final class VerticalDatumTypesTe } /** - * Tests the {@link VerticalDatumTypes#toLegacy(VerticalDatumType)} method. - * Tests the {@link VerticalDatumTypes#toLegacyCode(RealizationMethod)} method. ++ * Tests the {@link VerticalDatumTypes#toLegacyCode(VerticalDatumType)} method. */ @Test - public void testToLegacy() { - assertEquals(2002, VerticalDatumTypes.toLegacy(VerticalDatumType.valueOf("ELLIPSOIDAL"))); - assertEquals(2005, VerticalDatumTypes.toLegacy(VerticalDatumType.GEOIDAL)); - assertEquals(2006, VerticalDatumTypes.toLegacy(VerticalDatumType.DEPTH)); ++ @SuppressWarnings("deprecation") + public void testToLegacyCode() { - assertEquals(2002, VerticalDatumTypes.toLegacyCode(VerticalDatumTypes.ellipsoidal())); - assertEquals(2005, VerticalDatumTypes.toLegacyCode(RealizationMethod .GEOID)); - assertEquals(2006, VerticalDatumTypes.toLegacyCode(RealizationMethod .TIDAL)); ++ assertEquals(2002, VerticalDatumTypes.toLegacyCode(VerticalDatumType.valueOf("ELLIPSOIDAL"))); ++ assertEquals(2005, VerticalDatumTypes.toLegacyCode(VerticalDatumType.GEOIDAL)); ++ assertEquals(2006, VerticalDatumTypes.toLegacyCode(VerticalDatumType.DEPTH)); + } + + /** + * Tests the {@link VerticalDatumTypes#fromMethod(String)} method + * with names from the <abbr>EPSG</abbr> database. + */ + @Test + public void testFromMethod() { + assertEquals(RealizationMethod .LEVELLING, VerticalDatumTypes.fromMethod("Levelling-based")); + assertEquals(RealizationMethod .GEOID, VerticalDatumTypes.fromMethod("Geoid-based")); + assertEquals(RealizationMethod .TIDAL, VerticalDatumTypes.fromMethod("Tidal")); + assertEquals(VerticalDatumTypes.LOCAL, VerticalDatumTypes.fromMethod("Local").name()); } /**