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


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new d5d6c59c48 Adjust the handling of `Locale` in `TiledGridCoverage`. Add 
a check of whether a `ComputedImage` tile is in error.
d5d6c59c48 is described below

commit d5d6c59c48d9f94806c8f86f308eac422bb23222
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Tue Feb 24 11:46:44 2026 +0100

    Adjust the handling of `Locale` in `TiledGridCoverage`.
    Add a check of whether a `ComputedImage` tile is in error.
---
 .../main/org/apache/sis/image/ComputedImage.java   | 20 ++++++++++++++---
 .../main/org/apache/sis/image/ComputedTiles.java   | 26 +++++++++++++++++++++-
 .../org/apache/sis/storage/geotiff/DataSubset.java | 12 +---------
 .../org/apache/sis/storage/geotiff/ReaderTest.java |  1 +
 .../apache/sis/storage/tiling/ImageTileMatrix.java | 20 +++++++++++++----
 .../apache/sis/storage/tiling/IterationDomain.java |  5 +++--
 .../main/org/apache/sis/storage/tiling/Tile.java   |  4 ++--
 .../org/apache/sis/storage/tiling/TileStatus.java  |  2 +-
 .../sis/storage/tiling/TiledGridCoverage.java      | 20 +++++++----------
 .../storage/tiling/TiledGridCoverageResource.java  |  9 ++++++++
 .../main/org/apache/sis/util/collection/Cache.java |  4 ++--
 11 files changed, 85 insertions(+), 38 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedImage.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedImage.java
