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>