This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/sis.git
commit 3c800ecbf613bf07cf962cef6e7d9bdab100967f Merge: 8eb0911e58 3b34cf323f Author: Martin Desruisseaux <[email protected]> AuthorDate: Wed May 20 19:02:19 2026 +0200 Merge branch 'geoapi-3.1' .../main/org/apache/sis/console/CommandRunner.java | 4 +- .../apache/sis/console/FormattedOutputCommand.java | 2 +- .../org/apache/sis/console/TranslateCommand.java | 2 +- .../coverage/grid/CoordinateOperationFinder.java | 44 +- .../apache/sis/coverage/grid/GridCRSBuilder.java | 128 +++++- .../apache/sis/coverage/grid/GridGeometryTest.java | 48 ++ .../org/apache/sis/metadata/MetadataStandard.java | 2 +- .../org/apache/sis/metadata/TitleProperty.java | 2 +- .../main/org/apache/sis/metadata/TreeNode.java | 90 +++- .../org/apache/sis/metadata/TreeNodeChildren.java | 44 +- .../org/apache/sis/metadata/TreeTableView.java | 67 +-- .../apache/sis/metadata/ValueExistencePolicy.java | 104 +++-- .../main/org/apache/sis/metadata/package-info.java | 2 +- .../org/apache/sis/xml/PooledUnmarshaller.java | 8 +- .../main/org/apache/sis/xml/TransformedEvent.java | 2 +- .../main/org/apache/sis/xml/XML.java | 4 +- .../main/org/apache/sis/xml/bind/gcx/Anchor.java | 9 +- .../sis/xml/internal/shared/InputFactory.java | 42 +- .../main/org/apache/sis/xml/package-info.java | 24 +- .../apache/sis/metadata/TreeNodeChildrenTest.java | 14 +- .../test/org/apache/sis/metadata/TreeNodeTest.java | 11 +- .../apache/sis/metadata/TreeTableFormatTest.java | 15 +- .../org/apache/sis/metadata/TreeTableViewTest.java | 3 +- .../sis/xml/internal/shared/InputFactoryTest.java | 8 +- .../main/org/apache/sis/io/wkt/WKTFormat.java | 4 +- .../sis/referencing/cs/CoordinateSystems.java | 2 +- .../referencing/datum/DefaultDatumEnsemble.java | 31 +- .../apache/sis/referencing/datum/package-info.java | 2 +- .../factory/CommonAuthorityFactory.java | 6 +- .../referencing/factory/FactoryDataException.java | 2 +- .../referencing/factory/GeodeticObjectFactory.java | 2 +- ...xception.java => InternalFactoryException.java} | 28 +- .../internal/ParameterizedTransformBuilder.java | 4 +- .../internal/shared/CoordinateOperations.java | 4 +- .../internal/shared/OperationMethodExt.java | 73 +++ .../operation/AbstractCoordinateOperation.java | 7 +- .../operation/AbstractSingleOperation.java | 4 +- .../operation/CoordinateOperationContext.java | 2 +- .../operation/CoordinateOperationFinder.java | 69 ++- .../operation/CoordinateOperationRegistry.java | 14 +- .../operation/DefaultConcatenatedOperation.java | 4 +- .../DefaultCoordinateOperationFactory.java | 19 +- .../sis/referencing/operation/DefaultFormula.java | 9 +- .../operation/DefaultOperationMethod.java | 4 +- .../referencing/operation/gridded/LoadedGrid.java | 2 +- .../operation/projection/ZonedGridSystem.java | 3 +- .../provider/FranceGeocentricInterpolation.java | 3 +- .../GeocentricAffineBetweenGeographic.java | 3 +- .../operation/provider/GeocentricToGeographic.java | 3 +- .../operation/provider/Geographic3Dto2D.java | 3 +- .../operation/provider/Spherical2Dto3D.java | 3 +- .../operation/provider/VerticalOffset.java | 3 +- .../transform/DefaultMathTransformFactory.java | 3 +- .../transform/EllipsoidToRadiusTransform.java | 3 +- .../operation/transform/MathTransformProvider.java | 31 +- .../test/org/apache/sis/io/wkt/WKTFormatTest.java | 21 +- .../operation/DefaultTransformationTest.java | 3 +- .../main/org/apache/sis/storage/landsat/Band.java | 4 +- .../org/apache/sis/storage/landsat/BandGroup.java | 2 +- .../apache/sis/storage/landsat/LandsatStore.java | 2 +- .../apache/sis/storage/landsat/MetadataReader.java | 2 +- .../storage/landsat/LandsatStoreProviderTest.java | 2 +- .../apache/sis/storage/geotiff/Compression.java | 2 +- .../apache/sis/storage/geotiff/FormatModifier.java | 2 +- .../apache/sis/storage/geotiff/GeoTiffStore.java | 4 +- .../apache/sis/storage/geotiff/NativeMetadata.java | 106 ++++- .../org/apache/sis/storage/geotiff/Writer.java | 2 +- .../geotiff/reader/GridGeometryBuilder.java | 2 +- .../geotiff/reader/ImageMetadataBuilder.java | 2 +- .../sis/storage/geotiff/reader/Localization.java | 3 +- .../sis/storage/geotiff/reader/XMLMetadata.java | 5 +- .../sis/storage/geotiff/writer/GeoEncoder.java | 2 +- .../storage/geotiff/reader/XMLMetadataTest.java | 2 +- .../apache/sis/storage/netcdf/MetadataReader.java | 2 +- .../org/apache/sis/storage/netcdf/NetcdfStore.java | 2 +- .../sis/storage/netcdf/NetcdfStoreProvider.java | 2 +- .../apache/sis/storage/netcdf/base/Decoder.java | 2 +- .../sis/storage/netcdf/base/RasterResource.java | 2 +- .../sis/storage/netcdf/classic/ChannelDecoder.java | 2 +- .../sis/storage/netcdf/ucar/DecoderWrapper.java | 2 +- .../main/org/apache/sis/storage/sql/SQLStore.java | 4 +- .../apache/sis/storage/sql/feature/Database.java | 2 +- .../sis/storage/sql/feature/SchemaModifier.java | 4 +- .../sis/storage/sql/postgis/PostgresTest.java | 2 +- .../main/org/apache/sis/storage/gpx/Store.java | 2 +- .../main/org/apache/sis/storage/gpx/Types.java | 2 +- .../sis/storage/xml/stream/StaxDataStore.java | 41 +- .../org/apache/sis/storage/gpx/ReaderTest.java | 2 +- .../org/apache/sis/storage/gpx/UpdaterTest.java | 2 +- .../org/apache/sis/storage/gpx/WriterTest.java | 2 +- .../org.apache.sis.storage/main/module-info.java | 13 + .../apache/sis/io/stream/InternalOptionKey.java | 2 +- .../org/apache/sis/storage/AbstractFeatureSet.java | 2 +- .../sis/storage/AbstractGridCoverageResource.java | 2 +- .../org/apache/sis/storage/AbstractResource.java | 2 +- .../org/apache/sis/storage/CoverageSubset.java | 2 +- .../main/org/apache/sis/storage/DataOptionKey.java | 83 +--- .../main/org/apache/sis/storage/DataStore.java | 3 +- .../org/apache/sis/storage/DataStoreProvider.java | 13 + .../org/apache/sis/storage/DataStoreRegistry.java | 2 +- .../main/org/apache/sis/storage/FeatureSubset.java | 2 +- .../sis/storage/InternalDataStoreException.java | 9 +- .../main/org/apache/sis/storage/OptionKey.java | 297 ++++++++++++ .../org/apache/sis/storage/StorageConnector.java | 19 +- .../storage/aggregate/AggregatedFeatureSet.java | 2 +- .../sis/storage/aggregate/AggregatedResource.java | 2 +- .../aggregate/BandAggregateGridResource.java | 2 +- .../aggregate/ConcatenatedGridResource.java | 2 +- .../sis/storage/aggregate/GroupAggregate.java | 2 +- .../main/org/apache/sis/storage/base/CodeType.java | 12 +- .../sis/storage/base/DocumentedStoreProvider.java | 2 +- .../org/apache/sis/storage/base/PRJDataStore.java | 2 +- .../org/apache/sis/storage/base/URIDataStore.java | 12 +- .../sis/storage/base/URIDataStoreProvider.java | 14 +- .../org/apache/sis/storage/base/package-info.java | 2 +- .../main/org/apache/sis/storage/csv/Store.java | 9 +- .../org/apache/sis/storage/csv/StoreProvider.java | 6 +- .../org/apache/sis/storage/csv/package-info.java | 2 +- .../apache/sis/storage/esri/AsciiGridStore.java | 6 +- .../org/apache/sis/storage/esri/RasterStore.java | 2 +- .../main/org/apache/sis/storage/folder/Store.java | 7 +- .../apache/sis/storage/folder/StoreProvider.java | 4 +- .../apache/sis/storage/folder/WritableStore.java | 2 +- .../apache/sis/storage/image/WorldFileStore.java | 4 +- .../apache/sis/storage/image/WritableStore.java | 2 +- .../storage/{base => metadata}/LegalSymbols.java | 3 +- .../{base => metadata}/MetadataBuilder.java | 3 +- .../{base => metadata}/MetadataFetcher.java | 8 +- .../{base => metadata}/ResourceLineage.java | 2 +- .../storage/{base => metadata}/package-info.java | 4 +- .../sis/storage/modifier/CoverageModifier.java | 10 +- .../org/apache/sis/storage/tiling/TileMatrix.java | 2 +- .../apache/sis/storage/tiling/TileMatrixSet.java | 2 +- .../main/org/apache/sis/storage/wkt/Store.java | 4 +- .../main/org/apache/sis/storage/xml/Store.java | 4 +- .../org/apache/sis/storage/DataOptionKeyTest.java | 46 -- .../org/apache/sis/storage}/OptionKeyTest.java | 23 +- .../apache/sis/storage/StorageConnectorTest.java | 1 - .../apache/sis/storage/csv/StoreProviderTest.java | 2 +- .../test/org/apache/sis/storage/csv/StoreTest.java | 5 +- .../apache/sis/storage/esri/WritableStoreTest.java | 2 +- .../sis/storage/image/WorldFileStoreTest.java | 2 +- .../{base => metadata}/MetadataBuilderTest.java | 2 +- .../main/org/apache/sis/io/CompoundFormat.java | 77 ++-- .../main/org/apache/sis/io/LineAppender.java | 6 +- .../main/org/apache/sis/math/StatisticsFormat.java | 14 +- .../main/org/apache/sis/setup/GeometryLibrary.java | 2 +- .../main/org/apache/sis/setup/OptionKey.java | 46 +- .../main/org/apache/sis/setup/package-info.java | 5 +- .../sis/util/AbstractInternationalString.java | 22 +- .../main/org/apache/sis/util/Exceptions.java | 6 +- .../org/apache/sis/util/collection/TreeTable.java | 18 +- .../sis/util/collection/TreeTableFormat.java | 67 +-- .../apache/sis/util/internal/shared/Constants.java | 2 +- .../sis/util/internal/shared/PropertyFormat.java | 74 +-- .../internal/shared/TreeFormatCustomization.java | 51 --- .../sis/util/internal/shared/TreeTableForGUI.java | 42 ++ .../org/apache/sis/util/resources/Vocabulary.java | 10 + .../sis/util/resources/Vocabulary.properties | 2 + .../sis/util/resources/Vocabulary_fr.properties | 2 + .../storage/coveragejson/CoverageJsonStore.java | 2 +- .../sis/storage/geoheif/CoverageBuilder.java | 9 +- .../apache/sis/storage/geoheif/GeoHeifStore.java | 5 +- .../sis/storage/geoheif/UncompressedImage.java | 2 +- .../main/org/apache/sis/storage/isobmff/Box.java | 4 +- .../apache/sis/storage/isobmff/BoxRegistry.java | 9 + .../apache/sis/storage/isobmff/ContainerBox.java | 15 +- .../org/apache/sis/storage/isobmff/Extension.java | 20 +- .../org/apache/sis/storage/isobmff/FullBox.java | 41 +- .../{gimi/package-info.java => Incomplete.java} | 19 +- .../sis/storage/isobmff/MainBoxRegistry.java | 2 +- .../apache/sis/storage/isobmff/NodeSummary.java | 59 +++ .../org/apache/sis/storage/isobmff/Reader.java | 19 +- .../main/org/apache/sis/storage/isobmff/Root.java | 2 +- .../org/apache/sis/storage/isobmff/TreeNode.java | 507 +++++++++++++++------ .../storage/isobmff/base/ColourInformation.java | 2 +- .../sis/storage/isobmff/base/CombinaisonType.java | 2 +- .../apache/sis/storage/isobmff/base/Copyright.java | 3 +- .../sis/storage/isobmff/base/EntityToGroup.java | 2 + .../storage/isobmff/base/FDItemInfoExtension.java | 4 +- .../apache/sis/storage/isobmff/base/FileType.java | 2 +- .../apache/sis/storage/isobmff/base/GroupList.java | 2 +- .../sis/storage/isobmff/base/HandlerReference.java | 2 +- .../storage/isobmff/base/IdentifiedMediaData.java | 2 +- .../apache/sis/storage/isobmff/base/ItemInfo.java | 17 +- .../sis/storage/isobmff/base/ItemInfoEntry.java | 9 +- .../sis/storage/isobmff/base/ItemLocation.java | 2 +- .../sis/storage/isobmff/base/ItemProperties.java | 40 +- .../isobmff/base/ItemPropertyAssociation.java | 41 +- .../isobmff/base/ItemPropertyContainer.java | 2 +- .../sis/storage/isobmff/base/ItemReference.java | 5 +- .../org/apache/sis/storage/isobmff/base/Meta.java | 5 +- .../org/apache/sis/storage/isobmff/base/Movie.java | 2 +- .../sis/storage/isobmff/base/MovieHeader.java | 5 +- .../sis/storage/isobmff/base/OriginalFileType.java | 2 +- .../sis/storage/isobmff/base/PrimaryItem.java | 2 +- .../isobmff/base/ProgressiveDownloadInfo.java | 5 +- .../isobmff/base/SingleItemTypeReference.java | 2 +- .../org/apache/sis/storage/isobmff/base/Track.java | 2 +- .../sis/storage/isobmff/base/TrackHeader.java | 27 +- .../apache/sis/storage/isobmff/base/UserData.java | 2 +- .../storage/isobmff/{gimi => geo}/ModelCRS.java | 9 +- .../isobmff/{gimi => geo}/ModelTiePoint.java | 29 +- .../isobmff/{gimi => geo}/ModelTransformation.java | 6 +- .../isobmff/geo/TiledImageConfiguration.java | 164 +++++++ .../isobmff/{gimi => geo}/UnknownProperty.java | 4 +- .../isobmff/{gimi => geo}/package-info.java | 2 +- .../isobmff/gimi/TiledImageConfiguration.java | 56 --- .../sis/storage/isobmff/image/CreationTime.java | 1 + .../storage/isobmff/image/ModificationTime.java | 1 + .../sis/storage/isobmff/image/UserDescription.java | 3 +- .../sis/storage/isobmff/mpeg/ChromaLocation.java | 5 +- .../apache/sis/storage/isobmff/mpeg/Component.java | 1 + .../isobmff/mpeg/ComponentReferenceLevel.java | 5 +- .../isobmff/mpeg/DepthMappingInformation.java | 5 +- .../storage/isobmff/mpeg/DisparityInformation.java | 5 +- .../sis/storage/isobmff/mpeg/FieldInterlace.java | 5 +- .../storage/isobmff/mpeg/FieldInterlaceType.java | 5 +- .../isobmff/mpeg/FramePackingInformation.java | 5 +- .../mpeg/PolarizationPatternDefinition.java | 5 +- .../storage/isobmff/mpeg/SensorBadPixelsMap.java | 5 +- .../mpeg/SensorNonUniformityCorrection.java | 5 +- .../sis/storage/isobmff/mpeg/TAIClockInfo.java | 6 +- .../sis/storage/isobmff/mpeg/TAITimeStamp.java | 5 +- .../isobmff/mpeg/UncompressedFrameConfig.java | 2 +- .../storage/isobmff/video/ContentDescribes.java | 5 +- .../isobmff/{gimi => geo}/ExtensionTest.java | 4 +- .../org/apache/sis/storage/geopackage/Content.java | 2 +- .../sis/storage/geopackage/GpkgStoreProvider.java | 2 +- .../apache/sis/storage/geopackage/Initializer.java | 2 +- .../sis/storage/geopackage/GpkgStoreTest.java | 2 +- .../conformance/CoreConformanceTest.java | 2 +- .../main/org/apache/sis/storage/gsf/GSFStore.java | 2 +- .../sis/storage/shapefile/ShapefileProvider.java | 13 +- .../sis/storage/shapefile/ShapefileStore.java | 38 +- .../apache/sis/storage/shapefile/dbf/DBFField.java | 2 +- .../sis/storage/shapefile/shp/ShapeRecord.java | 1 + .../sis/storage/shapefile/ShapefileStoreTest.java | 31 ++ .../sis/storage/shapefile/dbf/DBFIOTest.java | 2 +- .../apache/sis/storage/shapefile/dbf/Snippets.java | 2 +- .../test/org/apache/sis/storage/shapefile/noid.cpg | 1 + .../test/org/apache/sis/storage/shapefile/noid.dbf | Bin 0 -> 147 bytes .../test/org/apache/sis/storage/shapefile/noid.prj | 1 + .../test/org/apache/sis/storage/shapefile/noid.shp | Bin 0 -> 128 bytes .../test/org/apache/sis/storage/shapefile/noid.shx | Bin 0 -> 108 bytes .../sis/storage/shapefile/shp/ShapeIOTest.java | 2 +- .../apache/sis/storage/shapefile/shp/Snippets.java | 2 +- .../apache/sis/gui/coverage/BandRangeTable.java | 6 +- .../sis/gui/coverage/ImagePropertyExplorer.java | 12 +- .../org/apache/sis/gui/dataset/FeatureTable.java | 19 +- .../sis/gui/internal/IdentityValueFactory.java | 4 +- .../sis/gui/internal/PropertyValueFormats.java | 4 +- .../sis/gui/internal/PropertyValueFormatter.java | 2 +- .../org/apache/sis/gui/metadata/MetadataTree.java | 157 +++++-- .../sis/gui/metadata/StandardMetadataTree.java | 10 +- .../org/apache/sis/gui/metadata/package-info.java | 2 +- .../org/apache/sis/storage/gdal/GDALStore.java | 4 +- .../apache/sis/storage/gdal/GDALStoreProvider.java | 2 +- .../org/apache/sis/storage/gdal/TiledResource.java | 2 +- 259 files changed, 2605 insertions(+), 1374 deletions(-) diff --cc endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCRSBuilder.java index 7a1df0e19d,5421b8639c..d3116da0a7 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCRSBuilder.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCRSBuilder.java @@@ -172,13 -247,11 +247,11 @@@ final class GridCRSBuilder extends Refe throws FactoryException { properties.put(DefiningConversion.NORMALIZED_KEY, Boolean.FALSE); - properties.put(ObjectDomain.SCOPE_KEY, SCOPE); + properties.put(Datum.SCOPE_KEY, SCOPE); grid.getGeographicExtent().ifPresent((domain) -> { - properties.put(ObjectDomain.DOMAIN_OF_VALIDITY_KEY, new DefaultExtent(null, domain, null, null)); + properties.put(Datum.DOMAIN_OF_VALIDITY_KEY, new DefaultExtent(null, domain, null, null)); }); - if (grid.isDefined(GridGeometry.EXTENT)) { - extent = grid.getExtent(); - } + fullGrid = grid; if (derived || grid.isDefined(GridGeometry.CRS | GridGeometry.GRID_TO_CRS)) try { separator = new TransformSeparator(grid.getGridToCRS(anchor).inverse()); return forComponent(name, grid.getCoordinateReferenceSystem(), 0, 0); diff --cc endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/TreeNodeChildrenTest.java index 879dbbc324,e59dfb3026..c6122ee9f7 --- a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/TreeNodeChildrenTest.java +++ b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/TreeNodeChildrenTest.java @@@ -232,11 -229,11 +232,11 @@@ public final class TreeNodeChildrenTes * We need to perform the tests on the "Date" node, not on the "DefaultCitation" node. */ final TreeTable.Node node = assertSingleton(create(citation, ValueExistencePolicy.COMPACT)); - assertEquals(15340, ((LocalDate) node.getValue(TableColumn.VALUE)).toEpochDay()); - final TreeNodeChildren children = (TreeNodeChildren) node.getChildren(); + assertEquals(15340, assertInstanceOf(LocalDate.class, node.getValue(TableColumn.VALUE)).toEpochDay()); + final TreeNodeChildren children = assertInstanceOf(TreeNodeChildren.class, node.getChildren()); final String[] expected = { // The "Date" node should be omitted because merged with the parent "Date" node. - "DateType.CREATION" + "DateType[CREATION]" }; assertEquals(0, children.titleProperty); assertFalse (children.isEmpty()); diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java index b4ca7845a3,8d78cd0390..03988ff65c --- 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 @@@ -439,24 -556,23 +439,23 @@@ check: if (it.hasNext()) * @hidden because nothing new to said. */ @Override - public boolean equals(final Object object, final ComparisonMode mode) { - if (!super.equals(object, mode)) { - return false; - } - switch (mode) { - case STRICT: { - final var that = (DefaultDatumEnsemble<?>) object; - return members.equals(that.members) && ensembleAccuracy.equals(that.ensembleAccuracy); - } - default: { - if (!(object instanceof DefaultDatumEnsemble<?>)) { - return false; + public boolean equals(final Object object, ComparisonMode mode) { + if (super.equals(object, mode)) { + switch (mode) { + case STRICT: { + final var that = (DefaultDatumEnsemble<?>) object; + return members.equals(that.members) && ensembleAccuracy.equals(that.ensembleAccuracy); + } + default: { - final var that = (DatumEnsemble<?>) object; ++ final var that = (DefaultDatumEnsemble<?>) object; + if (Utilities.deepEquals(getEnsembleAccuracy(), that.getEnsembleAccuracy(), mode)) { + if (mode == ComparisonMode.IGNORE_METADATA) mode = ComparisonMode.COMPATIBILITY; + return Utilities.deepEquals(getMembers(), that.getMembers(), mode); + } } - final var that = (DefaultDatumEnsemble<?>) object; - return Utilities.deepEquals(getMembers(), that.getMembers(), mode) && - Utilities.deepEquals(getEnsembleAccuracy(), that.getEnsembleAccuracy(), mode); } } + return false; } /** diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java index e5ccf4b103,611c8d7e25..9af989d31c --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java @@@ -1200,8 -1206,50 +1201,50 @@@ public class CoordinateOperationFinder if (isIdentity(step3)) return concatenate(step1, step2); if (canHide(step1.getName())) return concatenate(concatenate(step1, step2), step3); if (canHide(step3.getName())) return concatenate(step1, concatenate(step2, step3)); - final Map<String, ?> properties = defaultName(step1.getSourceCRS(), step3.getTargetCRS()); - return factory.createConcatenatedOperation(properties, step1, step2, step3); + return createConcatenatedOperation(step1.getSourceCRS(), step3.getTargetCRS(), step1, step2, step3); + } + + /** + * Creates an ordered sequence of two or more single coordinate operations. + * The {@code sourceCRS} and {@code targetCRS} arguments of this method are + * needed for detecting whether the source or last step needs to be reversed. + * + * <p>If any operation step uses a method that implements the {@link OperationMethodExt} interface, + * it will be used for enriching the metadata. It may go as far as overriding the default algorithm for + * computing the transform if a method supplies an {@value DefaultConcatenatedOperation#TRANSFORM_KEY} + * value.</p> + * + * @param sourceCRS the source <abbr>CRS</abbr>, or {@code null} for the source of the first step. + * @param targetCRS the target <abbr>CRS</abbr>, or {@code null} for the target of the last effective step. + * @param operations the sequence of operations. Should contain at least two operations. + * @return the concatenated operation created from the given arguments. + * @throws FactoryException if the object creation failed. + */ + private CoordinateOperation createConcatenatedOperation( + final CoordinateReferenceSystem sourceCRS, + final CoordinateReferenceSystem targetCRS, + final CoordinateOperation... operations) throws FactoryException + { + final var properties = new HashMap<String, Object>(4); + properties.put(IdentifiedObject.NAME_KEY, new CRSPair(sourceCRS, targetCRS).toString()); + final var merge = new Consumer<CoordinateOperation>() { + @Override public void accept(final CoordinateOperation operation) { + final OperationMethod method = CoordinateOperations.getMethod(operation); + if (method instanceof OperationMethodExt) { + final var provider = (OperationMethodExt) method; + provider.completeOperationMetadata(context, sourceCRS, targetCRS, properties); + } + if (operation instanceof ConcatenatedOperation) { + ((ConcatenatedOperation) operation).getOperations().stream().forEach(this); + } + } + }; + try { + for (CoordinateOperation step : operations) merge.accept(step); - return factory.createConcatenatedOperation(properties, sourceCRS, targetCRS, operations); ++ return factorySIS.createConcatenatedOperation(properties, sourceCRS, targetCRS, operations); + } catch (BackingStoreException e) { + throw e.unwrapOrRethrow(FactoryException.class); + } } /** diff --cc endorsed/src/org.apache.sis.storage.earthobservation/main/org/apache/sis/storage/landsat/MetadataReader.java index 646e176680,348fa06f0b..17f07b7b78 --- a/endorsed/src/org.apache.sis.storage.earthobservation/main/org/apache/sis/storage/landsat/MetadataReader.java +++ b/endorsed/src/org.apache.sis.storage.earthobservation/main/org/apache/sis/storage/landsat/MetadataReader.java @@@ -64,11 -64,10 +64,11 @@@ import org.apache.sis.referencing.inter import org.apache.sis.referencing.internal.shared.ReferencingFactoryContainer; import org.apache.sis.referencing.operation.provider.PolarStereographicB; import org.apache.sis.referencing.operation.provider.TransverseMercator; - import org.apache.sis.storage.base.MetadataBuilder; + import org.apache.sis.storage.metadata.MetadataBuilder; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.referencing.operation.MathTransform; +// Specific to the main branch: +import org.apache.sis.referencing.internal.shared.CoordinateOperations; +import org.apache.sis.referencing.operation.transform.MathTransformBuilder; /** diff --cc endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SchemaModifier.java index a0010991fa,05cd03b6dd..32ae640975 --- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SchemaModifier.java +++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SchemaModifier.java @@@ -17,12 -17,12 +17,12 @@@ package org.apache.sis.storage.sql.feature; import org.apache.sis.feature.builder.FeatureTypeBuilder; + import org.apache.sis.storage.OptionKey; import org.apache.sis.storage.DataStoreException; import org.apache.sis.io.stream.InternalOptionKey; - import org.apache.sis.setup.OptionKey; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.feature.FeatureType; +// Specific to the main branch: +import org.apache.sis.feature.DefaultFeatureType; /** diff --cc endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/gpx/Types.java index b5a77a06e2,3819d827c0..d6f19815c6 --- a/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/gpx/Types.java +++ b/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/gpx/Types.java @@@ -40,12 -40,12 +40,12 @@@ import org.apache.sis.feature.builder.P import org.apache.sis.feature.builder.AttributeRole; import org.apache.sis.feature.internal.shared.AttributeConvention; import org.apache.sis.geometry.wrapper.Geometries; - import org.apache.sis.storage.base.MetadataBuilder; + import org.apache.sis.storage.metadata.MetadataBuilder; import org.apache.sis.util.iso.DefaultNameFactory; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.feature.FeatureType; -import org.opengis.feature.Operation; +// Specific to the main branch: +import org.apache.sis.feature.AbstractOperation; +import org.apache.sis.feature.DefaultFeatureType; /** diff --cc endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/AggregatedFeatureSet.java index 76ed7914ed,2fbc724929..b6b4afdabb --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/AggregatedFeatureSet.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/AggregatedFeatureSet.java @@@ -30,10 -30,10 +30,10 @@@ import org.apache.sis.storage.Resource import org.apache.sis.storage.FeatureSet; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.AbstractFeatureSet; - import org.apache.sis.storage.base.MetadataBuilder; + import org.apache.sis.storage.metadata.MetadataBuilder; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.feature.FeatureType; +// Specific to the main branch: +import org.apache.sis.feature.DefaultFeatureType; /** diff --cc endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/Store.java index 7765fdbcdc,a773d56db7..ce216b3c6f --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/Store.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/Store.java @@@ -72,12 -72,13 +72,11 @@@ import org.apache.sis.geometry.Immutabl import org.apache.sis.geometry.wrapper.Geometries; import org.apache.sis.geometry.wrapper.GeometryType; import org.apache.sis.metadata.iso.DefaultMetadata; - import org.apache.sis.setup.OptionKey; import org.apache.sis.measure.Units; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.feature.Feature; -import org.opengis.feature.FeatureType; -import org.opengis.feature.PropertyType; -import org.opengis.feature.AttributeType; +// Specific to the main branch: +import org.apache.sis.feature.AbstractFeature; +import org.apache.sis.feature.AbstractIdentifiedType; /** @@@ -225,9 -226,9 +224,9 @@@ final class Store extends URIDataStore final Reader r = connector.commit(Reader.class, StoreProvider.NAME); source = (r instanceof BufferedReader) ? (BufferedReader) r : new LineNumberReader(r); geometries = Geometries.factory(connector.getOption(OptionKey.GEOMETRY_LIBRARY)); - dissociate = connector.getOption(DataOptionKey.FOLIATION_REPRESENTATION) == FoliationRepresentation.FRAGMENTED; + dissociate = connector.getOption(OptionKey.FOLIATION_REPRESENTATION) == FoliationRepresentation.FRAGMENTED; @SuppressWarnings("LocalVariableHidesMemberVariable") GeneralEnvelope envelope = null; - @SuppressWarnings("LocalVariableHidesMemberVariable") FeatureType featureType = null; + @SuppressWarnings("LocalVariableHidesMemberVariable") DefaultFeatureType featureType = null; @SuppressWarnings("LocalVariableHidesMemberVariable") Foliation foliation = null; try { final var elements = new ArrayList<String>(); diff --cc endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/StoreProvider.java index 64708c0c53,bd40e74acf..a587630dc7 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/StoreProvider.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/folder/StoreProvider.java @@@ -48,11 -48,8 +48,11 @@@ import org.apache.sis.storage.base.URID import org.apache.sis.storage.base.Capability; import org.apache.sis.storage.base.StoreMetadata; import org.apache.sis.storage.base.StoreUtilities; - import org.apache.sis.setup.OptionKey; + import org.apache.sis.util.logging.Logging; +// Specific to the main branch: +import org.apache.sis.parameter.DefaultParameterDescriptor; + /** * The provider of {@link Store} instances. This provider is intentionally registered with lowest priority diff --cc endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/PropertyFormat.java index c572de29ba,50cfe95def..713e3d5e31 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/PropertyFormat.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/PropertyFormat.java @@@ -121,13 -126,13 +126,13 @@@ public abstract class PropertyFormat ex final Locale locale = getLocale(); text = (locale != Locale.ROOT) ? ((Currency) value).getDisplayName(locale) : value.toString(); } else if (value instanceof Record) { - appendCollection(((Record) value).getAttributes().values(), recursive); - appendCollection(((Record) value).getFields().values()); ++ appendCollection(((Record) value).getAttributes().values()); return; } else if (value instanceof Iterable<?>) { - appendCollection((Iterable<?>) value, recursive); + appendCollection((Iterable<?>) value); return; } else if (value instanceof Object[]) { - appendCollection(Arrays.asList((Object[]) value), recursive); + appendCollection(Arrays.asList((Object[]) value)); return; } else if (value instanceof Map.Entry<?,?>) { final Map.Entry<?,?> entry = (Map.Entry<?,?>) value; diff --cc incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java index 415352c976,5bd2209ac6..26da5ef39f --- a/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java +++ b/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java @@@ -306,12 -308,8 +306,8 @@@ public final class ShapefileStore exten private int[] dbfPropertiesIndex; private ShapeHeader shpHeader; private DBFHeader dbfHeader; - /** - * Name of the field used as identifier, may be null. - */ - private String idField; private CoordinateReferenceSystem crs; - private FeatureType type; + private DefaultFeatureType type; /** * @param filter optional shape filter, must be in data CRS @@@ -336,10 -334,11 +332,11 @@@ * @throws DataStoreException */ private boolean mustGenerateId() throws DataStoreException { - getType(); - if (idField != null) return false; - if (readProperties == null) return true; - return readProperties.contains(AttributeConvention.IDENTIFIER); + try { + return getType().getProperty(AttributeConvention.IDENTIFIER) != null; - } catch (PropertyNotFoundException ex) { ++ } catch (IllegalArgumentException ex) { + return false; + } } /** diff --cc incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/ShapefileStoreTest.java index 92cebceb1b,4d355a9c6c..beac409aaf --- a/incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/ShapefileStoreTest.java +++ b/incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/ShapefileStoreTest.java @@@ -323,7 -328,33 +326,33 @@@ public class ShapefileStoreTest } } + /** + * Test incremental id creation. + */ + @Test + public void testGeneratedId() throws DataStoreException, IOException, URISyntaxException { + final URL url = ShapefileStoreTest.class.getResource("/org/apache/sis/storage/shapefile/noid.shp"); + try (final ShapefileStore store = new ShapefileStore(Paths.get(url.toURI()))) { + - final FeatureType type = store.getType(); - final PropertyType generatedID = type.getProperty(AttributeConvention.IDENTIFIER); - assertTrue(generatedID instanceof AttributeType); ++ final DefaultFeatureType type = store.getType(); ++ final var generatedID = type.getProperty(AttributeConvention.IDENTIFIER); ++ assertTrue(generatedID instanceof DefaultAttributeType); + assertEquals(5, type.getProperties(true).size()); + - try (Stream<Feature> stream = store.features(false)) { - Iterator<Feature> iterator = stream.iterator(); ++ try (Stream<AbstractFeature> stream = store.features(false)) { ++ Iterator<AbstractFeature> iterator = stream.iterator(); + assertTrue(iterator.hasNext()); - Feature feature1 = iterator.next(); ++ AbstractFeature feature1 = iterator.next(); + assertEquals("noid.1", feature1.getPropertyValue(AttributeConvention.IDENTIFIER)); + assertEquals("some text", feature1.getPropertyValue("text")); + + assertFalse(iterator.hasNext()); + } + } + + } + - private static FeatureType createType() { + private static DefaultFeatureType createType() { final FeatureTypeBuilder ftb = new FeatureTypeBuilder(); ftb.setName("test"); ftb.addAttribute(Integer.class).setName("id"); @@@ -335,9 -366,10 +364,10 @@@ return ftb.build(); } - private static Feature createFeature1(FeatureType type) { - Feature feature = type.newInstance(); + private static AbstractFeature createFeature1(DefaultFeatureType type) { + AbstractFeature feature = type.newInstance(); feature.setPropertyValue("geometry", GF.createPoint(new Coordinate(10,20))); + feature.setPropertyValue(AttributeConvention.IDENTIFIER, "test.1"); feature.setPropertyValue("id", 1); feature.setPropertyValue("text", "some text 1"); feature.setPropertyValue("integer", 123); @@@ -346,9 -378,10 +376,10 @@@ return feature; } - private static Feature createFeature2(FeatureType type) { - Feature feature = type.newInstance(); + private static AbstractFeature createFeature2(DefaultFeatureType type) { + AbstractFeature feature = type.newInstance(); feature.setPropertyValue("geometry", GF.createPoint(new Coordinate(30,40))); + feature.setPropertyValue(AttributeConvention.IDENTIFIER, "test.2");; feature.setPropertyValue("id", 2); feature.setPropertyValue("text", "some text 2"); feature.setPropertyValue("integer", 456); diff --cc optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/FeatureTable.java index 06509fbde4,4bb0f17dc1..198b895e5d --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/FeatureTable.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/FeatureTable.java @@@ -274,10 -274,10 +273,10 @@@ public class FeatureTable extends Table * Creates table columns for the current {@link #featureType}. */ private void createColumns() { - final Collection<? extends PropertyType> properties = featureType.getProperties(true); - final var columns = new ArrayList<TableColumn<Feature, ?>>(properties.size()); + final Collection<? extends AbstractIdentifiedType> properties = featureType.getProperties(true); - final List<TableColumn<AbstractFeature,?>> columns = new ArrayList<>(properties.size()); - final List<String> multiValued = new ArrayList<>(columns.size()); ++ final var columns = new ArrayList<TableColumn<AbstractFeature, ?>>(properties.size()); + final var multiValued = new ArrayList<String>(columns.size()); - for (final PropertyType pt : properties) { + for (final AbstractIdentifiedType pt : properties) { /* * Get localized text to show in column header. Also remember * the plain property name; it will be needed for ValueGetter. @@@ -308,7 -308,7 +307,7 @@@ * gives the whole collection. Fetching a particular element in that collection will * be ElementCell's work. */ - final TableColumn<AbstractFeature,Object> column = new TableColumn<>(title); - final var column = new TableColumn<Feature, Object>(title); ++ final var column = new TableColumn<AbstractFeature, Object>(title); column.setCellValueFactory(new ValueGetter(name)); column.setCellFactory(isMultiValued ? ElementCell::new : ValueCell::new); if (AttributeConvention.contains(qualifiedName)) { @@@ -325,7 -325,7 +324,7 @@@ } else { final ExpandableList list = getExpandableList(); list.setMultivaluedColumns(multiValued); - final TableColumn<AbstractFeature,AbstractFeature> column = new TableColumn<>("▤"); - final var column = new TableColumn<Feature, Feature>("▤"); ++ final var column = new TableColumn<AbstractFeature, AbstractFeature>("▤"); column.setCellValueFactory(IdentityValueFactory.instance()); column.setCellFactory(list); column.setReorderable(false); @@@ -348,7 -348,7 +347,7 @@@ * easy way to know the current row number. Fetching a particular element in that collection will be done by * {@link ExpandedFeature}. */ - private static final class ValueGetter implements Callback<TableColumn.CellDataFeatures<AbstractFeature,Object>, ObservableValue<Object>> { - private static final class ValueGetter implements Callback<TableColumn.CellDataFeatures<Feature, Object>, ObservableValue<Object>> { ++ private static final class ValueGetter implements Callback<TableColumn.CellDataFeatures<AbstractFeature, Object>, ObservableValue<Object>> { /** * The name of the feature property for which to fetch values. */ @@@ -382,13 -382,13 +381,13 @@@ * A cell displaying a value in {@link FeatureTable}. This base class expects single values. * If the property values are collections, then {@link ElementCell} should be used instead. */ - private static class ValueCell extends TableCell<AbstractFeature,Object> { - private static class ValueCell extends TableCell<Feature, Object> { ++ private static class ValueCell extends TableCell<AbstractFeature, Object> { /** * Creates a new cell for feature property value. * * @param column the column where the cell will be shown. */ - ValueCell(final TableColumn<AbstractFeature,Object> column) { - ValueCell(final TableColumn<Feature, Object> column) { ++ ValueCell(final TableColumn<AbstractFeature, Object> column) { // Column not used at this time, but we need it in method signature. } @@@ -430,7 -430,7 +429,7 @@@ * * @param column the column where the cell will be shown. */ - ElementCell(final TableColumn<AbstractFeature,Object> column) { - ElementCell(final TableColumn<Feature, Object> column) { ++ ElementCell(final TableColumn<AbstractFeature, Object> column) { super(column); }
