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 c70e0343f9a2df91505aa2a85490d603b04eebd3 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Sat Dec 17 11:28:59 2022 +0100 Fix an ArrayIndexOutOfBoundsException when the slices given to CoverageAggregator has no dimension that the aggregator can use as index. It happens for example if the slices have only 2 dimensions. --- .../sis/storage/aggregate/GridSliceLocator.java | 4 +- .../sis/storage/aggregate/GroupAggregate.java | 20 ++++++++++ .../sis/storage/aggregate/GroupByTransform.java | 17 +++++--- .../storage/aggregate/CoverageAggregatorTest.java | 46 ++++++++++++++++++++++ .../apache/sis/test/suite/StorageTestSuite.java | 3 +- 5 files changed, 82 insertions(+), 8 deletions(-) diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/aggregate/GridSliceLocator.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/aggregate/GridSliceLocator.java index b0c121c62e..3d59d252ef 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/storage/aggregate/GridSliceLocator.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/aggregate/GridSliceLocator.java @@ -77,7 +77,9 @@ final class GridSliceLocator { /** * Creates a new locator for slices at given coordinates. * - * @param searchDimension the dimension on which the searches are done. + * @param slices descriptions of the grid resources to use as slices in a multi-dimensional cube. + * @param searchDimension the dimension on which the searches for grid slices are done. + * @param resources an array of initially null elements where to store the resources. */ GridSliceLocator(final List<GridSlice> slices, final int searchDimension, final GridCoverageResource[] resources) { this.searchDimension = searchDimension; diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/aggregate/GroupAggregate.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/aggregate/GroupAggregate.java index 3e1997878b..1f52eb6890 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/storage/aggregate/GroupAggregate.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/aggregate/GroupAggregate.java @@ -114,6 +114,26 @@ final class GroupAggregate extends AbstractResource implements Aggregate, Aggreg this.name = name; } + /** + * Creates a new aggregate with the specified components, which will receive no further processing. + * This is invoked when the caller has not been able to group the slices in a multi-dimensional cube. + * The result stay an aggregate of heterogynous resources. + * + * @param listeners listeners of the parent resource, or {@code null} if none. + * @param name name of this aggregate, or {@code null} if none. + * @param components the resources to uses as components of this aggregate. + * @param sampleDimensions sample dimensions common to all grid coverage resources. + */ + GroupAggregate(final StoreListeners listeners, final String name, final GridCoverageResource[] components, + final List<SampleDimension> sampleDimensions) + { + super(listeners, true); + this.name = name; + this.components = components; + this.componentsAreLeaves = true; + this.sampleDimensions = sampleDimensions; + } + /** * Creates a new resource with the same data than given resource but a different merge strategy. * diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/aggregate/GroupByTransform.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/aggregate/GroupByTransform.java index 855d4c8878..271264a365 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/storage/aggregate/GroupByTransform.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/aggregate/GroupByTransform.java @@ -24,6 +24,7 @@ import java.text.FieldPosition; import org.opengis.referencing.operation.Matrix; import org.opengis.referencing.operation.MathTransform; import org.apache.sis.referencing.operation.transform.MathTransforms; +import org.apache.sis.storage.Resource; import org.apache.sis.storage.GridCoverageResource; import org.apache.sis.storage.event.StoreListeners; import org.apache.sis.coverage.grid.GridGeometry; @@ -148,16 +149,20 @@ final class GroupByTransform extends Group<GridSlice> { * @param sampleDimensions the sample dimensions of the resource to build. * @return the concatenated resource. */ - final GridCoverageResource createResource(final StoreListeners parentListeners, final List<SampleDimension> ranges) { + final Resource createResource(final StoreListeners parentListeners, final List<SampleDimension> ranges) { final int n = members.size(); if (n == 1) { return members.get(0).resource; } + final var slices = new GridCoverageResource[n]; + final String name = getName(parentListeners); final int[] dimensions = findConcatenatedDimensions(); - 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(getName(parentListeners), parentListeners, - domain, ranges, slices, locator, strategy); + if (dimensions.length == 0) { + for (int i=0; i<n; i++) slices[i] = members.get(i).resource; + return new GroupAggregate(parentListeners, name, slices, ranges); + } + final GridSliceLocator locator = new GridSliceLocator(members, dimensions[0], slices); + final GridGeometry domain = locator.union(geometry, members, GridSlice::getGridExtent); + return new ConcatenatedGridResource(name, parentListeners, domain, ranges, slices, locator, strategy); } } diff --git a/storage/sis-storage/src/test/java/org/apache/sis/storage/aggregate/CoverageAggregatorTest.java b/storage/sis-storage/src/test/java/org/apache/sis/storage/aggregate/CoverageAggregatorTest.java new file mode 100644 index 0000000000..df7e80a91e --- /dev/null +++ b/storage/sis-storage/src/test/java/org/apache/sis/storage/aggregate/CoverageAggregatorTest.java @@ -0,0 +1,46 @@ +/* + * 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.storage.aggregate; + +import org.apache.sis.storage.Aggregate; +import org.apache.sis.storage.DataStoreException; +import org.apache.sis.test.TestCase; +import org.junit.Test; + +import static org.junit.Assert.*; + + +/** + * Tests {@link CoverageAggregator}. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.3 + * @since 1.3 + * @module + */ +public final strictfp class CoverageAggregatorTest extends TestCase { + /** + * Tests an empty aggregator. + * + * @throws DataStoreException if an error occurred. + */ + @Test + public void testEmpty() throws DataStoreException { + final var aggregator = new CoverageAggregator(null); + assertTrue(((Aggregate) aggregator.build()).components().isEmpty()); + } +} diff --git a/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java b/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java index ad3ab0fa51..a669c14342 100644 --- a/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java +++ b/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java @@ -26,7 +26,7 @@ import org.junit.BeforeClass; * * @author Martin Desruisseaux (Geomatys) * @author Alexis Manin (Geomatys) - * @version 1.2 + * @version 1.3 * @since 0.3 * @module */ @@ -67,6 +67,7 @@ import org.junit.BeforeClass; org.apache.sis.internal.storage.folder.StoreTest.class, org.apache.sis.storage.aggregate.JoinFeatureSetTest.class, org.apache.sis.storage.aggregate.ConcatenatedFeatureSetTest.class, + org.apache.sis.storage.aggregate.CoverageAggregatorTest.class, org.apache.sis.storage.DataStoresTest.class }) public final strictfp class StorageTestSuite extends TestSuite {