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 88c4efc2c7686f7aab2592570a08d70fd8378e96 Merge: cb32b1b2f0 788778542c Author: Martin Desruisseaux <[email protected]> AuthorDate: Mon Jul 21 10:24:41 2025 +0200 Merge branch 'geoapi-4.0' into geoapi-3.1. Contains work in preparation to upgrade of the EPSG database and improvement in the handling of CRS of geometries of features. .../org/apache/sis/coverage/SampleDimension.java | 10 +- .../org/apache/sis/coverage/grid/GridCoverage.java | 2 +- .../org/apache/sis/feature/AbstractFeature.java | 55 +- .../main/org/apache/sis/feature/DenseFeature.java | 35 +- .../org/apache/sis/feature/EnvelopeOperation.java | 2 +- .../main/org/apache/sis/feature/Features.java | 14 +- .../main/org/apache/sis/feature/SparseFeature.java | 35 +- .../sis/feature/privy/AttributeConvention.java | 57 +- .../apache/sis/filter/BinaryGeometryFilter.java | 34 +- .../org/apache/sis/filter/BinarySpatialFilter.java | 5 +- .../main/org/apache/sis/filter/DistanceFilter.java | 5 +- .../apache/sis/filter/InvalidXPathException.java | 2 +- .../sis/filter/internal/GeometryConverter.java | 50 +- .../sis/filter/internal/GeometryFromFeature.java | 108 +++ .../main/org/apache/sis/filter/internal/Node.java | 38 +- .../apache/sis/filter/sqlmm/FunctionWithSRID.java | 4 +- .../apache/sis/filter/sqlmm/GeometryParser.java | 3 +- .../org/apache/sis/filter/sqlmm/ST_Transform.java | 6 +- .../apache/sis/geometry/wrapper/Geometries.java | 74 +- .../sis/geometry/wrapper/GeometryWithCRS.java | 92 --- .../sis/geometry/wrapper/GeometryWrapper.java | 316 ++++---- .../apache/sis/geometry/wrapper/esri/Wrapper.java | 3 +- .../apache/sis/geometry/wrapper/j2d/Factory.java | 2 +- .../sis/geometry/wrapper/j2d/PointWrapper.java | 13 +- .../apache/sis/geometry/wrapper/j2d/Wrapper.java | 8 +- .../apache/sis/geometry/wrapper/jts/Factory.java | 28 +- .../org/apache/sis/geometry/wrapper/jts/JTS.java | 45 +- .../apache/sis/geometry/wrapper/jts/Wrapper.java | 79 +- .../main/org/apache/sis/image/PixelIterator.java | 6 +- .../apache/sis/image/privy/ColorModelFactory.java | 3 + .../apache/sis/image/privy/ColorScaleBuilder.java | 17 +- .../feature/builder/AttributeTypeBuilderTest.java | 2 +- .../sis/feature/privy/AttributeConventionTest.java | 9 +- .../apache/sis/geometry/wrapper/jts/JTSTest.java | 6 +- .../org/apache/sis/metadata/MetadataStandard.java | 67 +- .../org/apache/sis/metadata/PropertyAccessor.java | 4 +- .../sis/metadata/StandardImplementation.java | 3 +- .../main/org/apache/sis/metadata/TreeNode.java | 2 +- .../org/apache/sis/metadata/TreeNodeChildren.java | 2 +- .../apache/sis/metadata/internal/ExcludedSet.java | 6 +- .../apache/sis/metadata/privy/SecondaryTrait.java | 45 ++ .../apache/sis/metadata/sql/MetadataSource.java | 6 +- .../org/apache/sis/metadata/sql/privy/Dialect.java | 20 +- .../apache/sis/metadata/sql/privy/Reflection.java | 2 - .../apache/sis/metadata/sql/privy/SQLBuilder.java | 59 +- .../sis/metadata/sql/privy/SQLUtilities.java | 9 +- .../sis/metadata/sql/privy/ScriptRunner.java | 15 +- .../apache/sis/metadata/sql/privy/Supports.java | 12 +- .../org/apache/sis/metadata/sql/privy/Syntax.java | 76 +- .../org/apache/sis/portrayal/CanvasContext.java | 8 +- .../org/apache/sis/geometry/CoordinateFormat.java | 4 +- .../main/org/apache/sis/io/wkt/VerticalInfo.java | 4 +- .../main/org/apache/sis/referencing/CRS.java | 7 +- .../main/org/apache/sis/referencing/CommonCRS.java | 6 +- .../apache/sis/referencing/GeodeticCalculator.java | 9 +- .../sis/referencing/MultiRegisterOperations.java | 4 +- .../sis/referencing/crs/AbstractSingleCRS.java | 37 +- .../sis/referencing/crs/DefaultGeographicCRS.java | 6 +- .../sis/referencing/crs/DefaultTemporalCRS.java | 4 +- .../sis/referencing/crs/ExplicitParameters.java | 4 +- .../sis/referencing/datum/DatumOrEnsemble.java | 456 +++++++++++ .../referencing/datum/DefaultDatumEnsemble.java | 674 +++++++++++++++- .../referencing/datum/DefaultPrimeMeridian.java | 2 +- .../apache/sis/referencing/datum/PseudoDatum.java | 885 --------------------- .../referencing/factory/GeodeticObjectFactory.java | 2 +- .../referencing/factory/sql/EPSGCodeFinder.java | 10 +- .../referencing/factory/sql/EPSGDataAccess.java | 176 ++-- .../sis/referencing/factory/sql/EPSGFactory.java | 24 +- .../sis/referencing/factory/sql/EPSGInstaller.java | 34 +- .../sis/referencing/factory/sql/EPSG_Prepare.sql | 18 +- .../sis/referencing/factory/sql/EPSG_README.md | 15 +- .../factory/sql/InstallationScriptProvider.java | 102 ++- .../sis/referencing/factory/sql/SQLTranslator.java | 385 +++++---- .../sis/referencing/factory/sql/TableInfo.java | 69 +- .../sis/referencing/factory/sql/package-info.java | 4 +- .../internal/ParameterizedTransformBuilder.java | 6 +- .../apache/sis/referencing/internal/Resources.java | 2 +- .../sis/referencing/internal/Resources.properties | 2 +- .../referencing/internal/Resources_fr.properties | 2 +- .../referencing/internal/SignReversalComment.java | 4 +- .../operation/CoordinateOperationFinder.java | 31 +- .../operation/CoordinateOperationRegistry.java | 6 +- .../operation/DefaultConcatenatedOperation.java | 4 +- .../referencing/operation/DefaultConversion.java | 3 +- .../DefaultCoordinateOperationFactory.java | 4 +- .../referencing/operation/SubOperationInfo.java | 1 + .../referencing/operation/gridded/GridFile.java | 8 +- .../sis/referencing/operation/matrix/Matrix1.java | 13 + .../sis/referencing/operation/matrix/Matrix2.java | 37 + .../sis/referencing/operation/matrix/Matrix3.java | 18 + .../sis/referencing/operation/matrix/Matrix4.java | 20 + .../referencing/operation/matrix/MatrixSIS.java | 8 +- .../operation/provider/AbstractProvider.java | 8 +- .../provider/FranceGeocentricInterpolation.java | 2 + .../sis/referencing/operation/provider/NADCON.java | 2 + .../sis/referencing/operation/provider/NTv2.java | 2 + .../operation/transform/AbstractMathTransform.java | 2 +- .../transform/DefaultMathTransformFactory.java | 6 +- .../operation/transform/TransformSeparator.java | 10 +- .../sis/referencing/privy/AffineTransform2D.java | 10 +- .../sis/referencing/privy/DefinitionVerifier.java | 38 +- .../privy/EllipsoidalHeightCombiner.java | 4 +- .../referencing/privy/ReferencingUtilities.java | 90 --- .../apache/sis/referencing/privy/WKTUtilities.java | 6 +- .../sis/io/wkt/GeodeticObjectParserTest.java | 2 +- .../sis/referencing/GeodesicsOnEllipsoidTest.java | 4 +- .../referencing/factory/sql/EPSGInstallerTest.java | 12 +- .../sis/referencing/factory/sql/TableInfoTest.java | 7 +- .../transform/InterpolatedTransformTest.java | 2 +- .../main/org/apache/sis/storage/landsat/Band.java | 13 +- .../sis/storage/geotiff/CompressedSubset.java | 23 +- .../org/apache/sis/storage/geotiff/DataCube.java | 19 +- .../org/apache/sis/storage/geotiff/DataSubset.java | 26 +- .../sis/storage/geotiff/ImageFileDirectory.java | 110 ++- .../apache/sis/storage/geotiff/inflater/LZW.java | 3 +- .../sis/storage/geotiff/reader/CRSBuilder.java | 6 +- .../sis/storage/geotiff/writer/GeoEncoder.java | 6 +- .../sis/storage/netcdf/base/FeatureSetTest.java | 6 +- .../apache/sis/storage/sql/feature/Analyzer.java | 5 +- .../apache/sis/storage/sql/feature/Database.java | 6 +- .../sis/storage/sql/feature/FeatureAdapter.java | 4 +- .../sis/storage/sql/feature/FeatureIterator.java | 4 +- .../sis/storage/sql/feature/FeatureStream.java | 34 +- .../sis/storage/sql/feature/InfoStatements.java | 17 +- .../sis/storage/sql/postgis/ExtentEstimator.java | 6 +- .../apache/sis/storage/sql/postgis/Postgres.java | 2 +- .../storage/sql/feature/GeometryGetterTest.java | 8 +- .../apache/sis/storage/base/TiledGridCoverage.java | 55 +- .../apache/sis/storage/base/TiledGridResource.java | 25 +- .../main/org/apache/sis/storage/csv/Store.java | 4 +- .../sis/storage/modifier/CoverageModifier.java | 103 ++- .../main/org/apache/sis/system/DataDirectory.java | 2 +- .../sis/util/privy/UnmodifiableArrayList.java | 2 +- .../org/apache/sis/util/CharSequencesTest.java | 63 +- .../org.apache.sis.geometries.processor.Processor | 28 + .../org/apache/sis/geometries/AttributesType.java | 6 +- .../main/org/apache/sis/geometries/BBox.java | 19 +- ...DefaultMultiPolygon.java => CompoundCurve.java} | 14 +- .../main/org/apache/sis/geometries/Geometries.java | 21 +- .../org/apache/sis/geometries/GeometryFactory.java | 105 +++ .../main/org/apache/sis/geometries/LineString.java | 10 +- .../main/org/apache/sis/geometries/LinearRing.java | 1 + .../main/org/apache/sis/geometries/MultiCurve.java | 1 + .../org/apache/sis/geometries/MultiLineString.java | 1 + .../main/org/apache/sis/geometries/MultiPoint.java | 1 + .../org/apache/sis/geometries/MultiPolygon.java | 2 + ...DefaultLineString.java => MultiPolyhedron.java} | 21 +- .../org/apache/sis/geometries/MultiSurface.java | 1 + .../main/org/apache/sis/geometries/OBBox.java | 3 +- .../main/org/apache/sis/geometries/Point.java | 3 +- .../org/apache/sis/geometries/PointSequence.java | 32 +- .../main/org/apache/sis/geometries/Polygon.java | 2 + .../main/org/apache/sis/geometries/Polyhedron.java | 63 ++ .../org/apache/sis/geometries/PreparedTIN.java | 11 +- .../sis/geometries/{LinearRing.java => Prism.java} | 38 +- .../main/org/apache/sis/geometries/Sphere.java | 3 +- .../main/org/apache/sis/geometries/TIN.java | 1 + .../main/org/apache/sis/geometries/Triangle.java | 22 +- .../CircularString.java} | 17 +- .../sis/geometries/math/AbstractTupleArray.java | 37 - .../org/apache/sis/geometries/math/Matrix.java | 5 +- .../org/apache/sis/geometries/math/Matrix2D.java | 50 +- .../org/apache/sis/geometries/math/Matrix3D.java | 42 +- .../org/apache/sis/geometries/math/Matrix4D.java | 40 +- .../org/apache/sis/geometries/math/MatrixND.java | 44 - .../main/org/apache/sis/geometries/math/Tuple.java | 46 +- .../org/apache/sis/geometries/math/TupleArray.java | 2 +- .../apache/sis/geometries/math/TupleArrays.java | 95 ++- .../sis/geometries/math/TupleUnmodifiable.java | 15 - .../org/apache/sis/geometries/math/Vectors.java | 111 ++- .../sis/geometries/{ => mesh}/MeshPrimitive.java | 41 +- .../{ => mesh}/MeshPrimitiveComparator.java | 9 +- .../{ => mesh}/MeshPrimitiveIndexes.java | 2 +- .../{ => mesh}/MeshPrimitiveVisitor.java | 12 +- .../geometries/{ => mesh}/MultiMeshPrimitive.java | 5 +- .../geometries/operation/GeometryOperations.java | 4 +- .../operation/spatialanalysis2d/ISOBand.java | 16 +- .../operation/spatialanalysis2d/ISOLine.java | 10 +- .../operation/spatialanalysis2d/IsoInclusion.java | 2 +- .../org/apache/sis/geometries/package-info.java | 2 + .../geometries/{ => privy}/AbstractGeometry.java | 10 +- .../sis/geometries/{ => privy}/ArraySequence.java | 13 +- .../{ => privy}/DefaultGeometryCollection.java | 4 +- .../geometries/{ => privy}/DefaultLineString.java | 5 +- .../geometries/{ => privy}/DefaultLinearRing.java | 5 +- .../DefaultMultiCurve.java} | 8 +- .../{ => privy}/DefaultMultiLineString.java | 7 +- .../geometries/{ => privy}/DefaultMultiPoint.java | 6 +- .../{ => privy}/DefaultMultiPolygon.java | 5 +- .../{ => privy}/DefaultMultiSurface.java | 4 +- .../sis/geometries/{ => privy}/DefaultPoint.java | 5 +- .../{ => privy}/DefaultPointSequence.java | 5 +- .../sis/geometries/{ => privy}/DefaultPolygon.java | 6 +- .../geometries/{ => privy}/DefaultTriangle.java | 5 +- .../processor/spatialanalysis2d/Intersection.java | 15 +- .../processor/spatialedition/ComputeAttribute.java | 28 +- .../geometries/processor/spatialedition/To3D.java | 35 +- .../processor/spatialedition/ToPrimitive.java | 50 +- .../processor/spatialedition/Transform.java | 112 ++- .../simplify/greedyinsert/TINBuilder.java | 10 +- .../simplify/greedyinsert/WTriangle.java | 6 +- .../sis/geometries/triangulate/EarClipping.java | 2 +- .../geometries/triangulate/delaunay/Delaunay.java | 4 +- .../triangulate/delaunay/OrientedEdge.java | 6 +- .../triangulate/delaunay/OrientedTriangle.java | 10 +- .../org/apache/sis/geometries/GeometriesTest.java | 170 ---- .../org/apache/sis/geometries/PreparedTINTest.java | 1 + .../org/apache/sis/geometries/PrimitiveTest.java | 64 -- .../org/apache/sis/geometries/TriangleTest.java | 6 +- .../sis/geometries/math/AbstractTupleTest.java | 38 - .../apache/sis/geometries/math/VectorsTest.java | 8 +- .../{ => mesh}/PrimitiveIndexesTest.java | 4 +- .../PrimitiveTest.java} | 67 +- .../{ => mesh}/PrimitiveVisitorTest.java | 9 +- .../operation/spatialanalysis2d/IsoBandTest.java | 2 +- .../geometries/{ => privy}/ArraySequenceTest.java | 4 +- .../processor/spatialanalysis2d/DistanceTest.java | 14 +- .../spatialanalysis2d/IntersectionTest.java | 2 +- .../processor/spatialedition/To3DTest.java | 2 +- .../processor/spatialedition/ToPrimitiveTest.java | 48 +- .../processor/spatialedition/TransformTest.java | 4 +- .../triangulate/delaunay/DelaunayTest.java | 4 +- .../triangulate/delaunay/OrientedEdgeTest.java | 4 +- .../sis/storage/geopackage/GpkgStoreTest.java | 2 +- .../sis/storage/shapefile/ShapefileStore.java | 21 +- .../sis/storage/shapefile/ShapefileStoreTest.java | 4 + netbeans-project/nbproject/project.xml | 1 + .../main/org/apache/sis/gui/map/StatusBar.java | 55 +- .../org/apache/sis/gui/map/ValuesFormatter.java | 25 +- .../org/apache/sis/gui/map/ValuesFromCoverage.java | 9 +- .../sis/referencing/factory/sql/epsg/README.md | 25 +- .../factory/sql/epsg/DataScriptFormatter.java | 30 +- .../sis/referencing/factory/sql/epsg/README.md | 87 +- .../factory/sql/epsg/ScriptProviderTest.java | 2 +- 234 files changed, 4169 insertions(+), 3298 deletions(-) diff --cc endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/Geometries.java index facdd123be,00c44ba879..d65ca53799 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/Geometries.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/Geometries.java @@@ -38,9 -39,13 +39,13 @@@ import org.apache.sis.system.Loggers import org.apache.sis.math.Vector; import org.apache.sis.setup.GeometryLibrary; import org.apache.sis.util.resources.Errors; + import org.apache.sis.util.collection.BackingStoreException; + + // Specific to the geoapi-3.1 and 4.0 branches: + import org.opengis.feature.Feature; -// Specific to the geoapi-4.0 branch: -import org.opengis.coordinate.MismatchedDimensionException; +// Specific to the main and geoapi-3.1 branches: +import org.opengis.geometry.MismatchedDimensionException; /** diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java index 4eceaac3c7,9941694085..f81040f0f3 --- 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 @@@ -339,7 -336,7 +339,7 @@@ public class DefaultTemporalCRS extend * @since 1.5 */ public final Temporal getOrigin() { // Must be final because invoked at construction time. - return TemporalDate.toTemporal(PseudoDatum.of(this).getOrigin()); - return DatumOrEnsemble.asDatum(this).getOrigin(); ++ return TemporalDate.toTemporal(DatumOrEnsemble.asDatum(this).getOrigin()); } /** diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/ExplicitParameters.java index 1a3266fe08,f49c4ab2eb..b052185510 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/ExplicitParameters.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/ExplicitParameters.java @@@ -58,9 -58,9 +58,9 @@@ final class ExplicitParameters extends /** * Creates a new temporary {@code Conversion} elements for the parameters of the given CRS. */ - ExplicitParameters(final AbstractDerivedCRS crs, final String keyword) { + ExplicitParameters(final AbstractDerivedCRS<?> crs, final String keyword) { conversion = crs.getConversionFromBase(); - ellipsoid = ReferencingUtilities.getEllipsoid(crs); + ellipsoid = DatumOrEnsemble.getEllipsoid(crs).orElse(null); this.keyword = keyword; } diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java index ebffe6fdfe,1e831e468d..1dfbebbb57 --- 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 @@@ -32,9 -51,11 +51,14 @@@ import org.apache.sis.util.ComparisonMo import org.apache.sis.util.Utilities; import org.apache.sis.util.resources.Errors; ++// Specific to the main and geoapi-3.1 branches: ++import java.util.Date; ++ // Specific to the geoapi-3.1 and geoapi-4.0 branches: - import java.util.Objects; + import org.opengis.referencing.crs.ParametricCRS; import org.opengis.referencing.datum.DatumEnsemble; + import org.opengis.referencing.datum.ParametricDatum; + import org.opengis.referencing.datum.RealizationMethod; /** @@@ -283,4 -473,397 +476,397 @@@ check: if (it.hasNext()) } return WKTKeywords.Ensemble; } + + /** + * An ensemble viewed as a low-accuracy geodetic datum. + * + * @see #create(Map, Collection, PositionalAccuracy) + * @see #castOrCopy(DatumEnsemble) + * @see DatumOrEnsemble#of(GeodeticCRS) + * @see DatumOrEnsemble#asTargetDatum(GeodeticCRS, GeodeticCRS) + */ + static final class Geodetic extends DefaultDatumEnsemble<GeodeticDatum> implements GeodeticDatum { + /** For cross-versions compatibility. */ + private static final long serialVersionUID = 7669230365507661290L; + + /** Returns the given ensemble as a pseudo-datum. */ + static GeodeticDatum datum(DatumEnsemble<GeodeticDatum> ensemble) { + return (ensemble == null || ensemble instanceof GeodeticDatum) + ? (GeodeticDatum) ensemble : new Geodetic(ensemble); + } + + /** Creates a new ensemble as a copy of the given ensemble. */ + Geodetic(DatumEnsemble<? extends GeodeticDatum> ensemble) { + super(ensemble, GeodeticDatum.class); + } + + /** Creates a new ensemble from the given properties. */ + Geodetic(Map<String,?> properties, List<? extends GeodeticDatum> members, PositionalAccuracy accuracy) { + super(properties, members, accuracy, GeodeticDatum.class); + } + + /** + * Returns the ellipsoid which is indirectly (through a datum) associated to this datum ensemble. + * If all members of the ensemble use the same ellipsoid, then this method returns that ellipsoid. + * + * @return the ellipsoid indirectly associated to this datum ensemble. + * @throws NoSuchElementException if the ensemble does not contain at least one member. + * @throws GeodeticException if the ellipsoid is not the same for all members of the datum ensemble. + */ + @Override + public Ellipsoid getEllipsoid() { + return getCommonMandatoryValue(GeodeticDatum::getEllipsoid); + } + + /** + * Returns the prime meridian which is indirectly (through a datum) associated to this datum ensemble. + * If all members of the ensemble use the same prime meridian, then this method returns that meridian. + * + * @return the prime meridian indirectly associated to this datum ensemble. + * @throws NoSuchElementException if the ensemble does not contain at least one member. + * @throws GeodeticException if the prime meridian is not the same for all members of the datum ensemble. + */ + @Override + public PrimeMeridian getPrimeMeridian() { + return getCommonMandatoryValue(GeodeticDatum::getPrimeMeridian); + } + } + + /** + * An ensemble viewed as a low-accuracy vertical datum. + * + * @see #create(Map, Collection, PositionalAccuracy) + * @see #castOrCopy(DatumEnsemble) + * @see DatumOrEnsemble#of(VerticalCRS) + * @see DatumOrEnsemble#asTargetDatum(VerticalCRS, VerticalCRS) + */ + static final class Vertical extends DefaultDatumEnsemble<VerticalDatum> implements VerticalDatum { + /** For cross-versions compatibility. */ + private static final long serialVersionUID = 7242417944400289818L; + + /** Returns the given ensemble as a pseudo-datum. */ + static VerticalDatum datum(DatumEnsemble<VerticalDatum> ensemble) { + return (ensemble == null || ensemble instanceof VerticalDatum) + ? (VerticalDatum) ensemble : new Vertical(ensemble); + } + + /** Creates a new ensemble as a copy of the given ensemble. */ + Vertical(DatumEnsemble<? extends VerticalDatum> ensemble) { + super(ensemble, VerticalDatum.class); + } + + /** Creates a new ensemble from the given properties. */ + Vertical(Map<String,?> properties, List<? extends VerticalDatum> members, PositionalAccuracy accuracy) { + super(properties, members, accuracy, VerticalDatum.class); + } + + /** + * Returns a realization method 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 has an empty value, + * then this method returns an empty value. + * + * @return the common realization method, or empty if there is no common value. + */ + @Override + public Optional<RealizationMethod> getRealizationMethod() { + return getCommonOptionalValue(VerticalDatum::getRealizationMethod); + } + } + + /** + * An ensemble viewed as a low-accuracy temporal datum. + * + * @see #create(Map, Collection, PositionalAccuracy) + * @see #castOrCopy(DatumEnsemble) + * @see DatumOrEnsemble#of(TemporalCRS) + * @see DatumOrEnsemble#asTargetDatum(TemporalCRS, TemporalCRS) + */ + static final class Time extends DefaultDatumEnsemble<TemporalDatum> implements TemporalDatum { + /** For cross-versions compatibility. */ + private static final long serialVersionUID = -4208563828181087035L; + + /** Returns the given ensemble as a pseudo-datum. */ + static TemporalDatum datum(DatumEnsemble<TemporalDatum> ensemble) { + return (ensemble == null || ensemble instanceof TemporalDatum) + ? (TemporalDatum) ensemble : new Time(ensemble); + } + + /** Creates a new ensemble as a copy of the given ensemble. */ + Time(DatumEnsemble<? extends TemporalDatum> ensemble) { + super(ensemble, TemporalDatum.class); + } + + /** Creates a new ensemble from the given properties. */ + Time(Map<String,?> properties, List<? extends TemporalDatum> members, PositionalAccuracy accuracy) { + super(properties, members, accuracy, TemporalDatum.class); + } + + /** + * Returns the temporal origin which is indirectly (through a datum) associated to this datum ensemble. + * If all members of the ensemble use the same temporal origin, then this method returns that origin. + * + * @return the temporal origin indirectly associated to this datum ensemble. + * @throws NoSuchElementException if the ensemble does not contain at least one member. + * @throws GeodeticException if the temporal origin is not the same for all members of the datum ensemble. + */ + @Override - public Temporal getOrigin() { ++ public Date getOrigin() { + return getCommonMandatoryValue(TemporalDatum::getOrigin); + } + } + + /** + * An ensemble viewed as a low-accuracy parametric datum. + * + * @see #create(Map, Collection, PositionalAccuracy) + * @see #castOrCopy(DatumEnsemble) + * @see DatumOrEnsemble#of(ParametricCRS) + * @see DatumOrEnsemble#asTargetDatum(ParametricCRS, ParametricCRS) + */ + static final class Parametric extends DefaultDatumEnsemble<ParametricDatum> implements ParametricDatum { + /** For cross-versions compatibility. */ + private static final long serialVersionUID = -8277774591738789437L; + + /** Returns the given ensemble as a pseudo-datum. */ + static ParametricDatum datum(DatumEnsemble<ParametricDatum> ensemble) { + return (ensemble == null || ensemble instanceof ParametricDatum) + ? (ParametricDatum) ensemble : new Parametric(ensemble); + } + + /** Creates a new ensemble as a copy of the given ensemble. */ + Parametric(DatumEnsemble<? extends ParametricDatum> ensemble) { + super(ensemble, ParametricDatum.class); + } + + /** Creates a new ensemble from the given properties. */ + Parametric(Map<String,?> properties, List<? extends ParametricDatum> members, PositionalAccuracy accuracy) { + super(properties, members, accuracy, ParametricDatum.class); + } + } + + /** + * An ensemble viewed as a low-accuracy engineering datum. + * + * @see #create(Map, Collection, PositionalAccuracy) + * @see #castOrCopy(DatumEnsemble) + * @see DatumOrEnsemble#of(EngineeringCRS) + * @see DatumOrEnsemble#asTargetDatum(EngineeringCRS, EngineeringCRS) + */ + static final class Engineering extends DefaultDatumEnsemble<EngineeringDatum> implements EngineeringDatum { + /** For cross-versions compatibility. */ + private static final long serialVersionUID = -8978468990963666861L; + + /** Returns the given ensemble as a pseudo-datum. */ + static EngineeringDatum datum(DatumEnsemble<EngineeringDatum> ensemble) { + return (ensemble == null || ensemble instanceof EngineeringDatum) + ? (EngineeringDatum) ensemble : new Engineering(ensemble); + } + + /** Creates a new ensemble as a copy of the given ensemble. */ + Engineering(DatumEnsemble<? extends EngineeringDatum> ensemble) { + super(ensemble, EngineeringDatum.class); + } + + /** Creates a new ensemble from the given properties. */ + Engineering(Map<String,?> properties, List<? extends EngineeringDatum> members, PositionalAccuracy accuracy) { + super(properties, members, accuracy, EngineeringDatum.class); + } + } + + /** + * Factory methods for finding the base type of all members of a list and instantiate + * the {@link DefaultDatumEnsemble} subclass corresponding to the type of all members. + * Each instance of {@code Factory} is immutable and thread-safe. + * There is one instance for each supported type. + * + * @param <D> base type of all members in the ensembles constructed by this factory instance. + * + * @see #create(Map, Collection, PositionalAccuracy) + * @see #castOrCopy(DatumEnsemble) + */ + private static abstract class Factory<D extends Datum> { + /** + * Base type of all members in the ensembles constructed by this factory instance. + */ + private final Class<D> type; + + /** + * Creates a new factory for ensembles in which all members are instances of the given type. + * + * @param type base type of all members in the ensembles constructed by this factory instance. + */ + private Factory(final Class<D> type) { + this.type = type; + } + + /** + * Finds a common type for all members in the given list, then creates a datum ensemble of that type. + * In principle, the {@code <D>} type should be restricted to one of the types hard-coded in this class. + * However, it is okay if {@code <D>} is a custom subclass because it appears only in the following places: + * + * <ul> + * <li>{@link #getMembers()}, which is a read-only collection (it is safe to cast {@code List<? extends D>} + * as {@code List<D>} when no write operation is allowed).</li> + * </ul> + * + * Exactly one of {@code object} and {@code properties} should be non-null. + * + * @param <D> base type of all members in the ensembles to create. + * @param object the source ensemble to copy, or {@code null} if none. + * @param properties the properties of the ensemble to create, or {@code null}. + * @param members members of the ensemble to copy or create. + * @param accuracy inaccuracy of the ensemble. Mandatory if {@code properties} is non-null. + * @return the copied or created ensemble. + * @throws ClassCastException if at least one member is not a {@link Datum}. + * Should never happen if the parameterized type of {@code members} is respected. + */ + static <D extends Datum> DefaultDatumEnsemble<D> forMemberType( + final DatumEnsemble<? extends D> object, + final Map<String,?> properties, + final List<? extends D> members, + final PositionalAccuracy accuracy) + { + nextType: for (final Factory<?> factory : FACTORIES) { + for (final Object member : members) { + if (!factory.type.isInstance(member)) { + continue nextType; + } + } + /* + * A more correct type would be `Factory<? super D>` because of the use of `isInstance(member)` + * instead of strict class equality. However, even `? super D` is not guaranteed to be correct, + * because nothing prevent a member from implementing two interfaces. In such case, the type of + * the first matching factory could be unrelated to `D` (e.g., `D` is `ParametricDatum` but all + * members also implement `VerticalDatum`). However, despite this uncertainty, the cast is okay + * because `D` appears only in `getMembers()` which returns a read-only collection. There is no + * method returning `Class<D>` and no guarantees that the returned object will implement `D`. + */ + @SuppressWarnings("unchecked") + final var selected = (Factory<D>) factory; // See above comment. + if (object != null) { + return selected.copy(object); + } else { + return selected.create(properties, members, accuracy); + } + } + throw new ClassCastException(); + } + + /** + * Creates a new ensemble of the type associated with this factory instance. + * + * @param properties the properties to be given to the identified object. + * @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. + * @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) + */ + abstract DefaultDatumEnsemble<D> create(Map<String,?> properties, List<? extends D> members, PositionalAccuracy accuracy); + + /** + * Creates a new ensemble with the same values as the specified one. + * + * @param ensemble the ensemble to copy. + * @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 #castOrCopy(DatumEnsemble) + */ + abstract DefaultDatumEnsemble<D> copy(DatumEnsemble<? extends D> object); + + /** + * Factories for all datum types supported by this class. The types are (in order) {@link GeodeticDatum}, + * {@link VerticalDatum}, {@link TemporalDatum}, {@link ParametricDatum} and {@link EngineeringDatum}. + * The types are tested in iteration order. For example, if a member implements both {@code VerticalDatum} + * {@code ParametricDatum} interface, then {@code VerticalDatum} has precedence. + */ + private static final Factory<?>[] FACTORIES = { + new Factory<GeodeticDatum>(GeodeticDatum.class) { + @Override + DefaultDatumEnsemble<GeodeticDatum> copy(DatumEnsemble<? extends GeodeticDatum> object) { + return new Geodetic(object); + } + + @Override + DefaultDatumEnsemble<GeodeticDatum> create(Map<String,?> properties, + List<? extends GeodeticDatum> members, PositionalAccuracy accuracy) + { + return new Geodetic(properties, members, accuracy); + } + }, + + new Factory<VerticalDatum>(VerticalDatum.class) { + @Override + DefaultDatumEnsemble<VerticalDatum> copy(DatumEnsemble<? extends VerticalDatum> object) { + return new Vertical(object); + } + + @Override + DefaultDatumEnsemble<VerticalDatum> create(Map<String,?> properties, + List<? extends VerticalDatum> members, PositionalAccuracy accuracy) + { + return new Vertical(properties, members, accuracy); + } + }, + + new Factory<TemporalDatum>(TemporalDatum.class) { + @Override + DefaultDatumEnsemble<TemporalDatum> copy(DatumEnsemble<? extends TemporalDatum> object) { + return new Time(object); + } + + @Override + DefaultDatumEnsemble<TemporalDatum> create(Map<String,?> properties, + List<? extends TemporalDatum> members, PositionalAccuracy accuracy) + { + return new Time(properties, members, accuracy); + } + }, + + new Factory<ParametricDatum>(ParametricDatum.class) { + @Override + DefaultDatumEnsemble<ParametricDatum> copy(DatumEnsemble<? extends ParametricDatum> object) { + return new Parametric(object); + } + + @Override + DefaultDatumEnsemble<ParametricDatum> create(Map<String,?> properties, + List<? extends ParametricDatum> members, PositionalAccuracy accuracy) + { + return new Parametric(properties, members, accuracy); + } + }, + + new Factory<EngineeringDatum>(EngineeringDatum.class) { + @Override + DefaultDatumEnsemble<EngineeringDatum> copy(DatumEnsemble<? extends EngineeringDatum> object) { + return new Engineering(object); + } + + @Override + DefaultDatumEnsemble<EngineeringDatum> create(Map<String,?> properties, + List<? extends EngineeringDatum> members, PositionalAccuracy accuracy) + { + return new Engineering(properties, members, accuracy); + } + }, + + new Factory<Datum>(Datum.class) { + @Override + DefaultDatumEnsemble<Datum> copy(DatumEnsemble<? extends Datum> object) { + return new DefaultDatumEnsemble<>(object, Datum.class); + } + + @Override + DefaultDatumEnsemble<Datum> create(Map<String,?> properties, + List<? extends Datum> members, PositionalAccuracy accuracy) + { + return new DefaultDatumEnsemble<>(properties, members, accuracy, Datum.class); + } + } + }; + } } diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/TableInfo.java index 2e5cbb01d9,f632440ebb..e032777c6a --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/TableInfo.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/TableInfo.java @@@ -26,10 -26,13 +26,10 @@@ import org.opengis.parameter.ParameterD import org.apache.sis.referencing.privy.WKTKeywords; import org.apache.sis.util.CharSequences; -// Specific to the geoapi-4.0 branch: -import org.apache.sis.referencing.crs.DefaultGeocentricCRS; - /** - * Information about a specific table. The MS-Access dialect of SQL is assumed; - * it will be translated into ANSI SQL later by {@link SQLTranslator#apply(String)} if needed. + * Information about a specific table. This class uses the mixed-case variant of the <abbr>EPSG</abbr> table names. + * If needed, those names will be converted by {@link SQLTranslator#apply(String)} to the actual table names. * * @author Martin Desruisseaux (IRD, Geomatys) */ @@@ -61,11 -64,16 +61,11 @@@ final class TableInfo * {@link EPSGDataAccess#createUnit(String)} * * The order is significant: it is the key for a {@code switch} statement. - * - * <h4>Ambiguity</h4> - * As of ISO 19111:2019, we have no standard way to identify the geocentric case from a {@link Class} argument - * because the standard does not provide the {@code GeocentricCRS} interface. This implementation fallbacks on - * the SIS-specific geocentric CRS class, with a {@link #where(IdentifiedObject, StringBuilder)} method which - * will substitute implementation-neutral objects by the Apache SIS class. */ + @SuppressWarnings("deprecation") static final TableInfo[] EPSG = { CRS = new TableInfo(CoordinateReferenceSystem.class, - "[Coordinate Reference System]", + "\"Coordinate Reference System\"", "COORD_REF_SYS_CODE", "COORD_REF_SYS_NAME", "COORD_REF_SYS_KIND", diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/DefinitionVerifier.java index 5d531c0e2f,bb84005056..ae75b10e61 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/DefinitionVerifier.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/DefinitionVerifier.java @@@ -305,10 -306,9 +306,10 @@@ public final class DefinitionVerifier /** * Returns a code indicating in which part the two given CRS differ. The given iterators usually iterate over * exactly one element, but may iterate over more elements if the CRS were instance of {@code CompoundCRS}. - * The returned value is one of {@link #METHOD}, {@link #CONVERSION}, {@link #CS}, {@link #DATUM}, - * {@link #PRIME_MERIDIAN}, {@link #ELLIPSOID} or {@link #OTHER} constants. + * The returned value is one of {@link #METHOD}, {@link #CONVERSION}, {@link #CS}, {@link #PRIME_MERIDIAN}, + * {@link #ELLIPSOID}, {@link #DATUM} or {@link #OTHER} constants. */ + @SuppressWarnings("deprecation") private static int diffCode(final Iterator<SingleCRS> authoritative, final Iterator<SingleCRS> given) { while (authoritative.hasNext() && given.hasNext()) { final SingleCRS crsA = authoritative.next(); diff --cc optional/src/org.apache.sis.referencing.epsg/test/org/apache/sis/referencing/factory/sql/epsg/README.md index ea9c066c1b,9e3fe552c7..8ccd767e75 --- a/optional/src/org.apache.sis.referencing.epsg/test/org/apache/sis/referencing/factory/sql/epsg/README.md +++ b/optional/src/org.apache.sis.referencing.epsg/test/org/apache/sis/referencing/factory/sql/epsg/README.md @@@ -85,25 -83,30 +83,30 @@@ Then open the `FKeys.sql` file for edit * At the end of all `ALTER TABLE` statement, append `ON UPDATE RESTRICT ON DELETE RESTRICT`. * Suppress trailing spaces and save. - In most cases this results in unmodified `FKeys.sql` file compared to the previous version. - + Usually, the above editions result in no change compared to the previous scripts (ignoring white spaces), + in which case the maintainer can just revert the changes in order to preserve the formatting. + However, if some changes are found in the schema, then hard-coded values in the `DataScriptFormatter` class may need + to be modified, in particular the `booleanColumnIndicesForTables` and `doubleColumnIndicesForTables` collections. - ### Main Execute the `main` method of the `org.apache.sis.referencing.factory.sql.epsg.DataScriptFormatter` class - located in the test directory of `sis-referencing` module - (adjust version numbers as needed; we may provide an easier way after migration to Jigsaw modules): + located in the test directory of the `org.apache.sis.non-free:sis-epsg` Maven sub-project. + Adjust version numbers as needed in the following commands: - ``` + ```bash cd _<path to SIS project directory>_ - mvn clean install + gradle clean test jar export CLASSPATH=~/.m2/repository/org/apache/derby/derby/10.14.2.0/derby-10.14.2.0.jar - export CLASSPATH=$PWD/core/sis-metadata/target/test-classes:$CLASSPATH - export CLASSPATH=$PWD/target/binaries/sis-referencing-1.x-SNAPSHOT.jar:$CLASSPATH - export CLASSPATH=$PWD/core/sis-metadata/target/test-classes:$CLASSPATH - export CLASSPATH=$PWD/core/sis-referencing/target/test-classes:$CLASSPATH - cd <path to local copy of http://svn.apache.org/repos/asf/sis/data/non-free/> - java org.apache.sis.referencing.factory.sql.epsg.DataScriptFormatter $EPSG_SCRIPTS/PostgreSQL_Data_Script.sql \ - sis-epsg/src/main/resources/org/apache/sis/referencing/factory/sql/epsg/Data.sql + export CLASSPATH=~/.m2/repository/javax/measure/unit-api/2.1.3/unit-api-2.1.3.jar:$CLASSPATH -export CLASSPATH=$PWD/geoapi/snapshot/geoapi/target/geoapi-4.0-SNAPSHOT.jar:$CLASSPATH ++export CLASSPATH=$PWD/geoapi/snapshot/geoapi/target/geoapi-3.1-SNAPSHOT.jar:$CLASSPATH + export CLASSPATH=$PWD/endorsed/build/libs/org.apache.sis.referencing.jar:$CLASSPATH + export CLASSPATH=$PWD/endorsed/build/libs/org.apache.sis.metadata.jar:$CLASSPATH + export CLASSPATH=$PWD/endorsed/build/libs/org.apache.sis.util.jar:$CLASSPATH + export CLASSPATH=$PWD/endorsed/build/classes/java/test/org.apache.sis.referencing:$CLASSPATH + export CLASSPATH=$PWD/endorsed/build/classes/java/test/org.apache.sis.metadata:$CLASSPATH + export CLASSPATH=$PWD/optional/build/classes/java/test/org.apache.sis.referencing.epsg:$CLASSPATH + + # From any directory + java org.apache.sis.referencing.factory.sql.epsg.DataScriptFormatter $EPSG_SCRIPTS/PostgreSQL_Data_Script.sql $NON_FREE_DIR/Data.sql ``` Run the tests. It it convenient to run `org.apache.sis.referencing.factory.sql.EPSGInstallerTest`
