This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit f2f389fa68f4112a35733d85182b06951e0de3ca Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Fri Sep 9 19:32:58 2022 +0200 Make the reference to source resource accessible throught lineage metadata. --- .../apache/sis/metadata/iso/extent/Extents.java | 55 +++++- .../sis/metadata/iso/extent/package-info.java | 2 +- .../internal/storage/DocumentedStoreProvider.java | 2 +- .../sis/internal/storage/MetadataBuilder.java | 23 ++- .../sis/internal/storage/ResourceLineage.java | 198 +++++++++++++++++++++ .../org/apache/sis/internal/storage/Resources.java | 5 + .../sis/internal/storage/Resources.properties | 1 + .../sis/internal/storage/Resources_fr.properties | 1 + .../sis/internal/storage/StoreUtilities.java | 26 +++ .../org/apache/sis/internal/storage/csv/Store.java | 2 +- .../org/apache/sis/storage/CoverageSubset.java | 15 ++ .../java/org/apache/sis/storage/FeatureSubset.java | 15 ++ .../org/apache/sis/storage/CoverageQueryTest.java | 8 +- .../org/apache/sis/storage/FeatureQueryTest.java | 8 +- 14 files changed, 352 insertions(+), 9 deletions(-) diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/Extents.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/Extents.java index ae145b88cc..9ed63cf613 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/Extents.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/Extents.java @@ -17,9 +17,13 @@ package org.apache.sis.metadata.iso.extent; import java.util.Date; +import java.util.Locale; import java.util.List; import java.util.ArrayList; -import java.util.Locale; +import java.util.Set; +import java.util.LinkedHashSet; +import java.util.Collection; +import java.util.Collections; import java.util.function.Function; import java.util.function.BiConsumer; import javax.measure.Unit; @@ -59,6 +63,7 @@ import org.apache.sis.util.ComparisonMode; import org.apache.sis.util.Static; import static java.lang.Math.*; +import static org.apache.sis.util.collection.Containers.isNullOrEmpty; import static org.apache.sis.internal.util.CollectionsExt.nonNull; import static org.apache.sis.internal.metadata.ReferencingServices.AUTHALIC_RADIUS; @@ -79,7 +84,7 @@ import org.opengis.geometry.Geometry; * </ul> * * @author Martin Desruisseaux (Geomatys) - * @version 1.2 + * @version 1.3 * * @see org.apache.sis.geometry.Envelopes * @@ -118,6 +123,52 @@ public final class Extents extends Static { WORLD = world; } + /** + * Returns the extents found in all {@code Identification} elements of the given metadata. + * If there is only one {@link Identification} element (which is the usual case), then its + * collection of extents is returned <em>as-is</em>; the collection is not copied. + * + * <p>In the less usual case where there is many {@link Identification} elements providing + * non-empty collection of extents, then this method returns the union of all collections + * without duplicated elements (duplication determined by {@link Object#equals(Object)}). + * In the special case where the first non-empty collection of extents contains all other + * collections, then that collection is returned <em>as-is</em>.</p> + * + * <div class="note"><b>Rational:</b> + * above policy makes a best effort for avoiding to create new collections. + * The reason is that collection implementations may perform lazy calculations of {@link Extent} elements. + * This method tries to preserve the lazy behavior (if any).</div> + * + * @param metadata the metadata, or {@code null} if none. + * @return extents found in all {@link Identification} elements, or an empty collection if none. + * + * @since 1.3 + */ + public static Collection<? extends Extent> fromIdentificationInfo(final Metadata metadata) { + Collection<? extends Extent> result = null; + if (metadata != null) { + Set<Extent> union = null; + for (final Identification id : nonNull(metadata.getIdentificationInfo())) { + if (id != null) { // Should not be allowed, but we are paranoiac. + final Collection<? extends Extent> extents = id.getExtents(); + if (extents != result && !isNullOrEmpty(extents)) { + if (result == null) { + result = extents; + } else { + if (union == null) { + union = new LinkedHashSet<>(result); + } + if (union.addAll(extents)) { + result = union; + } + } + } + } + } + } + return (result != null) ? result : Collections.emptyList(); + } + /** * Returns a single geographic bounding box from the specified metadata. If the given metadata * contains many {@link Identification} or many {@link Extent} instances, then this method returns diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/package-info.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/package-info.java index d5d88c6871..3f83535df4 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/package-info.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/package-info.java @@ -136,7 +136,7 @@ * @author Cédric Briançon (Geomatys) * @author Guilhem Legal (Geomatys) * @author Cullen Rombach (Image Matters) - * @version 1.0 + * @version 1.3 * @since 0.3 * @module */ diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DocumentedStoreProvider.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DocumentedStoreProvider.java index 7f653ac1fc..319760f61e 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DocumentedStoreProvider.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DocumentedStoreProvider.java @@ -27,7 +27,7 @@ import org.apache.sis.internal.system.Modules; /** - * Base class of data store provider having an entry in the metadata SQL database. + * Base class of data store providers having an entry in the metadata SQL database. * The primary key in the {@code MD_Format} table must be the name given at construction time. * * @author Martin Desruisseaux (Geomatys) diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java index dac07899b8..7ef829f5e6 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MetadataBuilder.java @@ -73,6 +73,7 @@ import org.apache.sis.metadata.iso.maintenance.*; import org.apache.sis.metadata.iso.spatial.*; import org.apache.sis.metadata.sql.MetadataStoreException; import org.apache.sis.metadata.sql.MetadataSource; +import org.apache.sis.storage.Resource; import org.apache.sis.storage.AbstractResource; import org.apache.sis.storage.AbstractFeatureSet; import org.apache.sis.storage.AbstractGridCoverageResource; @@ -110,7 +111,7 @@ import org.opengis.feature.FeatureType; * @author Rémi Maréchal (Geomatys) * @author Thi Phuong Hao Nguyen (VNSC) * @author Alexis Manin (Geomatys) - * @version 1.2 + * @version 1.3 * @since 0.8 * @module */ @@ -1081,7 +1082,8 @@ public class MetadataBuilder { /** * Adds information about the scope of the resource. - * The scope is typically {@link ScopeCode#DATASET}. + * The scope is typically (but not restricted to) {@link ScopeCode#COVERAGE}, + * {@link ScopeCode#FEATURE} or the more generic {@link ScopeCode#DATASET}. * Storage locations are: * * <ul> @@ -2892,6 +2894,23 @@ parse: for (int i = 0; i < length;) { } } + /** + * Creates metadata about the sources of a resource. + * Storage location is: + * + * <ul> + * <li>{@code metadata/resourceLineage/source}</li> + * </ul> + * + * @param sources the sources of the resource for which to describe the lineage. + * @throws DataStoreException if an error occurred while fetching metadata from a resource. + */ + public final void addSources(final Resource... sources) throws DataStoreException { + if (sources != null && sources.length != 0) { + ResourceLineage.setSources(lineage(), sources); + } + } + /** * Adds information about a source of data used for producing the resource. * Storage location is: diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ResourceLineage.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ResourceLineage.java new file mode 100644 index 0000000000..3c7f5a784e --- /dev/null +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ResourceLineage.java @@ -0,0 +1,198 @@ +/* + * 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.internal.storage; + +import java.util.Arrays; +import java.util.Collection; +import org.opengis.metadata.Metadata; +import org.opengis.metadata.MetadataScope; +import org.opengis.metadata.extent.Extent; +import org.opengis.metadata.lineage.Source; +import org.opengis.metadata.maintenance.Scope; +import org.opengis.metadata.maintenance.ScopeCode; +import org.opengis.metadata.citation.Citation; +import org.opengis.metadata.identification.Resolution; +import org.opengis.metadata.identification.Identification; +import org.opengis.referencing.ReferenceSystem; +import org.opengis.util.InternationalString; +import org.apache.sis.internal.util.CollectionsExt; +import org.apache.sis.metadata.iso.extent.Extents; +import org.apache.sis.metadata.iso.lineage.DefaultLineage; +import org.apache.sis.metadata.iso.maintenance.DefaultScope; +import org.apache.sis.storage.DataStoreException; +import org.apache.sis.storage.Resource; + +import static org.apache.sis.internal.util.CollectionsExt.nonNull; + + +/** + * Metadata about a resource which is a single source of another resource. + * This is an experimental class which may be revisited in any future version. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.3 + * @since 1.3 + * @module + */ +final class ResourceLineage implements Source { + /** + * The source of the derived resource described by the lineage. + */ + public final Resource source; + + /** + * Metadata of the source, or {@code null} if none. + * All properties returned by this class are inferred from those metadata. + */ + private final Metadata metadata; + + /** + * Creates a new source wrapping the given resource. + * + * @param source the source of the derived resource described by the resource lineage. + * @throws DataStoreException if an error occurred while fetching metadata from the source. + */ + private ResourceLineage(final Resource source) throws DataStoreException { + this.source = source; + metadata = source.getMetadata(); + } + + /** + * Writes metadata about the sources of a resource. + * + * @param lineage where to write lineage information. + * @param sources the sources of the resource for which to describe the lineage. + * @throws DataStoreException if an error occurred while fetching metadata from a resource. + */ + static void setSources(final DefaultLineage lineage, final Resource... sources) throws DataStoreException { + final ResourceLineage[] wrappers = new ResourceLineage[sources.length]; + for (int i=0; i<wrappers.length; i++) { + wrappers[i] = new ResourceLineage(sources[i]); + } + lineage.setSources(Arrays.asList(wrappers)); + } + + /** + * Returns a description of the level of the source data. + * Default implementation returns the title of the {@linkplain #getSourceCitation() source citation}. + * + * @return description of the level of the source data, or {@code null} if none. + */ + @Override + public InternationalString getDescription() { + final Citation citation = getSourceCitation(); + return (citation != null) ? citation.getTitle() : null; + } + + /** + * Returns the recommended reference to be used for the source data. + * Default implementation returns the first citation having a non-null title + * among the citations provided by {@link Metadata#getIdentificationInfo()}. + * + * @return recommended reference to be used for the source data, or {@code null}. + */ + @Override + public Citation getSourceCitation() { + if (metadata != null) { + for (final Identification info : nonNull(metadata.getIdentificationInfo())) { + final Citation citation = info.getCitation(); + if (citation != null) { + if (citation.getTitle() != null) { + return citation; + } + } + } + } + return null; + } + + /** + * Returns the type and extent of the source. Default implementation returns the resource scope + * declared in source metadata, together with the {@linkplain #getSourceExtents() source extents}. + * + * @return type and extent of the source, or {@code null} if none. + */ + @Override + public Scope getScope() { + return createScope(metadata); + } + + /** + * Creates a scope from the given resource metadata. + */ + private static Scope createScope(final Metadata metadata) { + if (metadata != null) { + ScopeCode level = null; + for (final MetadataScope ms : nonNull(metadata.getMetadataScopes())) { + level = ms.getResourceScope(); + if (level != null) break; + } + final Collection<? extends Extent> extents = Extents.fromIdentificationInfo(metadata); + if (level != null || !extents.isEmpty()) { + final DefaultScope scope = new DefaultScope(level); + scope.setExtents(extents); + return scope; + } + } + return null; + } + + /** + * Information about the spatial, vertical and temporal extent of the source data. + * Default implementation returns all extents declared in {@link Metadata#getIdentificationInfo()}. + * + * @return information about the extent of the source data. + * + * @deprecated As of ISO 19115:2014, moved to {@link Scope#getExtents()}. + */ + @Override + @Deprecated + public Collection<? extends Extent> getSourceExtents() { + return Extents.fromIdentificationInfo(metadata); + } + + /** + * Returns the spatial reference system used by the source data. + * Default implementation returns the first reference system declared by metadata. + * + * @return spatial reference system used by the source data, or {@code null}. + */ + @Override + public ReferenceSystem getSourceReferenceSystem() { + return (metadata != null) ? CollectionsExt.first(metadata.getReferenceSystemInfo()) : null; + } + + /** + * Spatial resolution expressed as a scale factor, an angle or a level of detail. + * Default implementation returns the first resolution found in identification information. + * + * @return spatial resolution, or {@code null} if none. + */ + @Override + public Resolution getSourceSpatialResolution() { + if (metadata != null) { + for (final Identification info : nonNull(metadata.getIdentificationInfo())) { + for (final Resolution candidate : nonNull(info.getSpatialResolutions())) { + if (candidate != null) { + return candidate; + } + } + } + } + return null; + } +} diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java index a4fe0b30c9..292e4a0920 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java @@ -336,6 +336,11 @@ public final class Resources extends IndexedResourceBundle { */ public static final short NotAWritableFeatureSet_1 = 47; + /** + * Original data. + */ + public static final short OriginalData = 76; + /** * Processing executed on {0}. */ diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties index ad995bb769..ce57d3a1cc 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties @@ -74,6 +74,7 @@ NoCommonFeatureType = No feature type is common to all the feature NoSuchResourceDirectory_1 = No directory of resources found at \u201c{0}\u201d. NoSuchResourceInAggregate_2 = Resource \u201c{1}\u201d is not part of aggregate \u201c{0}\u201d. NotAWritableFeatureSet_1 = Resource \u201c{0}\u201d is not a writable feature set. +OriginalData = Original data. ProcessingExecutedOn_1 = Processing executed on {0}. ResourceAlreadyExists_1 = A resource already exists at \u201c{0}\u201d. ResourceIdentifierCollision_2 = More than one resource have the \u201c{1}\u201d identifier in the \u201c{0}\u201d data store. diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties index bae8560190..a2dc7693cb 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties @@ -79,6 +79,7 @@ NoCommonFeatureType = Il n\u2019y a pas de type commun \u00e0 tout NoSuchResourceDirectory_1 = Aucun r\u00e9pertoire de ressources n\u2019a \u00e9t\u00e9 trouv\u00e9 \u00e0 l\u2019emplacement \u00ab\u202f{0}\u202f\u00bb. NoSuchResourceInAggregate_2 = La ressource \u00ab\u202f{1}\u202f\u00bb n\u2019est pas une partie de l\u2019agr\u00e9gat \u00ab\u202f{0}\u202f\u00bb. NotAWritableFeatureSet_1 = La ressource \u00ab\u202f{0}\u202f\u00bb n\u2019est pas un ensemble d\u2019entit\u00e9s accessibles en \u00e9criture. +OriginalData = Donn\u00e9es originales. ProcessingExecutedOn_1 = Traitement ex\u00e9cut\u00e9 sur {0}. ResourceAlreadyExists_1 = Une ressource existe d\u00e9j\u00e0 \u00e0 l\u2019emplacement \u00ab\u202f{0}\u202f\u00bb. ResourceIdentifierCollision_2 = Plusieurs ressources utilisent l\u2019identifiant \u00ab\u202f{1}\u202f\u00bb dans les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb. diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java index eaeb355bab..e9b9586c91 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java @@ -18,6 +18,8 @@ package org.apache.sis.internal.storage; import java.util.Set; import java.util.EnumSet; +import java.util.List; +import java.util.ArrayList; import java.util.Optional; import java.util.stream.Stream; import java.util.logging.Filter; @@ -34,6 +36,8 @@ import org.opengis.metadata.extent.GeographicExtent; import org.opengis.metadata.extent.GeographicBoundingBox; import org.opengis.metadata.identification.Identification; import org.opengis.metadata.identification.DataIdentification; +import org.opengis.metadata.lineage.Lineage; +import org.opengis.metadata.lineage.Source; import org.apache.sis.util.Static; import org.apache.sis.storage.FeatureSet; import org.apache.sis.storage.Resource; @@ -52,6 +56,8 @@ import org.apache.sis.util.resources.Errors; import org.apache.sis.util.CharSequences; import org.apache.sis.util.Classes; +import static org.apache.sis.internal.util.CollectionsExt.nonNull; + // Branch-dependent imports import org.opengis.feature.Feature; @@ -208,6 +214,26 @@ public final class StoreUtilities extends Static { return bounds; } + /** + * Fetches all resources that are the sources of a resource described by given metadata. + * + * @param metadata metadata of the resource for which to get the sources, or {@code null} if none. + * @return sources found in given metadata. + */ + public static List<Resource> getSources(final Metadata metadata) { + final List<Resource> sources = new ArrayList<>(); + if (metadata != null) { + for (final Lineage lineage : nonNull(metadata.getResourceLineages())) { + for (final Source candidate : nonNull(lineage.getSources())) { + if (candidate instanceof ResourceLineage) { + sources.add(((ResourceLineage) candidate).source); + } + } + } + } + return sources; + } + /** * Returns the most specific interface implemented by the given class. * For indicative purpose only, as this method has arbitrary behavior if more than one leaf is found. diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java index adb49da93a..9e6cba17f4 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java @@ -642,7 +642,7 @@ final class Store extends URIDataStore implements FeatureSet { listeners.warning(e); } builder.addEncoding(encoding, MetadataBuilder.Scope.ALL); - builder.addResourceScope(ScopeCode.DATASET, null); + builder.addResourceScope(ScopeCode.FEATURE, null); try { builder.addExtent(envelope); } catch (TransformException e) { diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageSubset.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageSubset.java index 0a68a344e8..447a81ca27 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageSubset.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/CoverageSubset.java @@ -18,6 +18,7 @@ package org.apache.sis.storage; import java.util.Arrays; import java.util.List; +import org.opengis.metadata.Metadata; import org.opengis.util.FactoryException; import org.opengis.referencing.operation.TransformException; import org.apache.sis.coverage.SampleDimension; @@ -28,6 +29,7 @@ import org.apache.sis.coverage.grid.GridRoundingMode; import org.apache.sis.coverage.grid.GridClippingMode; import org.apache.sis.coverage.grid.DisjointExtentException; import org.apache.sis.internal.storage.Resources; +import org.apache.sis.internal.storage.MetadataBuilder; import org.apache.sis.internal.util.UnmodifiableArrayList; @@ -65,6 +67,19 @@ final class CoverageSubset extends AbstractGridCoverageResource { this.query = query; } + /** + * Creates metadata about this subset. + * It includes information about the complete feature set. + */ + @Override + protected Metadata createMetadata() throws DataStoreException { + final MetadataBuilder builder = new MetadataBuilder(); + builder.addDefaultMetadata(this, listeners); + builder.addLineage(Resources.formatInternational(Resources.Keys.OriginalData)); + builder.addSources(source); + return builder.build(); + } + /** * Returns the valid extent of grid coordinates clipped to the area specified in the query. * It should be the geometry of the coverage that we get when invoking {@link #read read(…)} diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSubset.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSubset.java index 4affc9612e..c1e5d01d94 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSubset.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSubset.java @@ -18,7 +18,9 @@ package org.apache.sis.storage; import java.util.OptionalLong; import java.util.stream.Stream; +import org.opengis.metadata.Metadata; import org.apache.sis.internal.feature.FeatureUtilities; +import org.apache.sis.internal.storage.MetadataBuilder; import org.apache.sis.internal.storage.Resources; // Branch-dependent imports @@ -68,6 +70,19 @@ final class FeatureSubset extends AbstractFeatureSet { this.query = query; } + /** + * Creates metadata about this subset. + * It includes information about the complete feature set. + */ + @Override + protected Metadata createMetadata() throws DataStoreException { + final MetadataBuilder builder = new MetadataBuilder(); + builder.addDefaultMetadata(this, listeners); + builder.addLineage(Resources.formatInternational(Resources.Keys.OriginalData)); + builder.addSources(source); + return builder.build(); + } + /** * Returns a description of properties that are common to all features in this dataset. */ diff --git a/storage/sis-storage/src/test/java/org/apache/sis/storage/CoverageQueryTest.java b/storage/sis-storage/src/test/java/org/apache/sis/storage/CoverageQueryTest.java index 305908c2a8..ebe47db3cc 100644 --- a/storage/sis-storage/src/test/java/org/apache/sis/storage/CoverageQueryTest.java +++ b/storage/sis-storage/src/test/java/org/apache/sis/storage/CoverageQueryTest.java @@ -23,18 +23,20 @@ import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.coverage.grid.GridExtent; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.internal.referencing.j2d.AffineTransform2D; +import org.apache.sis.internal.storage.StoreUtilities; import org.apache.sis.referencing.crs.HardCodedCRS; import org.apache.sis.test.TestCase; import org.junit.Test; import static org.junit.Assert.*; +import static org.apache.sis.test.TestUtilities.getSingleton; /** * Tests {@link CoverageQuery} and (indirectly) {@link CoverageSubset}. * * @author Johann Sorel (Geomatys) - * @version 1.1 + * @version 1.3 * @since 1.1 */ public final strictfp class CoverageQueryTest extends TestCase { @@ -178,5 +180,9 @@ public final strictfp class CoverageQueryTest extends TestCase { request = createSubGrid(-4 + expansion); } assertEquals(request, coverage.getGridGeometry()); + /* + * Verify lineage metadata. They are stored in specialized sub-type of `Source`. + */ + assertSame(resource, getSingleton(StoreUtilities.getSources(subset.getMetadata()))); } } diff --git a/storage/sis-storage/src/test/java/org/apache/sis/storage/FeatureQueryTest.java b/storage/sis-storage/src/test/java/org/apache/sis/storage/FeatureQueryTest.java index a4d157da7a..3e8313826a 100644 --- a/storage/sis-storage/src/test/java/org/apache/sis/storage/FeatureQueryTest.java +++ b/storage/sis-storage/src/test/java/org/apache/sis/storage/FeatureQueryTest.java @@ -22,12 +22,14 @@ import java.util.Iterator; import java.util.stream.Collectors; import org.apache.sis.feature.builder.FeatureTypeBuilder; import org.apache.sis.internal.storage.MemoryFeatureSet; +import org.apache.sis.internal.storage.StoreUtilities; import org.apache.sis.filter.DefaultFilterFactory; import org.apache.sis.test.TestUtilities; import org.apache.sis.test.TestCase; import org.junit.Test; import static org.junit.Assert.*; +import static org.apache.sis.test.TestUtilities.getSingleton; // Branch-dependent imports import org.opengis.feature.Feature; @@ -47,7 +49,7 @@ import org.opengis.filter.SortProperty; * @author Johann Sorel (Geomatys) * @author Alexis Manin (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 1.2 + * @version 1.3 * @since 1.0 * @module */ @@ -141,6 +143,10 @@ public final strictfp class FeatureQueryTest extends TestCase { + "Actual:%n%s%n", i, expected, actual)); } } + /* + * Verify lineage metadata. They are stored in specialized sub-type of `Source`. + */ + assertSame(featureSet, getSingleton(StoreUtilities.getSources(fs.getMetadata()))); } /**