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();
     }

Reply via email to