index a1dd4db181..83d65a92a5 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedImage.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedImage.java
@@ -117,7 +117,7 @@ import org.apache.sis.image.internal.shared.ImageUtilities;
  * if the change to dirty state happened after the call to {@link 
#getTile(int, int) getTile(…)}.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.4
+ * @version 1.7
  * @since   1.1
  */
 public abstract class ComputedImage extends PlanarImage implements Disposable {
@@ -485,8 +485,8 @@ public abstract class ComputedImage extends PlanarImage 
implements Disposable {
      */
     @Override
     public final Raster getTile(final int tileX, final int tileY) {
-        final TileCache.Key key = new TileCache.Key(reference, tileX, tileY);
-        final Cache<TileCache.Key,Raster> cache = TileCache.GLOBAL;
+        final var key = new TileCache.Key(reference, tileX, tileY);
+        final Cache<TileCache.Key, Raster> cache = TileCache.GLOBAL;
         Raster tile = cache.peek(key);
         if (tile == null || reference.isTileDirty(key)) {
             /*
@@ -769,6 +769,20 @@ public abstract class ComputedImage extends PlanarImage 
implements Disposable {
                           Math.addExact(tiles.y, tiles.height - 1), true);
     }
 
+    /**
+     * Returns whether at least one tile in the given range of indices has the 
error status.
+     *
+     * @param  tiles  indices of tiles for which to check the error status.
+     * @return {@code true} if at least one tile is flagged as in error.
+     *
+     * @since 1.7
+     */
+    public boolean hasErrorFlag(final Rectangle tiles) {
+        return reference.hasErrorFlag(tiles.x, tiles.y,
+                          Math.addExact(tiles.x, tiles.width  - 1),
+                          Math.addExact(tiles.y, tiles.height - 1));
+    }
+
     /**
      * Invoked when a tile of a source image has been updated. This method 
should {@linkplain #markDirtyTiles
      * mark as dirty} all tiles of this {@code ComputedImage} that depend on 
the updated tile.
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedTiles.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedTiles.java
index b6aee07c9f..d92e01527a 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedTiles.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedTiles.java
@@ -21,6 +21,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.lang.ref.WeakReference;
 import java.awt.Point;
+import java.awt.Rectangle;
 import java.awt.image.TileObserver;
 import java.awt.image.ImagingOpException;
 import java.awt.image.WritableRenderedImage;
@@ -82,6 +83,7 @@ final class ComputedTiles extends 
WeakReference<ComputedImage> implements Dispos
      * @param  image  the image for which to release tiles on 
garbage-collection.
      * @param  ws     sources to observe for changes, or {@code null} if none.
      */
+    @SuppressWarnings("this-escape")
     ComputedTiles(final ComputedImage image, final WritableRenderedImage[] ws) 
{
         super(image, ReferenceQueueConsumer.QUEUE);
         cachedTiles = new HashMap<>();
@@ -273,7 +275,7 @@ final class ComputedTiles extends 
WeakReference<ComputedImage> implements Dispos
         synchronized (cachedTiles) {
             for (int tileY = minTileY; tileY <= maxTileY; tileY++) {
                 for (int tileX = minTileX; tileX <= maxTileX; tileX++) {
-                    final TileCache.Key key = new TileCache.Key(this, tileX, 
tileY);
+                    final var key = new TileCache.Key(this, tileX, tileY);
                     updated |= cachedTiles.replace(key, search, dirty);
                 }
             }
@@ -281,6 +283,28 @@ final class ComputedTiles extends 
WeakReference<ComputedImage> implements Dispos
         return updated;
     }
 
+    /**
+     * Returns whether at least one tile in the given range of indices is 
flagged as in error.
+     *
+     * @return {@code true} if at least one tile is flagged as in error.
+     *
+     * @see ComputedImage#hasErrorFlag(Rectangle)
+     */
+    public boolean hasErrorFlag(final int minTileX, final int minTileY, final 
int maxTileX, final int maxTileY) {
+        synchronized (cachedTiles) {
+            for (int tileY = minTileY; tileY <= maxTileY; tileY++) {
+                for (int tileX = minTileX; tileX <= maxTileX; tileX++) {
+                    final var key = new TileCache.Key(this, tileX, tileY);
+                    final Integer status = cachedTiles.get(key);
+                    if (status != null && status == ERROR) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
     /**
      * Invoked when a source is changing the content of one of its tile.
      * This method is interested only in events fired after the change is done.
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
index d3ce404665..3570da4926 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
@@ -17,7 +17,6 @@
 package org.apache.sis.storage.geotiff;
 
 import java.util.Arrays;
-import java.util.Locale;
 import java.nio.Buffer;
 import java.nio.file.Path;
 import java.io.Closeable;
@@ -32,7 +31,6 @@ import static java.lang.Math.subtractExact;
 import static java.lang.Math.multiplyExact;
 import static java.lang.Math.toIntExact;
 import org.opengis.util.GenericName;
-import org.apache.sis.util.Localized;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.iso.Names;
 import org.apache.sis.util.internal.shared.Numerics;
@@ -72,7 +70,7 @@ import static org.apache.sis.pending.jdk.JDK18.ceilDiv;
  *
  * @author  Martin Desruisseaux (Geomatys)
  */
-class DataSubset extends TiledGridCoverage implements Localized {
+class DataSubset extends TiledGridCoverage {
     /**
      * The resource which contain this {@code DataSubset}.
      * Used for fetching information like the input channel and where to 
report warnings.
@@ -188,14 +186,6 @@ class DataSubset extends TiledGridCoverage implements 
Localized {
         }
     }
 
-    /**
-     * Returns the locale for warning or error messages, or {@code null} if 
unspecified.
-     */
-    @Override
-    public final Locale getLocale() {
-        return source.listeners().getLocale();
-    }
-
     /**
      * Returns the path to the content of the specified data, or {@code null} 
if none or unknown.
      *
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/ReaderTest.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/ReaderTest.java
index fd9afada3a..af324c7db5 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/ReaderTest.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/ReaderTest.java
@@ -115,6 +115,7 @@ public class ReaderTest extends TestCase {
             assertTrue(tile.getContentPath().isEmpty());
 
             final Raster raster = raster(tile);
+            assertEquals(TileStatus.EXISTS, tile.getStatus());
             assertArrayEquals(tile.getIndices(), 
assertSingleton(matrix.getTiles(null, false).toList()).getIndices());
             assertSame(raster, raster(assertSingleton(matrix.getTiles(null, 
false).toList())));
         }
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/ImageTileMatrix.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/ImageTileMatrix.java
index 7cf69fe985..82e4bec8da 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/ImageTileMatrix.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/ImageTileMatrix.java
@@ -20,6 +20,7 @@ import java.util.Arrays;
 import java.util.Optional;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
+import java.awt.Rectangle;
 import java.awt.image.RenderedImage;
 import java.nio.file.Path;
 import org.opengis.util.GenericName;
@@ -39,6 +40,7 @@ import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.coverage.grid.GridCoverage2D;
 import org.apache.sis.coverage.grid.GridCoverageProcessor;
 import org.apache.sis.coverage.grid.IncompleteGridGeometryException;
+import org.apache.sis.image.ComputedImage;
 import org.apache.sis.image.internal.shared.ReshapedImage;
 import org.apache.sis.pending.jdk.JDK18;
 import org.apache.sis.util.ArgumentChecks;
@@ -272,17 +274,25 @@ final class ImageTileMatrix implements TileMatrix {
 
     /**
      * Returns the status of the tile at the given index.
+     * If the image is an instance of {@link ComputedImage},
+     * then this method checks whether the tile is in error.
+     *
+     * This method does not check whether the tile indexes are outside the 
image domain
+     * ({@link TileStatus#OUTSIDE_EXTENT}). This verification must be done by 
the caller.
      *
      * @param  image  image from which to get a tile status.
      * @param  tileX  row index of the tile for which to get the status.
      * @param  tileY  column index of the tile for which to get the status.
      * @return status of the tile at the specified indexes.
-     *
-     * @todo We should check if the image is an instance of {@code 
ComputedImage},
-     *       then check if the tile is in the cache. But it would require that 
we merge
-     *       the feature and storage modules if we want to reuse {@link 
TileStatus} enumeration.
      */
     private static TileStatus getTileStatus(final RenderedImage image, final 
int tileX, final int tileY) {
+        if (image instanceof ComputedImage) {
+            final var computed = (ComputedImage) image;
+            final var tiles = new Rectangle(tileX, tileY, 1, 1);
+            if (computed.hasErrorFlag(tiles)) {
+                return TileStatus.IN_ERROR;
+            }
+        }
         return TileStatus.EXISTS;
     }
 
@@ -439,6 +449,8 @@ final class ImageTileMatrix implements TileMatrix {
 
         /**
          * Creates the tile at the given indexes.
+         * The caller must ensure that the arguments are valid image tile 
indexes.
+         * This condition is not verified by this method.
          */
         @Override
         protected Tile createTile(final int tileX, final int tileY) {
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/IterationDomain.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/IterationDomain.java
index c4a0aa39e4..0f26f25fd7 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/IterationDomain.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/IterationDomain.java
@@ -77,8 +77,9 @@ abstract class IterationDomain<T> {
     }
 
     /**
-     * Creates a new item for the tile at the given indexes. If this method 
returns {@code null},
-     * then the tile is assumed missing and this iterator searches for the 
next tile.
+     * Creates a new item for the tile at the given indexes, or {@code null} 
if the tile is missing.
+     * The caller must ensure that the arguments are valid image tile indexes.
+     * This condition is not verified by this method.
      *
      * @param  tileX  column index of the tile.
      * @param  tileY  row index of the tile.
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/Tile.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/Tile.java
index a0197f31bd..2006879b92 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/Tile.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/Tile.java
@@ -86,8 +86,8 @@ public interface Tile {
 
     /**
      * Returns information about whether the tile failed to load.
-     * The return value can be {@link TileStatus#EXISTS} or {@link 
TileStatus#IN_ERROR};
-     * other enumeration values should not happen after a user successfully 
obtained this {@code Tile} instance.
+     * The return value can be {@link TileStatus#EXISTS} or {@link 
TileStatus#IN_ERROR}.
+     * Other enumeration values should not happen after a user successfully 
obtained this {@code Tile} instance.
      *
      * <h4>State transition</h4>
      * {@link TileStatus#EXISTS} is not a guarantee that a call to {@link 
#getResource()} will succeed.
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TileStatus.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TileStatus.java
index 36009bc3ce..bfb6e666bc 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TileStatus.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TileStatus.java
@@ -44,7 +44,7 @@ public enum TileStatus {
     UNKNOWN,
 
     /**
-     * The tile exists. However, this is not a guarantee that no I/O error 
will happen when reading the tile,
+     * The tile exists. However, there is no guarantee that no I/O error will 
happen when reading the tile,
      * neither that the tile will be non-empty. If an I/O error happens at 
tile reading time,
      * then the tile status should transition from {@code EXISTS} to {@link 
#IN_ERROR}.
      */
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverage.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverage.java
index c3561e64a3..c736b86c9e 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverage.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverage.java
@@ -270,6 +270,11 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
      */
     final boolean deferredTileReading;
 
+    /**
+     * The locale for warnings or error messages, or {@code null} for the 
default locale.
+     */
+    private final Locale locale;
+
     /**
      * Creates a new tiled grid coverage. This constructor does not load any 
tile.
      *
@@ -280,6 +285,7 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
      */
     protected TiledGridCoverage(final TiledGridCoverageResource.Subset subset) 
{
         super(subset.domain, subset.ranges);
+        locale              = subset.getLocale();
         xDimension          = subset.xDimension();
         yDimension          = subset.yDimension();
         deferredTileReading = subset.deferredTileReading();     // May be 
shorter than other arrays or the grid geometry.
@@ -323,21 +329,11 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
         forceWholeTiles = subset.forceWholeTiles(subSize);
     }
 
-    /**
-     * Returns the locale for error messages, or {@code null} for the default.
-     * The default implementation returns {@code null}.
-     *
-     * @return the locale for warning or error messages, or {@code null} if 
unspecified.
-     */
-    protected Locale getLocale() {
-        return null;
-    }
-
     /**
      * Returns the localized resources for error messages.
      */
     private Errors errors() {
-        return Errors.forLocale(getLocale());
+        return Errors.forLocale(locale);
     };
 
     /**
@@ -612,7 +608,7 @@ public abstract class TiledGridCoverage extends 
GridCoverage {
         } catch (DisjointExtentException | CannotEvaluateException e) {
             throw e;
         } catch (Exception e) {     // Too many exception types for listing 
them all.
-            throw new 
CannotEvaluateException(Resources.forLocale(getLocale()).getString(
+            throw new 
CannotEvaluateException(Resources.forLocale(locale).getString(
                     Resources.Keys.CanNotRenderImage_1, 
getIdentifier().toFullyQualifiedName()), e);
         }
         return image;
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverageResource.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverageResource.java
index 14854d64de..aa6d7cc585 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverageResource.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverageResource.java
@@ -18,6 +18,7 @@ package org.apache.sis.storage.tiling;
 
 import java.util.List;
 import java.util.Arrays;
+import java.util.Locale;
 import java.util.Objects;
 import java.util.Collection;
 import java.util.Spliterator;
@@ -814,6 +815,14 @@ check:  if (dataType.isInteger()) {
             }
             return true;
         }
+
+        /**
+         * Returns the locale for warnings and error messages.
+         * This is often {@code null}, which means to use the default locale.
+         */
+        final Locale getLocale() {
+            return listeners.getLocale();
+        }
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/Cache.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/Cache.java
index 7b23f38cab..a022d75ae6 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/Cache.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/Cache.java
@@ -768,8 +768,8 @@ public class Cache<K,V> extends AbstractMap<K,V> implements 
ConcurrentMap<K,V> {
     /**
      * Returns {@code true} if this map contains the specified key.
      * If the value is under computation in another thread, this method 
returns {@code true}
-     * without waiting for the computation result. This behavior is consistent 
with other
-     * {@code Map} methods in the following ways:
+     * without waiting for the computation result.
+     * For comparison, the behavior of other {@code Map} methods are:
      *
      * <ul>
      *   <li>{@link #get(Object)} blocks until the computation is 
completed.</li>

Reply via email to