This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit bda6b01110278437ecc37fad3a640938ff76d7fd Author: Martin Desruisseaux <[email protected]> AuthorDate: Sat Jul 11 15:20:34 2026 +0200 Create coverage name in a way more consistent with TIFF reader. --- .../org/apache/sis/util/resources/Vocabulary.java | 10 ++++++ .../sis/util/resources/Vocabulary.properties | 2 ++ .../sis/util/resources/Vocabulary_fr.properties | 2 ++ .../apache/sis/storage/geoheif/FromImageIO.java | 5 ++- .../apache/sis/storage/geoheif/GeoHeifStore.java | 6 ++-- .../main/org/apache/sis/storage/geoheif/Image.java | 7 ++-- .../apache/sis/storage/geoheif/ImageResource.java | 2 +- .../sis/storage/geoheif/ImageResourceBuilder.java | 31 ++++++++-------- .../sis/storage/geoheif/ResourceBuilder.java | 42 +++++++++++++++++----- .../org/apache/sis/storage/geoheif/TiledImage.java | 2 +- .../sis/storage/geoheif/UncompressedImage.java | 2 +- .../sis/storage/isobmff/base/ItemInfoEntry.java | 10 ------ .../org/apache/sis/storage/gdal/TiledCoverage.java | 9 +++-- .../org/apache/sis/storage/gdal/TiledResource.java | 11 +++--- 14 files changed, 88 insertions(+), 53 deletions(-) diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java index 2b15588fec..5621f15b1d 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java @@ -623,6 +623,11 @@ public class Vocabulary extends IndexedResourceBundle { */ public static final short GridOf_1 = 290; + /** + * Group {0} + */ + public static final short Group_1 = 291; + /** * Height */ @@ -708,6 +713,11 @@ public class Vocabulary extends IndexedResourceBundle { */ public static final short Isolines = 252; + /** + * Item {0} + */ + public static final short Item_1 = 292; + /** * Java home directory */ diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties index 867e72e9f4..2ce3cf511b 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties @@ -126,6 +126,7 @@ Grayscale = Grayscale Green = Green GridExtent = Grid extent GridOf_1 = Grid of \u201c{0}\u201d +Group_1 = Group {0} Height = Height Identifier = Identifier Identifiers = Identifiers @@ -143,6 +144,7 @@ Invalid = Invalid InverseOperation = Inverse operation Interval = Interval Isolines = Isolines +Item_1 = Item {0} JavaHome = Java home directory Julian = Julian Latitude = Latitude diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties index c5240d9ee1..0a28ebff61 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties @@ -133,6 +133,7 @@ Grayscale = Niveaux de gris Green = Vert GridExtent = \u00c9tendue de la grille GridOf_1 = Grille de \u00ab\u202f{0}\u202f\u00bb +Group_1 = Groupe {0} Height = Hauteur Identifier = Identifiant Identifiers = Identifiants @@ -150,6 +151,7 @@ Invalid = Invalide InverseOperation = Op\u00e9ration inverse Interval = Intervalle Isolines = Isolignes +Item_1 = Item {0} JavaHome = R\u00e9pertoire du Java Julian = Julien Latitude = Latitude diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/FromImageIO.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/FromImageIO.java index c6f319aaf0..fa5bd332f4 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/FromImageIO.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/FromImageIO.java @@ -61,7 +61,10 @@ final class FromImageIO extends Image implements IIOReadWarningListener { * @param name a name that identifies this image, for debugging purpose. * @throws DataStoreException if an error occurred while decoding <abbr>HEIF</abbr> boxes. */ - FromImageIO(ImageResourceBuilder builder, ByteRanges.Reader locator, final ImageReaderSpi provider, String name) + FromImageIO(final ImageResourceBuilder builder, + final ByteRanges.Reader locator, + final ImageReaderSpi provider, + final CharSequence name) throws DataStoreException { super(builder, locator, name); diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/GeoHeifStore.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/GeoHeifStore.java index 514bc3b37f..b2fe0c42aa 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/GeoHeifStore.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/GeoHeifStore.java @@ -84,14 +84,14 @@ public class GeoHeifStore extends DataStore implements Aggregate { * Defined as a namespace for use as the scope of children resources (the images). * May be {@code null}. * - * @see #createComponentName(String) + * @see #createComponentName(CharSequence) */ private final NameSpace namespace; /** * The factory to use for creating resource names in the namespace of this store. * - * @see #createComponentName(String) + * @see #createComponentName(CharSequence) */ final NameFactory nameFactory; @@ -203,7 +203,7 @@ public class GeoHeifStore extends DataStore implements Aggregate { * @param tip component name as the tip of the qualified name. * @return a name in the namespace of this store. */ - final LocalName createComponentName(final String tip) { + final LocalName createComponentName(final CharSequence tip) { return nameFactory.createLocalName(namespace, tip); } diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/Image.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/Image.java index eb7472b529..dea19015f5 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/Image.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/Image.java @@ -25,6 +25,7 @@ import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.DataStoreContentException; import org.apache.sis.storage.event.StoreListeners; import org.apache.sis.storage.isobmff.ByteRanges; +import org.apache.sis.util.internal.shared.Strings; /** @@ -39,7 +40,7 @@ abstract class Image { /** * A name that identifies this image, for debugging purposes. */ - private final String name; + private final CharSequence name; /** * Number of columns and rows in the tile matrix. @@ -71,7 +72,7 @@ abstract class Image { * @param name a name that identifies this image, for debugging purpose. * @throws DataStoreException if an error occurred while decoding <abbr>HEIF</abbr> boxes. */ - protected Image(final ImageResourceBuilder builder, final ByteRanges.Reader locator, final String name) + protected Image(final ImageResourceBuilder builder, final ByteRanges.Reader locator, final CharSequence name) throws DataStoreException { this.locator = locator; @@ -139,6 +140,6 @@ abstract class Image { */ @Override public String toString() { - return name; + return Strings.toString(getClass(), "name", name, "tiles", numXTiles + " × " + numYTiles); } } diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResource.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResource.java index 75153f40bd..5b8133f65f 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResource.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResource.java @@ -138,7 +138,7 @@ final class ImageResource extends TiledGridCoverageResource implements StoreReso ImageResource(final ImageResourceBuilder builder, Image[] tiles, final Image image) throws DataStoreException { super(builder.store()); this.store = builder.store(); - identifier = builder.name(); + identifier = builder.identifier(); sampleDimensions = builder.imageModel().sampleDimensions(builder); gridGeometry = builder.gridGeometry(); if (tiles == null) { diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResourceBuilder.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResourceBuilder.java index d1119f4119..73a0e31e92 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResourceBuilder.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResourceBuilder.java @@ -92,11 +92,9 @@ final class ImageResourceBuilder implements Emptiable { * as "symbolic name of the item (source file for file delivery transmissions)" and this * class assumes that the name is unique. * - * @todo Verify if {@link ItemInfoEntry#itemName} is really unique. - * - * @see #name() + * @see #identifier() */ - private String name; + private CharSequence identifier; /** * The size (in pixels) of the reconstructed image. @@ -372,7 +370,7 @@ final class ImageResourceBuilder implements Emptiable { * @param name name of the resource to create. * @return whether at least one ignored box was flagged as essential. */ - boolean reportUnknownBoxes(final String name) { + boolean reportUnknownBoxes(final CharSequence name) { boolean essential = false; if (!unknownBoxes.isEmpty()) { final Level level; @@ -431,14 +429,14 @@ final class ImageResourceBuilder implements Emptiable { * Builds the grid coverage resource for an untiled image. * This builder should not be used anymore after this method call. * - * @param name name of the resource. - * @param image the single tile of the image. + * @param identifier name of the resource. Should be unique for allowing its use as identifier. + * @param image the single tile of the image. * @return the resource. * @throws DataStoreContentException if the "grid to <abbr>CRS</abbr>" transform or the sample dimensions cannot be created. * @throws DataStoreException if the construction failed for another reason. */ - final ImageResource build(final String name, final Image image) throws DataStoreException { - this.name = name; + final ImageResource build(final CharSequence identifier, final Image image) throws DataStoreException { + this.identifier = identifier; return new ImageResource(this, null, image); } @@ -446,14 +444,14 @@ final class ImageResourceBuilder implements Emptiable { * Builds the grid coverage resource for a tiled image. * This builder should not be used anymore after this method call. * - * @param name name of the resource. - * @param tiles all tiles of the image. + * @param identifier name of the resource. Should be unique for allowing its use as identifier. + * @param tiles all tiles of the image. * @return the resource. * @throws DataStoreContentException if the "grid to <abbr>CRS</abbr>" transform or the sample dimensions cannot be created. * @throws DataStoreException if the construction failed for another reason. */ - final ImageResource build(final String name, final List<Image> tiles) throws DataStoreException { - this.name = name; + final ImageResource build(final CharSequence identifier, final List<Image> tiles) throws DataStoreException { + this.identifier = identifier; return new ImageResource(this, tiles.toArray(Image[]::new), null); } @@ -470,14 +468,15 @@ final class ImageResourceBuilder implements Emptiable { * Returns a name for the resource to create and opportunistically adds it to the metadata. * This method should be invoked exactly once. */ - public final GenericName name() { - GenericName gn = store().createComponentName(name); + public final GenericName identifier() { + GenericName gn = store().createComponentName(identifier); metadata().addIdentifier(gn, MetadataBuilder.Scope.RESOURCE); return gn; } /** - * Returns the builder of metadata. + * Returns the shared instance of metadata builder. The same instance may be shared by + * many {@link ImageResourceBuilder} in order to provide a consolidated set of metadata. */ public final MetadataBuilder metadata() { if (metadata == null) { diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ResourceBuilder.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ResourceBuilder.java index d6eb72b3a3..4a95c20fb3 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ResourceBuilder.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ResourceBuilder.java @@ -33,7 +33,6 @@ import java.io.IOException; import javax.imageio.spi.ImageReaderSpi; import org.opengis.util.GenericName; import org.opengis.referencing.operation.TransformException; -import org.apache.sis.util.ArraysExt; import org.apache.sis.storage.Resource; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.DataStoreContentException; @@ -55,7 +54,9 @@ import org.apache.sis.storage.isobmff.base.MediaData; import org.apache.sis.storage.isobmff.base.PrimaryItem; import org.apache.sis.storage.isobmff.image.DerivedImageReference; import org.apache.sis.storage.isobmff.image.ImagePyramid; +import org.apache.sis.util.ArraysExt; import org.apache.sis.util.resources.Errors; +import org.apache.sis.util.resources.Vocabulary; /** @@ -220,7 +221,8 @@ final class ResourceBuilder { case ItemLocation.BOXTYPE: { for (final ItemLocation.Item item : ((ItemLocation) box).items) { if (itemLocations.putIfAbsent(item.itemID, item) != null) { - warning("Many locations found for the \"{0}\" resource.", getResourceName(item.itemID)); + warning("Many locations found for the \"{0}\" resource.", + getResourceName(item.itemID, Vocabulary.Keys.Item_1)); } } break; @@ -250,7 +252,7 @@ final class ResourceBuilder { * @param message the message with a "{0}" pattern to be replaced by the resource name. * @param name the resource name. */ - private void warning(String message, final String name) { + private void warning(String message, final CharSequence name) { message = message.replace("{0}", name); store.warning(new LogRecord(Level.WARNING, message)); } @@ -267,18 +269,42 @@ final class ResourceBuilder { /** * Returns the name for the item specified by the given identifier. - * If no name is found, then the give {@code itemID} is formatted. + * If no name is found, then the given {@code itemID} is formatted. * * @param itemID identifier of the item for which to get name. + * @param key {@link Vocabulary} key to use in case of fallback on the numerical value. * @return a non-null item name. */ - private String getResourceName(final int itemID) { + private CharSequence getResourceName(final int itemID, final short key) { for (ItemInfoEntry entry : info(itemInfos.get(itemID))) { if (entry.itemName != null) { return entry.itemName; } } - return Integer.toUnsignedString(itemID); + // Use the `long` type only if necessary. + return Vocabulary.formatInternational(key, valueOf(itemID)); + } + + /** + * Returns the name for the given item. + * If no name is found, then the given {@code itemID} is formatted. + * + * @param entry the item for which to get the name. + * @return a non-null item name. + */ + private static CharSequence getResourceName(final ItemInfoEntry entry) { + if (entry.itemName != null) { + return entry.itemName; + } + return Vocabulary.formatInternational(Vocabulary.Keys.Item_1, valueOf(entry.itemID)); + } + + /** + * Returns the given integer as a wrapper object, with the integer considered as unsigned. + * The {@link Long} wrapper is used only if necessary for keeping the value positive. + */ + private static Number valueOf(final int itemID) { + return (itemID >= 0) ? Integer.valueOf(itemID) : Integer.toUnsignedLong(itemID); } /** @@ -360,7 +386,7 @@ final class ResourceBuilder { { ImageResourceBuilder firstBuilder = null; for (final ItemInfoEntry entry : info) { - final String name = entry.itemName(); + final CharSequence name = getResourceName(entry); if (entry.itemProtectionIndex != 0) { warning("The \"{0}\" resource is protected.", name); continue; @@ -511,7 +537,7 @@ final class ResourceBuilder { for (final GroupList box : groups) { for (Box child : box.children) { if (child instanceof EntityToGroup group) { // Should be the type of all children. - final GenericName name = store.createComponentName(getResourceName(group.groupID)); + final GenericName name = store.createComponentName(getResourceName(group.groupID, Vocabulary.Keys.Group_1)); final var components = new ArrayList<ImageResource>(group.entityID.length); for (int entityID : group.entityID) { final Iterator<Resource> it = itemResources.getOrDefault(entityID, List.of()).iterator(); diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/TiledImage.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/TiledImage.java index 55785105d7..655290ed2a 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/TiledImage.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/TiledImage.java @@ -55,7 +55,7 @@ final class TiledImage extends UncompressedImage { * @throws RasterFormatException if the sample model cannot be created. * @throws IOException if an error occurred while reading bytes from the input stream. */ - TiledImage(final ImageResourceBuilder builder, final ByteRanges.Reader locator, final String name) + TiledImage(final ImageResourceBuilder builder, final ByteRanges.Reader locator, final CharSequence name) throws DataStoreException, IOException { super(builder, locator, name); diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/UncompressedImage.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/UncompressedImage.java index c3338da048..4575a308a6 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/UncompressedImage.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/UncompressedImage.java @@ -89,7 +89,7 @@ class UncompressedImage extends Image { * @param name a name that identifies this image, for debugging purpose. * @throws DataStoreContentException if the "grid to <abbr>CRS</abbr>" transform or the sample dimensions cannot be created. */ - UncompressedImage(final ImageResourceBuilder builder, final ByteRanges.Reader locator, final String name) + UncompressedImage(final ImageResourceBuilder builder, final ByteRanges.Reader locator, final CharSequence name) throws DataStoreException { super(builder, locator, name); diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/base/ItemInfoEntry.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/base/ItemInfoEntry.java index ec648b0edd..7d1417cfd4 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/base/ItemInfoEntry.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/isobmff/base/ItemInfoEntry.java @@ -165,16 +165,6 @@ public final class ItemInfoEntry extends FullBox { } } - /** - * Returns the item name. If {@link #itemName} is null, then {@link #itemID} is used. - * This is used for formatting error messages and should not be used as real identifier. - * - * @return a non-null item name. - */ - public String itemName() { - return (itemName != null) ? itemName : Integer.toUnsignedString(itemID); - } - /** * Converts node properties to <abbr>ISO</abbr> 19115 metadata. * diff --git a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/TiledCoverage.java b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/TiledCoverage.java index 7fbe56ac17..2e82c7aaef 100644 --- a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/TiledCoverage.java +++ b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/TiledCoverage.java @@ -26,7 +26,6 @@ import org.opengis.util.GenericName; import org.apache.sis.util.logging.Logging; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.tiling.TiledGridCoverage; -import org.apache.sis.storage.tiling.TiledGridCoverageResource; // Test dependencies import org.apache.sis.image.internal.shared.AssertionMessages; @@ -47,9 +46,9 @@ final class TiledCoverage extends TiledGridCoverage { * Creates a new tiled grid coverage. * * @param owner the resource from which this coverage has been read. - * @param subset description of the {@link TiledGridCoverageResource} subset to cover. + * @param subset description of the {@link TiledResource} subset to cover. */ - TiledCoverage(final TiledResource owner, final TiledGridCoverageResource.Subset subset) { + TiledCoverage(final TiledResource owner, final TiledResource.Subset subset) { super(subset); this.owner = owner; } @@ -72,12 +71,12 @@ final class TiledCoverage extends TiledGridCoverage { /** * Returns all tiles in the given area of interest. Tile indices (0,0) locates the tile in the upper-left corner - * of this {@code TiledGridCoverage} (not necessarily the upper-left corner of the {@link TiledGridCoverageResource}). + * of this {@code TiledGridCoverage} (not necessarily the upper-left corner of the {@link TiledResource}). * The {@link Raster#getMinX()} and {@code getMinY()} coordinates of returned rasters * shall start at the given {@code iterator.offsetAOI} values. * * @param iterator an iterator over the tiles that intersect the Area Of Interest specified by user. - * @return tiles decoded from the {@link TiledGridCoverageResource}. + * @return tiles decoded from the {@link TiledResource}. * @throws ArithmeticException if an integer overflow occurred. */ @Override diff --git a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/TiledResource.java b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/TiledResource.java index 848ef79411..bcbb61ca7e 100644 --- a/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/TiledResource.java +++ b/optional/src/org.apache.sis.storage.gdal/main/org/apache/sis/storage/gdal/TiledResource.java @@ -83,11 +83,11 @@ final class TiledResource extends TiledGridCoverageResource { private final int imageIndex; /** - * The identifier of this resource, or {@code null} if none. + * The identifier of this resource, created when first needed. * * @see #getIdentifier() */ - private final GenericName identifier; + private volatile GenericName identifier; /** * The grid geometry of the raster, or {@code null} if not yet computed. @@ -174,7 +174,6 @@ final class TiledResource extends TiledGridCoverageResource { this.tileHeight = t.height; this.parent = parent; this.imageIndex = imageIndex; - this.identifier = parent.factory.createLocalName(parent.namespace, String.valueOf(imageIndex)).toFullyQualifiedName(); this.width = size.width(); this.height = size.height(); this.dataType = DataType.valueOf(size.type()); @@ -288,7 +287,11 @@ final class TiledResource extends TiledGridCoverageResource { */ @Override public final Optional<GenericName> getIdentifier() { - return Optional.ofNullable(identifier); + GenericName name = identifier; + if (name == null) { + identifier = name = parent.factory.createLocalName(parent.namespace, String.valueOf(imageIndex)).toFullyQualifiedName(); + } + return Optional.of(name); } /**
