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 e285c91d307caeb04c1ccfe4d401342bf45cdd3e Merge: 7232f07008 45a58d0acf Author: Martin Desruisseaux <[email protected]> AuthorDate: Fri May 29 11:09:07 2026 +0200 Merge branch 'geoapi-3.1'. Contains: - Replacement of `DataStoreProvider.TIMEZONE` by a more unified way to handle parameters. - Support transitive search of metadata title in tree representation. - Bug fixes in SQL store. .../org/apache/sis/console/OperationParser.java | 2 +- .../org/apache/sis/coverage/RegionOfInterest.java | 6 +- .../org/apache/sis/feature/FeatureOperations.java | 4 +- .../main/org/apache/sis/filter/base/Node.java | 5 +- .../sis/filter/sqlmm/FunctionDescription.java | 12 + .../geometry/wrapper/SpatialOperationContext.java | 3 +- .../org/apache/sis/metadata/AbstractMetadata.java | 36 +- .../main/org/apache/sis/metadata/CacheKey.java | 29 +- .../org/apache/sis/metadata/MetadataCopier.java | 10 +- .../org/apache/sis/metadata/MetadataStandard.java | 361 +++++++++++++-------- .../org/apache/sis/metadata/MetadataVisitor.java | 14 +- .../apache/sis/metadata/ModifiableMetadata.java | 11 +- .../org/apache/sis/metadata/PropertyAccessor.java | 2 +- .../main/org/apache/sis/metadata/Pruner.java | 2 +- .../sis/metadata/StandardImplementation.java | 6 +- .../main/org/apache/sis/metadata/StateChanger.java | 2 +- .../org/apache/sis/metadata/TitleProperty.java | 11 +- .../main/org/apache/sis/metadata/TreeNode.java | 41 ++- .../org/apache/sis/metadata/TreeNodeChildren.java | 78 +++-- .../apache/sis/metadata/ValueExistencePolicy.java | 1 + .../sis/metadata/internal/shared/Merger.java | 17 +- .../metadata/internal/shared/SecondaryTrait.java | 45 --- .../iso/DefaultApplicationSchemaInformation.java | 4 +- .../sis/metadata/iso/DefaultMetadataScope.java | 4 +- .../sis/metadata/iso/acquisition/DefaultEvent.java | 4 +- .../iso/acquisition/DefaultInstrument.java | 4 +- .../metadata/iso/acquisition/DefaultObjective.java | 2 +- .../metadata/iso/acquisition/DefaultOperation.java | 4 +- .../sis/metadata/iso/acquisition/DefaultPlan.java | 4 +- .../metadata/iso/acquisition/DefaultPlatform.java | 4 +- .../iso/acquisition/DefaultPlatformPass.java | 4 +- .../iso/acquisition/DefaultRequirement.java | 2 + .../sis/metadata/iso/acquisition/package-info.java | 2 +- .../iso/citation/DefaultOnlineResource.java | 4 +- .../sis/metadata/iso/citation/DefaultSeries.java | 4 +- .../metadata/iso/citation/DefaultTelephone.java | 4 +- .../sis/metadata/iso/citation/package-info.java | 2 +- .../iso/constraint/DefaultReleasability.java | 4 +- .../iso/constraint/DefaultSecurityConstraints.java | 4 +- .../sis/metadata/iso/constraint/package-info.java | 2 +- .../DefaultFeatureCatalogueDescription.java | 4 +- .../metadata/iso/distribution/DefaultDataFile.java | 16 +- .../metadata/iso/distribution/DefaultFormat.java | 4 +- .../metadata/iso/distribution/DefaultMedium.java | 4 +- .../metadata/iso/distribution/package-info.java | 2 +- .../iso/extent/DefaultGeographicDescription.java | 4 +- .../sis/metadata/iso/extent/package-info.java | 2 +- .../iso/identification/AbstractIdentification.java | 4 +- .../DefaultAggregateInformation.java | 7 +- .../identification/DefaultAssociatedResource.java | 4 +- .../iso/identification/DefaultBrowseGraphic.java | 4 +- .../identification/DefaultDataIdentification.java | 4 +- .../metadata/iso/identification/package-info.java | 2 +- .../sis/metadata/iso/lineage/DefaultAlgorithm.java | 4 +- .../sis/metadata/iso/lineage/DefaultLineage.java | 4 +- .../metadata/iso/lineage/DefaultProcessing.java | 4 +- .../sis/metadata/iso/lineage/package-info.java | 2 +- .../org/apache/sis/metadata/iso/package-info.java | 2 +- .../sis/metadata/iso/quality/AbstractElement.java | 4 +- .../iso/quality/DefaultConformanceResult.java | 4 +- .../iso/quality/DefaultEvaluationMethod.java | 4 +- .../DefaultEvaluationReportInformation.java | 4 +- .../iso/quality/DefaultSourceReference.java | 4 +- .../sis/metadata/iso/quality/package-info.java | 2 +- .../sis/metadata/iso/spatial/DefaultGCP.java | 2 +- .../metadata/iso/spatial/DefaultGCPCollection.java | 16 +- .../metadata/simple/SimpleIdentifiedObject.java | 23 +- .../apache/sis/metadata/simple/SimpleMetadata.java | 119 ++++++- .../apache/sis/metadata/sql/MetadataSource.java | 14 +- .../apache/sis/metadata/sql/MetadataWriter.java | 30 +- .../org/apache/sis/temporal/DefaultInstant.java | 13 + .../org/apache/sis/temporal/DefaultPeriod.java | 13 + .../main/org/apache/sis/temporal/TemporalDate.java | 13 + .../sis/xml/bind/metadata/replace/Parameter.java | 15 +- .../metadata/replace/ReferenceSystemMetadata.java | 13 + .../apache/sis/metadata/MetadataStandardTest.java | 8 +- .../sis/metadata/ModifiableMetadataTest.java | 1 + .../sis/metadata/PropertyConsistencyCheck.java | 16 +- .../apache/sis/metadata/TreeNodeChildrenTest.java | 5 +- .../sis/openoffice/ReferencingFunctions.java | 10 +- .../gazetteer/ReferencingByIdentifiers.java | 1 + .../sis/referencing/gazetteer/package-info.java | 2 +- .../sis/coordinate/DefaultCoordinateMetadata.java | 3 +- .../main/org/apache/sis/io/wkt/WKTDictionary.java | 8 +- .../sis/parameter/AbstractParameterDescriptor.java | 8 +- .../sis/parameter/DefaultParameterDescriptor.java | 18 +- .../parameter/DefaultParameterDescriptorGroup.java | 15 +- .../sis/parameter/DefaultParameterValue.java | 15 +- .../apache/sis/parameter/ParameterizedType.java | 49 +++ .../main/org/apache/sis/parameter/Parameters.java | 17 +- .../org/apache/sis/parameter/package-info.java | 2 +- .../sis/referencing/AbstractIdentifiedObject.java | 65 ++-- .../sis/referencing/AbstractReferenceSystem.java | 8 +- .../main/org/apache/sis/referencing/Builder.java | 6 +- .../apache/sis/referencing/GeodeticCalculator.java | 5 +- .../apache/sis/referencing/crs/AbstractCRS.java | 8 +- .../sis/referencing/crs/AbstractDerivedCRS.java | 2 +- .../sis/referencing/crs/AbstractSingleCRS.java | 5 +- .../sis/referencing/crs/DefaultCompoundCRS.java | 15 +- .../sis/referencing/crs/DefaultDerivedCRS.java | 29 +- .../sis/referencing/crs/DefaultEngineeringCRS.java | 15 +- .../sis/referencing/crs/DefaultGeocentricCRS.java | 10 +- .../sis/referencing/crs/DefaultGeodeticCRS.java | 10 +- .../sis/referencing/crs/DefaultGeographicCRS.java | 13 +- .../sis/referencing/crs/DefaultProjectedCRS.java | 15 +- .../sis/referencing/crs/DefaultTemporalCRS.java | 15 +- .../sis/referencing/crs/DefaultVerticalCRS.java | 15 +- .../apache/sis/referencing/crs/package-info.java | 2 +- .../org/apache/sis/referencing/cs/AbstractCS.java | 11 +- .../apache/sis/referencing/cs/DefaultAffineCS.java | 7 +- .../sis/referencing/cs/DefaultCartesianCS.java | 14 +- .../cs/DefaultCoordinateSystemAxis.java | 15 +- .../sis/referencing/cs/DefaultCylindricalCS.java | 14 +- .../sis/referencing/cs/DefaultEllipsoidalCS.java | 14 +- .../apache/sis/referencing/cs/DefaultLinearCS.java | 14 +- .../apache/sis/referencing/cs/DefaultPolarCS.java | 14 +- .../sis/referencing/cs/DefaultSphericalCS.java | 14 +- .../apache/sis/referencing/cs/DefaultTimeCS.java | 12 +- .../sis/referencing/cs/DefaultVerticalCS.java | 14 +- .../org/apache/sis/referencing/cs/Normalizer.java | 2 +- .../sis/referencing/datum/AbstractDatum.java | 7 +- .../referencing/datum/DefaultDatumEnsemble.java | 24 +- .../sis/referencing/datum/DefaultEllipsoid.java | 15 +- .../referencing/datum/DefaultEngineeringDatum.java | 15 +- .../referencing/datum/DefaultGeodeticDatum.java | 15 +- .../referencing/datum/DefaultParametricDatum.java | 2 +- .../referencing/datum/DefaultPrimeMeridian.java | 15 +- .../referencing/datum/DefaultTemporalDatum.java | 15 +- .../referencing/datum/DefaultVerticalDatum.java | 15 +- .../factory/GeodeticAuthorityFactory.java | 3 +- .../referencing/factory/GeodeticObjectFactory.java | 2 +- .../referencing/internal/ParameterizedType.java | 118 +++++++ .../internal/shared/AffineTransform2D.java | 11 + .../internal/shared/ReferencingUtilities.java | 51 +-- .../sis/referencing/legacy/DefaultImageCRS.java | 3 +- .../sis/referencing/legacy/DefaultImageDatum.java | 12 +- .../referencing/legacy/DefaultUserDefinedCS.java | 11 +- .../operation/AbstractCoordinateOperation.java | 6 +- .../apache/sis/referencing/operation/CRSPair.java | 3 +- .../operation/CoordinateOperationRegistry.java | 2 +- .../operation/DefaultConcatenatedOperation.java | 12 +- .../referencing/operation/DefaultConversion.java | 10 +- .../DefaultCoordinateOperationFactory.java | 6 +- .../operation/DefaultOperationMethod.java | 15 +- .../operation/DefaultPassThroughOperation.java | 15 +- .../referencing/operation/DefaultProjection.java | 2 +- .../operation/DefaultTransformation.java | 15 +- .../referencing/operation/matrix/MatrixSIS.java | 20 +- .../referencing/operation/matrix/package-info.java | 2 +- .../operation/transform/AbstractMathTransform.java | 20 +- .../operation/transform/package-info.java | 2 +- .../DefaultParameterDescriptorGroupTest.java | 20 +- .../parameter/DefaultParameterDescriptorTest.java | 119 +++---- .../sis/parameter/DefaultParameterValueTest.java | 46 +-- .../datum/DefaultDatumEnsembleTest.java | 96 ++++++ .../datum/DefaultGeodeticDatumTest.java | 6 +- .../sis/referencing/datum/HardCodedDatum.java | 2 +- .../apache/sis/storage/landsat/LandsatStore.java | 4 +- .../sis/storage/landsat/LandsatStoreProvider.java | 4 +- .../apache/sis/storage/geotiff/GeoTiffStore.java | 6 +- .../sis/storage/geotiff/GeoTiffStoreProvider.java | 13 +- .../sis/storage/geotiff/writer/GeoEncoder.java | 6 +- .../org/apache/sis/storage/netcdf/NetcdfStore.java | 4 +- .../sis/storage/netcdf/NetcdfStoreProvider.java | 10 +- .../sis/storage/netcdf/classic/VariableInfo.java | 4 +- .../org/apache/sis/storage/sql/feature/Column.java | 3 +- .../apache/sis/storage/sql/feature/Database.java | 21 ++ .../sis/storage/sql/feature/InfoStatements.java | 8 +- .../apache/sis/storage/sql/postgis/Postgres.java | 23 ++ .../main/org/apache/sis/storage/gpx/Metadata.java | 6 +- .../main/org/apache/sis/storage/gpx/Store.java | 2 +- .../org/apache/sis/storage/gpx/StoreProvider.java | 16 +- .../storage/xml/stream/StaxDataStoreProvider.java | 8 +- .../main/org/apache/sis/storage/DataStore.java | 27 +- .../org/apache/sis/storage/DataStoreProvider.java | 32 +- .../main/org/apache/sis/storage/OptionKey.java | 99 +++++- .../org/apache/sis/storage/StorageConnector.java | 1 + .../org/apache/sis/storage/base/PRJDataStore.java | 100 ++---- .../apache/sis/storage/base/StoreUtilities.java | 159 ++------- .../org/apache/sis/storage/base/URIDataStore.java | 96 ++++-- .../sis/storage/base/URIDataStoreOption.java | 336 +++++++++++++++++++ .../sis/storage/base/URIDataStoreProvider.java | 178 ++++------ .../main/org/apache/sis/storage/csv/Store.java | 27 +- .../org/apache/sis/storage/csv/StoreProvider.java | 67 +--- .../apache/sis/storage/esri/AsciiGridStore.java | 7 +- .../sis/storage/esri/AsciiGridStoreProvider.java | 7 +- .../org/apache/sis/storage/esri/RasterStore.java | 6 +- .../apache/sis/storage/esri/RawRasterStore.java | 2 +- .../sis/storage/esri/RawRasterStoreProvider.java | 7 +- .../main/org/apache/sis/storage/folder/Store.java | 42 +-- .../apache/sis/storage/folder/StoreProvider.java | 93 ++---- .../apache/sis/storage/folder/WritableStore.java | 10 +- .../sis/storage/image/WorldFileStoreProvider.java | 9 +- .../org/apache/sis/storage/internal/Resources.java | 7 +- .../sis/storage/internal/Resources.properties | 3 +- .../sis/storage/internal/Resources_fr.properties | 3 +- .../main/org/apache/sis/storage/wkt/Store.java | 10 +- .../org/apache/sis/storage/wkt/StoreFormat.java | 2 +- .../org/apache/sis/storage/wkt/StoreProvider.java | 63 ++-- .../apache/sis/storage/xml/AbstractProvider.java | 13 +- .../org/apache/sis/storage/xml/StoreProvider.java | 2 +- .../sis/storage/base/StoreUtilitiesTest.java | 15 +- ...tiesTest.java => URIDataStoreProviderTest.java} | 20 +- .../test/org/apache/sis/storage/csv/StoreTest.java | 3 +- .../org/apache/sis/storage/folder/StoreTest.java | 2 +- .../apache/sis/storage/wkt/StoreProviderTest.java | 6 +- .../org/apache/sis/measure/AbstractConverter.java | 21 +- .../main/org/apache/sis/measure/AbstractUnit.java | 25 +- .../apache/sis/measure/ConcatenatedConverter.java | 8 +- .../org/apache/sis/measure/LinearConverter.java | 8 +- .../main/org/apache/sis/measure/package-info.java | 10 +- .../main/org/apache/sis/util/Classes.java | 217 ++++++++----- .../main/org/apache/sis/util/ComparisonMode.java | 3 + .../org/apache/sis/util/LenientComparable.java | 39 ++- .../sis/util/resources/IndexedResourceBundle.java | 3 + .../test/org/apache/sis/util/ClassesTest.java | 10 + .../test/org/apache/sis/util/UtilitiesTest.java | 7 + .../storage/coveragejson/CoverageJsonStore.java | 4 +- .../coveragejson/CoverageJsonStoreProvider.java | 5 +- .../apache/sis/storage/geoheif/GeoHeifStore.java | 4 +- .../sis/storage/geoheif/GeoHeifStoreProvider.java | 9 +- .../sis/storage/geopackage/GpkgStoreProvider.java | 7 +- .../main/org/apache/sis/storage/gsf/GSFStore.java | 6 +- .../apache/sis/storage/gsf/GSFStoreProvider.java | 25 +- .../sis/storage/shapefile/ShapefileProvider.java | 45 +-- .../sis/storage/shapefile/ShapefileStore.java | 72 ++-- .../sis/storage/shapefile/ShapefileStoreTest.java | 27 +- .../org/apache/sis/storage/shapefile/Snippets.java | 7 +- .../org/apache/sis/gui/dataset/PathAction.java | 43 ++- .../org/apache/sis/gui/dataset/ResourceCell.java | 3 +- .../apache/sis/gui/referencing/FilterByDatum.java | 3 +- .../org/apache/sis/storage/gdal/GDALStore.java | 4 +- .../apache/sis/storage/gdal/GDALStoreProvider.java | 7 +- 233 files changed, 2828 insertions(+), 1830 deletions(-) diff --cc endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureOperations.java index 1924b1603b,74862f63c9..6062d2dd48 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureOperations.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureOperations.java @@@ -362,11 -356,11 +362,11 @@@ public final class FeatureOperations * of a previous call to {@link #expression expression(…)}, then invoking this method is equivalent * to invoking {@code expression(…)} again with the same arguments except for {@code expression}. * - * @param operation the operation to evaluate in a different way. + * @param property the operation to evaluate in a different way. * @param expression the new expression to use for evaluating the operation. * @return the new operation. May be the given operation if the expression is the same. - * @throws IllegalArgumentException if the {@linkplain Operation#getResult() result type} - * of the given operation is not an {@link AttributeType}. + * @throws IllegalArgumentException if the {@linkplain AbstractOperation#getResult() result type} + * of the given operation is not an {@code AttributeType}. * * @since 1.6 */ diff --cc endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/sqlmm/FunctionDescription.java index 3109918e4a,b49ffea275..15cba52a1d --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/sqlmm/FunctionDescription.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/sqlmm/FunctionDescription.java @@@ -247,12 -251,18 +247,24 @@@ final class FunctionDescription extend return 1; } + @Override public Set<T> getValidValues() {return null;} + @Override public Comparable<T> getMinimumValue() {return null;} + @Override public Comparable<T> getMaximumValue() {return null;} + @Override public T getDefaultValue() {return null;} + @Override public Unit<?> getUnit() {return null;} + + /** + * Returns the standard interface expected by {@code equals(…)} methods. + * Note that {@code equals(…)} actually require a stricter class, + * but we declare only the public interface here. + * + * @return {@code ParameterDescriptor.class}. + */ + @Override + public Type getStandardType() { + return ParameterDescriptor.class; + } + /** * Tests whether the given object is equal to this argument description. * diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/DefaultMetadataScope.java index 121d6a7074,b9a3e239fa..e01db826cf --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/DefaultMetadataScope.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/DefaultMetadataScope.java @@@ -21,13 -21,11 +21,14 @@@ import jakarta.xml.bind.annotation.XmlE import jakarta.xml.bind.annotation.XmlRootElement; import org.opengis.util.InternationalString; import org.opengis.metadata.maintenance.ScopeCode; + import org.apache.sis.metadata.TitleProperty; import org.apache.sis.util.iso.Types; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.metadata.MetadataScope; +// Specific to the main branch: +import org.opengis.annotation.UML; +import static org.opengis.annotation.Obligation.OPTIONAL; +import static org.opengis.annotation.Obligation.MANDATORY; +import static org.opengis.annotation.Specification.ISO_19115; /** diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultOnlineResource.java index c19fd68fa6,abb64fecb5..5ff4ca2e90 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultOnlineResource.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultOnlineResource.java @@@ -26,13 -26,9 +26,14 @@@ import org.opengis.metadata.citation.On import org.opengis.metadata.citation.OnlineResource; import org.apache.sis.xml.bind.gco.StringAdapter; import org.apache.sis.xml.bind.gco.URIAdapter; + import org.apache.sis.metadata.TitleProperty; import org.apache.sis.metadata.iso.ISOMetadata; +// Specific to the main branch: +import org.opengis.annotation.UML; +import static org.opengis.annotation.Obligation.OPTIONAL; +import static org.opengis.annotation.Specification.ISO_19115; + /** * Information about on-line sources from which the dataset, specification, or diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultTelephone.java index 6c5b2accb6,fb1d58421e..8a8db9b788 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultTelephone.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultTelephone.java @@@ -30,16 -30,11 +30,17 @@@ import org.apache.sis.xml.bind.FilterBy import org.apache.sis.xml.internal.shared.LegacyNamespaces; import org.apache.sis.xml.bind.gco.StringAdapter; import org.apache.sis.xml.bind.metadata.code.CI_TelephoneTypeCode; + import org.apache.sis.metadata.TitleProperty; import org.apache.sis.metadata.internal.Dependencies; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.metadata.citation.TelephoneType; +// Specific to the main branch: +import org.opengis.util.CodeList; +import org.opengis.annotation.UML; +import static org.opengis.annotation.Obligation.OPTIONAL; +import static org.opengis.annotation.Obligation.MANDATORY; +import static org.opengis.annotation.Specification.ISO_19115; +import org.apache.sis.pending.geoapi.evolution.InterimType; +import org.apache.sis.pending.geoapi.evolution.UnsupportedCodeList; /** diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/constraint/DefaultReleasability.java index 5c55f902c6,490e49dee5..b2b452ca82 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/constraint/DefaultReleasability.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/constraint/DefaultReleasability.java @@@ -22,13 -22,12 +22,14 @@@ import jakarta.xml.bind.annotation.XmlE import jakarta.xml.bind.annotation.XmlRootElement; import org.opengis.util.InternationalString; import org.opengis.metadata.constraint.Restriction; + import org.apache.sis.metadata.TitleProperty; import org.apache.sis.metadata.iso.ISOMetadata; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.metadata.constraint.Releasability; -import org.opengis.metadata.citation.Responsibility; +// Specific to the main branch: +import org.opengis.annotation.UML; +import static org.opengis.annotation.Obligation.OPTIONAL; +import static org.opengis.annotation.Specification.ISO_19115; +import org.apache.sis.metadata.iso.citation.DefaultResponsibility; /** diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/content/DefaultFeatureCatalogueDescription.java index a6fe7e5e2e,c04b1987b7..573bf4c6e5 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/content/DefaultFeatureCatalogueDescription.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/content/DefaultFeatureCatalogueDescription.java @@@ -198,9 -190,9 +198,9 @@@ public class DefaultFeatureCatalogueDes * * @since 1.0 */ - @Override + @UML(identifier="locale", obligation=CONDITIONAL, specification=ISO_19115) // @XmlElement at the end of this class. - public Map<Locale,Charset> getLocalesAndCharsets() { + public Map<Locale, Charset> getLocalesAndCharsets() { return locales = nonNullMap(locales, Locale.class); } diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/distribution/DefaultDataFile.java index 089730d5e2,8f186cab2e..bde2c10045 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/distribution/DefaultDataFile.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/distribution/DefaultDataFile.java @@@ -34,6 -35,6 +35,11 @@@ import org.apache.sis.xml.internal.shar // Specific to the main and geoapi-3.1 branches: import org.opengis.util.LocalName; ++// Specific to the main branch: ++import org.opengis.annotation.UML; ++import static org.opengis.annotation.Obligation.MANDATORY; ++import static org.opengis.annotation.Specification.ISO_19115; ++ /** * Description of a transfer data file. @@@ -170,6 -169,7 +177,7 @@@ public class DefaultDataFile extends IS * @see org.apache.sis.metadata.iso.identification.DefaultBrowseGraphic#getFileName() * @since 1.0 */ - @Override ++ @UML(identifier="fileName", obligation=MANDATORY, specification=ISO_19115) // Actually ISO_19115_3 @XmlElement(name = "fileName", required = true) public URI getFileName() { return fileName; diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/distribution/DefaultFormat.java index 61961893cb,9b13f58861..278e89f737 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/distribution/DefaultFormat.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/distribution/DefaultFormat.java @@@ -35,14 -35,9 +35,15 @@@ import org.apache.sis.xml.internal.shar import org.apache.sis.xml.bind.metadata.MD_Medium; import org.apache.sis.xml.bind.metadata.CI_Citation; import org.apache.sis.util.collection.Containers; + import org.apache.sis.metadata.TitleProperty; import org.apache.sis.metadata.iso.citation.DefaultCitation; +// Specific to the main branch: +import org.opengis.annotation.UML; +import static org.opengis.annotation.Obligation.OPTIONAL; +import static org.opengis.annotation.Obligation.MANDATORY; +import static org.opengis.annotation.Specification.ISO_19115; + /** * Description of the computer language construct that specifies the representation diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/identification/DefaultAssociatedResource.java index 1a2417928f,047899f7a7..d9792602cf --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/identification/DefaultAssociatedResource.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/identification/DefaultAssociatedResource.java @@@ -26,15 -26,11 +26,16 @@@ import org.opengis.metadata.identificat import org.apache.sis.xml.bind.metadata.CI_Citation; import org.apache.sis.xml.bind.metadata.code.DS_AssociationTypeCode; import org.apache.sis.xml.bind.metadata.code.DS_InitiativeTypeCode; + import org.apache.sis.metadata.TitleProperty; import org.apache.sis.metadata.iso.ISOMetadata; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.metadata.identification.AssociatedResource; +// Specific to the main branch: +import org.opengis.metadata.identification.AggregateInformation; +import org.opengis.annotation.UML; +import static org.opengis.annotation.Obligation.OPTIONAL; +import static org.opengis.annotation.Obligation.MANDATORY; +import static org.opengis.annotation.Obligation.CONDITIONAL; +import static org.opengis.annotation.Specification.ISO_19115; /** diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/identification/DefaultDataIdentification.java index 0ef0564a6e,19bdfe69ae..4658268997 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/identification/DefaultDataIdentification.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/identification/DefaultDataIdentification.java @@@ -205,9 -195,9 +205,9 @@@ public class DefaultDataIdentification * * @since 1.0 */ - @Override + @UML(identifier="defaultLocale+otherLocale", obligation=CONDITIONAL, specification=ISO_19115) // @XmlElement at the end of this class. - public Map<Locale,Charset> getLocalesAndCharsets() { + public Map<Locale, Charset> getLocalesAndCharsets() { return locales = nonNullMap(locales, Locale.class); } diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/quality/DefaultEvaluationReportInformation.java index e53b528e0c,f8a278fea3..270a3c7ce2 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/quality/DefaultEvaluationReportInformation.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/quality/DefaultEvaluationReportInformation.java @@@ -21,11 -21,10 +21,12 @@@ import jakarta.xml.bind.annotation.XmlE import jakarta.xml.bind.annotation.XmlRootElement; import org.opengis.util.InternationalString; import org.opengis.metadata.citation.Citation; + import org.apache.sis.metadata.TitleProperty; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.metadata.quality.StandaloneQualityReportInformation; +// Specific to the main branch: +import org.opengis.annotation.UML; +import static org.opengis.annotation.Obligation.MANDATORY; +import static org.opengis.annotation.Specification.UNSPECIFIED; /** diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/quality/DefaultSourceReference.java index 6a69eb7f34,a076cec35b..4093545401 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/quality/DefaultSourceReference.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/quality/DefaultSourceReference.java @@@ -20,12 -20,11 +20,13 @@@ import jakarta.xml.bind.annotation.XmlT import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlRootElement; import org.opengis.metadata.citation.Citation; + import org.apache.sis.metadata.TitleProperty; import org.apache.sis.xml.Namespaces; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.metadata.quality.SourceReference; +// Specific to the main branch: +import org.opengis.annotation.UML; +import static org.opengis.annotation.Obligation.MANDATORY; +import static org.opengis.annotation.Specification.UNSPECIFIED; /** @@@ -46,13 -45,13 +47,14 @@@ * * @author Alexis Gaillard (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 1.4 + * @version 1.7 * @since 1.3 */ + @TitleProperty(name = "citation") @XmlType(name = "DQM_SourceReference_Type", namespace = Namespaces.DQM) @XmlRootElement(name = "DQM_SourceReference", namespace = Namespaces.DQM) -public class DefaultSourceReference extends ISOMetadata implements SourceReference { +@UML(identifier="DQM_SourceReference", specification=UNSPECIFIED) +public class DefaultSourceReference extends ISOMetadata { /** * Serial number for inter-operability with different versions. */ diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleIdentifiedObject.java index 8b7b6722eb,902b2389f8..cd2432a33b --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleIdentifiedObject.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleIdentifiedObject.java @@@ -155,21 -125,33 +156,35 @@@ public class SimpleIdentifiedObject imp } /** - * Returns a narrative explanation of the role of this object. - * The default implementation returns {@link Identifier#getDescription()}. + * Method required by the {@link IdentifiedObject} interface. + * Current implementation returns {@code null}. + * + * <p>If a future version allows this method to returns a non-null value, + * revisit {@link #equals(Object, ComparisonMode)}.</p> * - * @return a narrative explanation of the role of this object. + * @return the remarks, or {@code null} if none. */ - public Optional<InternationalString> getDescription() { - @SuppressWarnings("LocalVariableHidesMemberVariable") - final Identifier name = this.name; - return Optional.ofNullable((name != null) ? name.getDescription() : null); + @Override + public final InternationalString getRemarks() { + return null; } + /** + * Returns the standard interface that defines the contract of this class. + * This is the base type required by all {@code equals(…)} methods + * for returning a potentially {@code true} value. + * + * @return {@code IdentifiedObject.class} or a subtype. + */ + @Override + public Type getStandardType() { + return IdentifiedObject.class; + } + /** * Returns a hash code value for this object. + * + * @return an arbitrary hash code value. */ @Override public int hashCode() { @@@ -223,19 -205,10 +238,21 @@@ return false; } + /** + * Throws an exception in all cases, since this object can't be formatted in a valid WKT. + * + * @return the Well Known Text. + * @throws UnsupportedOperationException always thrown. + */ + @Override + public String toWKT() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + /** - * Returns a pseudo-WKT representation for debugging purpose. + * Returns a pseudo-<abbr>WKT</abbr> representation for debugging purposes. + * + * @return a string representation for debugging purposes. */ @Override public String toString() { diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleMetadata.java index 306aaa2440,0c0d38f7d5..e619a9b3ad --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleMetadata.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/simple/SimpleMetadata.java @@@ -86,83 -74,41 +86,101 @@@ public class SimpleMetadata implements protected SimpleMetadata() { } + /** + * Unique identifier for this metadata record. ++ * ++ * @return {@code null}. + */ + @Override + public String getFileIdentifier() { + return null; + } + /** * Language(s) used for documenting metadata. * Also the language(s) used within the data. + * + * @return empty map. */ @Override - public Map<Locale, Charset> getLocalesAndCharsets() { - return Collections.emptyMap(); + public Collection<Locale> getLanguages() { + return Collections.emptySet(); // We use 'Set' because we handle 'Locale' like a CodeList. + } + + /** + * Language(s) used for documenting metadata. + * Also the language(s) used within the data. ++ * ++ * @return empty map. + */ + @Override + public Locale getLanguage() { + return null; + } + + /** + * Language(s) used for documenting metadata. + * Also the language(s) used within the data. ++ * ++ * @return empty collection. + */ + @Override + public Collection<Locale> getLocales() { + return Collections.emptySet(); // We use 'Set' because we handle 'Locale' like a CodeList. } /** - * The scope or type of resource for which metadata is provided. - * This method returns {@code this} for allowing call to {@link #getResourceScope()}. + * The character coding standard used for the metadata set. + * Also the character coding standard(s) used for the dataset. + * + * @return empty collection. + */ + @Override + public Collection<CharacterSet> getCharacterSets() { + return Collections.emptySet(); // We use 'Set' because we handle 'Charset' like a CodeList. + } + + /** + * The character coding standard used for the metadata set. + * Also the character coding standard(s) used for the dataset. + * - * @see #getResourceScope() - * @see #getName() ++ * @return {@code null}. */ @Override - public Collection<MetadataScope> getMetadataScopes() { - return Collections.singleton(this); + public CharacterSet getCharacterSet() { + return null; } /** - * Code for the metadata scope, fixed to {@link ScopeCode#DATASET} by default. This is part of the information - * provided by {@link #getMetadataScopes()}. The {@code DATASET} default value is consistent with the fact that + * Identification of the parent metadata record. ++ * ++ * @return {@code null}. + */ + @Override + public String getParentIdentifier() { + return null; + } + + /** + * Code for the metadata scope, fixed to {@link ScopeCode#DATASET} by default. + * The {@code DATASET} default value is consistent with the fact that * {@code SimpleMetadata} implements {@link DataIdentification}. + * + * @return {@code DATASET}. */ @Override - public ScopeCode getResourceScope() { - return ScopeCode.DATASET; + public Collection<ScopeCode> getHierarchyLevels() { + return Collections.singleton(ScopeCode.DATASET); + } + + /** + * Description of the metadata scope. ++ * ++ * @return empty collection. + */ + @Override + public Collection<String> getHierarchyLevelNames() { + return Collections.emptySet(); } /** @@@ -175,58 -123,11 +195,72 @@@ /** * Date(s) associated with the metadata. + * + * @return empty collection. */ @Override - public Collection<CitationDate> getDateInfo() { + public Date getDateStamp() { + return null; + } + + /** + * Citation(s) for the standard(s) to which the metadata conform. ++ * ++ * @return {@code null}. + */ + @Override + public String getMetadataStandardName() { + return null; + } + + /** + * As of ISO 19115:2014, replaced by {@code getMetadataStandards()} + * followed by {@link Citation#getEdition()}. ++ * ++ * @return {@code null}. + */ + @Override + public String getMetadataStandardVersion() { + return null; + } + + /** + * Online location(s) where the metadata is available. ++ * ++ * @return {@code null}. + */ + @Override + public String getDataSetUri() { + return null; + } + + /** + * Digital representation of spatial information in the dataset. ++ * ++ * @return empty collection. + */ + @Override + public Collection<SpatialRepresentation> getSpatialRepresentationInfo() { + return Collections.emptyList(); + } + + /** + * Description of the spatial and temporal reference systems used in the dataset. ++ * ++ * @return empty collection. + */ + @Override + public Collection<ReferenceSystem> getReferenceSystemInfo() { + return Collections.emptyList(); + } + + /** + * Information describing metadata extensions. ++ * ++ * @return empty collection. + */ + @Override + public Collection<MetadataExtensionInformation> getMetadataExtensionInfo() { return Collections.emptyList(); } @@@ -250,70 -153,6 +285,86 @@@ return Collections.singleton(this); } + /** + * Information about the feature and coverage characteristics. ++ * ++ * @return empty collection. + */ + @Override + public Collection<ContentInformation> getContentInfo() { + return Collections.emptyList(); + } + + /** + * Information about the distributor of and options for obtaining the resource(s). ++ * ++ * @return {@code null}. + */ + @Override + public Distribution getDistributionInfo() { + return null; + } + + /** + * Overall assessment of quality of a resource(s). ++ * ++ * @return empty collection. + */ + @Override + public Collection<DataQuality> getDataQualityInfo() { + return Collections.emptyList(); + } + + /** + * Information about the catalogue of rules defined for the portrayal of a resource(s). ++ * ++ * @return empty collection. + */ + @Override + public Collection<PortrayalCatalogueReference> getPortrayalCatalogueInfo() { + return Collections.emptyList(); + } + + /** + * Restrictions on the access and use of metadata. ++ * ++ * @return empty collection. + */ + @Override + public Collection<Constraints> getMetadataConstraints() { + return Collections.emptyList(); + } + + /** + * Information about the conceptual schema of a dataset. ++ * ++ * @return empty collection. + */ + @Override + public Collection<ApplicationSchemaInformation> getApplicationSchemaInfo() { + return Collections.emptyList(); + } + + /** + * Information about the acquisition of the data. ++ * ++ * @return empty collection. + */ + @Override + public Collection<AcquisitionInformation> getAcquisitionInformation() { + return Collections.emptyList(); + } + + /** + * Information about the frequency of metadata updates, and the scope of those updates. ++ * ++ * @return {@code null}. + */ + @Override + public MaintenanceInformation getMetadataMaintenance() { + return null; + } + /* ------------------------------------------------------------------------------------------------- * Implementation of the DataIdentification object returned by Metadata.getIdentificationInfo(). @@@ -332,48 -173,14 +385,58 @@@ /** * Brief narrative summary of the resource. * This is part of the information returned by {@link #getIdentificationInfo()}. + * - * @return null. ++ * @return {@code null}. */ @Override public InternationalString getAbstract() { return null; } + /** + * Summary of the intentions with which the resource was developed. + * This is part of the information returned by {@link #getIdentificationInfo()}. ++ * ++ * @return {@code null}. + */ + @Override + public InternationalString getPurpose() { + return null; + } + + /** + * Recognition of those who contributed to the resource. + * This is part of the information returned by {@link #getIdentificationInfo()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<String> getCredits() { + return Collections.emptyList(); + } + + /** + * Status of the resource. + * This is part of the information returned by {@link #getIdentificationInfo()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<Progress> getStatus() { + return Collections.emptySet(); // We use 'Set' because 'Progress' is a CodeList. + } + + /** + * Identification of, and means of communication with, person(s) and organisations associated with the resource(s). + * This is part of the information returned by {@link #getIdentificationInfo()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<ResponsibleParty> getPointOfContacts() { + return Collections.emptyList(); + } + /** * Methods used to spatially represent geographic information. * This is part of the information returned by {@link #getIdentificationInfo()}. @@@ -385,15 -194,6 +450,17 @@@ return Collections.singleton(SpatialRepresentationType.VECTOR); } + /** + * Factor which provides a general understanding of the density of spatial data in the resource. + * This is part of the information returned by {@link #getIdentificationInfo()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<Resolution> getSpatialResolutions() { + return Collections.emptyList(); + } + /** * Main theme(s) of the resource. * This is part of the information returned by {@link #getIdentificationInfo()}. @@@ -414,89 -218,6 +485,107 @@@ return Collections.emptyList(); } + /** + * Information about the frequency of resource updates, and the scope of those updates. + * This is part of the information returned by {@link #getIdentificationInfo()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<MaintenanceInformation> getResourceMaintenances() { + return Collections.emptyList(); + } + + /** + * Graphic that illustrates the resource(s) (should include a legend for the graphic). + * This is part of the information returned by {@link #getIdentificationInfo()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<BrowseGraphic> getGraphicOverviews() { + return Collections.emptyList(); + } + + /** + * Description of the format of the resource(s). + * This is part of the information returned by {@link #getIdentificationInfo()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<Format> getResourceFormats() { + return Collections.emptyList(); + } + + /** + * Category keywords, their type, and reference source. + * This is part of the information returned by {@link #getIdentificationInfo()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<Keywords> getDescriptiveKeywords() { + return Collections.emptyList(); + } + + /** + * Basic information about specific application(s) for which the resource(s) + * has/have been or is being used by different users. + * This is part of the information returned by {@link #getIdentificationInfo()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<Usage> getResourceSpecificUsages() { + return Collections.emptyList(); + } + + /** + * Information about constraints which apply to the resource(s). + * This is part of the information returned by {@link #getIdentificationInfo()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<Constraints> getResourceConstraints() { + return Collections.emptyList(); + } + + /** + * @deprecated As of ISO 19115:2014, replaced by {@code getAssociatedResources()}. ++ * ++ * @return empty collection. + */ + @Override + @Deprecated + public Collection<AggregateInformation> getAggregationInfo() { + return Collections.emptyList(); + } + + /** + * Description of the resource in the producer's processing environment, including items + * such as the software, the computer operating system, file name, and the dataset size. + * This is part of the information returned by {@link #getIdentificationInfo()}. ++ * ++ * @return {@code null}. + */ + @Override + public InternationalString getEnvironmentDescription() { + return null; + } + + /** + * Any other descriptive information about the resource. + * This is part of the information returned by {@link #getIdentificationInfo()}. ++ * ++ * @return {@code null}. + */ + @Override + public InternationalString getSupplementalInformation() { + return null; + } + /* ------------------------------------------------------------------------------------------------- * Implementation of the Citation object returned by DataIdentification.getCitation(). @@@ -505,67 -226,14 +594,81 @@@ /** * Name by which the cited resource is known. * This is part of the information returned by {@link #getCitation()}. + * - * @return null. ++ * @return {@code null}. */ @Override public InternationalString getTitle() { return null; } + /** + * Short names or other language names by which the cited information is known. + * This is part of the information returned by {@link #getCitation()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<InternationalString> getAlternateTitles() { + return Collections.emptyList(); + } + + /** + * Reference dates for the cited resource. + * This is part of the information returned by {@link #getCitation()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<CitationDate> getDates() { + return Collections.emptyList(); + } + + /** + * Version of the cited resource. + * This is part of the information returned by {@link #getCitation()}. ++ * ++ * @return {@code null}. + */ + @Override + public InternationalString getEdition() { + return null; + } + + /** + * Date of the edition. + * This is part of the information returned by {@link #getCitation()}. ++ * ++ * @return {@code null}. + */ + @Override + public Date getEditionDate() { + return null; + } + + /** + * Unique identifier for the resource. + * This is part of the information returned by {@link #getCitation()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<Identifier> getIdentifiers() { + return Collections.emptyList(); + } + + /** + * Role, name, contact and position information for individuals or organisations + * that are responsible for the resource. + * This is part of the information returned by {@link #getCitation()}. ++ * ++ * @return empty collection. + */ + @Override + public Collection<ResponsibleParty> getCitedResponsibleParties() { + return Collections.emptyList(); + } + /** * Mode in which the resource is represented. * This is part of the information returned by {@link #getCitation()}. @@@ -576,49 -246,4 +681,59 @@@ public Collection<PresentationForm> getPresentationForms() { return Collections.singleton(PresentationForm.TABLE_DIGITAL); } + + /** + * Information about the series, or aggregate dataset, of which the dataset is a part. + * This is part of the information returned by {@link #getCitation()}. ++ * ++ * @return {@code null}. + */ + @Override + public Series getSeries() { + return null; + } + + /** + * Other information required to complete the citation that is not recorded elsewhere. + * This is part of the information returned by {@link #getCitation()}. ++ * ++ * @return {@code null}. + */ + @Override + public InternationalString getOtherCitationDetails() { + return null; + } + + /** + * @deprecated Removed as of ISO 19115:2014. ++ * ++ * @return {@code null}. + */ + @Override + @Deprecated + public InternationalString getCollectiveTitle() { + return null; + } + + /** + * International Standard Book Number. + * This is part of the information returned by {@link #getCitation()}. ++ * ++ * @return {@code null}. + */ + @Override + public String getISBN() { + return null; + } + + /** + * International Standard Serial Number. + * This is part of the information returned by {@link #getCitation()}. ++ * ++ * @return {@code null}. + */ + @Override + public String getISSN() { + return null; + } } diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/MetadataWriter.java index 3eb34c344f,b6dcc0d6d5..815317dc4c --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/MetadataWriter.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/MetadataWriter.java @@@ -402,12 -407,12 +408,12 @@@ public class MetadataWriter extends Met * Once a dependency has been added to the database, the corresponding value in * the `asMap` HashMap is replaced by the identifier of the dependency we just added. */ - Map<String,FKey> referencedTables = null; - for (final Map.Entry<String,Object> entry : asSingletons.entrySet()) { + Map<String, FKey> referencedTables = null; + for (final Map.Entry<String, Object> entry : asSingletons.entrySet()) { Object value = entry.getValue(); final Class<?> type = value.getClass(); - if (ControlledVocabulary.class.isAssignableFrom(type)) { - value = addCode(stmt, (ControlledVocabulary) value); + if (CodeList.class.isAssignableFrom(type)) { + value = addCode(stmt, (CodeList<?>) value); } else if (type.isEnum()) { value = ((Enum<?>) value).name(); } else if (standard.isMetadata(type)) { diff --cc endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/DefaultInstant.java index 6a48878060,184373610c..290c010337 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/DefaultInstant.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/DefaultInstant.java @@@ -259,9 -261,21 +260,21 @@@ cmp: if (canTestBefore | canTestAfte if (canTestAfter && ((TimeMethods) comparators).isAfter .test(t1, t2)) return TemporalOperatorName.AFTER; if (canTestEqual && ((TimeMethods) comparators).isEqual .test(t1, t2)) return TemporalOperatorName.EQUALS; } - throw new IndeterminatePositionException(Errors.format(Errors.Keys.IndeterminatePosition)); + throw new DateTimeException(Errors.format(Errors.Keys.IndeterminatePosition)); } + /** + * Returns the standard interface that defines the contract of this class. + * This is the base type required by all {@code equals(…)} methods + * for returning a potentially {@code true} value. + * + * @return {@code Instant.class}. + */ + @Override + public final Type getStandardType() { + return Instant.class; + } + /** * Compares this instant with the given object, optionally ignoring timezone. * If the comparison mode ignores metadata, this method compares only the position on the timeline. diff --cc endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/PropertyConsistencyCheck.java index c5b04164e3,56a6207a4c..36f1e235ca --- a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/PropertyConsistencyCheck.java +++ b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/PropertyConsistencyCheck.java @@@ -133,7 -138,7 +135,7 @@@ public abstract class PropertyConsisten if (type == CodeList.class) { return null; } - final CodeList<?>[] codes = (CodeList<?>[]) type.getMethod("values", (Class[]) null).invoke(null, (Object[]) null); - final var codes = (ControlledVocabulary[]) type.getMethod("values", (Class[]) null).invoke(null, (Object[]) null); ++ final var codes = (CodeList<?>[]) type.getMethod("values", (Class[]) null).invoke(null, (Object[]) null); return codes[random.nextInt(codes.length)]; } catch (ReflectiveOperationException e) { fail(e.toString()); diff --cc endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java index 788e1f9c6d,0e92c07552..80224970a2 --- a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java +++ b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java @@@ -321,14 -311,8 +320,13 @@@ public class ReferencingFunctions exten } else if (object instanceof CoordinateSystem) { cs = (CoordinateSystem) object; } else { - final Object actual; - Class<?> actual = Classes.getStandardClass(object, Object.class); - if (actual == Object.class) actual = object.getClass(); ++ Object actual; + if (object instanceof DefaultDatumEnsemble) { + actual = "DatumEnsemble"; - } else if (object instanceof AbstractIdentifiedObject) { - actual = ((AbstractIdentifiedObject) object).getInterface(); + } else { - actual = Classes.getClass(object); ++ actual = Classes.getStandardClass(object, Object.class); ++ if (actual == Object.class) actual = object.getClass(); + } return Errors.forLocale(getJavaLocale()).getString(Errors.Keys.UnexpectedTypeForReference_3, codeOrPath, CoordinateReferenceSystem.class, actual); } diff --cc endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java index 9fa0d985cd,440541fbba..8fa075dfdb --- a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java +++ b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/ReferencingByIdentifiers.java @@@ -212,6 -195,20 +212,7 @@@ public abstract class ReferencingByIden properties.put(OVERALL_OWNER_KEY, party); return properties; } + - /** - * Returns the GeoAPI interface that defines the contract of this implementation class. - * This is the base type required by {@code equals(…)} methods for returning a potentially {@code true} value. - * The default implementation returns {@code ReferenceSystemUsingIdentifiers.class}. - * - * @return the GeoAPI interface implemented by this class. - * @since 1.7 - */ - @Override - public Type getStandardType() { - return ReferenceSystemUsingIdentifiers.class; - } - /** * Property used to characterize the spatial reference system. * diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/coordinate/DefaultCoordinateMetadata.java index 8d9c9ccdcb,4a16dc4448..cc970a5e94 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/coordinate/DefaultCoordinateMetadata.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/coordinate/DefaultCoordinateMetadata.java @@@ -31,7 -32,10 +31,6 @@@ import org.apache.sis.io.wkt.Formattabl import org.apache.sis.io.wkt.Formatter; import org.apache.sis.util.ComparisonMode; import org.apache.sis.util.LenientComparable; --import org.apache.sis.util.Utilities; - -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.coordinate.CoordinateMetadata; /** @@@ -40,11 -44,8 +39,11 @@@ * This default implementation provides <i>Well-Known Text</i> support. * It is immutable and serializable if the CRS and epoch are also serializable. * + * <h2>Future evolution</h2> + * This class is expected to implement a {@code CoordinateMetadata} interface after the next GeoAPI release. + * * @author Martin Desruisseaux (Geomatys) - * @version 1.5 + * @version 1.7 * @since 1.5 */ public class DefaultCoordinateMetadata extends FormattableObject diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java index e386038daa,c221b6873b..fcaa557ee0 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeocentricCRS.java @@@ -77,9 -78,9 +78,9 @@@ import org.apache.sis.referencing.datum * in the javadoc, this condition holds if all components were created using only SIS factories and static constants. * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 1.6 + * @version 1.7 * - * @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createGeodeticCRS(String) + * @see org.apache.sis.referencing.factory.GeodeticAuthorityFactory#createGeocentricCRS(String) * * @since 0.4 */ @@@ -220,18 -222,14 +221,19 @@@ public class DefaultGeocentricCRS exten } /** - * Returns the GeoAPI interface implemented by this class. - * The SIS implementation returns {@code GeocentricCRS.class}. + * Returns the GeoAPI interface that defines the contract of this implementation class. + * This is the base type required by {@code equals(…)} methods for returning a potentially {@code true} value. * + * <h4>Note for implementers</h4> + * Subclasses usually do not need to override this method since GeoAPI does not define {@code GeocentricCRS} + * sub-interface. Overriding possibility is left mostly for implementers who wish to extend GeoAPI with their + * own set of interfaces. + * * @return {@code GeocentricCRS.class} or a user-defined sub-interface. + * @since 1.7 */ @Override - public Class<? extends GeocentricCRS> getInterface() { + public Type getStandardType() { return GeocentricCRS.class; } diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java index 03988ff65c,f8e5089bce..e5386ec38c --- 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 @@@ -58,8 -59,13 +59,10 @@@ import org.apache.sis.util.collection.C import java.util.Date; import org.opengis.referencing.datum.VerticalDatumType; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import java.util.Optional; -import java.time.temporal.Temporal; -import org.opengis.referencing.crs.ParametricCRS; -import org.opengis.referencing.datum.DatumEnsemble; -import org.opengis.referencing.datum.ParametricDatum; -import org.opengis.referencing.datum.RealizationMethod; +// Specific to the main branch: ++import org.opengis.annotation.UML; ++import static org.opengis.annotation.Specification.ISO_19111; +import org.opengis.metadata.extent.Extent; /** @@@ -87,8 -93,7 +90,8 @@@ * * @since 1.5 */ - @SecondaryTrait(Datum.class) -public class DefaultDatumEnsemble<D extends Datum> extends AbstractIdentifiedObject implements DatumEnsemble<D>, Datum { ++@UML(identifier="DatumEnsemble", specification=ISO_19111) +public class DefaultDatumEnsemble<D extends Datum> extends AbstractIdentifiedObject implements Datum { /** * Serial number for inter-operability with different versions. */ @@@ -274,6 -309,23 +277,23 @@@ return ensemble; } + /** + * Returns the GeoAPI interface that defines the contract of this implementation class. + * This is the base type required by {@code equals(…)} methods for returning a potentially {@code true} value. + * + * @return {@code DatumEnsemble.class} or a user-defined sub-interface. + * @since 1.7 + */ + @Override + public Type getStandardType() { - return new ParameterizedType(DatumEnsemble.class) { ++ return new ParameterizedType(DefaultDatumEnsemble.class) { + @Override protected Class<?> getActualTypeArgument() { + Class<? extends Datum>[] types = Classes.getLeafInterfaces(DefaultDatumEnsemble.this.getClass(), Datum.class); + return (types.length != 0) ? types[0] : Datum.class; + } + }; + } + /* * NOTE: a previous version provided the following method: * diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultParametricDatum.java index ab7461f32a,f9331426ab..98247c6d25 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultParametricDatum.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultParametricDatum.java @@@ -127,8 -130,35 +127,8 @@@ public class DefaultParametricDatum ext super(datum); } - /** - * Returns a SIS datum implementation with the same values as the given arbitrary implementation. - * If the given object is {@code null}, then this method returns {@code null}. - * Otherwise if the given object is already a SIS implementation, then the given object is returned unchanged. - * Otherwise a new SIS implementation is created and initialized to the attribute values of the given object. - * - * @param object the object to get as a SIS implementation, or {@code null} if none. - * @return a SIS implementation containing the values of the given object (may be the - * given object itself), or {@code null} if the argument was null. - */ - public static DefaultParametricDatum castOrCopy(final ParametricDatum object) { - return (object == null) || (object instanceof DefaultParametricDatum) ? - (DefaultParametricDatum) object : new DefaultParametricDatum(object); - } - - /** - * Returns the GeoAPI interface that defines the contract of this implementation class. - * This is the base type required by {@code equals(…)} methods for returning a potentially {@code true} value. - * - * @return {@code ParametricDatum.class} or a user-defined sub-interface. - * @since 1.7 - */ - @Override - public Type getStandardType() { - return ParametricDatum.class; - } - /** - * Formats this datum as a <cite>Well Known Text</cite> {@code ParametricDatum[…]} element. + * Formats this datum as a <i>Well Known Text</i> {@code ParametricDatum[…]} element. * * <h4>Compatibility note</h4> * {@code ParametricDatum} is defined in the <abbr>WKT</abbr> 2 specification only. diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/shared/ReferencingUtilities.java index b897cfdc78,ff67fc7471..76b851ef5e --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/shared/ReferencingUtilities.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/shared/ReferencingUtilities.java @@@ -144,99 -134,6 +143,51 @@@ public final class ReferencingUtilitie return (crs != null) ? getUnit(crs.getCoordinateSystem()) : null; } - /** - * Returns the GeoAPI interface implemented by the given object, or the implementation class - * if the interface is unknown. This method can be used when the base type (CRS, CS, Datum…) - * is unknown, for example when preparing an error message. If the base type is known, then - * the method expecting a {@code baseType} argument should be preferred. - * - * @param object the object for which to get the GeoAPI interface, or {@code null}. - * @return GeoAPI interface or implementation class of the given object, or {@code null} if the given object is null. - */ - @SuppressWarnings("unchecked") - public static Class<?> getInterface(final Object object) { - if (object instanceof AbstractIdentifiedObject) { - return ((AbstractIdentifiedObject) object).getInterface(); - } else { - return getInterface(IdentifiedObject.class, (Class) Classes.getClass(object)); - } - } - - /** - * Returns the GeoAPI interface implemented by the given object, or the implementation class - * if the interface is unknown. - * - * @param <T> compile-time value of {@code baseType}. - * @param baseType parent interface of the desired type. - * @param object the object for which to get the GeoAPI interface, or {@code null}. - * @return GeoAPI interface or implementation class of the given object, or {@code null} if the given object is null. - */ - public static <T extends IdentifiedObject> Class<? extends T> getInterface(final Class<T> baseType, final T object) { - if (object instanceof AbstractIdentifiedObject) { - return ((AbstractIdentifiedObject) object).getInterface().asSubclass(baseType); - } else { - return getInterface(baseType, Classes.getClass(object)); - } - } - - /** - * Returns the GeoAPI interface implemented by the given class, or the class itself if the interface is unknown. - * - * @param <T> compile-time value of {@code baseType}. - * @param baseType parent interface of the desired type. - * @param type type of object for which to get the GeoAPI interface, or {@code null}. - * @return GeoAPI interface or implementation class, or {@code null} if the given type is null. - */ - public static <T extends IdentifiedObject> Class<? extends T> getInterface(final Class<T> baseType, final Class<? extends T> type) { - final Class<? extends T>[] types = Classes.getLeafInterfaces(type, baseType); - return (types.length != 0) ? types[0] : type; - } - + /** + * Copies all {@link SingleCRS} components from the given source to the given collection. + * For each {@link CompoundCRS} element found in the iteration, this method replaces the + * {@code CompoundCRS} by its {@linkplain CompoundCRS#getComponents() components}, which + * may themselves have other {@code CompoundCRS}. Those replacements are performed recursively + * until we obtain a flat view of CRS components. + * + * @param source the collection of single or compound CRS. + * @param addTo where to add the single CRS in order to obtain a flat view of {@code source}. + * @return {@code true} if this method found only single CRS in {@code source}, in which case {@code addTo} + * got the same content (assuming that {@code addTo} was empty prior this method call). + * @throws NoSuchElementException if a CRS component is missing. + * @throws ClassCastException if a CRS is neither a {@link SingleCRS} or a {@link CompoundCRS}. + * + * @see org.apache.sis.referencing.CRS#getSingleComponents(CoordinateReferenceSystem) + */ + public static boolean getSingleComponents(final Iterable<? extends CoordinateReferenceSystem> source, + final Collection<? super SingleCRS> addTo) throws ClassCastException + { + boolean sameContent = true; + for (final CoordinateReferenceSystem candidate : source) { + if (candidate instanceof CompoundCRS) { + getSingleComponents(((CompoundCRS) candidate).getComponents(), addTo); + sameContent = false; + } else if (candidate instanceof SingleCRS) { + addTo.add((SingleCRS) candidate); + } else { + /* + * Illegal class. Try to provide a better error message, in particular when the CRS component + * is nil because it is an unresolved xlink in a GML document. Nil objects are proxies, which + * have hard to understand class names. + */ + final String message; + if (candidate instanceof NilObject) { + message = Errors.format(Errors.Keys.NilObject_1, Identifiers.getNilReason((NilObject) candidate)); + throw new NoSuchElementException(message); + } else { - message = Errors.format(Errors.Keys.NestedElementNotAllowed_1, getInterface(candidate)); ++ message = Errors.format(Errors.Keys.NestedElementNotAllowed_1, Classes.getStandardType(candidate.getClass())); + throw new ClassCastException(message); + } + } + } + return sameContent; + } + /** * Returns {@code true} if the type of the given datum is ellipsoidal. A vertical datum is not allowed * to be ellipsoidal according ISO 19111, but Apache SIS relaxes this restriction in some limited cases, diff --cc endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultDatumEnsembleTest.java index 0000000000,e909944bec..5d3100a16b mode 000000,100644..100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultDatumEnsembleTest.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultDatumEnsembleTest.java @@@ -1,0 -1,99 +1,96 @@@ + /* + * 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.referencing.datum; + + import java.util.Map; + import java.util.List; + import org.opengis.metadata.Identifier; + import org.opengis.referencing.datum.GeodeticDatum; + import org.apache.sis.referencing.GeodeticException; + import org.apache.sis.metadata.KeyNamePolicy; + import org.apache.sis.metadata.MetadataStandard; + import org.apache.sis.metadata.ValueExistencePolicy; + import org.apache.sis.metadata.iso.quality.DefaultAbsoluteExternalPositionalAccuracy; + + // Test dependencies + import org.junit.jupiter.api.Test; + import static org.junit.jupiter.api.Assertions.*; + import static org.apache.sis.test.Assertions.assertMessageContains; + import org.apache.sis.test.TestCase; + -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.referencing.datum.DatumEnsemble; - + + /** + * Tests the {@link DefaultDatumEnsemble} class. + * + * @author Martin Desruisseaux (Geomatys) + */ + @SuppressWarnings("exports") + public class DefaultDatumEnsembleTest extends TestCase { + /** + * Creates a new test case. + */ + public DefaultDatumEnsembleTest() { + } + + /** + * Creates a dummy ensemble with <abbr>WGS</abbr> datum. + */ + private static DefaultDatumEnsemble<GeodeticDatum> WGS() { + return DefaultDatumEnsemble.create( + Map.of(DefaultDatumEnsemble.NAME_KEY, "Various WGS"), + GeodeticDatum.class, + List.of(HardCodedDatum.WGS84, HardCodedDatum.WGS72), + new DefaultAbsoluteExternalPositionalAccuracy()); + } + + /** + * Tests the creation of a datum ensemble with some arbitrary geodetic datum. + */ + @Test + public void testGeodetic() { + final DefaultDatumEnsemble<GeodeticDatum> ensemble = WGS(); + assertEquals("Various WGS", ensemble.getName().getCode()); + assertTrue(ensemble.getMembers().contains(HardCodedDatum.WGS84)); + assertTrue(ensemble.getMembers().contains(HardCodedDatum.WGS72)); + final GeodeticDatum geodetic = assertInstanceOf(GeodeticDatum.class, ensemble); - assertEquals("DatumEnsemble<GeodeticDatum>", ensemble.getStandardType().getTypeName()); ++ assertEquals("DefaultDatumEnsemble<GeodeticDatum>", ensemble.getStandardType().getTypeName()); + assertEquals(0, geodetic.getPrimeMeridian().getGreenwichLongitude()); + GeodeticException e = assertThrows(GeodeticException.class, () -> geodetic.getEllipsoid()); + assertMessageContains(e, "WGS"); + } + + /** + * Tests the view as a map. This test depends on {@link DefaultDatumEnsemble#getStandardType()}, + * which is invoked by the metadata module for determining which interface is the main one. + */ + @Test + public void testValueMap() { + final Map<String, Object> values = MetadataStandard.ISO_19111.asValueMap( + WGS(), null, KeyNamePolicy.UML_IDENTIFIER, ValueExistencePolicy.ALL); + assertEquals("Various WGS", assertInstanceOf(Identifier.class, values.get("name")).getCode()); + } + + /** + * Tests another view as a map where the object is specified as a class instead of as an instance. + */ + @Test + public void testNameMap() { + final Map<String, String> names = MetadataStandard.ISO_19111.asNameMap( - DatumEnsemble.class, KeyNamePolicy.UML_IDENTIFIER, KeyNamePolicy.SENTENCE); ++ DefaultDatumEnsemble.class, KeyNamePolicy.UML_IDENTIFIER, KeyNamePolicy.SENTENCE); + assertEquals("Name", names.get("name")); + } + } diff --cc endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/StoreUtilities.java index 276b4db1e6,f4975053e4..54fcc1b898 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/StoreUtilities.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/StoreUtilities.java @@@ -53,9 -47,8 +47,8 @@@ import org.apache.sis.system.Configurat import org.apache.sis.system.Modules; import org.apache.sis.util.resources.Errors; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.feature.Feature; +// Specific to the main branch: +import org.apache.sis.feature.AbstractFeature; - import org.apache.sis.metadata.iso.identification.AbstractIdentification; /** diff --cc endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/URIDataStoreOption.java index 0000000000,186806e78b..1a87520100 mode 000000,100644..100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/URIDataStoreOption.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/URIDataStoreOption.java @@@ -1,0 -1,333 +1,336 @@@ + /* + * 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.base; + + import java.net.URI; + import java.nio.file.StandardOpenOption; + import java.util.EnumSet; + import java.util.Collection; + import org.opengis.parameter.ParameterValueGroup; + import org.opengis.parameter.ParameterDescriptor; + import org.opengis.parameter.ParameterDescriptorGroup; + import org.opengis.parameter.ParameterNotFoundException; + import org.apache.sis.parameter.ParameterBuilder; + import org.apache.sis.storage.DataStoreProvider; + import org.apache.sis.storage.OptionKey; + import org.apache.sis.storage.StorageConnector; + import org.apache.sis.storage.IllegalOpenParameterException; + import org.apache.sis.storage.internal.Resources; + import org.apache.sis.util.ObjectConverters; + import org.apache.sis.util.UnconvertibleObjectException; + import org.apache.sis.util.resources.Errors; + import org.apache.sis.util.logging.Logging; + ++// Specific to the main branch: ++import org.apache.sis.parameter.DefaultParameterDescriptor; ++ + + /** + * Options supported by {@link URIDataStoreProvider}. + * This enumeration does the link between {@link ParameterDescriptor} and {@link OptionKey}. + * This enumeration contains all parameters used by all subclasses of {@link URIDataStore} + * in the Apache <abbr>SIS</abbr> code base. This is an enumeration for a closed universe, + * which is why it cannot be in exported <abbr>API</abbr>. + * This enumeration is useful for data stores that are containers of other data stores, + * such as the data store that read all files in a folder. + * + * <h4>Deferred construction of parameter descriptor</h4> + * Some parameters are used by only one {@link URIDataStore}. These parameters are constructed + * during the static initialization of the {@link URIDataStoreProvider} that use them. + * + * <h4>Future evolution</h4> + * This class is an attempt to bring a little bit of order in the mapping between parameters and option keys, + * at least for the most frequently used parameters. This class may change in any future <abbr>SIS</abbr> + * version according experience. + * + * @author Johann Sorel (Geomatys) + * @author Martin Desruisseaux (Geomatys) + */ + public enum URIDataStoreOption { + /** + * Description of the mandatory {@value URIDataStoreProvider#LOCATION} parameter. + * This is the only mandatory parameter in all {@link URIDataStoreProvider} implementations. + * + * @see URIDataStoreProvider#LOCATION + * @see #createForLocationOnly(String) + */ + LOCATION(URIDataStoreProvider.LOCATION, Resources.Keys.DataStoreLocation, URI.class), + + /** + * Description of the optional {@value URIDataStoreProvider#FORMAT} parameter. + * + * @see URIDataStoreProvider#FORMAT + */ + FORMAT(URIDataStoreProvider.FORMAT, Resources.Keys.DirectoryContentFormatName, String.class), + + /** + * Description of the optional {@value URIDataStoreProvider#CREATE} parameter of writable data stores. + * + * @see URIDataStoreProvider#CREATE + * @see OptionKey#OPEN_OPTIONS + */ + CREATE(URIDataStoreProvider.CREATE, Resources.Keys.DataStoreCreate, Boolean.class), + + /** + * Description of the optional parameter for character encoding used by the data store. + * This is used only when the data store does not have explicit encoding information. + * + * @see OptionKey#ENCODING + */ + ENCODING(OptionKey.ENCODING), + + /** + * Description of the parameter for formatting conventions of dates and numbers. + * This is used only when the data store does not have explicit locale information. + * + * @see OptionKey#LOCALE + */ + LOCALE(OptionKey.LOCALE), + + /** + * Description of the optional parameter for the time zone used by the data store. + * This is used only when the data store does not have explicit time zone information. + * + * @see OptionKey#TIMEZONE + */ + TIMEZONE(OptionKey.TIMEZONE), + + /** + * Description of the optional parameter for the default coordinate reference system. + * This is used only when the data store does not have explicit <abbr>CRS</abbr> information. + * + * @see OptionKey#DEFAULT_CRS + * @todo Use {@link CodeType} when parsing from text. + */ + DEFAULT_CRS(OptionKey.DEFAULT_CRS), + + /** + * Description of the optional "metadata" parameter. + * + * @see OptionKey#METADATA_PATH + */ + METADATA(OptionKey.METADATA_PATH), + + /** + * Description of the optional parameter for specifying whether to assemble + * distinct lines into a single {@code Feature} instance forming a foliation. + */ + FOLIATION(OptionKey.FOLIATION_REPRESENTATION); + + /** + * The option key for storing the parameter value in a storage connector, + * or {@code null} if none. + */ + private final OptionKey<?> option; + + /** + * The parameter descriptor for this option, or {@code null} if not yet constructed. + * + * @see #getParameterDescriptor() + */ + private volatile ParameterDescriptor<?> parameter; + + /** + * Creates a new enumeration value with deferred construction of the parameter descriptor. + * + * @param option associated option in {@link StorageConnector}. + */ + private URIDataStoreOption(final OptionKey<?> option) { + this.option = option; + } + + /** + * Creates a new enumeration value with immediate construction of the parameter descriptor. + * + * @param parameterName name of the parameter to create. + * @param description constant from {@link Resources} keys for the localized description. + * @param valueClass type of value of the parameter. + */ + private <V> URIDataStoreOption(final String parameterName, final short description, final Class<V> valueClass) { + option = null; + parameter = new ParameterBuilder() + .addName(parameterName) + .setDescription(Resources.formatInternational(description)) + .setRequired(ordinal() == 0) + .create(valueClass, null); + } + + /** + * Returns the parameter associated to this enumeration. + * + * @return the parameter (never {@code null}). + * @throws IllegalStateException if the parameter has not yet been initialized. + */ + public final ParameterDescriptor<?> getParameterDescriptor() { + ParameterDescriptor<?> p = parameter; + if (p == null) { + p = option.asOpenParameter().orElseThrow(() -> new IllegalStateException(name())); + } + return p; + } + + /** + * Returns the parameter name. + */ + private String parameterName() { + return getParameterDescriptor().getName().getCode(); + } + + /** + * Creates a parameter with the same name as this parameter but different type or remarks. + * + * @param builder the builder to use for creating the parameter. + * @param valueClass the new value class, or {@code null} for keeping the same class. + * @param remarks the new parameter remarks, or {@code null} for keeping the same remarks. + * @return parameter of the same name as {@link #parameter()} but the specified value class and remarks. + */ + public final ParameterDescriptor<?> deriveParameterDescriptor( + final ParameterBuilder builder, Class<?> valueClass, CharSequence remarks) + { - ParameterDescriptor<?> p = getParameterDescriptor(); ++ var p = (DefaultParameterDescriptor<?>) getParameterDescriptor(); + if (valueClass == null) valueClass = p.getValueClass(); + if (remarks == null) remarks = p.getRemarks(); + return builder.addName(p.getName()) + .setDescription(p.getDescription().orElse(null)) + .setRemarks(remarks) + .create(valueClass, null); + } + + /** + * Creates a parameter descriptor group containing only the mandatory parameters. + * The mandatory parameter is: {@link #LOCATION}. + * + * @param name short name of the data store format. + * @return the descriptor for open parameters with only mandatory parameters. + * + * @see URIDataStoreProvider#createOpenParameters(ParameterBuilder) + */ + public static ParameterDescriptorGroup createForLocationOnly(final String name) { + return new ParameterBuilder().addName(name).createGroup(LOCATION.getParameterDescriptor()); + } + + /** + * Returns a group of parameters set to the given mandatory values. + * This is a shortcut when only the mandatory parameters are defined. + * If the parameter descriptor group of the given provider contains parameters other than location, + * those additional parameters are present but without values. + * + * @param provider provider of the data store for which to get the parameters, or {@code null}. + * @param location value of {@link #LOCATION}, or {@code null} if none. + * @return the parameters with the given values, or {@code null} if {@code provider} or {@code location} is null. + */ + public static ParameterValueGroup createWithLocationOnly(final DataStoreProvider provider, final URI location) { + if (provider != null && location != null) { + final ParameterDescriptorGroup descriptor = provider.getOpenParameters(); + if (descriptor != null) { + final ParameterValueGroup pg = descriptor.createValue(); + pg.parameter(URIDataStoreProvider.LOCATION).setValue(location); + return pg; + } + } + return null; + } + + /** + * Sets the value of the parameter described by this enumeration value. + * + * @param parameters the parameters where to set the parameter. + * @param value the value to set, or {@code null} if none. + */ + public final void setValueOf(final ParameterValueGroup parameters, final Object value) { + if (value != null) { + parameters.parameter(parameterName()).setValue(value); + } + } + + /** + * Creates a storage connector initialized to the location declared in the given parameters. + * The {@value #LOCATION} parameter is unconditionally requested. The other parameters to be + * requested are specified in the {@code options} collection. + * Missing optional parameters are ignored. + * + * @param provider the provider for which to create a storage connector (for error messages). + * @param parameters the parameters to use for creating a storage connector. + * @param options options to include, or {@code null} for only the mandatory parameters. + * @param openOptions where to store open options, or {@code null} for storing them in the storage connector. + * @return the storage connector initialized to the location specified in the parameters. + * @throws IllegalOpenParameterException if no {@value URIDataStoreProvider#LOCATION} parameter has been found. + */ + public static StorageConnector connector(final DataStoreProvider provider, + final ParameterValueGroup parameters, + Collection<URIDataStoreOption> options, + EnumSet<StandardOpenOption> openOptions) + throws IllegalOpenParameterException + { + final StorageConnector connector; + try { + connector = new StorageConnector(parameters.parameter(URIDataStoreProvider.LOCATION).getValue()); + } catch (ParameterNotFoundException | NullPointerException e) { + throw new IllegalOpenParameterException( + Resources.format(Resources.Keys.UndefinedParameter_2, + provider.getShortName(), + URIDataStoreProvider.LOCATION), e); + } + if (options != null) { + for (final URIDataStoreOption option : options) { + if (option.option == null) continue; + final Object value; + try { + value = parameters.parameter(option.parameterName()).getValue(); + } catch (ParameterNotFoundException e) { + Logging.ignorableException(provider.getLogger(), URIDataStoreOption.class, "connector", e); + continue; + } + if (value != null) try { + switch (option) { + case CREATE: { + final boolean store = (openOptions == null); + if (store) { + openOptions = EnumSet.of(StandardOpenOption.WRITE); + } else { + openOptions.add(StandardOpenOption.WRITE); + } + if (ObjectConverters.convert(value, Boolean.class)) { + openOptions.add(StandardOpenOption.CREATE); + } + if (store) { + connector.setOption(OptionKey.OPEN_OPTIONS, openOptions.toArray(StandardOpenOption[]::new)); + } + break; + } + default: { + convertAndSet(option.option, value, connector); + break; + } + } + } catch (UnconvertibleObjectException e) { + throw new IllegalOpenParameterException(Errors.format( + Errors.Keys.IllegalOptionValue_2, option.parameterName(), value), e); + } + } + } + return connector; + } + + /** + * Set the given option to the given value in the given storage connector. + * Defined as a separated method for type-safety. + */ + private static <V> void convertAndSet(final OptionKey<V> option, final Object value, final StorageConnector connector) { + connector.setOption(option, ObjectConverters.convert(value, option.getElementType())); + } + } diff --cc endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/Store.java index ce216b3c6f,a3d55d71a3..e2d86bb732 --- 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 @@@ -207,13 -212,12 +210,12 @@@ final class Store extends URIDataStore * All parsed moving features, or {@code null} if none or if not yet parsed. If {@link #dissociate} * is {@code false}, then this list will be created by {@link #features(boolean)} when first needed. */ - private transient List<Feature> movingFeatures; + private transient List<AbstractFeature> movingFeatures; /** - * Creates a new CSV store from the given file, URL or stream. - * - * <p>If the CSV file is known to be a Moving Feature file, then the given connector should - * have an {@link OptionKey#ENCODING} value set to UTF-8.</p> + * Creates a new <abbr>CSV</abbr> store from the given file, <abbr>URL</abbr> or stream. + * If the <abbr>CSV</abbr> file is known to be a Moving Feature file, then the given + * connector should have an {@link OptionKey#ENCODING} value set to <abbr>UTF</abbr>-8. * * @param provider the factory that created this {@code DataStore} instance, or {@code null} if unspecified. * @param connector information about the storage (URL, stream, <i>etc</i>). diff --cc endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Classes.java index 9f6bb010c8,13c3175627..cc142b6cd2 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Classes.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/Classes.java @@@ -34,8 -35,7 +35,10 @@@ import java.lang.reflect.ParameterizedT import java.lang.reflect.Modifier; import org.opengis.annotation.UML; import org.apache.sis.pending.jdk.JDK12; - import org.apache.sis.pending.jdk.JDK19; + ++// Specific to the main branch: ++import org.opengis.util.InternationalString; + /** * Static methods working on {@link Class} objects. @@@ -346,21 -364,72 +367,75 @@@ public final class Classes } /** - * Returns the first type or super-type (including interface) considered "standard" in Apache SIS sense. - * This method applies the following heuristic rules, in that order: + * Returns the "standard" (in Apache <abbr>SIS</abbr> sense) interface or class of the given object. + * The {@code baseType} argument narrows the search for handling the case where many standard interfaces are + * implemented by the same class (e.g., <abbr>CRS</abbr> and <abbr>CS</abbr> may be implemented together). + * This method applies the following heuristic rules, in that order and ignoring rules that do not apply: + * + * <ul> + * <li>The class or raw-type declared by {@link LenientComparable#getStandardType()}.</li> + * <li>Otherwise, the first interface assignable to {@code baseType} which has the {@link UML} annotation.</li> + * <li>Otherwise, {@link Object#getClass()} if that class {@linkplain #isPublic(Class) is public}.</li> + * <li>Otherwise, the first public parent class assignable to {@code baseType}.</li> + * <li>Otherwise, {@code baseType}.</li> + * </ul> + * + * Those heuristic rules may be adjusted in any future Apache <abbr>SIS</abbr> version. + * + * @param <T> the compile-time value of the {@code baseType} argument. + * @param object the object for which to get the standard interface or class, or {@code null}. + * @param baseType the base type of the desired type (e.g., {@code CoordinateReferenceSystem.class}). + * @return the standard type implemented by {@code object}, or {@code null} if {@code object} is null. + * @throws NullPointerException if {@code baseType} is null. + * @throws ClassCastException if the condition documented in {@link LenientComparable#getStandardType()} is violated, + * or if {@code object} is not an instance of {@code baseType} (violation of this method parameterized type). + * + * @since 1.7 + */ + public static <T> Class<? extends T> getStandardClass(final T object, final Class<T> baseType) { + if (object instanceof LenientComparable) { + final Class<?> type = getRawClass(((LenientComparable) object).getStandardType()); + if (type != null) { + return type.asSubclass(baseType); + } + } + Class<?> type = getClass(object); + if (baseType.isInterface() || baseType == Object.class) { + for (final Class<?> candidate : getInterfaceSet(type, baseType)) { - if (candidate.isAnnotationPresent(UML.class)) { ++ if (candidate.isAnnotationPresent(UML.class) ++ // special cases for UML annotation not present in GeoAPI 3.0. ++ || InternationalString.class.isAssignableFrom(candidate)) ++ { + return candidate.asSubclass(baseType); + } + } + } + while (type != null) { + if (isPublic(type)) { + return type.asSubclass(baseType); + } + type = type.getSuperclass(); + if (!baseType.isAssignableFrom(type)) break; + } + return baseType; + } + + /** + * Returns the "standard" (in Apache <abbr>SIS</abbr> sense) interface or class of the given implementation class. + * This method applies the following heuristic rules, in that order and ignoring rules that do not apply: * * <ul> - * <li>If the given type implements at least one interface having the {@link UML} annotation, - * then the first annotated interface is returned.</li> - * <li>Otherwise the first public class or parent class is returned.</li> + * <li>The first interface extended or implemented by {@code type} which has the {@link UML} annotation.</li> + * <li>Otherwise, {@code type} if that class {@linkplain #isPublic(Class) is public}.</li> + * <li>Otherwise, the first public parent class.</li> + * <li>Otherwise, {@code type}.</li> * </ul> * - * Those heuristic rules may be adjusted in any future Apache SIS version. + * Those heuristic rules may be adjusted in any future Apache <abbr>SIS</abbr> version. * * @param <T> the compile-time type argument. - * @param type the type for which to get the standard interface or class. May be {@code null}. - * @return a standard interface implemented by {@code type}, or otherwise the most specific public class. - * Is {@code null} if the given {@code type} argument was null. + * @param type the type for which to get the standard interface or class, or {@code null}. + * @return the standard type assignable from {@code type}, or {@code type} (possibly null) if none. * * @since 1.0 */ diff --cc endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/IndexedResourceBundle.java index e8d872ba94,2495ccd6e4..ce5595a0c7 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/IndexedResourceBundle.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/IndexedResourceBundle.java @@@ -413,8 -417,10 +414,10 @@@ public abstract class IndexedResourceBu replacement = ((URI) element).getSchemeSpecificPart(); // For decoding encoded characters. } else if (element instanceof Class<?>) { replacement = Classes.getShortName(getPublicType((Class<?>) element)); + } else if (element instanceof Type) { + replacement = ((Type) element).getTypeName(); - } else if (element instanceof ControlledVocabulary) { - replacement = MetadataServices.getInstance().getCodeTitle((ControlledVocabulary) element, getLocale()); + } else if (element instanceof CodeList<?>) { + replacement = MetadataServices.getInstance().getCodeTitle((CodeList<?>) element, getLocale()); } else if (element instanceof Range<?>) { final Range<?> range = (Range<?>) element; replacement = new RangeFormat(getLocale(), range.getElementType()).format(range); diff --cc endorsed/src/org.apache.sis.util/test/org/apache/sis/util/ClassesTest.java index 26024dd249,0350add5ba..05c6610296 --- a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/ClassesTest.java +++ b/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/ClassesTest.java @@@ -46,6 -46,8 +46,7 @@@ import java.io.Serializable import java.awt.geom.Point2D; import javax.print.attribute.standard.PrinterStateReason; import javax.print.attribute.standard.PrinterStateReasons; + import org.opengis.util.InternationalString; -import org.opengis.metadata.extent.Extent; import org.opengis.referencing.IdentifiedObject; import org.opengis.referencing.ReferenceSystem; import org.opengis.referencing.cs.EllipsoidalCS; diff --cc incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java index 26da5ef39f,b3c1e6b611..7cd55f97a7 --- 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 @@@ -61,11 -60,10 +60,10 @@@ import org.locationtech.jts.geom.Polygo import org.opengis.geometry.Envelope; import org.opengis.metadata.Metadata; import org.opengis.metadata.Identifier; - import org.opengis.parameter.ParameterValueGroup; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.TransformException; +import org.opengis.util.FactoryException; +import org.opengis.util.GenericName; import org.apache.sis.geometry.ImmutableEnvelope; import org.apache.sis.geometry.Envelopes; import org.apache.sis.geometry.GeneralEnvelope; @@@ -350,12 -321,11 +319,11 @@@ public final class ShapefileStore exten } @Override - public synchronized FeatureType getType() throws DataStoreException { + public synchronized DefaultFeatureType getType() throws DataStoreException { if (type == null) { - if (!Files.isRegularFile(shpPath)) { + if (!Files.isRegularFile(locationAsPath)) { throw new DataStoreException("Shape files do not exist. Update FeatureType first to initialize this empty datastore"); } - final FeatureTypeBuilder ftb = new FeatureTypeBuilder(); ftb.setName(files.baseName); @@@ -711,13 -679,12 +679,12 @@@ } @Override - public synchronized void updateType(FeatureType newType) throws DataStoreException { + public synchronized void updateType(DefaultFeatureType newType) throws DataStoreException { if (!isDefaultView()) throw new DataStoreException("Resource not writable in current filter state"); - if (Files.exists(shpPath)) { + if (Files.exists(locationAsPath)) { throw new DataStoreException("Update type is possible only when files do not exist. It can be used to create a new shapefile but not to update one."); } - final Class<?>[] supportedDateTypes; // All types other than the one at index 0 will lost information. if (timezone == null) { supportedDateTypes = new Class<?>[] { @@@ -736,12 -703,12 +703,12 @@@ final DBFHeader dbfHeader = new DBFHeader(); dbfHeader.lastUpdate = LocalDate.now(); dbfHeader.fields = new DBFField[0]; - final Charset charset = userDefinedCharSet == null ? StandardCharsets.UTF_8 : userDefinedCharSet; + final Charset charset = (encoding == null) ? StandardCharsets.UTF_8 : encoding; CoordinateReferenceSystem crs = CommonCRS.WGS84.normalizedGeographic(); - for (PropertyType pt : newType.getProperties(true)) { - if (pt instanceof AttributeType) { - final AttributeType at = (AttributeType) pt; + for (AbstractIdentifiedType pt : newType.getProperties(true)) { + if (pt instanceof DefaultAttributeType) { + final DefaultAttributeType at = (DefaultAttributeType) pt; final Class valueClass = at.getValueClass(); final String attName = at.getName().tip().toString(); @@@ -858,10 -825,11 +825,11 @@@ } @Override - public void add(Iterator<? extends Feature> features) throws DataStoreException { + public void add(Iterator<? extends AbstractFeature> features) throws DataStoreException { if (!isDefaultView()) throw new DataStoreException("Resource not writable in current filter state"); - if (!Files.exists(shpPath)) throw new DataStoreException("FeatureType do not exist, use updateType before modifying features."); - + if (!Files.exists(locationAsPath)) { + throw new DataStoreException("FeatureType do not exist, use updateType before modifying features."); + } final Writer writer = new Writer(charset); try { //write existing features @@@ -889,10 -857,11 +857,11 @@@ } @Override - public void removeIf(Predicate<? super Feature> filter) throws DataStoreException { + public void removeIf(Predicate<? super AbstractFeature> filter) throws DataStoreException { if (!isDefaultView()) throw new DataStoreException("Resource not writable in current filter state"); - if (!Files.exists(shpPath)) throw new DataStoreException("FeatureType do not exist, use updateType before modifying features."); - + if (!Files.exists(locationAsPath)) { + throw new DataStoreException("FeatureType do not exist, use updateType before modifying features."); + } final Writer writer = new Writer(charset); try { //write existing features not matching filter @@@ -914,10 -883,11 +883,11 @@@ } @Override - public void replaceIf(Predicate<? super Feature> filter, UnaryOperator<Feature> updater) throws DataStoreException { + public void replaceIf(Predicate<? super AbstractFeature> filter, UnaryOperator<AbstractFeature> updater) throws DataStoreException { if (!isDefaultView()) throw new DataStoreException("Resource not writable in current filter state"); - if (!Files.exists(shpPath)) throw new DataStoreException("FeatureType do not exist, use updateType before modifying features."); - + if (!Files.exists(locationAsPath)) { + throw new DataStoreException("FeatureType do not exist, use updateType before modifying features."); + } final Writer writer = new Writer(charset); try { //write existing features applying modifications diff --cc incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/ShapefileStoreTest.java index beac409aaf,3f8586bc93..9171163a1c --- 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 @@@ -63,10 -74,10 +72,10 @@@ public class ShapefileStoreTest @Test public void testStream() throws URISyntaxException, DataStoreException { final URL url = ShapefileStoreTest.class.getResource("/org/apache/sis/storage/shapefile/point.shp"); - try (final ShapefileStore store = new ShapefileStore(Paths.get(url.toURI()))) { + try (final ShapefileStore store = create(url)) { //check feature type - final FeatureType type = store.getType(); + final DefaultFeatureType type = store.getType(); assertEquals("point", type.getName().toString()); assertEquals(9, type.getProperties(true).size()); assertNotNull(type.getProperty("sis:identifier")); @@@ -118,9 -129,9 +127,9 @@@ @Test public void testEnvelopeFilter() throws URISyntaxException, DataStoreException { final URL url = ShapefileStoreTest.class.getResource("/org/apache/sis/storage/shapefile/point.shp"); - try (final ShapefileStore store = new ShapefileStore(Paths.get(url.toURI()))) { + try (final ShapefileStore store = create(url)) { - final FilterFactory<Feature, Object, Object> ff = DefaultFilterFactory.forFeatures(); + final DefaultFilterFactory<AbstractFeature, Object, Object> ff = DefaultFilterFactory.forFeatures(); final GeneralEnvelope env = new GeneralEnvelope(CommonCRS.WGS84.normalizedGeographic()); env.setRange(0, 2, 3); @@@ -249,8 -260,8 +258,8 @@@ @Test public void testAddFeatures(@TempDir final Path folder) throws URISyntaxException, DataStoreException, IOException { final Path temp = folder.resolve("test.shp"); - try (final ShapefileStore store = new ShapefileStore(temp)) { + try (final ShapefileStore store = create(temp)) { - FeatureType type = createType(); + DefaultFeatureType type = createType(); store.updateType(type); type = store.getType(); @@@ -271,12 -282,12 +280,12 @@@ @Test public void testRemoveFeatures(@TempDir final Path folder) throws DataStoreException, IOException { final Path temp = folder.resolve("test.shp"); - try (final ShapefileStore store = new ShapefileStore(temp)) { + try (final ShapefileStore store = create(temp)) { - FeatureType type = createType(); + DefaultFeatureType type = createType(); store.updateType(type); type = store.getType(); - Feature feature1 = createFeature1(type); - Feature feature2 = createFeature2(type); + AbstractFeature feature1 = createFeature1(type); + AbstractFeature feature2 = createFeature2(type); store.add(List.of(feature1, feature2).iterator()); //remove first feature @@@ -299,12 -310,12 +308,12 @@@ @Test public void testReplaceFeatures(@TempDir final Path folder) throws DataStoreException, IOException { final Path temp = folder.resolve("test.shp"); - try (final ShapefileStore store = new ShapefileStore(temp)) { + try (final ShapefileStore store = create(temp)) { - FeatureType type = createType(); + DefaultFeatureType type = createType(); store.updateType(type); type = store.getType(); - Feature feature1 = createFeature1(type); - Feature feature2 = createFeature2(type); + AbstractFeature feature1 = createFeature1(type); + AbstractFeature feature2 = createFeature2(type); store.add(List.of(feature1, feature2).iterator()); //remove first feature @@@ -332,17 -343,17 +341,17 @@@ @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()))) { + try (final ShapefileStore store = create(url)) { - 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")); diff --cc incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/Snippets.java index f76cb70704,8cc67a88d7..e5e8c80501 --- a/incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/Snippets.java +++ b/incubator/src/org.apache.sis.storage.shapefile/test/org/apache/sis/storage/shapefile/Snippets.java @@@ -29,11 -29,13 +29,12 @@@ import org.apache.sis.geometry.GeneralE import org.apache.sis.referencing.CommonCRS; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.FeatureQuery; + import org.apache.sis.storage.StorageConnector; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.feature.Feature; -import org.opengis.feature.FeatureType; -import org.opengis.filter.BinarySpatialOperator; -import org.opengis.filter.FilterFactory; +// Specific to the main branch: +import org.apache.sis.feature.AbstractFeature; +import org.apache.sis.feature.DefaultFeatureType; +import org.apache.sis.filter.Filter; /** diff --cc optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/FilterByDatum.java index 66377022fe,22884a35b0..8e2648cf3e --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/FilterByDatum.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/FilterByDatum.java @@@ -34,12 -34,8 +34,11 @@@ import org.opengis.referencing.crs.Vert import org.opengis.referencing.crs.EngineeringCRS; import org.apache.sis.util.Classes; import org.apache.sis.referencing.CRS; - import org.apache.sis.referencing.internal.shared.ReferencingUtilities; import org.apache.sis.util.Utilities; +// Specific to the main branch: +import static org.apache.sis.pending.geoapi.referencing.MissingMethods.getDatumEnsemble; + /** * Filter of reference systems that are compatible with the data to render.
