This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-3.1 in repository https://gitbox.apache.org/repos/asf/sis.git
commit eb20f53e20d2f678e87ac4aa4481d4db2628708e Merge: b6af5d3997 409c3a3234 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Sun Dec 17 10:59:41 2023 +0100 Merge branch 'geoapi-4.0' into geoapi-3.1. Contains initial version of shapefile writer and improvement in JShell environment. .../main/org/apache/sis/console/AboutCommand.java | 10 +- .../main/org/apache/sis/console/Command.java | 26 +- .../main/org/apache/sis/console/CommandRunner.java | 127 +- .../apache/sis/console/FormattedOutputCommand.java | 25 +- .../org/apache/sis/console/IdentifierCommand.java | 12 +- .../main/org/apache/sis/console/InfoCommand.java | 2 +- .../org/apache/sis/console/MetadataCommand.java | 5 +- .../main/org/apache/sis/console/Option.java | 5 + .../main/org/apache/sis/console/Options.properties | 7 +- .../org/apache/sis/console/Options_fr.properties | 7 +- .../apache/sis/console/ResourcesDownloader.java | 3 +- .../main/org/apache/sis/console/SIS.java | 69 +- .../org/apache/sis/console/TransformCommand.java | 49 +- .../org/apache/sis/console/TranslateCommand.java | 4 +- .../org/apache/sis/coverage/grid/GridGeometry.java | 14 +- .../org/apache/sis/feature/FeatureOperations.java | 3 +- .../apache/sis/metadata/internal/Identifiers.java | 27 + .../apache/sis/metadata/internal/NameMeaning.java | 4 +- .../sis/metadata/internal/ReferencingServices.java | 35 +- .../apache/sis/metadata/internal/Resources.java | 9 +- .../sis/metadata/internal/Resources.properties | 2 +- .../sis/metadata/internal/Resources_fr.properties | 2 +- .../sis/metadata/iso/extent/DefaultExtent.java | 4 +- .../iso/extent/DefaultGeographicBoundingBox.java | 4 +- .../iso/extent/DefaultSpatialTemporalExtent.java | 4 +- .../metadata/iso/extent/DefaultTemporalExtent.java | 4 +- .../metadata/iso/extent/DefaultVerticalExtent.java | 4 +- .../iso/extent/NotSpatioTemporalException.java | 86 ++ .../sis/metadata/iso/extent/package-info.java | 2 +- .../apache/sis/xml/bind/IdentifierMapAdapter.java | 2 +- .../sis/xml/bind/ModifiableIdentifierMap.java | 2 +- .../sis/xml/bind/NonMarshalledAuthority.java | 2 +- .../sis/xml/CharSequenceSubstitutionTest.java | 19 +- .../test/org/apache/sis/xml/LegacyCodesTest.java | 98 +- .../org/apache/sis/xml/MarshallerPoolTest.java | 2 +- .../test/org/apache/sis/xml/NamespacesTest.java | 15 +- .../apache/sis/xml/NilReasonMarshallingTest.java | 41 +- .../test/org/apache/sis/xml/TransformerTest.java | 28 +- .../apache/sis/xml/TransformingNamespacesTest.java | 4 +- .../org/apache/sis/xml/UUIDMarshallingTest.java | 35 +- .../org/apache/sis/xml/ValueConverterTest.java | 2 +- .../org/apache/sis/xml/XLinkMarshallingTest.java | 9 +- .../test/org/apache/sis/xml/XLinkTest.java | 96 +- .../test/org/apache/sis/xml/XPointerTest.java | 2 +- .../org/apache/sis/geometry/EnvelopeReducer.java | 2 + .../apache/sis/geometry/WraparoundAdjustment.java | 4 +- .../main/org/apache/sis/io/wkt/AbstractParser.java | 3 +- .../org/apache/sis/io/wkt/FormattableObject.java | 17 +- .../main/org/apache/sis/io/wkt/Formatter.java | 60 +- .../main/org/apache/sis/io/wkt/WKTDictionary.java | 2 +- .../main/org/apache/sis/io/wkt/WKTFormat.java | 12 +- .../main/org/apache/sis/io/wkt/package-info.java | 2 +- .../sis/parameter/DefaultParameterValue.java | 1 + .../org/apache/sis/parameter/ParameterFormat.java | 11 +- .../main/org/apache/sis/parameter/Parameters.java | 6 +- .../main/org/apache/sis/referencing/CRS.java | 31 +- .../apache/sis/referencing/IdentifiedObjects.java | 4 +- .../sis/referencing/ImmutableIdentifier.java | 2 +- .../sis/referencing/crs/DefaultCompoundCRS.java | 4 + .../sis/referencing/crs/DefaultGeodeticCRS.java | 1 + .../cs/DefaultCoordinateSystemAxis.java | 6 +- .../sis/referencing/datum/DefaultEllipsoid.java | 1 + .../sis/referencing/factory/CacheRecord.java | 5 +- .../referencing/factory/CommonAuthorityCode.java | 3 +- .../factory/ConcurrentAuthorityFactory.java | 24 +- .../referencing/factory/sql/EPSGDataAccess.java | 2 +- .../sis/referencing/factory/sql/SQLTranslator.java | 14 +- .../apache/sis/referencing/internal/Resources.java | 33 +- .../sis/referencing/internal/Resources.properties | 5 +- .../referencing/internal/Resources_fr.properties | 5 +- .../referencing/internal/ServicesForMetadata.java | 85 +- .../operation/transform/MathTransformProvider.java | 35 +- .../sis/referencing/util/ReferencingUtilities.java | 18 +- .../test/org/apache/sis/io/wkt/FormatterTest.java | 11 - .../internal/ServicesForMetadataTest.java | 30 +- .../referencing/util/j2d/ShapeUtilitiesViewer.java | 5 +- .../sis/storage/netcdf/base/RasterResource.java | 2 +- .../org/apache/sis/storage/gpx/WritableStore.java | 2 +- .../services/java.nio.file.spi.FileTypeDetector | 2 +- .../org.apache.sis.storage/main/module-info.java | 2 +- .../sis/io/stream/ChannelImageOutputStream.java | 2 - .../main/org/apache/sis/io/stream/IOUtilities.java | 62 +- .../apache/sis/io/stream/OutputStreamAdapter.java | 2 +- .../main/org/apache/sis/storage/DataOptionKey.java | 47 +- .../org/apache/sis/storage/DataStoreProvider.java | 10 +- .../org/apache/sis/storage/DataStoreRegistry.java | 3 +- .../main/org/apache/sis/storage/ProbeReader.java | 2 +- .../org/apache/sis/storage/StorageConnector.java | 10 +- .../apache/sis/storage/base/MetadataBuilder.java | 193 ++- .../org/apache/sis/storage/base/PRJDataStore.java | 44 +- .../org/apache/sis/storage/base/URIDataStore.java | 203 ++- .../main/org/apache/sis/storage/csv/Store.java | 3 +- .../org/apache/sis/storage/csv/StoreProvider.java | 2 +- .../org/apache/sis/storage/esri/RasterStore.java | 4 +- .../apache/sis/storage/esri/RawRasterStore.java | 3 +- .../sis/storage/esri/RawRasterStoreProvider.java | 5 +- .../apache/sis/storage/folder/WritableStore.java | 3 +- .../apache/sis/storage/image/WorldFileStore.java | 20 +- .../apache/sis/storage/image/WritableStore.java | 7 + .../internal}/InputStreamAdapter.java | 15 +- .../org/apache/sis/storage/internal/Resources.java | 5 + .../sis/storage/internal/Resources.properties | 1 + .../sis/storage/internal/Resources_fr.properties | 1 + .../internal}/RewindableLineReader.java | 2 +- .../{internal => services}/StoreTypeDetector.java | 2 +- .../apache/sis/storage/services/package-info.java | 19 +- .../main/org/apache/sis/storage/wkt/Store.java | 2 + .../main/org/apache/sis/storage/xml/Store.java | 1 + .../org/apache/sis/io/stream/IOUtilitiesTest.java | 15 +- .../org/apache/sis/storage/DataOptionKeyTest.java | 33 +- .../apache/sis/storage/StorageConnectorTest.java | 81 +- .../test/org/apache/sis/storage/esri/BIL.prj | 7 + .../test/org/apache/sis/storage/esri/BIP.prj | 7 + .../test/org/apache/sis/storage/esri/BSQ.prj | 7 + .../internal}/RewindableLineReaderTest.java | 39 +- .../org/apache/sis/io/IdentifiedObjectFormat.java | 3 +- .../main/org/apache/sis/measure/AbstractUnit.java | 3 +- .../main/org/apache/sis/measure/UnitFormat.java | 62 +- .../main/org/apache/sis/measure/UnitRegistry.java | 3 +- .../main/org/apache/sis/pending/jdk/JDK21.java | 62 + .../main/org/apache/sis/setup/OptionKey.java | 28 +- .../main/org/apache/sis/setup/package-info.java | 2 +- .../main/org/apache/sis/system/DataDirectory.java | 3 +- .../main/org/apache/sis/system/Environment.java | 87 ++ .../main/org/apache/sis/util/ArraysExt.java | 83 +- .../main/org/apache/sis/util/Printable.java | 42 + .../org/apache/sis/util/internal/Constants.java | 5 + .../apache/sis/util/internal/DefinitionURI.java | 81 +- .../main/org/apache/sis/util/internal/Strings.java | 11 + .../main/org/apache/sis/util/resources/Errors.java | 5 + .../apache/sis/util/resources/Errors.properties | 1 + .../apache/sis/util/resources/Errors_fr.properties | 1 + .../sis/util/resources/IndexedResourceBundle.java | 2 +- .../org/apache/sis/measure/UnitFormatTest.java | 117 +- .../test/org/apache/sis/setup/OptionKeyTest.java | 4 +- .../test/org/apache/sis/util/ArraysExtTest.java | 26 +- .../sis/util/internal/DefinitionURITest.java | 190 +-- .../main/module-info.java | 7 +- .../storage/shapefile/DataStoreQueryException.java | 50 - .../shapefile/DataStoreQueryResultException.java | 50 - .../shapefile/DbaseFileNotFoundException.java | 50 - .../sis/storage/shapefile/InputFeatureStream.java | 379 ------ .../shapefile/InputFeatureStream.properties | 9 - .../shapefile/InputFeatureStream_fr.properties | 9 - .../shapefile/InvalidDbaseFileFormatException.java | 34 - .../shapefile/InvalidShapefileFormatException.java | 50 - .../apache/sis/storage/shapefile/ShapeFile.java | 206 ---- .../sis/storage/shapefile/ShapeTypeEnum.java | 73 -- .../shapefile/ShapefileNotFoundException.java | 50 - .../sis/storage/shapefile/ShapefileProvider.java | 24 + .../sis/storage/shapefile/ShapefileStore.java | 105 +- .../shapefile/{jdbc/sql => cpg}/package-info.java | 5 +- .../apache/sis/storage/shapefile/dbf/DBFField.java | 147 ++- .../sis/storage/shapefile/dbf/DBFHeader.java | 63 +- .../sis/storage/shapefile/dbf/DBFReader.java | 48 +- .../sis/storage/shapefile/dbf/DBFWriter.java | 39 +- .../dbf/{DBFRecord.java => package-info.java} | 28 +- .../storage/shapefile/internal/AutoChecker.java | 184 --- ...nvalidRecordNumberForDirectAccessException.java | 62 - .../SQLNoDirectAccessAvailableException.java | 47 - .../internal/SQLShapefileNotFoundException.java | 47 - .../shapefile/internal/ShapefileByteReader.java | 464 ------- .../internal/ShapefileByteReader.properties | 36 - .../internal/ShapefileByteReader_fr.properties | 36 - .../shapefile/internal/ShapefileDescriptor.java | 198 --- .../storage/shapefile/internal/package-info.java | 22 - .../shapefile/jdbc/AbstractDbase3ByteReader.java | 281 ----- .../jdbc/AbstractDbase3ByteReader.properties | 14 - .../jdbc/AbstractDbase3ByteReader_fr.properties | 14 - .../sis/storage/shapefile/jdbc/AbstractJDBC.java | 158 --- .../storage/shapefile/jdbc/AbstractJDBC.properties | 23 - .../shapefile/jdbc/AbstractJDBC_fr.properties | 1 - .../storage/shapefile/jdbc/CommonByteReader.java | 129 -- .../shapefile/jdbc/CommonByteReader.properties | 3 - .../sis/storage/shapefile/jdbc/DBFDriver.java | 141 --- .../shapefile/jdbc/DBase3FieldDescriptor.java | 146 --- .../jdbc/DBase3FieldDescriptor.properties | 7 - .../jdbc/DBase3FieldDescriptor_fr.properties | 1 - .../sis/storage/shapefile/jdbc/DBaseDataType.java | 99 -- .../storage/shapefile/jdbc/Dbase3ByteReader.java | 132 -- .../storage/shapefile/jdbc/MappedByteReader.java | 307 ----- .../shapefile/jdbc/MappedByteReader.properties | 30 - .../shapefile/jdbc/MappedByteReader_fr.properties | 30 - .../jdbc/SQLConnectionClosedException.java | 64 - .../jdbc/SQLInvalidDbaseFileFormatException.java | 47 - .../jdbc/connection/AbstractConnection.java | 414 ------- .../jdbc/connection/AbstractConnection.properties | 6 - .../connection/AbstractConnection_fr.properties | 6 - .../shapefile/jdbc/connection/DBFConnection.java | 332 ----- .../jdbc/connection/DBFConnection.properties | 49 - .../jdbc/connection/DBFConnection_fr.properties | 39 - .../connection/SQLClosingIOFailureException.java | 64 - .../shapefile/jdbc/connection/package-info.java | 19 - .../jdbc/metadata/AbstractDatabaseMetaData.java | 202 --- .../jdbc/metadata/DBFDatabaseMetaData.java | 1300 -------------------- .../jdbc/metadata/DBFResultSetMataData.java | 473 ------- .../jdbc/metadata/DBFResultSetMataData.properties | 14 - .../metadata/DBFResultSetMataData_fr.properties | 4 - .../shapefile/jdbc/metadata/package-info.java | 21 - .../jdbc/resultset/AbstractResultSet.java | 703 ----------- .../jdbc/resultset/AbstractResultSet.properties | 1 - .../jdbc/resultset/AbstractResultSet_fr.properties | 1 - .../jdbc/resultset/BuiltInMemoryResultSet.java | 192 --- ...iltInMemoryResultSetForCatalogNamesListing.java | 51 - ...DBFBuiltInMemoryResultSetForColumnsListing.java | 460 ------- ...ltInMemoryResultSetForColumnsListing.properties | 8 - ...nMemoryResultSetForColumnsListing_fr.properties | 8 - .../DBFBuiltInMemoryResultSetForSchemaListing.java | 51 - .../DBFBuiltInMemoryResultSetForTablesListing.java | 88 -- ...iltInMemoryResultSetForTablesListing.properties | 2 - ...uiltInMemoryResultSetForTablesTypesListing.java | 74 -- ...MemoryResultSetForTablesTypesListing.properties | 2 - .../jdbc/resultset/DBFRecordBasedResultSet.java | 609 --------- .../resultset/DBFRecordBasedResultSet.properties | 28 - .../DBFRecordBasedResultSet_fr.properties | 28 - .../shapefile/jdbc/resultset/DBFResultSet.java | 965 --------------- .../jdbc/resultset/DBFResultSet.properties | 10 - .../jdbc/resultset/DBFResultSet_fr.properties | 4 - .../resultset/SQLIllegalColumnIndexException.java | 77 -- .../jdbc/resultset/SQLNoResultException.java | 64 - .../jdbc/resultset/SQLNoSuchFieldException.java | 77 -- .../jdbc/resultset/SQLNotDateException.java | 90 -- .../jdbc/resultset/SQLNotNumericException.java | 90 -- .../shapefile/jdbc/resultset/package-info.java | 21 - .../storage/shapefile/jdbc/sql/ClauseResolver.java | 391 ------ .../shapefile/jdbc/sql/ClauseResolver.properties | 25 - .../jdbc/sql/ClauseResolver_fr.properties | 16 - .../jdbc/sql/ConditionalClauseResolver.java | 39 - .../storage/shapefile/jdbc/sql/CrudeSQLParser.java | 137 --- .../shapefile/jdbc/sql/CrudeSQLParser.properties | 12 - .../jdbc/sql/SQLIllegalParameterException.java | 90 -- .../jdbc/sql/SQLInvalidStatementException.java | 64 - .../sql/SQLUnsupportedParsingFeatureException.java | 64 - .../jdbc/statement/AbstractStatement.java | 304 ----- .../shapefile/jdbc/statement/DBFStatement.java | 240 ---- .../jdbc/statement/DBFStatement.properties | 22 - .../jdbc/statement/DBFStatement_fr.properties | 12 - .../apache/sis/storage/shapefile/package-info.java | 23 +- .../shapefile/shp/ShapeGeometryEncoder.java | 151 ++- .../sis/storage/shapefile/shp/ShapeHeader.java | 15 +- .../sis/storage/shapefile/shp/ShapeReader.java | 29 + .../sis/storage/shapefile/shp/ShapeRecord.java | 55 +- .../sis/storage/shapefile/shp/ShapeType.java | 83 +- .../sis/storage/shapefile/shp/ShapeWriter.java | 48 +- .../shapefile/{jdbc => shp}/package-info.java | 14 +- .../sis/storage/shapefile/shx/IndexReader.java | 27 +- .../sis/storage/shapefile/shx/IndexWriter.java | 37 +- .../{jdbc/statement => shx}/package-info.java | 6 +- .../shapefile/ABRALicenseePt_4326_clipped.dbf | Bin 5861 -> 0 bytes .../shapefile/ABRALicenseePt_4326_clipped.prj | 1 - .../shapefile/ABRALicenseePt_4326_clipped.shp | Bin 184 -> 0 bytes .../shapefile/ABRALicenseePt_4326_clipped.shx | Bin 124 -> 0 bytes .../test/org/apache/sis/storage/shapefile/NOTES.md | 12 - .../sis/storage/shapefile/ShapeFileTest.java | 209 ---- .../sis/storage/shapefile/ShapefileStoreTest.java | 89 +- .../shapefile/SignedBikeRoute_4326_clipped.dbf | Bin 7363 -> 0 bytes .../shapefile/SignedBikeRoute_4326_clipped.prj | 1 - .../shapefile/SignedBikeRoute_4326_clipped.shp | Bin 1148 -> 0 bytes .../shapefile/SignedBikeRoute_4326_clipped.shx | Bin 148 -> 0 bytes .../org/apache/sis/storage/shapefile/Snippets.java | 106 ++ .../sis/storage/shapefile/dbf/DBFIOTest.java | 46 +- .../apache/sis/storage/shapefile/dbf/Snippets.java | 95 ++ .../jdbc/AbstractTestBaseForInternalJDBC.java | 73 -- .../storage/shapefile/jdbc/DBFConnectionTest.java | 93 -- .../storage/shapefile/jdbc/DBFResultSetTest.java | 206 ---- .../storage/shapefile/jdbc/DBFStatementTest.java | 98 -- .../apache/sis/storage/shapefile/jdbc/README.md | 60 - .../shapefile/jdbc/sql/WhereClauseTest.java | 147 --- .../sis/storage/shapefile/shp/ShapeIOTest.java | 4 +- .../apache/sis/storage/shapefile/shp/Snippets.java | 81 ++ .../src/org.apache.sis.gui/bundle/conf/imports.jsh | 1 + 271 files changed, 3078 insertions(+), 13991 deletions(-) diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java index 3c83d68e83,3e13498216..565bacfc57 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java @@@ -51,15 -52,12 +52,15 @@@ import org.apache.sis.util.ArgumentChec import org.apache.sis.util.iso.Types; import org.apache.sis.util.resources.Errors; import org.apache.sis.util.resources.Vocabulary; - import org.apache.sis.referencing.IdentifiedObjects; - import org.apache.sis.metadata.internal.NameToIdentifier; import org.apache.sis.util.internal.CollectionsExt; import org.apache.sis.util.internal.X364; + import org.apache.sis.referencing.IdentifiedObjects; + import org.apache.sis.metadata.internal.NameToIdentifier; import static org.apache.sis.util.collection.Containers.hashMapCapacity; +// Specific to the main and geoapi-3.1 branches: +import org.opengis.referencing.ReferenceIdentifier; + // Specific to the geoapi-3.1 and geoapi-4.0 branches: import org.opengis.util.ControlledVocabulary; diff --cc endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java index 852b17066c,24953fbd3a..c2863733cb --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java @@@ -3250,9 -3284,13 +3287,13 @@@ parse: for (int i = 0; i < length; for (final Identification info : component.getIdentificationInfo()) { final Citation c = info.getCitation(); if (c != null) { - // Title, identifiers and series are assumed to not apply (see Javadoc). + // Title (except first one), identifiers and series are assumed to not apply (see Javadoc). + @SuppressWarnings("LocalVariableHidesMemberVariable") final DefaultCitation citation = citation(); + if (citation.getTitle() == null) { + citation.setTitle(c.getTitle()); + } - for (Responsibility r : c.getCitedResponsibleParties()) { + for (ResponsibleParty r : c.getCitedResponsibleParties()) { addIfNotPresent(citation.getCitedResponsibleParties(), r); } for (OnlineResource r : c.getOnlineResources()) { @@@ -3353,6 -3407,81 +3411,81 @@@ return true; } + /** + * Replaces any null metadata element by the last element from the parent. + * This is used for continuing the edition of an existing metadata. + */ + private void useParentElements() { + if (identification == null) identification = last (DefaultDataIdentification.class, metadata, DefaultMetadata::getIdentificationInfo); + if (gridRepresentation == null) gridRepresentation = last (DefaultGridSpatialRepresentation.class, metadata, DefaultMetadata::getSpatialRepresentationInfo); + if (coverageDescription == null) coverageDescription = last (DefaultCoverageDescription.class, metadata, DefaultMetadata::getContentInfo); + if (featureDescription == null) featureDescription = last (DefaultFeatureCatalogueDescription.class, metadata, DefaultMetadata::getContentInfo); + if (acquisition == null) acquisition = last (DefaultAcquisitionInformation.class, metadata, DefaultMetadata::getAcquisitionInformation); + if (lineage == null) lineage = last (DefaultLineage.class, metadata, DefaultMetadata::getResourceLineages); - if (distribution == null) distribution = last (DefaultDistribution.class, metadata, DefaultMetadata::getDistributionInfo); ++ if (distribution == null) distribution = fetch(DefaultDistribution.class, metadata, DefaultMetadata::getDistributionInfo); + if (citation == null) citation = fetch(DefaultCitation.class, identification, AbstractIdentification::getCitation); + if (extent == null) extent = last (DefaultExtent.class, identification, AbstractIdentification::getExtents); + if (constraints == null) constraints = last (DefaultLegalConstraints.class, identification, AbstractIdentification::getResourceConstraints); - if (responsibility == null) responsibility = last (DefaultResponsibility.class, citation, DefaultCitation::getCitedResponsibleParties); ++ if (responsibility == null) responsibility = last (DefaultResponsibleParty.class, citation, DefaultCitation::getCitedResponsibleParties); + if (party == null) party = last (AbstractParty.class, responsibility, DefaultResponsibility::getParties); + if (attributeGroup == null) attributeGroup = last (DefaultAttributeGroup.class, coverageDescription, DefaultCoverageDescription::getAttributeGroups); + if (sampleDimension == null) sampleDimension = last (DefaultSampleDimension.class, attributeGroup, DefaultAttributeGroup::getAttributes); + if (format == null) format = last (DefaultFormat.class, distribution, DefaultDistribution::getDistributionFormats); + if (platform == null) platform = last (DefaultPlatform.class, acquisition, DefaultAcquisitionInformation::getPlatforms); + if (processStep == null) processStep = last (DefaultProcessStep.class, lineage, DefaultLineage::getProcessSteps); + if (processing == null) processing = fetch(DefaultProcessing.class, processStep, DefaultProcessStep::getProcessingInformation); + } + + /** + * Returns the element of the given source metadata if it is of the desired class. + * This method is equivalent to {@link #last(Class, Object, Function)} but for a singleton. + * + * @param <S> the type of the source metadata. + * @param <E> the type of metadata element provided by the source. + * @param <T> the type of the desired metadata element. + * @param target the type of the desired metadata element. + * @param source the source metadata, or {@code null} if none. + * @param getter the getter to use for fetching elements from the source metadata. + * @return the metadata element from the source, or {@code null} if none. + */ + private static <S extends ISOMetadata, E, T extends E> T fetch(final Class<T> target, final S source, + final Function<S,E> getter) + { + if (source != null) { + final E last = getter.apply(source); + if (target.isInstance(last)) { + return target.cast(last); + } + } + return null; + } + + /** + * Returns the element of the given source metadata if it is of the desired class. + * This method is equivalent to {@link #fetch(Class, Object, Function)} but for a collection. + * + * @param <S> the type of the source metadata. + * @param <E> the type of metadata element provided by the source. + * @param <T> the type of the desired metadata element. + * @param target the type of the desired metadata element. + * @param source the source metadata, or {@code null} if none. + * @param getter the getter to use for fetching elements from the source metadata. + * @return the metadata element from the source, or {@code null} if none. + */ + private static <S extends ISOMetadata, E, T extends E> T last(final Class<T> target, final S source, + final Function<S,Collection<E>> getter) + { + if (source != null) { + // If not a sequenced collection, the iteration may be in any order. + for (final E last : JDK21.reversed(getter.apply(source))) { + if (target.isInstance(last)) { + return target.cast(last); + } + } + } + return null; + } + /** * Writes all pending metadata objects into the {@link DefaultMetadata} root class. * Then all {@link #identification}, {@link #gridRepresentation}, <i>etc.</i> fields