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 e92eacbe6dfc8a76c369a7b51a304550bba93a80 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Mon Nov 27 11:06:21 2023 +0100 Fix a ClassCastException when no resource is using deferred loading. --- .../aggregate/ConcatenatedGridCoverage.java | 27 ++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridCoverage.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridCoverage.java index 42de890c71..6cfec2278a 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridCoverage.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridCoverage.java @@ -63,12 +63,20 @@ final class ConcatenatedGridCoverage extends GridCoverage { private static final class Loader { /** * Whether loading of grid coverages should be deferred to rendering time. - * This is a bit set packed as {@code long} values. A bit value of 1 means + * This is a bit set packed as {@code int} values. A bit value of 1 means * that the coverages at the corresponding index should be loaded from the * {@linkplain #slices slices} at same index only when first needed. * + * <h4>Invariant</h4> + * Deferred {@linkplain #slices slices} shall be instances of {@link GridCoverage} + * and non-deferred slices shall be instances of {@link GridCoverageResource}. + * So the {@code deferred} flags are redundant with {@code instanceof} checks. + * However, implementation classes may implement both interfaces. + * So those flags tell how to use a slice instance. + * * @see ConcatenatedGridResource#deferredLoading * @see #isDeferred(int) + * @see #valid() */ final int[] deferred; @@ -176,6 +184,7 @@ final class ConcatenatedGridCoverage extends GridCoverage { this.isConverted = source.isConverted; this.locator = source.locator; this.strategy = source.strategy; + assert valid(); } /** @@ -192,6 +201,20 @@ final class ConcatenatedGridCoverage extends GridCoverage { this.locator = source.locator; this.strategy = source.strategy; this.isConverted = converted; + assert valid(); + } + + /** + * Verifies that all {@linkplain #slices} are instances of the expected interface. + * This is used for assertions only. + */ + private boolean valid() { + for (int i=0; i < slices.length; i++) { + final Object actual = slices[i]; + Class<?> expected = isDeferred(i) ? GridCoverageResource.class : GridCoverage.class; + if (!expected.isInstance(actual)) throw new AssertionError(actual); + } + return true; } /** @@ -200,7 +223,7 @@ final class ConcatenatedGridCoverage extends GridCoverage { * If {@code false}, then {@code slices[i]} shall be an instance of {@link GridCoverage}. */ private boolean isDeferred(final int i) { - return (loader == null) || (loader.deferred[i >>> Numerics.INT_SHIFT] & (1 << i)) != 0; + return (loader != null) && (loader.deferred[i >>> Numerics.INT_SHIFT] & (1 << i)) != 0; } /**