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 7f93d02b529612e33850f422d69ba830a8547eba Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Sat Sep 10 15:52:11 2022 +0200 Provide a little bit more information about queries in the lineage metadata. --- .../sis/internal/storage/MetadataBuilder.java | 24 +++++-- .../sis/internal/storage/ResourceLineage.java | 76 ++++++++++++---------- .../org/apache/sis/internal/storage/Resources.java | 15 +++-- .../sis/internal/storage/Resources.properties | 5 +- .../sis/internal/storage/Resources_fr.properties | 5 +- .../org/apache/sis/storage/CoverageSubset.java | 4 +- .../java/org/apache/sis/storage/FeatureSubset.java | 4 +- 7 files changed, 82 insertions(+), 51 deletions(-) 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 7ef829f5e6..e6fbad0cd9 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 @@ -1051,7 +1051,7 @@ public class MetadataBuilder { public final void addLanguage(final Locale language, final Scope scope) { ArgumentChecks.ensureNonNull("scope", scope); if (language != null) { - // No need to use 'addIfNotPresent(…)' because Locale collection is a Set by default. + // No need to use `addIfNotPresent(…)` because Locale collection is a Set by default. if (scope != Scope.RESOURCE) metadata().getLanguages().add(language); if (scope != Scope.METADATA) identification().getLanguages().add(language); } @@ -1074,7 +1074,7 @@ public class MetadataBuilder { public final void addEncoding(final Charset encoding, final Scope scope) { ArgumentChecks.ensureNonNull("scope", scope); if (encoding != null) { - // No need to use 'addIfNotPresent(…)' because Charset collection is a Set by default. + // No need to use `addIfNotPresent(…)` because Charset collection is a Set by default. if (scope != Scope.RESOURCE) metadata().getCharacterSets().add(encoding); if (scope != Scope.METADATA) identification().getCharacterSets().add(encoding); } @@ -1417,7 +1417,7 @@ public class MetadataBuilder { */ public final void addTopicCategory(final TopicCategory topic) { if (topic != null) { - // No need to use 'addIfNotPresent(…)' for enumerations. + // No need to use `addIfNotPresent(…)` for enumerations. identification().getTopicCategories().add(topic); } } @@ -1805,7 +1805,7 @@ parse: for (int i = 0; i < length;) { */ public final void addAccessConstraint(final Restriction restriction) { if (restriction != null) { - // No need to use 'addIfNotPresent(…)' for code lists. + // No need to use `addIfNotPresent(…)` for code lists. constraints().getAccessConstraints().add(restriction); } } @@ -2042,7 +2042,7 @@ parse: for (int i = 0; i < length;) { */ public final void addSpatialRepresentation(final SpatialRepresentationType type) { if (type != null) { - // No need to use 'addIfNotPresent(…)' for code lists. + // No need to use `addIfNotPresent(…)` for code lists. identification().getSpatialRepresentationTypes().add(type); } } @@ -2895,7 +2895,7 @@ parse: for (int i = 0; i < length;) { } /** - * Creates metadata about the sources of a resource. + * Adds metadata about the sources of a resource. * Storage location is: * * <ul> @@ -2904,10 +2904,17 @@ parse: for (int i = 0; i < length;) { * * @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. + * + * @see #addLineage(CharSequence) + * @see #addProcessDescription(CharSequence) */ public final void addSources(final Resource... sources) throws DataStoreException { if (sources != null && sources.length != 0) { - ResourceLineage.setSources(lineage(), sources); + final ResourceLineage[] wrappers = new ResourceLineage[sources.length]; + for (int i=0; i<wrappers.length; i++) { + wrappers[i] = new ResourceLineage(sources[i]); + } + lineage().getSources().addAll(Arrays.asList(wrappers)); } } @@ -2929,6 +2936,7 @@ parse: for (int i = 0; i < length;) { * @param level hierarchical level of the source (e.g. model), or {@code null} if unspecified. * @param feature more detailed name for {@code level}, or {@code null} if none. * + * @see #addSources(Resource...) * @see #addProcessing(CharSequence, String) * @see #addProcessDescription(CharSequence) */ @@ -2969,6 +2977,8 @@ parse: for (int i = 0; i < length;) { * @param metadata the metadata of the source, or {@code null} if none. * @param level hierarchical level of the source (e.g. feature). Should not be null. * @param features names of dataset, features or attributes used in the source. + * + * @see #addSources(Resource...) */ public final void addSource(final Metadata metadata, final ScopeCode level, final CharSequence... features) { if (metadata != null) { 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 index 3c7f5a784e..6e81c658e0 100644 --- 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 @@ -16,7 +16,6 @@ */ package org.apache.sis.internal.storage; -import java.util.Arrays; import java.util.Collection; import org.opengis.metadata.Metadata; import org.opengis.metadata.MetadataScope; @@ -30,8 +29,8 @@ 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.ModifiableMetadata; 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; @@ -60,32 +59,29 @@ final class ResourceLineage implements Source { */ private final Metadata metadata; + /** + * The scope, computed when first requested. + * + * @see #getScope() + */ + private transient Scope scope; + + /** + * Whether {@link #scope} has been initialized. The result may still be null. + */ + private boolean scopeInitialized; + /** * 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 { + 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}. @@ -127,35 +123,49 @@ final class ResourceLineage implements Source { * @return type and extent of the source, or {@code null} if none. */ @Override - public Scope getScope() { - return createScope(metadata); + public synchronized Scope getScope() { + if (!scopeInitialized) { + scopeInitialized = true; + final ScopeCode level = getScopeLevel(); + final Collection<? extends Extent> extents = getSourceExtents(); + if (level != null || !extents.isEmpty()) { + final DefaultScope scope = new DefaultScope(level); + scope.setExtents(extents); + scope.transitionTo(ModifiableMetadata.State.FINAL); + this.scope = scope; + } + } + return scope; } /** - * Creates a scope from the given resource metadata. + * Returns the type (coverage, feature, …) of the source to be stored in the "level" attribute of the scope. + * + * @return scope level (coverage, feature, …), or {@code null} if none. */ - private static Scope createScope(final Metadata metadata) { + private ScopeCode getScopeLevel() { + ScopeCode level = null; 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; + final ScopeCode c = ms.getResourceScope(); + if (c != null) { + if (level == null) { + level = c; + } else if (!level.equals(c)) { + level = null; + break; + } + } } } - return null; + return level; } /** * 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. + * @return information about the extent of the source data, or an empty collection if none. * * @deprecated As of ISO 19115:2014, moved to {@link Scope#getExtents()}. */ 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 292e4a0920..5aabcbf31d 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,11 +336,6 @@ 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}. */ @@ -421,6 +416,11 @@ public final class Resources extends IndexedResourceBundle { */ public static final short StreamIsWriteOnce_1 = 21; + /** + * Query a subset of “{0}”. + */ + public static final short SubsetQuery_1 = 77; + /** * Can not open {0} data store without “{1}” parameter. */ @@ -431,6 +431,11 @@ public final class Resources extends IndexedResourceBundle { */ public static final short UnexpectedNumberOfCoordinates_4 = 58; + /** + * Unfiltered data. + */ + public static final short UnfilteredData = 76; + /** * Format of “{0}” is not recognized. */ 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 ce57d3a1cc..662c15ae1b 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,7 +74,6 @@ 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. @@ -91,7 +90,9 @@ StreamIsNotReadable_1 = Stream \u201c{0}\u201d is not readable. StreamIsNotWritable_1 = Stream \u201c{0}\u201d is not writable. StreamIsReadOnce_1 = The \u201c{0}\u201d data store can be read only once. StreamIsWriteOnce_1 = Can not modify previously written data in \u201c{0}\u201d. +SubsetQuery_1 = Query a subset of \u201c{0}\u201d. UndefinedParameter_2 = Can not open {0} data store without \u201c{1}\u201d parameter. -UnknownFormatFor_1 = Format of \u201c{0}\u201d is not recognized. UnexpectedNumberOfCoordinates_4 = The \u201c{0}\u201d feature at {1} has a {3} coordinate values, while we expected a multiple of {2}. +UnfilteredData = Unfiltered data. +UnknownFormatFor_1 = Format of \u201c{0}\u201d is not recognized. UsedOnlyIfNotEncoded = Used only if this information is not encoded with the data. 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 a2dc7693cb..2d3a34bdc5 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,7 +79,6 @@ 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. @@ -96,7 +95,9 @@ StreamIsNotReadable_1 = Les donn\u00e9es de \u00ab\u202f{0}\u202f\u0 StreamIsNotWritable_1 = Le flux de donn\u00e9es \u00ab\u202f{0}\u202f\u00bb ne g\u00e8re pas les \u00e9critures. StreamIsReadOnce_1 = Les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb ne peuvent \u00eatre lues qu\u2019une seule fois. StreamIsWriteOnce_1 = Ne peut pas revenir sur les donn\u00e9es d\u00e9j\u00e0 \u00e9crites dans \u00ab\u202f{0}\u202f\u00bb. +SubsetQuery_1 = Requ\u00eate d\u2019un sous-ensemble de \u00ab\u202f{0}\u202f\u00bb. UndefinedParameter_2 = Ne peut pas ouvrir une source de donn\u00e9es {0} sans le param\u00e8tre \u00ab\u202f{1}\u202f\u00bb. -UnknownFormatFor_1 = Le format de \u00ab\u202f{0}\u202f\u00bb n\u2019est pas reconnu. UnexpectedNumberOfCoordinates_4 = L\u2019entit\u00e9 nomm\u00e9e \u00ab\u202f{0}\u202f\u00bb \u00e0 {1} contient {3} coordonn\u00e9es, alors qu\u2019on attendait un multiple de {2}. +UnfilteredData = Donn\u00e9es non-filtr\u00e9es. +UnknownFormatFor_1 = Le format de \u00ab\u202f{0}\u202f\u00bb n\u2019est pas reconnu. UsedOnlyIfNotEncoded = Utilis\u00e9 seulement si cette information n\u2019est pas encod\u00e9e avec les donn\u00e9es. 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 447a81ca27..a5978ddf22 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 @@ -30,6 +30,7 @@ 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.storage.StoreUtilities; import org.apache.sis.internal.util.UnmodifiableArrayList; @@ -75,7 +76,8 @@ final class CoverageSubset extends AbstractGridCoverageResource { protected Metadata createMetadata() throws DataStoreException { final MetadataBuilder builder = new MetadataBuilder(); builder.addDefaultMetadata(this, listeners); - builder.addLineage(Resources.formatInternational(Resources.Keys.OriginalData)); + builder.addLineage(Resources.formatInternational(Resources.Keys.UnfilteredData)); + builder.addProcessDescription(Resources.formatInternational(Resources.Keys.SubsetQuery_1, StoreUtilities.getLabel(source))); builder.addSources(source); return builder.build(); } 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 c1e5d01d94..4ffd33face 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 @@ -21,6 +21,7 @@ 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.StoreUtilities; import org.apache.sis.internal.storage.Resources; // Branch-dependent imports @@ -78,7 +79,8 @@ final class FeatureSubset extends AbstractFeatureSet { protected Metadata createMetadata() throws DataStoreException { final MetadataBuilder builder = new MetadataBuilder(); builder.addDefaultMetadata(this, listeners); - builder.addLineage(Resources.formatInternational(Resources.Keys.OriginalData)); + builder.addLineage(Resources.formatInternational(Resources.Keys.UnfilteredData)); + builder.addProcessDescription(Resources.formatInternational(Resources.Keys.SubsetQuery_1, StoreUtilities.getLabel(source))); builder.addSources(source); return builder.build(); }