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