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 9cb97c64c3e89899bef6299568ad5f1b2a33ec5f
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Wed Feb 11 18:33:20 2026 +0100

    Add a `GridExtent.reshape(long[])` method and use that for simplifying some 
code.
    Minor opportunistic reformating.
---
 .../org/apache/sis/coverage/grid/GridExtent.java   | 61 ++++++++++++++++------
 .../apache/sis/coverage/grid/GridExtentTest.java   | 10 +++-
 .../sis/storage/geotiff/ImageFileDirectory.java    |  5 +-
 .../sis/storage/UnsupportedQueryException.java     |  1 +
 .../sis/storage/aggregate/GridSliceLocator.java    |  5 +-
 .../apache/sis/storage/base/TiledGridCoverage.java |  5 +-
 .../org/apache/sis/storage/CoverageQueryTest.java  |  8 ++-
 .../storage/MemoryGridCoverageResourceTest.java    |  6 ++-
 .../sis/storage/test/CoverageReadConsistency.java  |  2 +-
 .../main/org/apache/sis/util/ArgumentChecks.java   | 26 ++++++++-
 .../main/org/apache/sis/gui/map/MapCanvas.java     |  6 ++-
 11 files changed, 98 insertions(+), 37 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java
index 07d68fc690..e7c887de45 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java
@@ -92,7 +92,7 @@ import org.opengis.coverage.grid.GridCoordinates;
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Alexis Manin (Geomatys)
  * @author  Johann Sorel (Geomatys)
- * @version 1.5
+ * @version 1.7
  * @since   1.0
  */
 public class GridExtent implements GridEnvelope, LenientComparable, 
