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 a4f26d4229b3bc599f26bbf8c8f3805a01608de7
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Tue Aug 2 14:55:35 2022 +0200

    Make the netCDF reader more robust to the case where a coordinate system 
axis has zero dimension.
    Such axes are omitted, but we need to adjust the number of dimensions 
accordingly.
---
 .../java/org/apache/sis/internal/netcdf/Grid.java  | 31 +++++++++-------------
 .../apache/sis/internal/netcdf/impl/GridInfo.java  | 19 +++++++------
 .../sis/internal/netcdf/impl/package-info.java     |  2 +-
 .../sis/internal/netcdf/ucar/GridWrapper.java      | 29 ++++++++++----------
 .../apache/sis/storage/netcdf/MetadataReader.java  | 21 +++++++--------
 .../org/apache/sis/internal/netcdf/GridTest.java   |  6 ++---
 .../sis/internal/netcdf/impl/GridInfoTest.java     |  4 +--
 7 files changed, 52 insertions(+), 60 deletions(-)

diff --git 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java
index 71af070182..0438456f1a 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Grid.java
@@ -48,7 +48,7 @@ import org.apache.sis.util.ArraysExt;
  * if a variable dimensions should considered as bands instead of 
spatiotemporal dimensions.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.3
  *
  * @see Decoder#getGridCandidates()
  *
