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 49f489db9e123d9a649331513b209c69140ddb63
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Thu Dec 26 15:20:34 2024 +0100

    Fix an `IndexOutOfBoundsException` when fetching netCDF metadata.
    Adjust the title of GeoTIFF file declared in metadata.
---
 .../apache/sis/storage/geotiff/GeoTiffStore.java   |  9 ++++-
 .../sis/storage/geotiff/ImageFileDirectory.java    | 27 ++++----------
 .../apache/sis/storage/netcdf/MetadataReader.java  |  1 +
 .../apache/sis/storage/base/MetadataBuilder.java   | 43 +++++++++++++++-------
 4 files changed, 46 insertions(+), 34 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/GeoTiffStore.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/GeoTiffStore.java
index 34925a609e..d17f719e18 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/GeoTiffStore.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/GeoTiffStore.java
@@ -67,6 +67,7 @@ import org.apache.sis.coverage.SubspaceNotSpecifiedException;
 import org.apache.sis.coverage.grid.GridCoverage;
 import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.SimpleInternationalString;
 import org.apache.sis.util.privy.Constants;
 import org.apache.sis.util.privy.ListOfUnknownSize;
 import org.apache.sis.util.collection.BackingStoreException;
@@ -420,7 +421,13 @@ public class GeoTiffStore extends DataStore implements 
Aggregate {
              * file did not specified any ImageDescription tag, then we will 
add the filename as a title instead of an
              * identifier because the title is mandatory in ISO 19115 metadata.
              */
-            getIdentifier().ifPresent((id) -> 
builder.addTitleOrIdentifier(id.toString(), MetadataBuilder.Scope.ALL));
+            getIdentifier().ifPresent((id) -> {
+                builder.addIdentifier(id, MetadataBuilder.Scope.ALL);
+                // Replace the `ResourceInternationalString` for "Image 1".
+                if (!(builder.getTitle() instanceof 
SimpleInternationalString)) {
+                    builder.setTitle(id.toString());
+                }
+            });
             builder.setISOStandards(true);
             final DefaultMetadata md = builder.build();
             metadata = customizer.customize(new SchemaModifier.Source(this), 
md);
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
index 23c8926929..7c4fc0e5cf 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
@@ -469,13 +469,6 @@ final class ImageFileDirectory extends DataCube {
         return reader.store.encoding;
     }
 
-    /**
-     * Returns the image index used in the default identifier.
-     */
-    private String getImageIndex() {
-        return String.valueOf(index + 1);
-    }
-
     /**
      * Returns the identifier in the namespace of the {@link GeoTiffStore}.
      * The first image has the sequence number "1", optionally customized.
@@ -495,7 +488,8 @@ final class ImageFileDirectory extends DataCube {
                     // Should not happen because `setOverviewIdentifier(…)` 
should have been invoked.
                     return Optional.empty();
                 }
-                GenericName name = 
reader.nameFactory.createLocalName(reader.store.namespace(), getImageIndex());
+                final String tip = String.valueOf(index + 1);
+                GenericName name = 
reader.nameFactory.createLocalName(reader.store.namespace(), tip);
                 name = name.toFullyQualifiedName();     // Because "1" alone 
is not very informative.
                 final var source = new SchemaModifier.Source(reader.store, 
index, getDataType());
                 identifier = reader.store.customizer.customize(source, name);
@@ -1389,19 +1383,12 @@ final class ImageFileDirectory extends DataCube {
             source = null;          // Note: the `index` value is invalid in 
this case.
         } else {
             source = new SchemaModifier.Source(reader.store, index, 
getDataType());
-        }
-        getIdentifier().ifPresent((id) -> {
-            metadata.addIdentifier(id, ImageMetadataBuilder.Scope.RESOURCE);
-            final CharSequence title;
-            if (!getImageIndex().equals(id.tip().toString())) {
-                title = id.toString();
-            } else if (source != null && !metadata.hasTitle()) {
-                title = 
Vocabulary.formatInternational(Vocabulary.Keys.Image_1, index + 1);
-            } else {
-                return;     // Return from lambda, not from `createMetadata()`.
+            if (metadata.getTitle() == null) {
+                // Note: `GeoTiffStore.getMetadata()` relies on this value not 
being a `String`.
+                
metadata.addTitle(Vocabulary.formatInternational(Vocabulary.Keys.Image_1, index 
+ 1));
             }
-            metadata.addTitle(title);
-        });
+        }
+        metadata.addIdentifier(getIdentifier().orElse(null), 
ImageMetadataBuilder.Scope.RESOURCE);
         /*
          * Add information about sample dimensions.
          *
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java
index ec5dcd4b19..a8cd6c636b 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/MetadataReader.java
@@ -766,6 +766,7 @@ split:  while ((start = 
CharSequences.skipLeadingWhitespaces(value, start, lengt
         /*
          * If at least one vertical coordinate is available, add a 
VerticalExtent.
          */
+        convention = Math.min(convention, VERTICAL_ALTERNATIVES.length - 1);
         for (int i=0; i <= convention; i++) {
             if (fillExtent(VERTICAL_ALTERNATIVES[i], Units.METRE, null, 
extent, 0)) {
                 addVerticalExtent(extent[0], extent[1], verticalCRS);
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
index 258a05277a..9d5f24b289 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
@@ -851,7 +851,7 @@ public class MetadataBuilder {
      * @throws DataStoreException if an error occurred while reading metadata 
from the data store.
      */
     public final void addDefaultMetadata(final AbstractResource resource, 
final StoreListeners listeners) throws DataStoreException {
-        if (!hasTitle()) {
+        if (getTitle() == null) {
             // Note: title is mandatory in ISO metadata, contrarily to the 
identifier.
             resource.getIdentifier().ifPresent((name) -> addTitle(new 
Sentence(name)));
         }
@@ -1200,6 +1200,33 @@ public class MetadataBuilder {
         return s1.toString().equals(s2.toString());
     }
 
+    /**
+     * Returns the current citation title. This method is typically used for 
deciding
+     * whether to use some fallback as title, because titles are mandatory in 
ISO 19115.
+     *
+     * @return the title defined in the current citation, or {@code null} if 
none.
+     */
+    public final InternationalString getTitle() {
+        return (citation != null) ? citation.getTitle() : null;
+    }
+
+    /**
+     * Sets the title, replacing any previous value.
+     * Storage location is:
+     *
+     * <ul>
+     *   <li>{@code metadata/identificationInfo/citation/title}</li>
+     * </ul>
+     *
+     * @param title  the resource title, or {@code null} for no-operation.
+     */
+    public final void setTitle(final CharSequence title) {
+        final InternationalString i18n = trim(title);
+        if (i18n != null) {
+            citation().setTitle(i18n);
+        }
+    }
+
     /**
      * Adds a title or alternate title of the resource, if not already present.
      * This operation does nothing if the title is already defined and the 
given
@@ -1248,7 +1275,7 @@ public class MetadataBuilder {
      */
     public final void addTitleOrIdentifier(final String code, Scope scope) {
         if (scope != Scope.METADATA) {
-            if (!hasTitle()) {
+            if (getTitle() == null) {
                 addTitle(code);
                 if (scope == Scope.RESOURCE) {
                     return;
@@ -1259,16 +1286,6 @@ public class MetadataBuilder {
         addIdentifier(null, code, scope);
     }
 
-    /**
-     * Returns whether the current citation has a title. This method is 
typically used for deciding
-     * whether to use some fallback as title, because titles are mandatory in 
ISO 19115.
-     *
-     * @return whether a title is defined in the current citation.
-     */
-    public final boolean hasTitle() {
-        return (citation != null) && citation.getTitle() != null;
-    }
-
     /**
      * Adds a version of the resource.
      * If a version already exists, the new one will be appended after a new 
line.
@@ -3233,7 +3250,7 @@ public class MetadataBuilder {
          *
          * We could easily factor out the above pattern in a method, but we 
don't do that because
          * it would invoke `bla().getFoos()` before the loop. We want that 
call to happen only if
-         * the collection contains at least one element. Usually there is only 
0 or 1 element.
+         * the collection contains at least one element. Usually, there is 
only 0 or 1 element.
          */
         for (final Identification info : component.getIdentificationInfo()) {
             final Citation c = info.getCitation();

Reply via email to