You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2024/08/30 13:51:13 UTC
(sis) 01/01: Merge branch 'geoapi-3.1'.
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 589b2aa29aa3fa6a54142cb0d518992ec9cebcba
Merge: 4c46d7bb98 2563f4abe5
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Fri Aug 30 15:49:57 2024 +0200
Merge branch 'geoapi-3.1'.
buildSrc/build.gradle.kts | 4 +-
.../apache/sis/buildtools/gradle/Conventions.java | 3 +-
.../apache/sis/buildtools/gradle/Dependency.java | 5 +
.../sis/buildtools/gradle/ModularCompilation.java | 2 +-
.../org/apache/sis/buildtools/maven/Generator.java | 52 +-
.../apache/sis/coverage/grid/GridDerivation.java | 1 +
.../sis/coverage/privy/ColorModelFactory.java | 2 -
.../sis/feature/builder/AttributeTypeBuilder.java | 2 +-
.../apache/sis/geometry/wrapper/GeometryType.java | 178 +-
.../apache/sis/geometry/wrapper/esri/Factory.java | 2 +-
.../apache/sis/geometry/wrapper/j2d/Factory.java | 2 +-
.../sis/geometry/wrapper/GeometryTypeTest.java | 25 +-
.../org.apache.sis.metadata/main/module-info.java | 1 +
.../org/apache/sis/metadata/iso/ISOMetadata.java | 2 +-
.../iso/quality/DefaultQuantitativeResult.java | 2 +-
.../apache/sis/metadata/sql/MetadataWriter.java | 14 +-
.../org/apache/sis/metadata/sql/privy/Dialect.java | 81 +-
.../apache/sis/metadata/sql/privy/SQLBuilder.java | 40 +
.../sis/metadata/sql/privy/SQLUtilities.java | 22 +-
.../sis/metadata/sql/privy/ScriptRunner.java | 6 +-
.../apache/sis/metadata/sql/privy/Supports.java | 74 +
.../org/apache/sis/util/iso/DefaultScopedName.java | 5 +-
.../sis/metadata/sql/IdentifierGeneratorTest.java | 2 +-
.../org/apache/sis/metadata/sql/TestDatabase.java | 10 +-
.../gazetteer/ReferencingByIdentifiers.java | 6 +-
.../main/module-info.java | 1 +
.../org/apache/sis/geometry/ArrayEnvelope.java | 22 +-
.../org/apache/sis/geometry/DirectPosition1D.java | 2 +-
.../apache/sis/geometry/GeneralDirectPosition.java | 6 +-
.../main/org/apache/sis/io/wkt/Formatter.java | 5 +-
.../sis/parameter/DefaultParameterDescriptor.java | 3 +
.../parameter/DefaultParameterDescriptorGroup.java | 4 +
.../org/apache/sis/parameter/TensorValues.java | 6 +
.../sis/referencing/AbstractIdentifiedObject.java | 3 +
.../apache/sis/referencing/crs/AbstractCRS.java | 2 +
.../sis/referencing/crs/AbstractDerivedCRS.java | 6 +-
.../sis/referencing/crs/AbstractSingleCRS.java | 6 +-
.../sis/referencing/crs/DefaultCompoundCRS.java | 6 +-
.../sis/referencing/crs/DefaultDerivedCRS.java | 4 +-
.../sis/referencing/crs/DefaultProjectedCRS.java | 4 +-
.../org/apache/sis/referencing/cs/AbstractCS.java | 4 +
.../cs/DefaultCoordinateSystemAxis.java | 2 +
.../sis/referencing/datum/AbstractDatum.java | 65 +-
.../sis/referencing/datum/BursaWolfParameters.java | 20 +-
.../referencing/datum/DefaultDatumEnsemble.java | 5 +-
.../sis/referencing/datum/DefaultEllipsoid.java | 4 +
.../referencing/datum/DefaultGeodeticDatum.java | 159 +-
.../sis/referencing/datum/DefaultImageDatum.java | 4 +
.../referencing/datum/DefaultPrimeMeridian.java | 4 +
.../referencing/datum/DefaultTemporalDatum.java | 4 +
.../referencing/datum/DefaultVerticalDatum.java | 91 +
.../apache/sis/referencing/datum/PseudoDatum.java | 33 +-
.../sis/referencing/datum/TimeDependentBWP.java | 16 +-
.../referencing/factory/GeodeticObjectFactory.java | 70 +-
.../referencing/factory/sql/EPSGDataAccess.java | 14 +-
.../operation/AbstractCoordinateOperation.java | 2 +
.../operation/DefaultConcatenatedOperation.java | 6 +-
.../operation/DefaultOperationMethod.java | 2 +
.../operation/DefaultPassThroughOperation.java | 6 +-
.../operation/matrix/GeneralMatrix.java | 2 +-
.../operation/matrix/NonSquareMatrix.java | 2 +-
.../operation/transform/ConcatenatedTransform.java | 2 +-
.../operation/transform/CopyTransform.java | 2 +-
.../operation/transform/DatumShiftTransform.java | 6 +-
.../transform/EllipsoidToCentricTransform.java | 6 +-
.../transform/ExponentialTransform1D.java | 4 +-
.../operation/transform/InterpolatedTransform.java | 6 +-
.../operation/transform/LinearTransform1D.java | 4 +-
.../operation/transform/MolodenskyTransform.java | 6 +-
.../operation/transform/PassThroughTransform.java | 6 +-
.../operation/transform/PoleRotation.java | 4 +
.../operation/transform/PowerTransform1D.java | 4 +-
.../operation/transform/ProjectiveTransform.java | 4 +-
.../operation/transform/ScaleTransform.java | 4 +-
.../transform/SpecializableTransform.java | 9 +-
.../operation/transform/TranslationTransform.java | 4 +-
.../operation/transform/WraparoundTransform.java | 4 +
.../main/org/apache/sis/storage/landsat/Band.java | 2 +-
.../apache/sis/storage/landsat/LandsatStore.java | 7 +-
.../apache/sis/storage/landsat/package-info.java | 2 +-
.../apache/sis/storage/geotiff/GeoTiffStore.java | 6 +-
.../sis/storage/geotiff/GeoTiffStoreProvider.java | 8 +-
.../org/apache/sis/storage/geotiff/Writer.java | 5 +
.../apache/sis/storage/geotiff/package-info.java | 3 +-
.../sis/storage/geotiff/spi/SchemaModifier.java | 2 +-
.../storage/geotiff/writer/CompressionChannel.java | 6 +-
.../sis/storage/geotiff/writer/PixelChannel.java | 1 +
.../storage/geotiff/writer/PredictorChannel.java | 1 +
.../org/apache/sis/storage/geotiff/writer/ZIP.java | 1 +
.../org/apache/sis/storage/netcdf/NetcdfStore.java | 7 +-
.../apache/sis/storage/netcdf/package-info.java | 2 +-
.../main/module-info.java | 24 +-
.../org/apache/sis/storage/sql/DataAccess.java | 338 +++
.../apache/sis/storage/sql/ResourceDefinition.java | 47 +-
.../main/org/apache/sis/storage/sql/SQLStore.java | 503 +++-
.../apache/sis/storage/sql/SQLStoreProvider.java | 16 +-
.../apache/sis/storage/sql/SimpleFeatureStore.java | 168 ++
.../apache/sis/storage/sql/feature/Analyzer.java | 172 +-
.../sis/storage/sql/feature/CRSEncoding.java} | 28 +-
.../apache/sis/storage/sql/feature/Database.java | 507 ++--
.../sis/storage/sql/feature/FeatureAnalyzer.java | 3 +-
.../sis/storage/sql/feature/FeatureIterator.java | 14 +-
.../sis/storage/sql/feature/FeatureStream.java | 11 +-
.../sis/storage/sql/feature/GeometryGetter.java | 4 +-
.../storage/sql/feature/GeometryTypeEncoding.java | 56 +
.../sis/storage/sql/feature/InfoStatements.java | 729 +++--
.../sis/storage/sql/feature/QueryAnalyzer.java | 2 +-
.../sis/storage/sql/feature/SchemaModifier.java | 2 +-
.../sis/storage/sql/feature/SpatialSchema.java | 212 ++
.../org/apache/sis/storage/sql/feature/Table.java | 5 +-
.../sis/storage/sql/feature/TableAnalyzer.java | 1 -
.../sis/storage/sql/feature/ValueGetter.java | 6 +-
.../org/apache/sis/storage/sql/package-info.java | 32 +-
.../sis/storage/sql/postgis/ExtendedInfo.java | 7 +-
.../sis/storage/sql/postgis/ExtentEstimator.java | 2 +-
.../apache/sis/storage/sql/postgis/Postgres.java | 42 +-
.../org/apache/sis/util/stream/DeferredStream.java | 64 +-
.../org/apache/sis/storage/sql/DataAccessTest.java | 69 +
.../org/apache/sis/storage/sql/SQLStoreTest.java | 45 +-
.../storage/sql/feature/InfoStatementsTest.java | 161 ++
.../sql/feature/SelectionClauseWriterTest.java | 2 +-
.../sql/feature/TemporalValueGetterTest.java | 2 +-
.../sis/storage/sql/postgis/PostgresTest.java | 4 +-
.../org.apache.sis.storage/main/module-info.java | 4 +
.../apache/sis/io/stream/InternalOptionKey.java | 25 +
.../main/org/apache/sis/storage/DataStore.java | 22 +-
.../org/apache/sis/storage/StorageConnector.java | 91 +-
.../main/org/apache/sis/storage/URLDataSource.java | 198 ++
.../org/apache/sis/storage/WritableAggregate.java | 2 +-
.../apache/sis/storage/base/MetadataFetcher.java | 126 +-
.../apache/sis/storage/base/TiledGridCoverage.java | 18 +-
.../org/apache/sis/storage/internal/Resources.java | 5 +
.../sis/storage/internal/Resources.properties | 1 +
.../sis/storage/internal/Resources_fr.properties | 1 +
.../src/org.apache.sis.util/main/module-info.java | 1 +
.../main/org/apache/sis/util/privy/Constants.java | 2 +-
.../org/apache/sis/test/TestConfiguration.java | 18 +-
incubator/build.gradle.kts | 66 +
.../org.apache.sis.storage.DataStoreProvider | 4 +
.../main/module-info.java | 57 +
.../org/apache/sis/storage/geopackage/Content.java | 466 ++++
.../sis/storage/geopackage/ContentHandler.java | 91 +
.../sis/storage/geopackage/ContentWriter.java | 232 ++
.../org/apache/sis/storage/geopackage/Core.sql | 126 +
.../sis/storage/geopackage/Extension Metadata.sql | 38 +
.../sis/storage/geopackage/Extension Schema.sql | 40 +
.../Extension Tiled Gridded Coverage Data.sql | 47 +
.../apache/sis/storage/geopackage/GpkgStore.java | 456 +++
.../sis/storage/geopackage/GpkgStoreProvider.java | 284 ++
.../apache/sis/storage/geopackage/Initializer.java | 178 ++
.../sis/storage/geopackage/package-info.java | 22 +-
.../apache/sis/storage/geopackage/FeatureSet.sql | 164 ++
.../storage/geopackage/GpkgStoreProviderTest.java | 32 +-
.../sis/storage/geopackage/GpkgStoreTest.java | 339 +++
.../conformance/CoreConformanceTest.java | 219 ++
.../org.apache.sis.storage.DataStoreProvider | 4 +
...org.apache.sis.storage.gimi.isobmff.BoxRegistry | 8 +
.../main/module-info.java | 25 +-
.../org/apache/sis/storage/gimi/GimiProvider.java | 108 +
.../org/apache/sis/storage/gimi/GimiStore.java | 177 ++
.../main/org/apache/sis/storage/gimi/GimiTile.java | 66 +
.../apache/sis/storage/gimi/GimiTileMatrix.java | 116 +
.../apache/sis/storage/gimi/GimiTileMatrixSet.java | 72 +
.../org/apache/sis/storage/gimi/GimiUtils.java | 52 +
.../main/org/apache/sis/storage/gimi/Item.java | 136 +
.../org/apache/sis/storage/gimi/ResourceGrid.java | 134 +
.../apache/sis/storage/gimi/ResourceImageJpeg.java | 61 +
.../storage/gimi/ResourceImageUncompressed.java | 181 ++
.../apache/sis/storage/gimi/ResourcePyramid.java | 145 +
.../apache/sis/storage/gimi/ResourceUnknown.java | 34 +-
.../storage/gimi/internal/MatrixGridRessource.java | 137 +
.../sis/storage/gimi/internal/ScaleSortedMap.java | 104 +
.../sis/storage/gimi/internal/StringUtilities.java | 63 +
.../sis/storage/gimi/internal/TileMatrices.java | 64 +
.../org/apache/sis/storage/gimi/isobmff/Box.java | 278 ++
.../sis/storage/gimi/isobmff/BoxRegistry.java | 64 +
.../apache/sis/storage/gimi/isobmff/FullBox.java | 23 +-
.../sis/storage/gimi/isobmff/ISOBMFFReader.java | 157 ++
.../apache/sis/storage/gimi/isobmff/gimi/GIMI.java | 65 +
.../gimi/isobmff/gimi/ModelTiePointProperty.java | 63 +
.../isobmff/gimi/ModelTransformationProperty.java | 34 +-
.../gimi/isobmff/gimi/WellKnownText2Property.java | 27 +-
.../gimi/isobmff/iso14496_10/ContentDescribes.java | 19 +-
.../gimi/isobmff/iso14496_10/ISO14496_10.java | 60 +
.../isobmff/iso14496_12/ColourInformation.java | 55 +
.../gimi/isobmff/iso14496_12/CombinaisonType.java | 33 +-
.../gimi/isobmff/iso14496_12/EntityToGroup.java | 28 +-
.../gimi/isobmff/iso14496_12/ExtendedType.java | 25 +-
.../gimi/isobmff/iso14496_12/Extension.java | 19 +-
.../isobmff/iso14496_12/FDItemInfoExtension.java | 28 +-
.../storage/gimi/isobmff/iso14496_12/FileType.java | 16 +-
.../gimi/isobmff/iso14496_12/FreeSpace.java | 19 +-
.../gimi/isobmff/iso14496_12/GeneralType.java | 52 +
.../gimi/isobmff/iso14496_12/GroupList.java | 23 +-
.../gimi/isobmff/iso14496_12/HandlerReference.java | 33 +-
.../gimi/isobmff/iso14496_12/ISO14496_12.java | 114 +
.../isobmff/iso14496_12/IdentifiedMediaData.java | 49 +
.../storage/gimi/isobmff/iso14496_12/ItemData.java | 28 +-
.../gimi/isobmff/iso14496_12/ItemFullProperty.java | 16 +-
.../storage/gimi/isobmff/iso14496_12/ItemInfo.java | 42 +-
.../gimi/isobmff/iso14496_12/ItemInfoEntry.java | 74 +
.../gimi/isobmff/iso14496_12/ItemLocation.java | 155 ++
.../gimi/isobmff/iso14496_12/ItemProperties.java | 23 +-
.../gimi/isobmff/iso14496_12/ItemProperty.java | 16 +-
.../iso14496_12/ItemPropertyAssociation.java | 68 +
.../isobmff/iso14496_12/ItemPropertyContainer.java | 23 +-
.../gimi/isobmff/iso14496_12/ItemReference.java | 49 +
.../gimi/isobmff/iso14496_12/MediaData.java | 28 +-
.../sis/storage/gimi/isobmff/iso14496_12/Meta.java | 24 +-
.../storage/gimi/isobmff/iso14496_12/Movie.java | 24 +-
.../gimi/isobmff/iso14496_12/MovieHeader.java | 30 +-
.../gimi/isobmff/iso14496_12/OriginalFileType.java | 23 +-
.../gimi/isobmff/iso14496_12/PrimaryItem.java | 32 +-
.../iso14496_12/ProgressiveDownloadInfo.java | 28 +-
.../iso14496_12/SingleItemTypeReference.java | 49 +
.../iso14496_12/SingleItemTypeReferenceLarge.java | 26 +-
.../storage/gimi/isobmff/iso14496_12/Track.java | 24 +-
.../gimi/isobmff/iso14496_12/TrackHeader.java | 28 +-
.../gimi/isobmff/iso23001_17/ChromaLocation.java | 27 +-
.../isobmff/iso23001_17/ComponentDefinition.java | 67 +
.../gimi/isobmff/iso23001_17/ComponentPalette.java | 57 +
.../iso23001_17/ComponentPatternDefinition.java | 49 +
.../iso23001_17/ComponentReferenceLevel.java | 27 +-
.../iso23001_17/DepthMappingInformation.java | 27 +-
.../isobmff/iso23001_17/DisparityInformation.java | 27 +-
.../iso23001_17/FieldInterlaceProperty.java | 27 +-
.../isobmff/iso23001_17/FieldInterlaceType.java | 27 +-
.../iso23001_17/FramePackingInformation.java | 27 +-
.../gimi/isobmff/iso23001_17/ISO23001_17.java | 92 +
.../iso23001_17/PolarizationPatternDefinition.java | 27 +-
.../isobmff/iso23001_17/SensorBadPixelsMap.java | 27 +-
.../iso23001_17/SensorNonUniformityCorrection.java | 27 +-
.../gimi/isobmff/iso23001_17/TAIClockInfo.java | 48 +
.../gimi/isobmff/iso23001_17/TAITimeStamp.java | 45 +
.../iso23001_17/UncompressedFrameConfig.java | 92 +
.../isobmff/iso23008_12/DerivedImageReference.java | 19 +-
.../gimi/isobmff/iso23008_12/ISO23008_12.java | 71 +
.../iso23008_12/ImagePyramidEntityGroup.java | 62 +
.../isobmff/iso23008_12/ImageSpatialExtents.java | 44 +-
.../iso23008_12/PixelInformationProperty.java | 30 +-
.../iso23008_12/UserDescriptionProperty.java | 33 +-
.../org/apache/sis/storage/gimi/package-info.java | 14 +-
.../org/apache/sis/storage/gimi/StoreTest.java | 17 +-
.../main/module-info.java | 15 +-
.../main/org/apache/sis/storage/gsf/Attitude.java | 89 +
.../main/org/apache/sis/storage/gsf/Comment.java | 63 +
.../main/org/apache/sis/storage/gsf/DataID.java | 69 +
.../main/org/apache/sis/storage/gsf/GSF.java | 1786 ++++++++++++
.../apache/sis/storage/gsf/GSFRecordReader.java | 88 +
.../apache/sis/storage/gsf/HVNavigationError.java | 89 +
.../main/org/apache/sis/storage/gsf/Header.java | 40 +-
.../main/org/apache/sis/storage/gsf/History.java | 105 +
.../apache/sis/storage/gsf/NavigationError.java | 96 +
.../main/org/apache/sis/storage/gsf/Position.java | 74 +
.../apache/sis/storage/gsf/PositionOffsets.java | 86 +
.../sis/storage/gsf/ProcessingParameters.java | 65 +
.../main/org/apache/sis/storage/gsf/Records.java | 146 +
.../apache/sis/storage/gsf/SBSensorSpecific.java | 110 +
.../main/org/apache/sis/storage/gsf/SVP.java | 90 +
.../org/apache/sis/storage/gsf/ScaleFactors.java | 72 +
.../main/org/apache/sis/storage/gsf/ScaleInfo.java | 85 +
.../apache/sis/storage/gsf/SensorParameters.java | 106 +
.../org/apache/sis/storage/gsf/SensorSpecific.java | 108 +
.../org/apache/sis/storage/gsf/SingleBeamPing.java | 216 ++
.../org/apache/sis/storage/gsf/StructClass.java | 219 ++
.../org/apache/sis/storage/gsf/SwathBathyPing.java | 354 +++
.../apache/sis/storage/gsf/SwathBathySummary.java | 94 +
.../main/org/apache/sis/storage/gsf/TimeSpec.java | 60 +
.../org/apache/sis/storage/gsf/package-info.java | 14 +-
.../sis/storage/gsf/specific/BDBSpecific.java | 133 +
.../sis/storage/gsf/specific/CmpSassSpecific.java | 73 +
.../sis/storage/gsf/specific/DeltaTSpecific.java | 405 +++
.../sis/storage/gsf/specific/EM100Specific.java | 152 +
.../sis/storage/gsf/specific/EM121ASpecific.java | 454 +++
.../sis/storage/gsf/specific/EM12Specific.java | 356 +++
.../storage/gsf/specific/EM3ImagerySpecific.java | 488 ++++
.../sis/storage/gsf/specific/EM3RawSpecific.java | 875 ++++++
.../sis/storage/gsf/specific/EM3RawTxSector.java | 488 ++++
.../sis/storage/gsf/specific/EM3RunTime.java | 1313 +++++++++
.../sis/storage/gsf/specific/EM3Specific.java | 539 ++++
.../storage/gsf/specific/EM4ImagerySpecific.java | 670 +++++
.../sis/storage/gsf/specific/EM4Specific.java | 832 ++++++
.../sis/storage/gsf/specific/EM4TxSector.java | 533 ++++
.../sis/storage/gsf/specific/EM950Specific.java | 320 +++
.../sis/storage/gsf/specific/EMPUStatus.java | 356 +++
.../apache/sis/storage/gsf/specific/EMRunTime.java | 1531 ++++++++++
.../sis/storage/gsf/specific/EchotracSpecific.java | 184 ++
.../sis/storage/gsf/specific/ElacMkIISpecific.java | 364 +++
.../storage/gsf/specific/GeoSwathPlusSpecific.java | 1212 ++++++++
.../sis/storage/gsf/specific/KMALLExtraDet.java | 218 ++
.../storage/gsf/specific/KMALLImagerySpecific.java | 126 +
.../sis/storage/gsf/specific/KMALLSpecific.java | 988 +++++++
.../sis/storage/gsf/specific/KMALLTxSector.java | 670 +++++
.../gsf/specific/Klein5410BssImagerySpecific.java | 297 ++
.../storage/gsf/specific/Klein5410BssSpecific.java | 851 ++++++
.../sis/storage/gsf/specific/MGD77Specific.java | 320 +++
.../sis/storage/gsf/specific/NOSHDBSpecific.java | 140 +
.../gsf/specific/R2SonicImagerySpecific.java | 1355 +++++++++
.../sis/storage/gsf/specific/R2SonicSpecific.java | 1568 +++++++++++
.../gsf/specific/Reson7100ImagerySpecific.java | 173 ++
.../storage/gsf/specific/Reson7100Specific.java | 2267 +++++++++++++++
.../gsf/specific/Reson8100ImagerySpecific.java | 127 +
.../storage/gsf/specific/Reson8100Specific.java | 1301 +++++++++
.../gsf/specific/ResonTSeriesImagerySpecific.java | 173 ++
.../storage/gsf/specific/ResonTSeriesSpecific.java | 2923 ++++++++++++++++++++
.../sis/storage/gsf/specific/SBAmpSpecific.java | 320 +++
.../sis/storage/gsf/specific/SBBDBSpecific.java | 444 +++
.../storage/gsf/specific/SBEchotracSpecific.java | 309 +++
.../sis/storage/gsf/specific/SBMGD77Specific.java | 400 +++
.../sis/storage/gsf/specific/SBNOSHDBSpecific.java | 218 ++
.../storage/gsf/specific/SBNavisoundSpecific.java | 173 ++
.../storage/gsf/specific/SeaBat8101Specific.java | 850 ++++++
.../sis/storage/gsf/specific/SeaBatIISpecific.java | 490 ++++
.../sis/storage/gsf/specific/SeaBatSpecific.java | 320 +++
.../storage/gsf/specific/SeaBeam2112Specific.java | 524 ++++
.../sis/storage/gsf/specific/SeabeamSpecific.java | 94 +
.../sis/storage/gsf/specific/SeamapSpecific.java | 521 ++++
.../sis/storage/gsf/specific/TypeIIISpecific.java | 319 +++
.../test/org/apache/sis/storage/gsf/StoreTest.java | 17 +-
.../apache/sis/storage/shapefile/dbf/DBFField.java | 22 +-
.../sis/storage/shapefile/dbf/DBFHeader.java | 3 +-
netbeans-project/ivy.xml | 17 +-
netbeans-project/nbproject/project.properties | 9 +
netbeans-project/nbproject/project.xml | 1 +
optional/build.gradle.kts | 95 +-
.../apache/sis/gui/coverage/CoverageCanvas.java | 4 +-
.../main/META-INF/NOTICE | 1 +
.../org.apache.sis.setup.InstallationResources | 4 +
.../main/module-info.java | 43 +
.../sis/resources/embedded/EmbeddedResources.java | 153 +
.../sis/resources/embedded/package-info.java | 35 +
.../resources/embedded/EmbeddedResourcesTest.java | 141 +
.../apache/sis/resources/embedded/Generator.java | 222 ++
.../main/META-INF/NOTICE | 10 +
.../org.apache.sis.setup.InstallationResources | 4 +
.../main/module-info.java | 41 +
.../sis/referencing/factory/sql/epsg/.gitignore | 7 +
.../sis/referencing/factory/sql/epsg/README.md | 23 +
.../factory/sql/epsg/ScriptProvider.java | 104 +
.../referencing/factory/sql/epsg/package-info.java | 37 +
.../factory/sql/epsg/DataScriptFormatter.java | 3 +-
.../factory/sql/epsg/DataScriptFormatterTest.java | 2 +-
.../referencing/factory/sql/epsg/DebugTools.sql | 0
.../sis/referencing/factory/sql/epsg/README.md | 3 +-
.../factory/sql/epsg/ScriptProviderTest.java | 91 +
settings.gradle.kts | 20 +-
346 files changed, 46246 insertions(+), 1672 deletions(-)
diff --cc buildSrc/src/main/java/org/apache/sis/buildtools/gradle/Dependency.java
index 1ac9152a01,45f821fdd7..b95757d8c3
--- a/buildSrc/src/main/java/org/apache/sis/buildtools/gradle/Dependency.java
+++ b/buildSrc/src/main/java/org/apache/sis/buildtools/gradle/Dependency.java
@@@ -70,7 -72,11 +72,10 @@@ public final class Dependency
Map.entry("gui", "application:sis-javafx"), // Optional.
Map.entry("cql", "core:sis-cql"), // Incubator.
Map.entry("storage.shapefile", "core:sis-shapefile"),
+ Map.entry("storage.gimi", "core:sis-gimi"),
+ Map.entry("storage.gsf", "core:sis-gsf"),
+ Map.entry("storage.geopackage", "core:sis-geopackage"),
Map.entry("storage.coveragejson", "core:sis-coveragejson"),
- Map.entry("portrayal.map", "core:sis-portrayal-map"),
Map.entry("webapp", "application:sis-webapp")
);
diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
index aade867a1e,d99f986546..1bb9d6cded
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
@@@ -87,11 -87,9 +87,12 @@@ import org.apache.sis.geometry.Abstract
import org.apache.sis.geometry.AbstractEnvelope;
import org.apache.sis.xml.NilObject;
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.util.ControlledVocabulary;
-import org.opengis.referencing.ObjectDomain;
+// Specific to the main branch:
+import org.opengis.util.CodeList;
+import org.opengis.referencing.ReferenceIdentifier;
+import org.apache.sis.referencing.DefaultObjectDomain;
++import org.apache.sis.referencing.datum.AbstractDatum;
+import org.apache.sis.referencing.internal.Legacy;
/**
@@@ -889,8 -887,8 +890,8 @@@ public class Formatter implements Local
private void appendForSubtypes(final IdentifiedObject object) {
InternationalString anchor = null, scope = null;
Extent area = null;
-- if (object instanceof Datum) {
- anchor = ((Datum) object).getAnchorPoint();
- anchor = ((Datum) object).getAnchorDefinition().orElse(null);
++ if (object instanceof AbstractDatum) {
++ anchor = ((AbstractDatum) object).getAnchorPoint();
} else if (!(object instanceof ReferenceSystem || object instanceof CoordinateOperation)) {
return;
}
diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
index 8619fca435,7454658ac6..a4bcb99c7e
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
@@@ -576,6 -567,6 +576,9 @@@ public class AbstractIdentifiedObject e
* The domain includes a scope (description of the primary purpose of this object) together
* with a domain of validity (spatial and temporal extent in which the object can be used).
*
++ * <div class="note"><b>Upcoming API change:</b>
++ * the type of collection elements may become {@code ObjectDomain} after the next GeoAPI release.</div>
++ *
* @return scopes and domains of validity of this object.
*
* @since 1.4
diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
index 3cd29c850f,7fc8ec1690..cabcc1e865
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
@@@ -46,10 -46,9 +46,11 @@@ import org.apache.sis.io.wkt.Formatter
import static org.apache.sis.util.Utilities.deepEquals;
import static org.apache.sis.util.collection.Containers.property;
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.referencing.datum.DynamicReferenceFrame;
-import org.opengis.metadata.Identifier;
+// Specific to the main branch:
+import org.opengis.referencing.ReferenceIdentifier;
+import org.opengis.metadata.extent.Extent;
+import org.apache.sis.referencing.internal.Legacy;
++import org.apache.sis.pending.geoapi.referencing.DynamicReferenceFrame;
/**
@@@ -360,35 -335,20 +361,46 @@@ public class AbstractDatum extends Abst
@XmlSchemaType(name = "date")
@XmlElement(name = "realizationEpoch")
public Date getRealizationEpoch() {
- return Datum.super.getRealizationEpoch();
+ return getAnchorEpoch().map(Legacy::toDate).orElse(null);
+ }
+
+ /**
+ * Returns the region or timeframe in which this datum is valid, or {@code null} if unspecified.
+ *
+ * @return area or region or timeframe in which this datum is valid, or {@code null}.
+ *
+ * @deprecated Replaced by {@link #getDomains()} as of ISO 19111:2019.
+ */
+ @Override
+ @Deprecated(since = "1.4")
+ public Extent getDomainOfValidity() {
+ return Legacy.getDomainOfValidity(getDomains());
+ }
+
+ /**
+ * Returns the domain or limitations of usage, or {@code null} if unspecified.
+ *
+ * @return description of domain of usage, or limitations of usage, for which this datum object is valid.
+ *
+ * @deprecated Replaced by {@link #getDomains()} as of ISO 19111:2019.
+ */
+ @Override
+ @Deprecated(since = "1.4")
+ public InternationalString getScope() {
+ return Legacy.getScope(getDomains());
}
+ /**
+ * Returns the frame reference epoch if this datum is dynamic, or {@code null} if this datum is static.
+ * This method is overridden with public access in Apache SIS {@code Dynamic} subclasses.
+ * The default implementation should be suitable for non-SIS implementations.
+ *
+ * @return the reference epoch if this datum is dynamic, or {@code null} if this datum is static.
+ */
+ Temporal getFrameReferenceEpoch() {
+ return (this instanceof DynamicReferenceFrame) ? ((DynamicReferenceFrame) this).getFrameReferenceEpoch() : null;
+ }
+
/**
* Returns the date on which the datum definition was published.
*
@@@ -471,6 -433,12 +483,12 @@@
* {@linkplain #getAnchorDefinition() anchor definition}, {@linkplain #getAnchorEpoch() anchor epoch},
* and the {@linkplain #getDomains() domains}.
*
+ * <h4>Static versus dynamic datum</h4>
- * If this datum implements the {@link DynamicReferenceFrame} interface, then the given object needs
++ * If this datum implements the {@code DynamicReferenceFrame} interface, then the given object needs
+ * to also implement that interfaces and provide the same reference epoch for being considered equal.
- * Conversely, if this datum does not implement {@link DynamicReferenceFrame}, then the given object
++ * Conversely, if this datum does not implement {@code DynamicReferenceFrame}, then the given object
+ * also need to <em>not</em> implement that interface for being considered equal.
+ *
* @param object the object to compare to {@code this}.
* @param mode {@link ComparisonMode#STRICT STRICT} for performing a strict comparison, or
* {@link ComparisonMode#IGNORE_METADATA IGNORE_METADATA} for comparing only
@@@ -485,13 -453,18 +503,24 @@@
switch (mode) {
case STRICT: {
final var that = (AbstractDatum) object;
- return Objects.equals(anchorEpoch, that.anchorEpoch) &&
- Objects.equals(anchorDefinition, that.anchorDefinition);
+ return Objects.equals(anchorEpoch, that.anchorEpoch) &&
+ Objects.equals(anchorDefinition, that.anchorDefinition) &&
+ Objects.equals(publicationDate, that.publicationDate) &&
+ Objects.equals(conventionalRS, that.conventionalRS);
}
case BY_CONTRACT: {
- final Datum that = (Datum) object;
- return deepEquals(getRealizationEpoch(), that.getRealizationEpoch(), mode) &&
- deepEquals(getAnchorPoint(), that.getAnchorPoint(), mode);
- final var that = (Datum) object;
++ if (!(object instanceof AbstractDatum)) {
++ return getAnchorEpoch().isEmpty() &&
++ getAnchorDefinition().isEmpty() &&
++ getPublicationDate().isEmpty() &&
++ getConventionalRS().isEmpty();
++ }
++ final var that = (AbstractDatum) object;
+ return compareDynamicReferenceFrames(that, mode) &&
+ deepEquals(getAnchorEpoch(), that.getAnchorEpoch(), mode) &&
+ deepEquals(getAnchorDefinition(), that.getAnchorDefinition(), mode) &&
+ deepEquals(getPublicationDate(), that.getPublicationDate(), mode) &&
+ deepEquals(getConventionalRS(), that.getConventionalRS(), mode);
}
default: {
/*
diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
index d01ff32b00,b95286c5f9..bb9ca3308d
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
@@@ -54,8 -52,9 +52,9 @@@ import static org.apache.sis.util.Argum
import static org.apache.sis.util.ArgumentChecks.ensureNonNullElement;
import static org.apache.sis.referencing.privy.WKTUtilities.toFormattable;
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.referencing.datum.DynamicReferenceFrame;
-import org.opengis.metadata.Identifier;
+// Specific to the main branch:
+import org.opengis.referencing.ReferenceIdentifier;
++import org.apache.sis.pending.geoapi.referencing.DynamicReferenceFrame;
/**
@@@ -511,6 -495,112 +495,115 @@@ public class DefaultGeodeticDatum exten
return selector.best();
}
+ /**
+ * Returns the position vector transformation (geocentric domain) as an affine transform.
+ * If this datum is dynamic, the frame reference epoch is used.
+ * Otherwise, a time is computed from the temporal area of interest.
+ *
- * @see DynamicReferenceFrame#getFrameReferenceEpoch()
+ * @see BursaWolfParameters#getPositionVectorTransformation(Temporal)
+ */
+ private Matrix createTransformation(final BursaWolfParameters bursaWolf, final Extent areaOfInterest) {
+ Temporal epoch = null;
+ /*
+ * Implementation note: we know that we do not need to compute an instant if the parameters is
+ * not a subclass of BursaWolfParameters. This optimisation covers the vast majority of cases.
+ */
+ if (bursaWolf.getClass() != BursaWolfParameters.class) {
+ epoch = getFrameReferenceEpoch();
+ if (epoch == null) {
+ epoch = Extents.getInstant(areaOfInterest, null, 0.5).orElse(null);
+ // 0.5 is for choosing the instant midway between start and end.
+ }
+ }
+ return bursaWolf.getPositionVectorTransformation(epoch);
+ }
+
+ /**
+ * A geodetic reference frame in which some of the defining parameters have time dependency.
+ * The parameter values are valid at the time given by the
+ * {@linkplain #getFrameReferenceEpoch() frame reference epoch}.
+ *
++ * <div class="note"><b>Upcoming API change:</b>
++ * this class may implement a {@code DynamicReferenceFrame} interface from the GeoAPI standard
++ * after the next GeoAPI release. In the meantime, {@code DynamicReferenceFrame} is not a public API.</div>
++ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.5
+ * @since 1.5
+ */
+ public static class Dynamic extends DefaultGeodeticDatum implements DynamicReferenceFrame {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = 6117199873814779662L;
+
+ /**
+ * The epoch to which the definition of the dynamic reference frame is referenced.
+ */
+ @SuppressWarnings("serial") // Standard Java implementations are serializable.
+ private final Temporal frameReferenceEpoch;
+
+ /**
+ * Creates a dynamic reference frame from the given properties.
+ * See super-class constructor for more information.
+ *
+ * @param properties the properties to be given to the identified object.
+ * @param ellipsoid the ellipsoid.
+ * @param primeMeridian the prime meridian.
+ * @param epoch the epoch to which the definition of the dynamic reference frame is referenced.
+ */
+ public Dynamic(Map<String,?> properties, Ellipsoid ellipsoid, PrimeMeridian primeMeridian, Temporal epoch) {
+ super(properties, ellipsoid, primeMeridian);
+ frameReferenceEpoch = Objects.requireNonNull(epoch);
+ }
+
+ /**
+ * Creates a new datum with the same values as the specified datum, which must be dynamic.
+ *
+ * @param datum the datum to copy.
- * @throws ClassCastException if the given datum is not an instance of {@link DynamicReferenceFrame}.
++ * @throws ClassCastException if the given datum is not an instance of {@code DynamicReferenceFrame}.
+ *
+ * @see #castOrCopy(GeodeticDatum)
+ */
+ protected Dynamic(final GeodeticDatum datum) {
+ super(datum);
+ frameReferenceEpoch = Objects.requireNonNull(((DynamicReferenceFrame) datum).getFrameReferenceEpoch());
+ }
+
+ /**
+ * Returns the epoch to which the coordinates of stations defining the dynamic reference frame are referenced.
+ * The type of the returned object depends on the epoch accuracy and the calendar in use.
+ * It may be merely a {@link java.time.Year}.
+ *
+ * @return the epoch to which the definition of the dynamic reference frame is referenced.
+ */
+ @Override
+ public Temporal getFrameReferenceEpoch() {
+ return frameReferenceEpoch;
+ }
+
+ /**
+ * Compares the specified object with this datum for equality.
+ *
+ * @hidden because nothing new to said.
+ */
+ @Override
+ public boolean equals(final Object object, final ComparisonMode mode) {
+ return super.equals(object) && (mode != ComparisonMode.STRICT ||
+ frameReferenceEpoch.equals(((Dynamic) object).frameReferenceEpoch));
+ }
+
+ /**
+ * Invoked by {@code hashCode()} for computing the hash code when first needed.
+ *
+ * @hidden because nothing new to said.
+ */
+ @Override
+ protected long computeHashCode() {
+ return super.computeHashCode() + 31 * frameReferenceEpoch.hashCode();
+ }
+ }
+
/**
* Returns {@code true} if either the {@linkplain #getName() primary name} or at least
* one {@linkplain #getAlias() alias} matches the given string according heuristic rules.
diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultVerticalDatum.java
index fd46ba3bd7,0ea312039c..2f07233dd9
--- 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
@@@ -35,8 -36,11 +36,9 @@@ import org.apache.sis.metadata.privy.Im
// 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 java.util.Optional;
-import org.opengis.referencing.datum.DynamicReferenceFrame;
-import org.opengis.referencing.datum.RealizationMethod;
-import org.opengis.metadata.Identifier;
+// Specific to the main branch:
+import org.opengis.referencing.ReferenceIdentifier;
++import org.apache.sis.pending.geoapi.referencing.DynamicReferenceFrame;
/**
@@@ -231,12 -248,96 +233,97 @@@ public class DefaultVerticalDatum exten
* but in a programmatic way more suitable to coordinate transformation engines.
*
* @return the type of this vertical datum.
- *
- * @deprecated As of ISO 19111:2019, the {@code VerticalDatumType} argument is replaced by {@code RealizationMethod}.
*/
@Override
- @Deprecated(since = "2.0") // Temporary version number until this branch is released.
public VerticalDatumType getVerticalDatumType() {
- return type;
+ return type();
}
+ /**
+ * A vertical reference frame in which some of the defining parameters have time dependency.
+ * The parameter values are valid at the time given by the
+ * {@linkplain #getFrameReferenceEpoch() frame reference epoch}.
+ *
++ * <div class="note"><b>Upcoming API change:</b>
++ * this class may implement a {@code DynamicReferenceFrame} interface from the GeoAPI standard
++ * after the next GeoAPI release. In the meantime, {@code DynamicReferenceFrame} is not a public API.</div>
++ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.5
+ * @since 1.5
+ */
+ public static class Dynamic extends DefaultVerticalDatum implements DynamicReferenceFrame {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = -2047994195060747008L;
+
+ /**
+ * The epoch to which the definition of the dynamic reference frame is referenced.
+ */
+ @SuppressWarnings("serial") // Standard Java implementations are serializable.
+ private final Temporal frameReferenceEpoch;
+
+ /**
+ * Creates a dynamic reference frame from the given properties.
+ * See super-class constructor for more information.
+ *
- * @param properties the properties to be given to the identified object.
- * @param epoch the epoch to which the definition of the dynamic reference frame is referenced.
++ * @param properties the properties to be given to the identified object.
++ * @param type the type of this vertical datum.
++ * @param epoch the epoch to which the definition of the dynamic reference frame is referenced.
+ */
- public Dynamic(Map<String,?> properties, RealizationMethod method, Temporal epoch) {
- super(properties, method);
++ public Dynamic(Map<String,?> properties, VerticalDatumType type, Temporal epoch) {
++ super(properties, type);
+ frameReferenceEpoch = Objects.requireNonNull(epoch);
+ }
+
+ /**
+ * Creates a new datum with the same values as the specified datum, which must be dynamic.
+ *
+ * @param datum the datum to copy.
- * @param method the realization method (geoid, tidal, <i>etc.</i>), or {@code null} if unspecified.
- * @throws ClassCastException if the given datum is not an instance of {@link DynamicReferenceFrame}.
++ * @throws ClassCastException if the given datum is not an instance of {@code DynamicReferenceFrame}.
+ *
+ * @see #castOrCopy(VerticalDatum)
+ */
+ protected Dynamic(final VerticalDatum datum) {
+ super(datum);
+ frameReferenceEpoch = Objects.requireNonNull(((DynamicReferenceFrame) datum).getFrameReferenceEpoch());
+ }
+
+ /**
+ * Returns the epoch to which the coordinates of stations defining the dynamic reference frame are referenced.
+ * The type of the returned object depends on the epoch accuracy and the calendar in use.
+ * It may be merely a {@link java.time.Year}.
+ *
+ * @return the epoch to which the definition of the dynamic reference frame is referenced.
+ */
+ @Override
+ public Temporal getFrameReferenceEpoch() {
+ return frameReferenceEpoch;
+ }
+
+ /**
+ * Compares the specified object with this datum for equality.
+ *
+ * @hidden because nothing new to said.
+ */
+ @Override
+ public boolean equals(final Object object, final ComparisonMode mode) {
+ return super.equals(object) && (mode != ComparisonMode.STRICT ||
+ frameReferenceEpoch.equals(((Dynamic) object).frameReferenceEpoch));
+ }
+
+ /**
+ * Invoked by {@code hashCode()} for computing the hash code when first needed.
+ *
+ * @hidden because nothing new to said.
+ */
+ @Override
+ protected long computeHashCode() {
+ return super.computeHashCode() + 31 * frameReferenceEpoch.hashCode();
+ }
+ }
+
/**
* Compares this vertical datum with the specified object for equality.
*
@@@ -245,8 -346,11 +332,10 @@@
* {@link ComparisonMode#IGNORE_METADATA IGNORE_METADATA} for comparing only
* properties relevant to coordinate transformations.
* @return {@code true} if both objects are equal.
+ *
+ * @hidden because nothing new to said.
*/
@Override
- @SuppressWarnings("deprecation")
public boolean equals(final Object object, final ComparisonMode mode) {
if (object == this) {
return true; // Slight optimization.
diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/PseudoDatum.java
index c215bd1211,eed9024fad..ed0dc4a523
--- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/PseudoDatum.java
+++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/PseudoDatum.java
@@@ -43,8 -43,9 +43,9 @@@ import java.util.Date
import org.opengis.referencing.ReferenceIdentifier;
import org.opengis.metadata.extent.Extent;
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import java.time.temporal.Temporal;
-import org.opengis.referencing.ObjectDomain;
+// Specific to the main branch:
++import org.apache.sis.referencing.DefaultObjectDomain;
+import static org.apache.sis.pending.geoapi.referencing.MissingMethods.getDatumEnsemble;
/**
@@@ -427,6 -465,18 +431,20 @@@ public abstract class PseudoDatum<D ext
return ensemble.getIdentifiers();
}
+ /**
+ * Returns the usage of the datum ensemble.
+ *
++ * <div class="note"><b>Upcoming API change:</b>
++ * the type of collection elements may become {@code ObjectDomain} after the next GeoAPI release.</div>
++ *
+ * @return {@code ensemble.getDomains()}.
+ *
+ * @hidden because nothing new to said.
+ */
- @Override
- public Collection<ObjectDomain> getDomains() {
++ public Collection<DefaultObjectDomain> getDomains() {
+ return ensemble.getDomains();
+ }
+
/**
* Returns the domain of validity common to all datum members, if any.
*
diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
index ae296a5de6,098500a7cf..2a4cf23176
--- 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
@@@ -25,6 -25,6 +25,7 @@@ import java.util.logging.Level
import java.util.logging.Logger;
import java.util.logging.LogRecord;
import java.util.concurrent.atomic.AtomicReference;
++import java.time.temporal.Temporal;
import java.lang.reflect.Constructor;
import jakarta.xml.bind.JAXBException;
import javax.measure.Unit;
@@@ -721,6 -701,39 +722,37 @@@ public class GeodeticObjectFactory exte
return unique("createGeodeticDatum", datum);
}
+ /**
+ * Creates a dynamic geodetic reference frame from ellipsoid and frame reference epoch.
+ * The arguments are the same as for the {@linkplain #createGeodeticDatum(Map, Ellipsoid,
+ * PrimeMeridian) static datum}, with the addition of a mandatory frame reference epoch.
- * The returned object implements the {@link DynamicReferenceFrame} interface.
+ *
+ * @param properties name and other properties to give to the new object.
+ * @param ellipsoid the ellipsoid to use in new geodetic reference frame.
+ * @param primeMeridian the prime meridian to use in new geodetic reference frame.
+ * @param epoch the epoch to which the definition of the dynamic reference frame is referenced.
+ * @throws FactoryException if the object creation failed.
+ *
+ * @see DefaultGeodeticDatum.Dynamic#Dynamic(Map, Ellipsoid, PrimeMeridian, Temporal)
+ * @see GeodeticAuthorityFactory#createGeodeticDatum(String)
+ *
+ * @since 1.5
+ */
- @Override
+ public GeodeticDatum createGeodeticDatum(final Map<String,?> properties,
+ final Ellipsoid ellipsoid,
+ final PrimeMeridian primeMeridian,
+ final Temporal epoch)
+ throws FactoryException
+ {
+ final DefaultGeodeticDatum datum;
+ try {
+ datum = new DefaultGeodeticDatum.Dynamic(complete(properties), ellipsoid, primeMeridian, epoch);
+ } catch (IllegalArgumentException exception) {
+ throw new InvalidGeodeticParameterException(exception);
+ }
+ return unique("createGeodeticDatum", datum);
+ }
+
/**
* Creates a prime meridian, relative to Greenwich.
* Defines the origin from which longitude values are determined.
@@@ -1068,22 -1082,30 +1100,21 @@@
}
/**
- * Creates a vertical <abbr>CRS</abbr> from a reference frame.
- * This is a shortcut for the {@linkplain #createVerticalCRS(Map, VerticalDatum, DefaultDatumEnsemble, VerticalCS)
- * more generic method} without datum ensemble.
+ * 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.
+ * 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.
+ * @return the coordinate reference system for the given properties.
* @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)
+ public VerticalCRS createVerticalCRS(Map<String, ?> properties, VerticalDatum datum, VerticalCS cs)
throws FactoryException
{
- final DefaultVerticalDatum datum;
- try {
- datum = new DefaultVerticalDatum(complete(properties), method);
- } catch (IllegalArgumentException exception) {
- throw new InvalidGeodeticParameterException(exception);
- }
- return unique("createVerticalDatum", datum);
+ return createVerticalCRS(properties, datum, null, cs);
}
/**
@@@ -1110,6 -1135,37 +1141,35 @@@
return unique("createVerticalDatum", datum);
}
+ /**
- * Creates a dynamic vertical datum from a realization method and a frame reference epoch.
- * The arguments are the same as for the {@linkplain #createVerticalDatum(Map, RealizationMethod)
++ * Creates a dynamic vertical datum from an enumerated type value and a frame reference epoch.
++ * The arguments are the same as for the {@linkplain #createVerticalDatum(Map, VerticalDatumType)
+ * static datum}, with the addition of a mandatory frame reference epoch.
- * The returned object implements the {@link DynamicReferenceFrame} interface.
+ *
+ * @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.
++ * @param type the type of this vertical datum (often geoidal).
+ * @param epoch the epoch to which the definition of the dynamic reference frame is referenced.
+ * @throws FactoryException if the object creation failed.
+ *
- * @see DefaultVerticalDatum.Dynamic#Dynamic(Map, RealizationMethod, Temporal)
++ * @see DefaultVerticalDatum.Dynamic#Dynamic(Map, VerticalDatumType, Temporal)
+ * @see GeodeticAuthorityFactory#createVerticalDatum(String)
+ *
- * @since 2.0 (temporary version number until this branch is released)
++ * @since 1.5
+ */
- @Override
+ public VerticalDatum createVerticalDatum(final Map<String,?> properties,
- final RealizationMethod method,
++ final VerticalDatumType type,
+ final Temporal epoch)
+ throws FactoryException
+ {
+ final DefaultVerticalDatum datum;
+ try {
- datum = new DefaultVerticalDatum.Dynamic(complete(properties), method, epoch);
++ datum = new DefaultVerticalDatum.Dynamic(complete(properties), type, epoch);
+ } catch (IllegalArgumentException exception) {
+ throw new InvalidGeodeticParameterException(exception);
+ }
+ return unique("createVerticalDatum", datum);
+ }
+
/**
* Creates a vertical coordinate system.
* This coordinate system can be used with vertical and derived CRS.
diff --cc endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStore.java
index fd0419bee0,468f211524..6011e0d287
--- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStore.java
+++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStore.java
@@@ -82,10 -124,14 +124,14 @@@ public abstract class SQLStore extends
private final GeometryLibrary geomLibrary;
/**
- * The result of inspecting database schema for deriving {@link org.opengis.feature.FeatureType}s.
+ * The result of inspecting database schema for deriving {@code FeatureType}s.
* Created when first needed. May be discarded and recreated if the store needs a refresh.
+ *
+ * @see #model()
+ * @see #model(Connection)
+ * @see #refresh()
*/
- private Database<?> model;
+ private volatile Database<?> model;
/**
* Fully qualified names (including catalog and schema) of the tables to include in this store.
diff --cc endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureIterator.java
index d8d2e69b31,ba0836a33d..30b9a8dfce
--- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureIterator.java
+++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureIterator.java
@@@ -27,14 -27,13 +27,13 @@@ import java.sql.ResultSet
import java.sql.SQLException;
import org.apache.sis.metadata.sql.privy.SQLBuilder;
import org.apache.sis.storage.InternalDataStoreException;
- import org.apache.sis.util.collection.BackingStoreException;
import org.apache.sis.util.collection.WeakValueHashMap;
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.feature.Feature;
-import org.opengis.filter.SortOrder;
-import org.opengis.filter.SortProperty;
-import org.opengis.filter.SortBy;
+// Specific to the main branch:
+import org.apache.sis.feature.AbstractFeature;
+import org.apache.sis.pending.geoapi.filter.SortOrder;
+import org.apache.sis.pending.geoapi.filter.SortProperty;
+import org.apache.sis.pending.geoapi.filter.SortBy;
/**
@@@ -214,13 -214,11 +214,11 @@@ final class FeatureIterator implements
* Gives the next feature to the given consumer.
*/
@Override
- public boolean tryAdvance(final Consumer<? super Feature> action) {
+ public boolean tryAdvance(final Consumer<? super AbstractFeature> action) {
try {
return fetch(action, false);
- } catch (RuntimeException e) {
- throw e;
} catch (Exception e) {
- throw new BackingStoreException(e);
+ throw FeatureStream.cannotExecute(e);
}
}
@@@ -228,13 -226,11 +226,11 @@@
* Gives all remaining features to the given consumer.
*/
@Override
- public void forEachRemaining(final Consumer<? super Feature> action) {
+ public void forEachRemaining(final Consumer<? super AbstractFeature> action) {
try {
fetch(action, true);
- } catch (RuntimeException e) {
- throw e;
} catch (Exception e) {
- throw new BackingStoreException(e);
+ throw FeatureStream.cannotExecute(e);
}
}
diff --cc endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureStream.java
index 78d71280e5,f1485ce02f..1ad73ac900
--- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureStream.java
+++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureStream.java
@@@ -34,14 -35,12 +35,12 @@@ import org.apache.sis.util.privy.String
import org.apache.sis.util.stream.DeferredStream;
import org.apache.sis.util.stream.PaginedStream;
import org.apache.sis.filter.privy.SortByComparator;
- import org.apache.sis.util.privy.Strings;
import org.apache.sis.storage.DataStoreException;
- import org.apache.sis.util.collection.BackingStoreException;
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.feature.Feature;
-import org.opengis.filter.Filter;
-import org.opengis.filter.SortBy;
+// Specific to the main branch:
+import org.apache.sis.filter.Filter;
+import org.apache.sis.feature.AbstractFeature;
+import org.apache.sis.pending.geoapi.filter.SortBy;
/**
diff --cc endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/InfoStatements.java
index 50d68debce,35f9163eab..a535c3b43b
--- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/InfoStatements.java
+++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/InfoStatements.java
@@@ -49,10 -57,9 +57,9 @@@ import org.apache.sis.util.privy.Consta
import org.apache.sis.io.wkt.Convention;
import org.apache.sis.io.wkt.WKTFormat;
import org.apache.sis.io.wkt.Warnings;
- import org.apache.sis.referencing.factory.IdentifiedObjectFinder;
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.metadata.Identifier;
+// Specific to the main branch:
+import org.opengis.referencing.ReferenceIdentifier;
/**
@@@ -475,23 -624,25 +624,25 @@@ public class InfoStatements implements
/*
* First, iterate over the identifiers declared in the CRS object.
* If we cannot find an identifier that we can map to a SRID, then this loop may be
- * executed more times with CRS from EPSG database that are equal, ignore axis order.
+ * executed more times with CRS from EPSG database that are equal, ignoring axis order.
*/
- for (final Identifier id : candidate.getIdentifiers()) {
+ for (final ReferenceIdentifier id : candidate.getIdentifiers()) {
final String authority = id.getCodeSpace();
if (authority == null) continue;
- final String code = id.getCode();
- if (!done.add(new SimpleImmutableEntry<>(authority, code))) {
- continue; // Skip "authority:code" that we already tried.
- }
- final int codeValue;
+ final int code;
try {
- codeValue = Integer.parseInt(code);
+ code = Integer.parseInt(id.getCode());
} catch (NumberFormatException e) {
- if (error == null) error = e;
- else error.addSuppressed(e);
+ if (tryWithGivenCRS) {
+ if (error == null) error = e;
+ else error.addSuppressed(e);
+ }
continue; // Ignore codes that are not integers.
}
+ final SRID search = new SRID(crs, authority, code);
+ if (done.putIfAbsent(search, code > 0) != null) {
+ continue; // Skip "authority:code" that we already tried.
+ }
/*
* Found an "authority:code" pair that we did not tested before.
* Get the WKT and verifies if the CRS is approximately equal.
diff --cc endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/package-info.java
index bf8c64d3e1,ec2b149779..f650b19a16
--- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/package-info.java
+++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/package-info.java
@@@ -17,26 -17,31 +17,31 @@@
/**
- * Data store capable to read and create features from a JDBC connection to a database.
- * {@link org.apache.sis.storage.sql.SQLStore} takes a one or more tables at construction time.
+ * Data store capable to read and write features using a JDBC connection to a database.
+ * {@link org.apache.sis.storage.sql.SimpleFeatureStore} takes one or more tables at construction time.
- * Each enumerated table is represented by a {@link org.opengis.feature.FeatureType}.
- * Each row in those table represents a {@link org.opengis.feature.Feature} instance.
- * Each relation defined by a foreigner key is represented by an {@link org.opengis.feature.FeatureAssociationRole}
+ * Each enumerated table is represented by a {@code FeatureType}.
+ * Each row in those table represents a {@code Feature} instance.
+ * Each relation defined by a foreigner key is represented by an {@code FeatureAssociationRole}
* to another feature (with transitive dependencies automatically resolved), and the other columns are represented
- * by {@link org.opengis.feature.AttributeType}.
+ * by {@code AttributeType}.
*
- * <p>The storage of spatial features in SQL databases is described by the
+ * <p>The storage of spatial features in <abbr>SQL</abbr> databases is described by the
* <a href="https://www.ogc.org/standards/sfs">OGC Simple feature access - Part 2: SQL option</a>
- * international standard, also known as ISO 19125-2. Implementation of geometric types and operations must
- * be provided by the database (sometimes through an extension, for example PostGIS on PostgreSQL databases).
- * This Java package uses those provided types and operations.</p>
+ * international standard, also known as ISO 19125-2.
+ * The implementation of geometric objects and their operations must be provided by the database.
+ * This is sometimes provided by an extension that needs to be installed explicitly.
+ * For example, when using PostgreSQL, the PostGIS extension is recommended.</p>
+ *
+ * <p>The tables to use as {@linkplain org.apache.sis.storage.sql.ResourceDefinition resource definitions}
+ * must be specified at construction time. There is no automatic discovery mechanism. Note that discovery
+ * may be done by other modules. For example, Geopackage module uses the {@code "gpkg_contents"} table.</p>
*
* <h2>Performance tips</h2>
* <p>A subset of features can be obtained by applying filters on the stream returned by
* {@link org.apache.sis.storage.FeatureSet#features(boolean)}.
* While the filter can be any {@link java.util.function.Predicate},
- * performances will be much better if they are instances of {@link org.opengis.filter.Filter}
+ * performances will be much better if they are instances of {@link org.apache.sis.filter.Filter}
- * because Apache SIS will know how to translate some of them to SQL statements.</p>
+ * because Apache SIS will know how to translate some of them to <abbr>SQL</abbr> statements.</p>
*
* <p>In filter expressions like {@code ST_Intersects(A,B)} where the <var>A</var> and <var>B</var> parameters are
* two sub-expressions evaluating to geometry values, if one of those expressions is a literal, then that literal
diff --cc endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/SQLStoreTest.java
index ed3f348bfb,80a484c799..3f8bb5a415
--- a/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/SQLStoreTest.java
+++ b/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/SQLStoreTest.java
@@@ -163,10 -174,10 +172,10 @@@ public final class SQLStoreTest extend
* Creates a {@link SQLStore} instance with the specified table as a resource, then tests some queries.
*/
private void testTableQuery(final StorageConnector connector, final ResourceDefinition table) throws Exception {
- try (SQLStore store = new SQLStore(new SQLStoreProvider(), connector, table)) {
+ try (SimpleFeatureStore store = new SimpleFeatureStore(new SQLStoreProvider(), connector, table)) {
verifyFeatureTypes(store);
final Map<String,Integer> countryCount = new HashMap<>();
- try (Stream<Feature> features = store.findResource("Cities").features(false)) {
+ try (Stream<AbstractFeature> features = store.findResource("Cities").features(false)) {
features.forEach((f) -> verifyContent(f, countryCount));
}
assertEquals(Integer.valueOf(2), countryCount.remove("CAN"));
@@@ -490,8 -503,8 +499,8 @@@
* Tests a user supplied query followed by another query built from filters.
*/
private void verifyNestedSQLQuery(final StorageConnector connector) throws Exception {
- try (SQLStore store = new SQLStore(null, connector, ResourceDefinition.query("MyParks",
+ try (SimpleFeatureStore store = new SimpleFeatureStore(null, connector, ResourceDefinition.query("MyParks",
- "SELECT * FROM " + SCHEMA + ".\"Parks\"")))
+ "SELECT * FROM " + SCHEMA + ".\"Parks\" ORDER BY \"native_name\" DESC")))
{
final FeatureSet parks = store.findResource("MyParks");
/*
diff --cc endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataFetcher.java
index 5d3028e619,b9d249cb25..9cd162687b
--- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataFetcher.java
+++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataFetcher.java
@@@ -40,11 -44,13 +44,13 @@@ import org.opengis.metadata.spatial.Cel
import org.opengis.metadata.spatial.Georectified;
import org.opengis.metadata.spatial.SpatialRepresentation;
import org.opengis.metadata.spatial.GridSpatialRepresentation;
+ import org.apache.sis.storage.event.StoreListeners;
import org.apache.sis.util.collection.CodeListSet;
+ import org.apache.sis.temporal.TemporalDate;
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.metadata.citation.Party;
-import org.opengis.metadata.citation.Responsibility;
+// Specific to the main branch:
+import org.opengis.metadata.citation.ResponsibleParty;
+import org.apache.sis.metadata.iso.DefaultMetadata;
/**
@@@ -58,6 -64,21 +64,21 @@@
* @param <T> type of temporal objects.
*/
public abstract class MetadataFetcher<T> {
+ /**
+ * Types of date to accept as a date of last update, in preference order.
+ */
+ private static final DateType[] LAST_UPDATE_TYPES = {
- DateType.LAST_UPDATE,
- DateType.LAST_REVISION,
++ DateType.valueOf("LAST_UPDATE"),
++ DateType.valueOf("LAST_REVISION"),
+ DateType.REVISION,
- DateType.IN_FORCE,
- DateType.RELEASED,
- DateType.DISTRIBUTION,
++ DateType.valueOf("IN_FORCE"),
++ DateType.valueOf("RELEASED"),
++ DateType.valueOf("DISTRIBUTION"),
+ DateType.PUBLICATION,
- DateType.ADOPTED,
++ DateType.valueOf("ADOPTED"),
+ DateType.CREATION
+ };
+
/**
* Title of the resource, or {@code null} if none.
*
@@@ -397,4 -457,47 +460,47 @@@
* @return subclass-dependent object representing the given date.
*/
protected abstract T convertDate(final Date date);
+
+ /**
+ * Returns the first date of type {@link DateType#LAST_UPDATE}.
+ * If there is no last update, then this method fallbacks on {@link DateType#LAST_REVISION}.
+ * If there is no last revision, then this method fallbacks on {@link DateType#REVISION}, <i>etc.</i>
+ *
+ * @param metadata the metadata from which to get the date of last update.
+ * @param zone the timezone to use if the time is local, or {@code null} if none.
+ * @param listeners where to report warnings, or {@code null} if none.
+ * @return date of last update, or {@code null} if none.
+ *
+ * @see #lastUpdate
+ */
+ public static Instant lastUpdate(final Metadata metadata, final ZoneId zone, final StoreListeners listeners) {
+ Temporal lastUpdate = null;
+ if (metadata != null) {
+ int lastUpdateType = LAST_UPDATE_TYPES.length;
+ search: for (Identification info : metadata.getIdentificationInfo()) {
+ final Citation citation = info.getCitation();
+ if (citation != null) {
+ for (CitationDate date : citation.getDates()) {
+ final DateType type = date.getDateType();
+ for (int i = lastUpdateType; --i >= 0;) {
+ if (LAST_UPDATE_TYPES[i].equals(type)) {
+ lastUpdateType = i;
- lastUpdate = date.getReferenceDate();
++ lastUpdate = TemporalDate.toTemporal(date.getDate());
+ if (i == 0) break search;
+ }
+ }
+ }
+ }
+ }
+ }
+ try {
+ return TemporalDate.toInstant(lastUpdate, zone);
+ } catch (DateTimeException e) {
+ if (listeners == null) {
+ throw e;
+ }
+ listeners.warning(e);
+ return null;
+ }
+ }
}
diff --cc endorsed/src/org.apache.sis.util/main/module-info.java
index a0950420fe,150970c359..08bbfa92ad
--- a/endorsed/src/org.apache.sis.util/main/module-info.java
+++ b/endorsed/src/org.apache.sis.util/main/module-info.java
@@@ -119,7 -119,10 +119,8 @@@ module org.apache.sis.util
org.apache.sis.storage.netcdf,
org.apache.sis.storage.geotiff,
org.apache.sis.storage.earthobservation,
- org.apache.sis.cql, // In the "incubator" sub-project.
- org.apache.sis.portrayal.map, // In the "incubator" sub-project.
org.apache.sis.portrayal,
+ org.apache.sis.storage.gsf, // In the "incubator" sub-project.
org.apache.sis.cloud.aws,
org.apache.sis.console,
org.apache.sis.gui, // In the "optional" sub-project.
diff --cc incubator/build.gradle.kts
index 8dbc812029,a60706f6ae..d4a0e06d86
--- a/incubator/build.gradle.kts
+++ b/incubator/build.gradle.kts
@@@ -47,6 -47,8 +47,7 @@@ dependencies
api(files("../endorsed/build/classes/java/main/org.apache.sis.referencing"))
api(files("../endorsed/build/classes/java/main/org.apache.sis.feature"))
api(files("../endorsed/build/classes/java/main/org.apache.sis.storage"))
+ api(files("../endorsed/build/classes/java/main/org.apache.sis.storage.sql"))
- api(files("../endorsed/build/classes/java/main/org.apache.sis.portrayal"))
// Test dependencies
testImplementation(tests.junit5)
@@@ -95,11 -102,45 +98,38 @@@ fun addRead(args : MutableList<String>
args.add(module + '=' + dependencies)
}
+ /*
+ * Adds a JVM argument for making an internal package accessible to another module.
+ * This is for making internal packages accessible to JUnit or to some test classes
+ * defined in other modules.
+ */
+ fun addExport(args : MutableList<String>, module : String, pkg : String, consumers : String) {
+ args.add("--add-exports")
+ args.add(module + '/' + pkg + '=' + consumers)
+ }
+
+ /*
+ * Add compiler and runtime options for patching the Apache SIS main modules with the test classes.
+ * The same options are required for both compiling and executing the tests.
+ */
+ fun addExportForTests(args : MutableList<String>) {
+ /*
+ * Some test classes need access to more internal packages than requested by the main classes.
+ * The following lines may need to be edited when export statements are added or removed in a
+ * module-info.java file of main source code, or when a test class starts using or stop using
+ * an internal API.
+ */
+ // ――――――――――――― Module name ――――――――――――――――――――――― Package to export ―――――――――――――――
- addExport(args, "org.apache.sis.feature", "org.apache.sis.geometry.wrapper.jts",
- "org.apache.sis.portrayal.map")
-
+ addExport(args, "org.apache.sis.feature", "org.apache.sis.geometry.wrapper",
+ "org.apache.sis.storage.geopackage")
-
- addExport(args, "org.apache.sis.storage", "org.apache.sis.storage.base",
- "org.apache.sis.portrayal.map")
+ }
+
/*
* Discover and execute JUnit-based tests.
*/
tasks.test {
val args = mutableListOf("-enableassertions")
+ addExportForTests(args)
- addExport(args, "org.apache.sis.cql", "org.apache.sis.cql", "ALL-UNNAMED")
setAllJvmArgs(args)
testLogging {
events("FAILED", "STANDARD_OUT", "STANDARD_ERROR")
diff --cc incubator/src/org.apache.sis.storage.geopackage/test/org/apache/sis/storage/geopackage/GpkgStoreTest.java
index 0000000000,950a00ba9c..a64f58c76d
mode 000000,100644..100644
--- a/incubator/src/org.apache.sis.storage.geopackage/test/org/apache/sis/storage/geopackage/GpkgStoreTest.java
+++ b/incubator/src/org.apache.sis.storage.geopackage/test/org/apache/sis/storage/geopackage/GpkgStoreTest.java
@@@ -1,0 -1,338 +1,339 @@@
+ /*
+ * 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.storage.geopackage;
+
+ import java.net.URL;
+ import java.net.URI;
+ import java.net.URISyntaxException;
+ import java.io.IOException;
+ import java.io.File;
+ import java.nio.file.Files;
+ import java.nio.file.Path;
+ import java.nio.file.StandardOpenOption;
+ import java.sql.Connection;
+ import java.sql.DriverManager;
+ import java.sql.SQLException;
+ import java.sql.Statement;
+ import java.util.List;
+ import java.util.stream.Stream;
-import org.opengis.feature.AttributeType;
-import org.opengis.feature.Feature;
-import org.opengis.feature.PropertyType;
+ import org.apache.sis.geometry.wrapper.Geometries;
+ import org.apache.sis.geometry.wrapper.GeometryWrapper;
+ import org.apache.sis.referencing.IdentifiedObjects;
+ import org.apache.sis.setup.OptionKey;
+ import org.apache.sis.storage.DataStore;
+ import org.apache.sis.storage.DataStoreException;
+ import org.apache.sis.storage.DataStores;
+ import org.apache.sis.storage.FeatureSet;
+ import org.apache.sis.storage.StorageConnector;
+
++import org.apache.sis.feature.AbstractFeature;
++import org.apache.sis.feature.AbstractIdentifiedType;
++import org.apache.sis.feature.DefaultAttributeType;
++
+ import org.junit.jupiter.api.Test;
+ import org.junit.jupiter.api.parallel.Execution;
+ import org.junit.jupiter.api.parallel.ExecutionMode;
+ import static org.junit.jupiter.api.Assertions.*;
+ import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
+
+ /**
+ * Tests the Geopackage store.
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+ @Execution(ExecutionMode.SAME_THREAD)
+ public final class GpkgStoreTest {
+ /**
+ * Creates a new test case.
+ */
+ public GpkgStoreTest() {
+ }
+
+ /**
+ * Returns the URL to the {@code FeatureSet.gpkg} file.
+ * If that file does not exists, it is created from the SQL script.
+ *
+ * @return {@link URL} or {@link Path} to the test Geopackage file.
+ * @throws DataStoreException if the Geopackage test file cannot be created.
+ */
+ private static Object getTestFile() throws DataStoreException {
+ URL file = GpkgStoreTest.class.getResource("FeatureSet.gpkg");
+ if (file == null) try {
+ final Path source = Path.of(GpkgStoreTest.class.getResource("FeatureSet.sql").toURI());
+ final Path target = source.resolveSibling("FeatureSet.gpkg").toAbsolutePath();
+ try (Connection c = DriverManager.getConnection("jdbc:sqlite:" + target)) {
+ try (Statement s = c.createStatement()) {
+ s.executeUpdate("PRAGMA main.application_id = " + GpkgStoreProvider.APPLICATION_ID + ';'
+ + "PRAGMA main.user_version = " + GpkgStoreProvider.VERSION + ';');
+ s.executeUpdate(Files.readString(source));
+ }
+ }
+ return target;
+ } catch (URISyntaxException | IOException | SQLException e) {
+ throw new DataStoreException("Cannot create the Geopackage test file.", e);
+ }
+ return file;
+ }
+
+ /**
+ * Tests reading a feature set from a Geopackage file.
+ *
+ * @throws DataStoreException if the Geopackage test file cannot be created or read.
+ */
+ @Test
+ public void testFeatureSet() throws DataStoreException {
+ try (DataStore store = DataStores.open(getTestFile())) {
+ final var gpkg = assertInstanceOf(GpkgStore.class, store);
+ assertEquals(7, gpkg.components().size());
+ /*
+ * Reads and verifies two features from the Geopackage test file.
+ */
+ FeatureSet fs = getResource(gpkg, "nogeom");
+ assertPropertiesEqual(fs, null, "sis:identifier", "fid", "id");
+ { // For keeping `the features` scope locale.
- final Feature[] features = getFeatures(fs).toArray(Feature[]::new);
++ final AbstractFeature[] features = getFeatures(fs).toArray(AbstractFeature[]::new);
+ assertEquals(2, features.length);
+ assertEquals(1, features[0].getPropertyValue("fid"));
+ assertEquals(1, features[0].getPropertyValue("id"));
+ assertEquals(2, features[1].getPropertyValue("fid"));
+ assertEquals(2, features[1].getPropertyValue("id"));
+ }
+ /*
+ * Reads and verifies a feature containing a point.
+ */
+ fs = getResource(gpkg, "point");
+ assertPropertiesEqual(fs, "Point",
+ "sis:identifier",
+ "sis:envelope",
+ "sis:geometry",
+ "fid",
+ "geometry",
+ "text",
+ "int32",
+ "int64",
+ "float",
+ "date",
+ "datetime",
+ "bool");
+
+ assertGeometryEquals(fs, "OGC:CRS84", "POINT (3.8691634241245 43.64618798638135)");
+ { // For keeping the `feature` scope local.
- final Feature feature = getFeatures(fs).get(0);
++ final AbstractFeature feature = getFeatures(fs).get(0);
+ assertEquals("some text", feature.getPropertyValue("text"));
+ assertEquals(123, feature.getPropertyValue("int32"));
+ assertEquals(123456, feature.getPropertyValue("int64"));
+ assertEquals(123.456, feature.getPropertyValue("float"));
+ assertEquals("2024-08-07", feature.getPropertyValue("date"));
+ assertEquals("2024-08-07T12:34:56.000", feature.getPropertyValue("datetime"));
+ assertEquals(1, feature.getPropertyValue("bool"));
+ }
+ /*
+ * Reads and verifies a feature containing a multi-point geometry.
+ */
+ fs = getResource(gpkg, "multipoint");
+ assertPropertiesEqual(fs, "MultiPoint",
+ "sis:identifier",
+ "sis:envelope",
+ "sis:geometry",
+ "fid",
+ "geom");
+
+ assertGeometryEquals(fs, "EPSG:2154",
+ "MULTIPOINT ((770147.9089501069 6283260.318250759), (770224.707537184 6283233.947140678))");
+ /*
+ * Reads and verifies a feature containing a line string.
+ */
+ fs = getResource(gpkg, "line");
+ assertPropertiesEqual(fs, "LineString",
+ "sis:identifier",
+ "sis:envelope",
+ "sis:geometry",
+ "fid",
+ "geom");
+
+ assertGeometryEquals(fs, "EPSG:3857",
+ "LINESTRING (430669.3103960207 5411208.981453437, 430655.7744657199 5410643.121416978)");
+ /*
+ * Reads and verifies a feature containing a multi-lines geometry.
+ */
+ fs = getResource(gpkg, "multiline");
+ assertPropertiesEqual(fs, "MultiLineString",
+ "sis:identifier",
+ "sis:envelope",
+ "sis:geometry",
+ "fid",
+ "geom");
+
+ assertGeometryEquals(fs, "EPSG:3395",
+ "MULTILINESTRING ((430750.52597782505 5381116.187674649, 430967.10086263693 5380950.761655851), "
+ + "(430753.08021745336 5381153.51545164, 430917.9595504581 5381182.577731505))");
+ /*
+ * Reads and verifies a feature containing a polygon.
+ */
+ fs = getResource(gpkg, "polygon");
+ assertPropertiesEqual(fs, "Polygon",
+ "sis:identifier",
+ "sis:envelope",
+ "sis:geometry",
+ "fid",
+ "geom");
+
+ assertGeometryEquals(fs, "EPSG:3857",
+ "POLYGON ((430696.4716464551 5410782.480781593, 430696.03196823364 5410729.011400482, "
+ + "430716.6968446369 5410730.2266102545, 430718.01587930095 5410780.050348468, "
+ + "430696.4716464551 5410782.480781593))");
+ /*
+ * Reads and verifies a feature containing a multi-polygons.
+ */
+ fs = getResource(gpkg, "multipolygon");
+ assertPropertiesEqual(fs, "MultiPolygon",
+ "sis:identifier",
+ "sis:envelope",
+ "sis:geometry",
+ "fid",
+ "geom");
+
+ assertGeometryEquals(fs, "EPSG:3395",
+ "MULTIPOLYGON (((430795.5091658133 5381110.830395544, "
+ + "430796.60836136667 5381129.2969556395, 430832.2222972956 5381126.118282802, "
+ + "430831.0131821869 5381108.711284476, 430795.5091658133 5381110.830395544)), "
+ + "((430849.25982837286 5381155.483207256, 430849.1499088174 5381151.396330676, "
+ + "430855.0855648057 5381151.547696444, 430855.4153234717 5381154.877743942, "
+ + "430849.25982837286 5381155.483207256)))");
+ }
+ }
+
+ /**
+ * Returns the resource of the given name.
+ *
+ * @param store the store from which to get the feature set.
+ * @param name name of the desired feature set.
+ * @return the requested feature set.
+ * @throws DataStoreException if no feature set of the given name was found.
+ */
+ private static FeatureSet getResource(final GpkgStore store, final String name) throws DataStoreException {
+ return assertInstanceOf(FeatureSet.class, store.findResource(name));
+ }
+
+ /**
+ * Asserts that the properties of the given feature set have the specified names.
+ * The geometry is expected to be always in the property at index 4 for all features
+ * (this is the case for the {@code FeatureSet.gpkg} test file).
+ *
+ * @param fs the feature set from which to get the properties.
+ * @param geometryIndex index of the geometry property.
+ * @param propertyNames the expected names of all properties.
+ */
+ private static void assertPropertiesEqual(final FeatureSet fs, final String geometryType,
+ final String... propertyNames) throws DataStoreException
+ {
- final PropertyType[] properties = fs.getType().getProperties(true).toArray(PropertyType[]::new);
++ final AbstractIdentifiedType[] properties = fs.getType().getProperties(true).toArray(AbstractIdentifiedType[]::new);
+ assertEquals(propertyNames.length, properties.length, "properties.size()");
+ for (int i=0; i<propertyNames.length; i++) {
+ assertEquals(propertyNames[i], properties[i].getName().toString());
+ }
+ if (geometryType != null) {
- var attribute = assertInstanceOf(AttributeType.class, properties[4]);
++ var attribute = assertInstanceOf(DefaultAttributeType.class, properties[4]);
+ assertEquals(geometryType, attribute.getValueClass().getSimpleName());
+ }
+ }
+
+ /**
+ * Returns all feature instances as a list.
+ *
+ * @param fs the feature set from which to get the feature instances.
+ * @return all feature instances.
+ */
- private static List<Feature> getFeatures(final FeatureSet fs) throws DataStoreException {
- try (Stream<Feature> stream = fs.features(false)) {
++ private static List<AbstractFeature> getFeatures(final FeatureSet fs) throws DataStoreException {
++ try (Stream<AbstractFeature> stream = fs.features(false)) {
+ return stream.toList();
+ }
+ }
+
+ /**
+ * Asserts that the geometry of the given feature set is equal to the expected WKT.
+ * This method opportunistically verifies that the value of the {@code "fid"} property is 1.
+ *
+ * @param resource the feature set from which to get a single feature instance.
+ * @param expectedCRS identifier of the expected CRS.
+ * @param expectedWKT expected geometry in WKT format.
+ */
+ private static void assertGeometryEquals(final FeatureSet resource, final String expectedCRS, final String expectedWKT)
+ throws DataStoreException
+ {
- final List<Feature> features = getFeatures(resource);
++ final List<AbstractFeature> features = getFeatures(resource);
+ assertEquals(1, features.size());
- final Feature feature = features.get(0);
++ final AbstractFeature feature = features.get(0);
+
+ GeometryWrapper geometry = Geometries.wrap(feature.getPropertyValue("sis:geometry")).get();
+ assertEquals(expectedCRS, IdentifiedObjects.getIdentifierOrName(geometry.getCoordinateReferenceSystem()));
+ assertEquals(expectedWKT, geometry.formatWKT(1));
+ assertEquals(1, feature.getPropertyValue("fid"));
+ }
+
+ /**
+ * Tests opening the file from a JDBC URL.
+ *
+ * @throws Exception if a <abbr>SQL</abbr>, I/O or other error occurred.
+ */
+ @Test
+ public void testOpeningFromJDBC_URL() throws Exception {
+ final Object file = getTestFile();
+ final Path path = (file instanceof Path) ? (Path) file : Path.of(((URL) file).toURI());
+ try (DataStore store = DataStores.open(new URI("jdbc:sqlite:" + path))) {
+ final var gpkg = assertInstanceOf(GpkgStore.class, store);
+ final var fs = getResource(gpkg, "polygon");
+ final var fi = fs.features(false).findAny().orElseThrow();
+ assertEquals(1, fi.getPropertyValue("fid"));
+ }
+ }
+
+ /**
+ * Tests creating an empty database, then opening it as a read-only file.
+ *
+ * @throws Exception if a <abbr>SQL</abbr>, I/O or other error occurred.
+ */
+ @Test
+ public void testOpeningReadOnlyDatabase() throws Exception {
+ final File file = File.createTempFile("sis-test", ".gpkg");
+ try {
+ // Create an empty database.
+ final var connector = new StorageConnector(file);
+ connector.setOption(OptionKey.OPEN_OPTIONS, new StandardOpenOption[] {
+ StandardOpenOption.CREATE_NEW,
+ StandardOpenOption.WRITE,
+ StandardOpenOption.READ
+ });
+ try (GpkgStore store = new GpkgStore(null, connector)) {
+ final var gpkg = assertInstanceOf(GpkgStore.class, store);
+ assertTrue(gpkg.components().isEmpty());
+ }
+ assertNotEquals(0, file.length());
+
+ // Make file read only, skip test if we cannot do that.
+ assumeTrue(file.setWritable(false));
+ try (DataStore store = DataStores.open(file)) {
+ final var gpkg = assertInstanceOf(GpkgStore.class, store);
+ assertTrue(gpkg.components().isEmpty()); // Should not raise any exception.
+ }
+ } finally {
+ assertTrue(file.setWritable(true));
+ assertTrue(file.delete());
+ }
+ }
+ }
diff --cc incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/internal/TileMatrices.java
index 0000000000,ab1b01b566..1f4398b0e3
mode 000000,100644..100644
--- a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/internal/TileMatrices.java
+++ b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/internal/TileMatrices.java
@@@ -1,0 -1,60 +1,64 @@@
+ /*
+ * 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.storage.gimi.internal;
+
+ import java.util.stream.LongStream;
+ import java.util.stream.Stream;
+ import org.apache.sis.coverage.grid.GridExtent;
+
+ /**
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+ public class TileMatrices {
+
+ private TileMatrices(){}
+
+
+ /**
+ * Create a stream of point in the GridExtent.
+ *
+ * TODO : make a more efficient implementation.
+ */
+ public static Stream<long[]> pointStream(GridExtent extent) {
+ final int dimension = extent.getDimension();
- final long[] low = extent.getLow().getCoordinateValues();
- final long[] high = extent.getHigh().getCoordinateValues();
++ final long[] low = new long[dimension];
++ final long[] high = new long[dimension];
++ for (int i=0; i<dimension; i++) {
++ low[i] = extent.getLow(i);
++ high[i] = extent.getHigh(i);
++ }
+
+ Stream<long[]> stream = LongStream.range(low[0], high[0]+1)
+ .mapToObj((long value) -> {
+ final long[] array = new long[dimension];
+ array[0] = value;
+ return array;
+ });
+ for (int i = 1; i <dimension; i++) {
+ final int idx = i;
+ stream = stream.flatMap((long[] t) -> LongStream.range(low[idx], high[idx]+1)
+ .mapToObj((long value) -> {
+ final long[] array = t.clone();
+ array[idx] = value;
+ return array;
+ }));
+ }
+ return stream;
+ }
+
+ }
diff --cc netbeans-project/ivy.xml
index 9532a5ffd2,02d580d8dc..5f97b17f2c
--- a/netbeans-project/ivy.xml
+++ b/netbeans-project/ivy.xml
@@@ -11,10 -11,8 +11,10 @@@
<ivy-module version="2.0">
<info organisation="org.apache" module="sis"/>
<dependencies defaultconf="default">
+ <dependency org="org.opengis" name="geoapi" rev="3.0.2"/>
+ <dependency org="org.opengis" name="geoapi-conformance" rev="3.0.2"/>
<dependency org="javax.measure" name="unit-api" rev="2.1.3"/>
- <dependency org="org.glassfish.jaxb" name="jaxb-runtime" rev="4.0.4"/>
+ <dependency org="org.glassfish.jaxb" name="jaxb-runtime" rev="4.0.5"/>
<dependency org="org.eclipse" name="yasson" rev="3.0.3"/>
<dependency org="com.esri.geometry" name="esri-geometry-api" rev="2.2.4"/>
<dependency org="org.locationtech.jts" name="jts-core" rev="1.19.0"/>
diff --cc netbeans-project/nbproject/project.properties
index da94918e12,b157430750..9f48612b3e
--- a/netbeans-project/nbproject/project.properties
+++ b/netbeans-project/nbproject/project.properties
@@@ -110,9 -117,12 +117,11 @@@ test.options = --add-modules jama,Geogr
--add-exports org.apache.sis.metadata/org.apache.sis.xml.privy=org.apache.sis.storage.geotiff \
--add-exports org.apache.sis.metadata/org.apache.sis.xml.bind.gcx=org.apache.sis.referencing \
--add-exports org.apache.sis.metadata/org.apache.sis.metadata.privy=org.apache.sis.referencing.gazetteer \
+ --add-exports org.apache.sis.metadata/org.apache.sis.metadata.sql.privy=org.apache.sis.referencing.epsg \
--add-exports org.apache.sis.referencing/org.apache.sis.referencing.internal=org.apache.sis.openoffice \
--add-exports org.apache.sis.feature/org.apache.sis.feature.privy=org.apache.sis.storage.sql \
- --add-exports org.apache.sis.feature/org.apache.sis.geometry.wrapper.jts=org.apache.sis.storage.sql,org.apache.sis.portrayal.map \
+ --add-exports org.apache.sis.feature/org.apache.sis.geometry.wrapper.jts=org.apache.sis.storage.sql \
+ --add-exports org.apache.sis.feature/org.apache.sis.geometry.wrapper=org.apache.sis.storage.geopackage \
- --add-exports org.apache.sis.storage/org.apache.sis.storage.base=org.apache.sis.portrayal.map \
--add-exports org.apache.sis.storage/org.apache.sis.storage.test=${modules.list}
#
diff --cc optional/src/org.apache.sis.referencing.database/test/org/apache/sis/resources/embedded/EmbeddedResourcesTest.java
index 0000000000,80e2813ab1..8858f0d601
mode 000000,100644..100644
--- a/optional/src/org.apache.sis.referencing.database/test/org/apache/sis/resources/embedded/EmbeddedResourcesTest.java
+++ b/optional/src/org.apache.sis.referencing.database/test/org/apache/sis/resources/embedded/EmbeddedResourcesTest.java
@@@ -1,0 -1,140 +1,141 @@@
+ /*
+ * 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.resources.embedded;
+
+ import java.io.IOException;
+ import java.sql.Connection;
+ import java.sql.ResultSet;
+ import java.sql.Statement;
+ import java.util.ServiceLoader;
+ import javax.sql.DataSource;
+ import org.opengis.util.FactoryException;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
+ import org.apache.sis.setup.InstallationResources;
+ import org.apache.sis.metadata.sql.privy.Initializer;
+ import org.apache.sis.system.DataDirectory;
+ import org.apache.sis.referencing.CRS;
+ import org.apache.sis.referencing.factory.sql.epsg.ScriptProvider;
+
++import org.apache.sis.referencing.crs.AbstractCRS;
++
+ // Test dependencies
+ import org.junit.jupiter.api.Test;
+ import static org.junit.jupiter.api.Assertions.*;
+ import static org.junit.jupiter.api.Assumptions.assumeTrue;
+ import org.apache.sis.test.TestUtilities;
+
+
+ /**
+ * Tests {@link EmbeddedResources}.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ */
+ public final strictfp class EmbeddedResourcesTest {
+ /**
+ * Whether the database has been created.
+ */
+ private static boolean databaseCreated;
+
+ /**
+ * Creates a new test case.
+ */
+ public EmbeddedResourcesTest() {
+ }
+
+ /**
+ * Skips the test if the EPSG scripts are not present.
+ * This method uses {@code LICENSE.txt} as a sentinel file.
+ */
+ private static void assumeDataPresent() {
+ assumeTrue(ScriptProvider.class.getResource("LICENSE.txt") != null,
+ "EPSG resources not found. See `README.md` for manual installation.");
+ }
+
+ /**
+ * Returns the {@link EmbeddedResources} instance declared in the {@code META-INF/services/} directory.
+ * The provider may coexist with providers defined in other modules, so we need to filter them.
+ */
+ private static synchronized InstallationResources getInstance() {
+ if (!databaseCreated) try {
+ new Generator().run();
+ databaseCreated = true;
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
+
+ InstallationResources provider = null;
+ for (InstallationResources candidate : ServiceLoader.load(InstallationResources.class)) {
+ if (candidate instanceof EmbeddedResources) {
+ assertNull(provider, "Expected only one instance.");
+ provider = candidate;
+ }
+ }
+ assertNotNull(provider, "Expected an instance.");
+ return provider;
+ }
+
+ /**
+ * Tests fetching the licenses.
+ *
+ * @throws IOException if an error occurred while reading a license.
+ */
+ @Test
+ public void testLicences() throws IOException {
+ assumeDataPresent();
+ final InstallationResources provider = getInstance();
+ assertTrue(provider.getLicense("Embedded", null, "text/plain").contains("IOGP"));
+ assertTrue(provider.getLicense("Embedded", null, "text/html" ).contains("IOGP"));
+ }
+
+ /**
+ * Tests connecting to the database.
+ *
+ * @throws Exception if an error occurred while fetching the data source, or connecting to the database.
+ */
+ @Test
+ public void testConnection() throws Exception {
+ assumeDataPresent();
+ final String dir = DataDirectory.getenv();
+ assertTrue((dir == null) || dir.isEmpty(), "The SIS_DATA environment variable must be unset for enabling this test.");
+ final DataSource ds = Initializer.getDataSource();
+ assertNotNull(ds, "Cannot find the data source.");
+ try (Connection c = ds.getConnection()) {
+ assertEquals("jdbc:derby:classpath:SIS_DATA/Databases/spatial-metadata", c.getMetaData().getURL(), "URL");
+ try (Statement s = c.createStatement()) {
+ try (ResultSet r = s.executeQuery("SELECT COORD_REF_SYS_NAME FROM EPSG.\"Coordinate Reference System\" WHERE COORD_REF_SYS_CODE = 4326")) {
+ assertTrue(r.next(), "ResultSet.next()");
+ assertEquals(r.getString(1), "WGS 84");
+ assertFalse(r.next(), "ResultSet.next()");
+ }
+ }
+ }
+ }
+
+ /**
+ * Tests {@link CRS#forCode(String)} with the embedded database. This test asks for a CRS for which
+ * no hard-coded fallback exists in {@link org.apache.sis.referencing.CommonCRS}. Consequently this
+ * test should fail if we do not have a connection to a complete EPSG database.
+ *
+ * @throws FactoryException if an error occurred while creating the CRS.
+ */
+ @Test
+ public void testCrsforCode() throws FactoryException {
+ assumeDataPresent();
- CoordinateReferenceSystem crs = CRS.forCode("EPSG:6676");
++ var crs = assertInstanceOf(AbstractCRS.class, CRS.forCode("EPSG:6676"));
+ String area = TestUtilities.getSingleton(crs.getDomains()).getDomainOfValidity().getDescription().toString();
+ assertTrue(area.contains("Japan"), area);
+ }
+ }
diff --cc settings.gradle.kts
index f312fd21d4,f2921b2bec..a5e37ecf51
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@@ -57,10 -59,10 +57,10 @@@ dependencyResolutionManagement
*/
versionCatalogs {
create("libs") {
- library("geoapi", "org.opengis", "geoapi-pending") .version {strictly(geoapiVersion)}
+ library("geoapi", "org.opengis", "geoapi") .version {strictly(geoapiVersion)}
library("units", "javax.measure", "unit-api") .version {strictly("[2.1, 3.0["); prefer("2.1.3")}
- library("jaxb.api", "jakarta.xml.bind", "jakarta.xml.bind-api").version {strictly("[4.0, 5.0["); prefer("4.0.1")}
- library("jaxb.impl", "org.glassfish.jaxb", "jaxb-runtime") .version {strictly("[4.0, 5.0["); prefer("4.0.4")}
+ library("jaxb.api", "jakarta.xml.bind", "jakarta.xml.bind-api").version {strictly("[4.0, 5.0["); prefer("4.0.2")}
+ library("jaxb.impl", "org.glassfish.jaxb", "jaxb-runtime") .version {strictly("[4.0, 5.0["); prefer("4.0.5")}
library("yasson", "org.eclipse", "yasson") .version {strictly("[3.0, 4.0["); prefer("3.0.3")}
library("jts.core", "org.locationtech.jts", "jts-core") .version {strictly("[1.15, 2.0["); prefer("1.19.0")}
library("esri.geometry", "com.esri.geometry", "esri-geometry-api") .version {strictly("[2.0, 3.0["); prefer("2.2.4")}