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 e7830aa Refactor `TiledGridCoverage.getDisplayName()` as `getIdentifier()` in anticipation for `TileMatrix` implementation. e7830aa is described below commit e7830aa371321de71c726917109f97aa59d2ae80 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Mon Mar 28 12:57:34 2022 +0200 Refactor `TiledGridCoverage.getDisplayName()` as `getIdentifier()` in anticipation for `TileMatrix` implementation. --- .../sis/internal/geotiff/SchemaModifier.java | 5 ++-- .../org/apache/sis/storage/geotiff/DataCube.java | 13 ++++++++++ .../org/apache/sis/storage/geotiff/DataSubset.java | 10 +++++--- .../apache/sis/storage/geotiff/GeoTiffStore.java | 2 +- .../sis/storage/geotiff/ImageFileDirectory.java | 29 ++++++++++++++++++---- .../sis/storage/geotiff/MultiResolutionImage.java | 17 ++++++++++++- .../sis/internal/storage/TiledGridCoverage.java | 10 +++++--- 7 files changed, 69 insertions(+), 17 deletions(-) diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/SchemaModifier.java b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/SchemaModifier.java index 6d19bab..90db81d 100644 --- a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/SchemaModifier.java +++ b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/geotiff/SchemaModifier.java @@ -31,7 +31,7 @@ import org.opengis.util.GenericName; * * <h2>Image indices</h2> * All image {@code index} arguments in this interfaces starts with 0 for the first (potentially pyramided) image - * are are incremented by 1 after each <em>pyramid</em>, as defined by the cloud Optimized GeoTIFF specification. + * and are incremented by 1 after each <em>pyramid</em>, as defined by the cloud Optimized GeoTIFF specification. * Consequently those indices may differ from TIFF <cite>Image File Directory</cite> (IFD) indices. * * @todo May move to public API (in revised form) in a future version. @@ -50,9 +50,8 @@ public interface SchemaModifier { * @param identifier the default identifier computed by {@code GeoTiffStore}. May be {@code null} * if {@code GeoTiffStore} has been unable to determine an identifier by itself. * @return the identifier to use, or {@code null} if none. - * @throws DataStoreException if an exception occurred while computing a new identifier. */ - default GenericName customize(final int image, final GenericName identifier) throws DataStoreException { + default GenericName customize(final int image, final GenericName identifier) { return identifier; } diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/DataCube.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/DataCube.java index 7cfa2cc..664ca72 100644 --- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/DataCube.java +++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/DataCube.java @@ -17,10 +17,12 @@ package org.apache.sis.storage.geotiff; import java.util.Locale; +import java.util.Optional; import java.nio.file.Path; import java.awt.image.DataBuffer; import java.awt.image.SampleModel; import java.awt.image.BandedSampleModel; +import org.opengis.util.GenericName; import org.apache.sis.storage.DataStore; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.DataStoreContentException; @@ -97,6 +99,17 @@ abstract class DataCube extends TiledGridResource implements ResourceOnFileSyste } /** + * Returns an human-readable identification of this coverage. + * The namespace should be the {@linkplain #filename() filename} + * and the tip can be an image index, citation, or overview level. + * + * <p>The returned value should never be empty. An empty value would be a failure + * to {@linkplain ImageFileDirectory#setOverviewIdentifier initialize overviews}.</p> + */ + @Override + public abstract Optional<GenericName> getIdentifier(); + + /** * Gets the paths to files used by this resource, or an empty array if unknown. */ @Override diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/DataSubset.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/DataSubset.java index 5da38e2..e003987 100644 --- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/DataSubset.java +++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/DataSubset.java @@ -25,6 +25,7 @@ import java.awt.Point; import java.awt.image.BandedSampleModel; import java.awt.image.DataBuffer; import java.awt.image.Raster; +import org.opengis.util.GenericName; import org.apache.sis.image.DataType; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.DataStoreContentException; @@ -184,11 +185,14 @@ class DataSubset extends TiledGridCoverage implements Localized { } /** - * Returns an human-readable identification of this coverage for error messages. + * Returns an human-readable identification of this coverage. + * The namespace should be the {@linkplain #filename() filename} + * and the tip can be an image index, citation, or overview level. */ @Override - protected final String getDisplayName() { - return source.filename(); + protected final GenericName getIdentifier() { + // Should never be empty (see `DataCube.getIdentifier()` contract). + return source.getIdentifier().get(); } /** diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java index d404dff..783f177 100644 --- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java +++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/GeoTiffStore.java @@ -217,7 +217,7 @@ public class GeoTiffStore extends DataStore implements Aggregate { * Returns the namespace to use in identifier of components, or {@code null} if none. * This method must be invoked inside a block synchronized on {@code this}. */ - final NameSpace namespace() throws DataStoreException { + final NameSpace namespace() { if (!isNamespaceSet && reader != null) { final NameFactory f = reader.nameFactory; GenericName name = null; diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java index f9dfbcd..f0b9a2c 100644 --- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java +++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java @@ -31,8 +31,9 @@ import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.RasterFormatException; import org.opengis.metadata.Metadata; import org.opengis.metadata.citation.DateType; -import org.opengis.util.FactoryException; import org.opengis.util.GenericName; +import org.opengis.util.NameSpace; +import org.opengis.util.FactoryException; import org.opengis.referencing.operation.TransformException; import org.apache.sis.referencing.operation.transform.MathTransforms; import org.apache.sis.internal.geotiff.Resources; @@ -457,15 +458,20 @@ final class ImageFileDirectory extends DataCube { /** * Returns the identifier in the namespace of the {@link GeoTiffStore}. * The first image has the sequence number "1", optionally customized. - * Reduced-resolution (overviews) images have no identifier. + * If this image is an overview, then its namespace should be the name of the base image + * and the tip should be "overview-level" where "level" is a number starting at 1. + * + * <p>The returned value should never be empty. An empty value would be a + * failure to {@linkplain #setOverviewIdentifier initialize overviews}.</p> * * @see #getMetadata() */ @Override - public Optional<GenericName> getIdentifier() throws DataStoreException { + public Optional<GenericName> getIdentifier() { synchronized (getSynchronizationLock()) { if (identifier == null) { if (isReducedResolution()) { + // Should not happen because `setOverviewIdentifier(…)` should have been invoked. return Optional.empty(); } final String id = String.valueOf(index + 1); @@ -478,6 +484,17 @@ final class ImageFileDirectory extends DataCube { } /** + * Sets the identifier for an overview level. This is used only for a pyramid. + * The image with finest resolution is used as the namespace for all overviews. + * + * @param base name of the image with finest resolution. + * @param overview 1 for the first overview, 2 for the next one, etc. + */ + final void setOverviewIdentifier(final NameSpace base, final int overview) { + identifier = reader.nameFactory.createLocalName(base, "overview-" + overview); + } + + /** * Adds the value read from the current position in the given stream for the entry identified * by the given GeoTIFF tag. This method may store the value either in a field of this class, * or directly in the {@link ImageMetadataBuilder}. However in the latter case, this method @@ -1169,10 +1186,11 @@ final class ImageFileDirectory extends DataCube { * This method opportunistically computes default value of optional fields * when those values can be computed from other (usually mandatory) fields. * + * @return {@code true} if the method has been invoked for the first time. * @throws DataStoreContentException if a mandatory tag is missing and can not be inferred. */ - final void validateMandatoryTags() throws DataStoreContentException { - if (isValidated) return; + final boolean validateMandatoryTags() throws DataStoreContentException { + if (isValidated) return false; if (imageWidth < 0) throw missingTag(Tags.ImageWidth); if (imageHeight < 0) throw missingTag(Tags.ImageLength); final short offsetsTag, byteCountsTag; @@ -1295,6 +1313,7 @@ final class ImageFileDirectory extends DataCube { throw missingTag(Tags.ModelTiePoints); } isValidated = true; + return true; } /** diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/MultiResolutionImage.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/MultiResolutionImage.java index 6247dec..81c04c6 100644 --- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/MultiResolutionImage.java +++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/MultiResolutionImage.java @@ -19,6 +19,7 @@ package org.apache.sis.storage.geotiff; import java.util.List; import java.util.Arrays; import java.io.IOException; +import org.opengis.util.NameSpace; import org.opengis.util.FactoryException; import org.opengis.geometry.DirectPosition; import org.opengis.referencing.datum.PixelInCell; @@ -49,6 +50,12 @@ import org.apache.sis.referencing.CRS; */ final class MultiResolutionImage extends GridResourceWrapper { /** + * Name of the image at finest resolution. + * This is used as the namespace for overviews. + */ + private NameSpace namespace; + + /** * Descriptions of each <cite>Image File Directory</cite> (IFD) in the GeoTIFF file. */ private final ImageFileDirectory[] levels; @@ -109,11 +116,19 @@ final class MultiResolutionImage extends GridResourceWrapper { * @return image at the given pyramid level. */ private ImageFileDirectory getImageFileDirectory(final int index) throws IOException, DataStoreException { + assert Thread.holdsLock(getSynchronizationLock()); final ImageFileDirectory dir = levels[index]; if (dir.hasDeferredEntries) { dir.reader.resolveDeferredEntries(dir); } - dir.validateMandatoryTags(); + if (dir.validateMandatoryTags() && index != 0) { + if (namespace == null) { + final ImageFileDirectory base = levels[0]; + // Identifier should never be empty (see `DataCube.getIdentifier()` contract). + namespace = base.reader.nameFactory.createNameSpace(base.getIdentifier().get(), null); + } + dir.setOverviewIdentifier(namespace, index); + } return dir; } diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/TiledGridCoverage.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/TiledGridCoverage.java index 766c43e..1f6a737 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/TiledGridCoverage.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/TiledGridCoverage.java @@ -26,6 +26,7 @@ import java.awt.image.SampleModel; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.RenderedImage; import java.awt.image.Raster; +import org.opengis.util.GenericName; import org.opengis.coverage.CannotEvaluateException; import org.opengis.geometry.MismatchedDimensionException; import org.apache.sis.coverage.grid.GridCoverage; @@ -34,6 +35,7 @@ import org.apache.sis.coverage.grid.DisjointExtentException; import org.apache.sis.internal.coverage.j2d.DeferredProperty; import org.apache.sis.internal.coverage.j2d.TiledImage; import org.apache.sis.storage.DataStoreException; +import org.apache.sis.storage.tiling.TileMatrixSet; import org.apache.sis.util.collection.WeakValueHashMap; import org.apache.sis.util.resources.Errors; @@ -249,12 +251,12 @@ public abstract class TiledGridCoverage extends GridCoverage { } /** - * Returns a name that identifies this coverage. It may be the filename. - * This is used for error messages. + * Returns a unique name that identifies this coverage. + * The name shall be unique in the {@link TileMatrixSet}. * * @return an human-readable identification of this coverage. */ - protected abstract String getDisplayName(); + protected abstract GenericName getIdentifier(); /** * Returns the locale for error messages, or {@code null} for the default. @@ -446,7 +448,7 @@ public abstract class TiledGridCoverage extends GridCoverage { } } catch (Exception e) { // Too many exception types for listing them all. throw new CannotEvaluateException(Resources.forLocale(getLocale()).getString( - Resources.Keys.CanNotRenderImage_1, getDisplayName()), e); + Resources.Keys.CanNotRenderImage_1, getIdentifier().toFullyQualifiedName()), e); } return image; }