@@ -144,20 +144,17 @@ public abstract class Grid extends NamedElement {
      * This is the number of dimensions of the <em>grid</em>.
      * It should be equal to the size of {@link #getDimensions()} list.
      *
+     * <h4>Note on target dimensions</h4>
+     * A {@code getTargetDimensions()} method would return the number of 
dimensions of the
+     * <em>coordinate reference system</em>, which is the target of the 
<cite>"grid to CRS"</cite> conversion.
+     * However we do not provide that method because, while it should be equal 
to {@code getAxes(decoder).length},
+     * it sometime differs because {@link #getAxes(Decoder)} may exclude axis 
with zero dimensions.
+     * The latter method should be used as the authoritative one.
+     *
      * @return number of grid dimensions.
      */
     public abstract int getSourceDimensions();
 
-    /**
-     * Returns the number of dimensions of target coordinates in the 
<cite>"grid to CRS"</cite> conversion.
-     * This is the number of dimensions of the <em>coordinate reference 
system</em>.
-     * It should be equal to the length of the array returned by {@link 
#getAxes(Decoder)},
-     * but caller should be robust to inconsistencies.
-     *
-     * @return number of CRS dimensions.
-     */
-    public abstract int getTargetDimensions();
-
     /**
      * Returns the dimensions of this grid, in netCDF (reverse of "natural") 
order. Each element in the list
      * contains the number of cells in the dimension, together with 
implementation-specific information.
@@ -182,10 +179,8 @@ public abstract class Grid extends NamedElement {
     protected abstract List<Dimension> getDimensions();
 
     /**
-     * Returns the axes of the coordinate reference system. The size of this 
array is expected equals to the
-     * value returned by {@link #getTargetDimensions()}, but the caller should 
be robust to inconsistencies.
-     * The axis order is CRS order (reverse of netCDF order) for consistency 
with the common practice in the
-     * {@code "coordinates"} attribute.
+     * Returns the axes of the coordinate reference system. The axis order is 
CRS order (reverse of netCDF order)
+     * for consistency with the common practice in the {@code "coordinates"} 
attribute.
      *
      * <p>This method returns a direct reference to the cached array; do not 
modify.</p>
      *
@@ -397,9 +392,9 @@ public abstract class Grid extends NamedElement {
              * (the source) +1, and the number of rows is the number of 
dimensions in the CRS (the target) +1.
              * The order of dimensions in the transform is the reverse of the 
netCDF dimension order.
              */
-            int lastSrcDim = getSourceDimensions();                         // 
Will be decremented later, then kept final.
-            int lastTgtDim = getTargetDimensions();
-            final int[] deferred = new int[axes.length];                    // 
Indices of axes that have been deferred.
+            int lastSrcDim = getSourceDimensions();         // Will be 
decremented later, then kept final.
+            int lastTgtDim = axes.length;                   // Should be 
`getTargetDimensions()` but some axes may have been excluded.
+            final int[] deferred = new int[axes.length];    // Indices of axes 
that have been deferred.
             final List<MathTransform> nonLinears = new 
ArrayList<>(axes.length);
             final Matrix affine = Matrices.createZero(lastTgtDim + 1, 
lastSrcDim + 1);
             affine.setElement(lastTgtDim--, lastSrcDim--, 1);
diff --git 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridInfo.java
 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridInfo.java
index 27c97fd734..f41c864edf 100644
--- 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridInfo.java
+++ 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridInfo.java
@@ -42,7 +42,7 @@ import ucar.nc2.constants.CF;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Johann Sorel (Geomatys)
- * @version 1.0
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -120,16 +120,15 @@ final class GridInfo extends Grid {
         return domain.length;
     }
 
-    /**
-     * Returns the number of dimensions of target coordinates in the 
<cite>"grid to CRS"</cite> conversion.
-     * This is the number of dimensions of the <em>coordinate reference 
system</em>.
-     * It should be equal to the size of the array returned by {@link 
#getAxes(Decoder)},
-     * but caller should be robust to inconsistencies.
+    /*
+     * A `getTargetDimensions()` method would be like below, but is
+     * excluded because `getAxes(…).length` is the authoritative value:
+     *
+     *     @Override
+     *     public int getTargetDimensions() {
+     *         return range.length;
+     *     }
      */
-    @Override
-    public int getTargetDimensions() {
-        return range.length;
-    }
 
     /**
      * Returns the dimensions of this grid, in netCDF (reverse of "natural") 
order.
diff --git 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/package-info.java
 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/package-info.java
index 2319110d21..c44733af16 100644
--- 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/package-info.java
+++ 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/package-info.java
@@ -30,7 +30,7 @@
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.3
  * @since   0.3
  * @module
  */
diff --git 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridWrapper.java
 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridWrapper.java
index 2d0cde99b6..2eb9b2a8fc 100644
--- 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridWrapper.java
+++ 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridWrapper.java
@@ -45,7 +45,7 @@ import org.apache.sis.util.ArraysExt;
  * Many netCDF variables may be associated to the same {@code GridWrapper} 
instance.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -193,16 +193,15 @@ final class GridWrapper extends Grid {
         return netcdfCS.getRankDomain();
     }
 
-    /**
-     * Returns the number of dimensions of target coordinates in the 
<cite>"grid to CRS"</cite> conversion.
-     * This is the number of dimensions of the <em>coordinate reference 
system</em>.
-     * It should be equal to the length of the array returned by {@link 
#getAxes(Decoder)},
-     * but caller should be robust to inconsistencies.
+    /*
+     * A `getTargetDimensions()` method would be like below, but is
+     * excluded because `getAxes(…).length` is the authoritative value:
+     *
+     *     @Override
+     *     public int getTargetDimensions() {
+     *         return netcdfCS.getRankRange();
+     *     }
      */
-    @Override
-    public int getTargetDimensions() {
-        return netcdfCS.getRankRange();
-    }
 
     /**
      * Returns the dimensions of this grid, in netCDF (reverse of "natural") 
order.
@@ -257,9 +256,9 @@ next:       for (final String name : axisNames) {
          * In this method, `sourceDim` and `targetDim` are relative to "grid 
to CRS" conversion.
          * So `sourceDim` is the grid (domain) dimension and `targetDim` is 
the CRS (range) dimension.
          */
+        int axisCount = 0;
         int targetDim = range.size();
         final Axis[] axes = new Axis[targetDim];
-        final int lastDim = targetDim - 1;
         while (--targetDim >= 0) {
             final CoordinateAxis axis = range.get(targetDim);
             final Variable wrapper = ((DecoderWrapper) 
decoder).getWrapperFor(axis);
@@ -307,9 +306,11 @@ next:       for (final String name : axisNames) {
                  * package, we can proceed as if the dimension does not exist 
(`i` not incremented).
                  */
             }
-            axes[lastDim - targetDim] = new Axis(abbreviation, 
axis.getPositive(),
-                    ArraysExt.resize(indices, i), ArraysExt.resize(sizes, i), 
wrapper);
+            if (i != 0) {   // Variables with 0 dimensions sometime happen.
+                axes[axisCount++] = new Axis(abbreviation, axis.getPositive(),
+                        ArraysExt.resize(indices, i), ArraysExt.resize(sizes, 
i), wrapper);
+            }
         }
-        return axes;
+        return ArraysExt.resize(axes, axisCount);
     }
 }
diff --git 
a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
 
b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
index 15c099b14b..d4996187bc 100644
--- 
a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
+++ 
b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
@@ -113,7 +113,7 @@ import static 
org.apache.sis.internal.util.CollectionsExt.first;
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Thi Phuong Hao Nguyen (VNSC)
  * @author  Alexis Manin (Geomatys)
- * @version 1.2
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -684,17 +684,13 @@ split:  while ((start = 
CharSequences.skipLeadingWhitespaces(value, start, lengt
     /**
      * Adds information about axes and cell geometry.
      * This is the {@code <mdb:spatialRepresentationInfo>} element in XML.
+     * We work on grid axes instead of Coordinate Reference System axes because
+     * {@code 
metadata/spatialRepresentationInfo/axisDimensionProperties/dimensionSize} seems 
to imply that.
      *
      * @param  cs  the grid geometry (related to the netCDF coordinate system).
      * @throws ArithmeticException if the size of an axis exceeds {@link 
Integer#MAX_VALUE}, or other overflow occurs.
      */
-    private void addSpatialRepresentationInfo(final Grid cs) throws 
IOException, DataStoreException {
-        /*
-         * We work on grid axes instead of Coordinate Reference System axes 
because
-         * 
`metadata/spatialRepresentationInfo/axisDimensionProperties/dimensionSize`
-         * seems to imply that.
-         */
-        final Axis[] axes = cs.getAxes(decoder);
+    private void addSpatialRepresentationInfo(final Axis[] axes) throws 
IOException, DataStoreException {
         for (int i=0; i<axes.length; i++) {
             final Axis axis = axes[i];
             /*
@@ -1059,10 +1055,11 @@ split:  while ((start = 
CharSequences.skipLeadingWhitespaces(value, start, lengt
          * is built from the netCDF CoordinateSystem objects.
          */
         for (final Grid cs : decoder.getGridCandidates()) {
-            if (cs.getSourceDimensions() >= Grid.MIN_DIMENSION &&
-                cs.getTargetDimensions() >= Grid.MIN_DIMENSION)
-            {
-                addSpatialRepresentationInfo(cs);
+            if (cs.getSourceDimensions() >= Grid.MIN_DIMENSION) {
+                final Axis[] axes = cs.getAxes(decoder);
+                if (axes.length >= Grid.MIN_DIMENSION) {
+                    addSpatialRepresentationInfo(axes);
+                }
             }
         }
         setISOStandards(hasGridCoverages);
diff --git 
a/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/GridTest.java 
b/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/GridTest.java
index f9f487d1e1..7f14447fb2 100644
--- 
a/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/GridTest.java
+++ 
b/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/GridTest.java
@@ -63,7 +63,7 @@ public strictfp class GridTest extends TestCase {
     }
 
     /**
-     * Tests {@link Grid#getSourceDimensions()} and {@link 
Grid#getTargetDimensions()}.
+     * Tests {@link Grid#getSourceDimensions()} and {@code 
Grid.getTargetDimensions()}.
      *
      * @throws IOException if an I/O error occurred while opening the file.
      * @throws DataStoreException if a logical error occurred.
@@ -72,12 +72,12 @@ public strictfp class GridTest extends TestCase {
     public void testDimensions() throws IOException, DataStoreException {
         Grid geometry = 
getSingleton(filter(selectDataset(TestData.NETCDF_2D_GEOGRAPHIC).getGridCandidates()));
         assertEquals("getSourceDimensions()", 2, 
geometry.getSourceDimensions());
-        assertEquals("getTargetDimensions()", 2, 
geometry.getTargetDimensions());
+        assertEquals("getTargetDimensions()", 2, 
geometry.getAxes(decoder()).length);
 
         final int n = includeRuntimeDimension ? 5 : 4;
         geometry = 
getSingleton(filter(selectDataset(TestData.NETCDF_4D_PROJECTED).getGridCandidates()));
         assertEquals("getSourceDimensions()", 4, 
geometry.getSourceDimensions());
-        assertEquals("getTargetDimensions()", n, 
geometry.getTargetDimensions());
+        assertEquals("getTargetDimensions()", n, 
geometry.getAxes(decoder()).length);
     }
 
     /**
diff --git 
a/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/GridInfoTest.java
 
b/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/GridInfoTest.java
index 3ed876279a..e084c7b054 100644
--- 
a/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/GridInfoTest.java
+++ 
b/storage/sis-netcdf/src/test/java/org/apache/sis/internal/netcdf/impl/GridInfoTest.java
@@ -34,7 +34,7 @@ import org.opengis.test.dataset.TestData;
  * passed.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -70,7 +70,7 @@ public final strictfp class GridInfoTest extends GridTest {
         final Grid[] copy = new Grid[geometries.length];
         int count = 0;
         for (final Grid geometry : geometries) {
-            if (geometry.getSourceDimensions() != 1 || 
geometry.getTargetDimensions() != 1) {
+            if (geometry.getSourceDimensions() != 1) {
                 copy[count++] = geometry;
             }
         }

Reply via email to