Serializable {
@@ -355,28 +355,33 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
      *
      * @see #getLow()
      * @see #getHigh()
-     * @see #insertDimension(int, DimensionNameType, long, long, boolean)
+     * @see #reshape(long[], long[], boolean)
      */
     public GridExtent(final DimensionNameType[] axisTypes, final long[] low, 
final long[] high, final boolean isHighIncluded) {
-        final int dimension = high.length;
-        if (low != null && low.length != dimension) {
-            throw new 
IllegalArgumentException(Errors.format(Errors.Keys.MismatchedDimension_2, 
low.length, dimension));
-        }
-        if (axisTypes != null && axisTypes.length != dimension) {
-            throw new 
IllegalArgumentException(Errors.format(Errors.Keys.MismatchedArrayLengths));
-        }
-        coordinates = allocate(dimension);
+        ArgumentChecks.ensureNonNull("high", high);
+        coordinates = pack(axisTypes != null ? axisTypes.length : high.length, 
low, high, isHighIncluded);
+        types = validateAxisTypes(axisTypes);
+        validateCoordinates();
+    }
+
+    /**
+     * Returns the given coordinates packed in a single array.
+     * This method verifies that the array lengths match the expected number 
of dimensions.
+     */
+    private static long[] pack(final int dimension, final long[] low, final 
long[] high, final boolean isHighIncluded) {
+        ArgumentChecks.ensureDimensionMatches("low",  dimension, low);
+        ArgumentChecks.ensureDimensionMatches("high", dimension, high);
+        final long[] coordinates = allocate(dimension);
         if (low != null) {
             System.arraycopy(low, 0, coordinates, 0, dimension);
         }
         System.arraycopy(high, 0, coordinates, dimension, dimension);
         if (!isHighIncluded) {
-            for (int i=dimension; i < coordinates.length; i++) {
+            for (int i = dimension; i < coordinates.length; i++) {
                 coordinates[i] = Math.decrementExact(coordinates[i]);
             }
         }
-        types = validateAxisTypes(axisTypes);
-        validateCoordinates();
+        return coordinates;
     }
 
     /**
@@ -644,8 +649,8 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
 
     /**
      * Creates a new grid extent with the same axes as the given extent, but 
different coordinates.
-     * This constructor does not invoke {@link #validateCoordinates()}; we 
presume that the caller's
-     * computation is correct.
+     * This constructor does not invoke {@link #validateCoordinates()}, 
instead it presumes that the
+     * caller's computation is correct.
      *
      * @param enclosing    the extent from which to copy axes, or {@code null} 
if none.
      * @param coordinates  the coordinates. This array is not cloned.
@@ -1644,6 +1649,32 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
         return Arrays.equals(c, coordinates) ? this : resize;
     }
 
+    /**
+     * Returns an extent with the same number of dimensions and the same axes 
than this extent,
+     * but different coordinate values.
+     *
+     * @param  low             the valid minimum grid coordinates (always 
inclusive), or {@code null} for all zeros.
+     * @param  high            the valid maximum grid coordinates, inclusive 
or exclusive depending on the next argument.
+     * @param  isHighIncluded  {@code true} if the {@code high} values are 
inclusive, or {@code false} if they are exclusive.
+     * @throws IllegalArgumentException if a coordinate value in the low part 
is
+     *         greater than the corresponding coordinate value in the high 
part.
+     * @return a grid extent with the same axes but the given coordinates.
+     *
+     * @see #GridExtent(DimensionNameType[], long[], long[], boolean)
+     *
+     * @since 1.7
+     */
+    public GridExtent reshape(final long[] low, final long[] high, final 
boolean isHighIncluded) {
+        ArgumentChecks.ensureNonNull("high", high);
+        final long[] copy = pack(getDimension(), low, high, isHighIncluded);
+        if (Arrays.equals(copy, coordinates)) {
+            return this;
+        }
+        final var extent = new GridExtent(this, copy);
+        extent.validateCoordinates();
+        return extent;
+    }
+
     /**
      * Creates a new grid extent subsampled by the given number of cells along 
each grid dimensions.
      * This method divides {@linkplain #getLow(int) low coordinates} and 
{@linkplain #getSize(int) grid sizes}
diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridExtentTest.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridExtentTest.java
index f8d5785caf..d80f1bab6a 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridExtentTest.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/grid/GridExtentTest.java
@@ -71,8 +71,14 @@ public final class GridExtentTest extends TestCase {
      */
     private static GridExtent create3D() {
         return new GridExtent(
-                new DimensionNameType[] {DimensionNameType.COLUMN, 
DimensionNameType.ROW, DimensionNameType.TIME},
-                new long[] {100, 200, 40}, new long[] {500, 800, 50}, false);
+                new DimensionNameType[] {
+                    DimensionNameType.COLUMN,
+                    DimensionNameType.ROW,
+                    DimensionNameType.TIME
+                },
+                new long[] {100, 200, 40},
+                new long[] {500, 800, 50},
+                false);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
index f7005e7c37..25570a7b9c 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
@@ -35,7 +35,6 @@ import static javax.imageio.plugins.tiff.GeoTIFFTagSet.*;
 import static javax.imageio.plugins.tiff.BaselineTIFFTagSet.*;
 import org.opengis.metadata.Metadata;
 import org.opengis.metadata.citation.DateType;
-import org.opengis.metadata.spatial.DimensionNameType;
 import org.opengis.util.GenericName;
 import org.opengis.util.NameSpace;
 import org.opengis.util.FactoryException;
@@ -1486,11 +1485,9 @@ final class ImageFileDirectory extends DataCube {
         final GridGeometry geometry = fullResolution.getGridGeometry();
         final GridExtent fullExtent = geometry.getExtent();
         final int dimension = fullExtent.getDimension();
-        final var axisTypes = new DimensionNameType[dimension];
         final var scales    = new double[dimension];
         final var high      = new long[dimension];
         for (int i=0; i<dimension; i++) {
-            axisTypes[i] = fullExtent.getAxisType(i).orElse(null);
             final long size;
             switch (i) {
                 case 0:  size = imageWidth;  break;
@@ -1503,7 +1500,7 @@ final class ImageFileDirectory extends DataCube {
         if (referencing == null) {
             gridGeometry = new GridGeometry(
                     geometry,
-                    new GridExtent(axisTypes, null, high, true),
+                    fullExtent.reshape(null, high, true),
                     MathTransforms.scale(scales));
         }
         if (samplesPerPixel == fullResolution.samplesPerPixel) {
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/UnsupportedQueryException.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/UnsupportedQueryException.java
index b0a5d879ac..1b61b1b438 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/UnsupportedQueryException.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/UnsupportedQueryException.java
@@ -27,6 +27,7 @@ package org.apache.sis.storage;
  *   <li>The query is requesting a property that does not exist in the {@link 
Resource}.</li>
  *   <li>The values in the {@link DataStore} are unconvertible to some 
characteristics
  *       (e.g., type or name) requested by the query.</li>
+ *   <li>The query is too large (e.g., overflows the capability of some 
integer type).</li>
  * </ul>
  *
  * This exception may be thrown when {@link FeatureSet#subset(Query)} is 
executed,
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/GridSliceLocator.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/GridSliceLocator.java
index 5af99db062..6333116a62 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/GridSliceLocator.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/GridSliceLocator.java
@@ -18,7 +18,6 @@ package org.apache.sis.storage.aggregate;
 
 import java.util.Arrays;
 import org.opengis.util.InternationalString;
-import org.opengis.metadata.spatial.DimensionNameType;
 import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.util.ArraysExt;
@@ -96,11 +95,9 @@ final class GridSliceLocator {
         this.sliceHighs      = new long[selected.length];
         GridExtent aoi = domain.getExtent();
         final int dimension = aoi.getDimension();
-        final var axes = new DimensionNameType[dimension];
         final var low  = new long[dimension];
         final var high = new long[dimension];
         for (int i=0; i<dimension; i++) {
-            axes[i] = aoi.getAxisType(i).orElse(null);
             low [i] = Long.MAX_VALUE;
             high[i] = Long.MIN_VALUE;
         }
@@ -114,7 +111,7 @@ final class GridSliceLocator {
                 high[j] = Math.max(high[j], extent.getHigh(j));
             }
         }
-        if (!aoi.equals(aoi = new GridExtent(axes, low, high, true))) {
+        if (!aoi.equals(aoi = aoi.reshape(low, high, true))) {
             var crs = domain.isDefined(GridGeometry.CRS) ? 
domain.getCoordinateReferenceSystem() : null;
             domain = new GridGeometry(aoi, GridSlice.CELL_ANCHOR, 
domain.getGridToCRS(GridSlice.CELL_ANCHOR), crs);
         }
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridCoverage.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridCoverage.java
index 332778096c..b921826c94 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridCoverage.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridCoverage.java
@@ -36,7 +36,6 @@ import static java.lang.Math.decrementExact;
 import static java.lang.Math.toIntExact;
 import static java.lang.Math.floorDiv;
 import org.opengis.util.GenericName;
-import org.opengis.metadata.spatial.DimensionNameType;
 import org.apache.sis.coverage.grid.GridCoverage;
 import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.grid.DisjointExtentException;
@@ -1076,15 +1075,13 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
          */
         public GridExtent getFullRegionInResourceCoordinates() {
             final int dimension = tileLower.length;
-            final var    axes  = new DimensionNameType[dimension];
             final long[] lower = new long[dimension];
             final long[] upper = new long[dimension];
             for (int i=0; i<dimension; i++) {
-                axes [i] = readExtent.getAxisType(i).orElse(null);
                 lower[i] = Math.max(coverageTileToResourceCell(tileLower[i], 
i),   readExtent.getLow(i));
                 upper[i] = Math.min(coverageTileToResourceCell(tileUpper[i], 
i)-1, readExtent.getHigh(i));
             }
-            return new GridExtent(axes, lower, upper, true);
+            return readExtent.reshape(lower, upper, true);
         }
 
         /**
diff --git 
a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageQueryTest.java
 
b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageQueryTest.java
index 3202f5e829..11ea0815e6 100644
--- 
a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageQueryTest.java
+++ 
b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageQueryTest.java
@@ -37,6 +37,7 @@ import org.apache.sis.referencing.crs.HardCodedCRS;
  *
  * @author  Johann Sorel (Geomatys)
  */
+@SuppressWarnings("exports")
 public final class CoverageQueryTest extends TestCase {
     /**
      * The coordinate reference system used by the tests.
@@ -82,8 +83,11 @@ public final class CoverageQueryTest extends TestCase {
      * Creates an arbitrary grid geometry included inside the {@linkplain 
#resource} extent.
      */
     private GridGeometry createSubGrid(final int expansion) {
-        final GridExtent extent = new GridExtent(
-                new DimensionNameType[] {DimensionNameType.COLUMN, 
DimensionNameType.ROW},
+        final var extent = new GridExtent(
+                new DimensionNameType[] {
+                    DimensionNameType.COLUMN,
+                    DimensionNameType.ROW
+                },
                 new long[] { 7 - expansion, 19 - expansion},
                 new long[] {21 + expansion, 27 + expansion}, true);
 
diff --git 
a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/MemoryGridCoverageResourceTest.java
 
b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/MemoryGridCoverageResourceTest.java
index e900922d2f..e80ff9878d 100644
--- 
a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/MemoryGridCoverageResourceTest.java
+++ 
b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/MemoryGridCoverageResourceTest.java
@@ -75,9 +75,11 @@ public final class MemoryGridCoverageResourceTest extends 
TestCase {
      * Creates an arbitrary grid geometry included inside the {@linkplain 
#resource} extent.
      */
     private GridGeometry createSubGrid() {
-        final var extent = new GridExtent(null,
+        final var extent = new GridExtent(
+                null,
                 new long[] {7, 4},
-                new long[] {WIDTH - 9, HEIGHT - 11}, true);
+                new long[] {WIDTH - 9, HEIGHT - 11},
+                true);
 
         return new GridGeometry(extent, PixelInCell.CELL_CENTER, gridToCRS, 
crs);
     }
diff --git 
a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/test/CoverageReadConsistency.java
 
b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/test/CoverageReadConsistency.java
index f44e47ccdf..ae7a4460bd 100644
--- 
a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/test/CoverageReadConsistency.java
+++ 
b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/test/CoverageReadConsistency.java
@@ -319,7 +319,7 @@ public abstract class CoverageReadConsistency<S extends 
DataStore> extends TestC
                 subsampling[d] += random.nextInt(StrictMath.max(rs / 16, 1));
             }
         }
-        return gg.derive().subgrid(new GridExtent(null, low, high, true), 
subsampling).build();
+        return gg.derive().subgrid(fullExtent.reshape(low, high, true), 
subsampling).build();
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArgumentChecks.java 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArgumentChecks.java
index d842f5a165..ca28d60e38 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArgumentChecks.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/ArgumentChecks.java
@@ -83,7 +83,7 @@ import org.opengis.coverage.grid.GridEnvelope;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Alexis Manin (Geomatys)
- * @version 1.6
+ * @version 1.7
  * @since   0.3
  */
 public final class ArgumentChecks {
@@ -779,6 +779,30 @@ public final class ArgumentChecks {
         }
     }
 
+    /**
+     * Ensures that the given array of indices, if non-null, has the expected 
number of dimensions
+     * (taken as its length). This method does nothing if the given array is 
null.
+     *
+     * @param  name      the name of the argument to be checked. Used only if 
an exception is thrown.
+     * @param  expected  the expected number of dimensions.
+     * @param  indices   the array of indices to check for its number of 
dimensions, or {@code null}.
+     * @throws MismatchedDimensionException if the given array of indices is 
non-null and does not have
+     *         the expected number of dimensions (taken as its length).
+     *
+     * @since 1.7
+     */
+    public static void ensureDimensionMatches(final String name, final int 
expected, final long[] indices)
+            throws MismatchedDimensionException
+    {
+        if (indices != null) {
+            final int dimension = indices.length;
+            if (dimension != expected) {
+                throw new MismatchedDimensionException(Errors.format(
+                        Errors.Keys.MismatchedDimension_3, name, expected, 
dimension));
+            }
+        }
+    }
+
     /**
      * Ensures that the given vector, if non-null, has the expected number of 
dimensions
      * (taken as its length). This method does nothing if the given vector is 
null.
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java
index 10c3de3a84..4f3c69678b 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java
@@ -1195,9 +1195,11 @@ public abstract class MapCanvas extends PlanarCanvas {
                     return;
                 }
                 invalidObjectiveToDisplay = false;
-                final var extent = new GridExtent(null,
+                final var extent = new GridExtent(
+                        null,
                         new long[] {Math.round(target.getMinX()), 
Math.round(target.getMinY())},
-                        new long[] {Math.round(target.getMaxX()), 
Math.round(target.getMaxY())}, false);
+                        new long[] {Math.round(target.getMaxX()), 
Math.round(target.getMaxY())},
+                        false);
                 /*
                  * The main purpose of this block is to find the initial value 
of the `objectiveToDisplay` transform
                  * (named `crsToDisplay` here). If that value was explicitly 
specified by a call to `initialize(…)`,

Reply via email to