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 01376f0492e26af21ab306192b1f19dd751e9eb5
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Mon Sep 12 17:40:17 2022 +0200

    When an aggregation is simplified because it contains only one element, 
inherit the name of its parent.
    The parent may itself inherit the name of its parent, etc. This is needed 
because otherwise
    when showing resources in a tree, we tend to get names that are the same as 
siblings.
---
 .../storage/aggregate/AggregatedResource.java      | 42 +++++++++++++++++++++
 .../aggregate/ConcatenatedGridResource.java        | 33 +++++++++++++++--
 .../storage/aggregate/CoverageAggregator.java      |  8 ++--
 .../sis/internal/storage/aggregate/Group.java      | 33 ++++++++++++-----
 .../internal/storage/aggregate/GroupAggregate.java | 43 +++++++++++++++++++---
 .../sis/internal/storage/aggregate/GroupByCRS.java |  2 +-
 .../internal/storage/aggregate/GroupBySample.java  |  2 +-
 .../storage/aggregate/GroupByTransform.java        |  4 +-
 8 files changed, 139 insertions(+), 28 deletions(-)

diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/AggregatedResource.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/AggregatedResource.java
new file mode 100644
index 0000000000..315d96d246
--- /dev/null
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/AggregatedResource.java
@@ -0,0 +1,42 @@
+/*
+ * 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.aggregate;
+
+import org.apache.sis.storage.Resource;
+
+
+/**
+ * The result of an aggregation computed by {@link CoverageAggregator}.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.3
+ * @since   1.3
+ * @module
+ */
+interface AggregatedResource {
+    /**
+     * Sets the name of the resource.
+     *
+     * @param  name  new name of the resource.
+     */
+    void setName(String name);
+
+    /**
+     * Specifies the resource to declare in lineage metadata as the source of 
this resource.
+     */
+    void setSourceMetadata(Resource source);
+}
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/ConcatenatedGridResource.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/ConcatenatedGridResource.java
index 2cda0e6a5d..773faa3169 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/ConcatenatedGridResource.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/ConcatenatedGridResource.java
@@ -52,7 +52,12 @@ import org.apache.sis.util.ArraysExt;
  * @since   1.3
  * @module
  */
-final class ConcatenatedGridResource extends AbstractGridCoverageResource {
+final class ConcatenatedGridResource extends AbstractGridCoverageResource 
implements AggregatedResource {
+    /**
+     * Name of this resource.
+     */
+    private String name;
+
     /**
      * The grid geometry of this aggregated resource.
      *
@@ -104,35 +109,57 @@ final class ConcatenatedGridResource extends 
AbstractGridCoverageResource {
      * An optional resource to declare as the source of this aggregate in 
lineage metadata.
      * This is reset to {@code null} when no longer needed.
      */
-    Resource sourceMetadata;
+    private Resource sourceMetadata;
 
     /**
      * Creates a new aggregated resource.
      *
+     * @param  name       name of the grid coverage to create.
      * @param  listeners  listeners of the parent resource, or {@code null} if 
none.
      * @param  domain     value to be returned by {@link #getGridGeometry()}.
      * @param  ranges     value to be returned by {@link 
#getSampleDimensions()}.
      * @param  slices     the slices of this resource, in the same order than 
{@code coordinatesOfSlices}.
      */
-    ConcatenatedGridResource(final StoreListeners         listeners,
+    ConcatenatedGridResource(final String                 name,
+                             final StoreListeners         listeners,
                              final GridGeometry           domain,
                              final List<SampleDimension>  ranges,
                              final GridCoverageResource[] slices,
                              final GridSliceLocator       locator)
     {
         super(listeners, false);
+        this.name             = name;
         this.gridGeometry     = domain;
         this.sampleDimensions = ranges;
         this.slices           = slices;
         this.locator          = locator;
     }
 
+    /**
+     * Modifies the name of the resource.
+     * This information is used for metadata.
+     */
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * Specifies the resource to declare in lineage metadata as the source of 
this resource.
+     * This information is used for metadata.
+     */
+    @Override
+    public void setSourceMetadata(final Resource source) {
+        sourceMetadata = source;
+    }
+
     /**
      * Creates when first requested the metadata about this resource.
      */
     @Override
     protected Metadata createMetadata() throws DataStoreException {
         final MetadataBuilder builder = new MetadataBuilder();
+        builder.addTitle(name);
         builder.addDefaultMetadata(this, listeners);
         if (sourceMetadata != null) {
             builder.addSources(sourceMetadata);
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/CoverageAggregator.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/CoverageAggregator.java
index 43007263c4..b6e5cbfca9 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/CoverageAggregator.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/CoverageAggregator.java
@@ -82,7 +82,7 @@ public final class CoverageAggregator extends 
Group<GroupBySample> {
      * @return a name which can be used as aggregation name, or {@code null} 
if none.
      */
     @Override
-    final String getName(final Locale locale) {
+    final String createName(final Locale locale) {
         return (listeners != null) ? listeners.getSourceName() : null;
     }
 
@@ -213,10 +213,8 @@ public final class CoverageAggregator extends 
Group<GroupBySample> {
         final GroupAggregate aggregate = prepareAggregate(listeners);
         aggregate.fillWithChildAggregates(this, 
GroupBySample::createComponents);
         final Resource result = aggregate.simplify(this);
-        if (result instanceof GroupAggregate) {
-            ((GroupAggregate) result).sourceMetadata = sourceMetadata;
-        } else if (result instanceof ConcatenatedGridResource) {
-            ((ConcatenatedGridResource) result).sourceMetadata = 
sourceMetadata;
+        if (result instanceof AggregatedResource) {
+            ((AggregatedResource) result).setSourceMetadata(sourceMetadata);
         }
         return result;
     }
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/Group.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/Group.java
index e78ef1f4fa..7a51c4d337 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/Group.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/Group.java
@@ -36,6 +36,13 @@ import org.apache.sis.storage.event.StoreListeners;
  * @module
  */
 abstract class Group<E> {
+    /**
+     * The name of this group, or {@code null} if not yet computed.
+     *
+     * @see #getName(StoreListeners)
+     */
+    private String name;
+
     /**
      * All members of this group. This list is populated by calls to {@link 
GridSlice#addTo(List)}.
      * Accesses to this list should be synchronized during the phase when this 
list is populated,
@@ -52,13 +59,26 @@ abstract class Group<E> {
     }
 
     /**
-     * Returns a name for this group.
+     * Creates a name for this group.
      * This is used as the resource name if an aggregated resource needs to be 
created.
      *
      * @param  locale  the locale for the name to return, or {@code null} for 
the default.
      * @return a name which can be used as aggregation name.
      */
-    abstract String getName(Locale locale);
+    abstract String createName(Locale locale);
+
+    /**
+     * Returns the name of this group.
+     *
+     * @param  listeners  listeners from which to get the locale, or {@code 
null} for the default.
+     * @return a name which can be used as aggregation name.
+     */
+    final String getName(final StoreListeners listeners) {
+        if (name == null) {
+            name = createName(listeners == null ? null : 
listeners.getLocale());
+        }
+        return name;
+    }
 
     /**
      * Prepares an initially empty aggregate.
@@ -68,14 +88,7 @@ abstract class Group<E> {
      * @return an initially empty aggregate.
      */
     final GroupAggregate prepareAggregate(final StoreListeners listeners) {
-        final int count = members.size();
-        final String name;
-        if (count >= GroupAggregate.KEEP_ALIVE) {
-            name = getName(listeners == null ? null : listeners.getLocale());
-        } else {
-            name = null;        // Because it will not be needed.
-        }
-        return new GroupAggregate(listeners, name, count);
+        return new GroupAggregate(listeners, getName(listeners), 
members.size());
     }
 
     /**
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupAggregate.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupAggregate.java
index 7a5069f56b..f28902ecf8 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupAggregate.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupAggregate.java
@@ -31,6 +31,7 @@ import org.apache.sis.storage.GridCoverageResource;
 import org.apache.sis.storage.event.StoreListeners;
 import org.apache.sis.internal.storage.MetadataBuilder;
 import org.apache.sis.internal.util.UnmodifiableArrayList;
+import org.apache.sis.internal.util.Strings;
 import org.apache.sis.coverage.SampleDimension;
 import org.apache.sis.geometry.Envelopes;
 import org.apache.sis.geometry.ImmutableEnvelope;
@@ -50,17 +51,17 @@ import org.apache.sis.geometry.ImmutableEnvelope;
  * @since   1.3
  * @module
  */
-final class GroupAggregate extends AbstractResource implements Aggregate {
+final class GroupAggregate extends AbstractResource implements Aggregate, 
AggregatedResource {
     /**
      * Minimum number of components for keeping this aggregate after analysis.
      */
-    static final int KEEP_ALIVE = 2;
+    private static final int KEEP_ALIVE = 2;
 
     /**
      * Name of this aggregate, or {@code null} if none.
      * This is <strong>not</strong> a persistent identifier.
      */
-    private final String name;
+    private String name;
 
     /**
      * The components of this aggregate. Array elements are initially null, 
but should all become non-null
@@ -101,7 +102,7 @@ final class GroupAggregate extends AbstractResource 
implements Aggregate {
      * An optional resource to declare as the source of this aggregate in 
lineage metadata.
      * This is reset to {@code null} when no longer needed.
      */
-    Resource sourceMetadata;
+    private Resource sourceMetadata;
 
     /**
      * Creates a new aggregate with the specified number of components.
@@ -129,7 +130,7 @@ final class GroupAggregate extends AbstractResource 
implements Aggregate {
      *                     The first {@link BiConsumer} argument is a {@code 
children} member (the source)
      *                     and the second argument is the sub-aggregate to 
initialize (the target).
      */
-    final <E extends Group> void fillWithChildAggregates(final Group<E> 
children, final BiConsumer<E,GroupAggregate> childFiller) {
+    final <E extends Group<?>> void fillWithChildAggregates(final Group<E> 
children, final BiConsumer<E,GroupAggregate> childFiller) {
         assert components.length == children.members.size();
         for (int i=0; i < components.length; i++) {
             final E member = children.members.get(i);
@@ -170,7 +171,11 @@ final class GroupAggregate extends AbstractResource 
implements Aggregate {
             }
         }
         if (components.length == 1) {
-            return components[0];
+            final Resource c = components[0];
+            if (c instanceof AggregatedResource) {
+                ((AggregatedResource) c).setName(name);
+            }
+            return c;
         }
         return aggregator.existingAggregate(components).orElse(this);
     }
@@ -223,6 +228,24 @@ final class GroupAggregate extends AbstractResource 
implements Aggregate {
         return ImmutableEnvelope.castOrCopy(Envelopes.union(envelopes));
     }
 
+    /**
+     * Modifies the name of the resource.
+     * This information is used for metadata.
+     */
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * Specifies the resource to declare in lineage metadata as the source of 
this resource.
+     * This information is used for metadata.
+     */
+    @Override
+    public void setSourceMetadata(final Resource source) {
+        sourceMetadata = source;
+    }
+
     /**
      * Creates when first requested the metadata about this aggregate.
      * The metadata contains the title for this aggregation, the sample 
dimensions
@@ -248,4 +271,12 @@ final class GroupAggregate extends AbstractResource 
implements Aggregate {
         }
         return builder.build();
     }
+
+    /**
+     * Returns a string representation of this aggregate for debugging 
purposes.
+     */
+    @Override
+    public String toString() {
+        return Strings.toString(getClass(), "name", name, "size", 
components.length);
+    }
 }
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupByCRS.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupByCRS.java
index ad7c393642..1893360e8d 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupByCRS.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupByCRS.java
@@ -60,7 +60,7 @@ final class GroupByCRS<E> extends Group<E> {
      * Returns a name for this group.
      */
     @Override
-    final String getName(final Locale locale) {
+    final String createName(final Locale locale) {
         return IdentifiedObjects.getDisplayName(crs, locale);
     }
 
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupBySample.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupBySample.java
index 1d2d5713ae..f42124f0da 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupBySample.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupBySample.java
@@ -54,7 +54,7 @@ final class GroupBySample extends 
Group<GroupByCRS<GroupByTransform>> {
      * Returns a name for this group.
      */
     @Override
-    final String getName(final Locale locale) {
+    final String createName(final Locale locale) {
         final StringJoiner name = new StringJoiner(", ");
         for (final SampleDimension range : ranges) {
             name.add(range.getName().toInternationalString().toString(locale));
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupByTransform.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupByTransform.java
index 031db6ce89..83dd19ccf5 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupByTransform.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/aggregate/GroupByTransform.java
@@ -75,7 +75,7 @@ final class GroupByTransform extends Group<GridSlice> {
      * that they differ by their resolution.
      */
     @Override
-    final String getName(final Locale locale) {
+    final String createName(final Locale locale) {
         final Vocabulary    v = Vocabulary.getResources(locale);
         final StringBuffer  b = new 
StringBuffer(v.getLabel(Vocabulary.Keys.Resolution));
         final NumberFormat  f = NumberFormat.getIntegerInstance(v.getLocale());
@@ -148,6 +148,6 @@ final class GroupByTransform extends Group<GridSlice> {
         final GridCoverageResource[] slices  = new GridCoverageResource[n];
         final GridSliceLocator       locator = new GridSliceLocator(members, 
dimensions[0], slices);
         final GridGeometry           domain  = locator.union(geometry, 
members, GridSlice::getGridExtent);
-        return new ConcatenatedGridResource(parentListeners, domain, ranges, 
slices, locator);
+        return new ConcatenatedGridResource(getName(parentListeners), 
parentListeners, domain, ranges, slices, locator);
     }
 }

Reply via email to