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 fdf30a0  Resolve name collision in RasterResource.identifier when two 
netCDF variables use the same "standard_name" attribute value.
fdf30a0 is described below

commit fdf30a0e8133ac5f67f4d1d1e033623bfaf4f5db
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Tue Apr 9 16:42:58 2019 +0200

    Resolve name collision in RasterResource.identifier when two netCDF 
variables use the same "standard_name" attribute value.
---
 .../apache/sis/internal/netcdf/RasterResource.java | 46 +++++++++++++++++++---
 .../org/apache/sis/internal/netcdf/Variable.java   |  6 ++-
 2 files changed, 45 insertions(+), 7 deletions(-)

diff --git 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
index 96259f8..e384680 100644
--- 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
+++ 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
@@ -18,6 +18,7 @@ package org.apache.sis.internal.netcdf;
 
 import java.util.Map;
 import java.util.List;
+import java.util.HashMap;
 import java.util.ArrayList;
 import java.io.IOException;
 import java.nio.file.Path;
@@ -87,11 +88,16 @@ public final class RasterResource extends 
AbstractGridResource implements Resour
     };
 
     /**
-     * The identifier of this grid resource. This is the variable name.
+     * The identifier of this grid resource. This is {@link 
Variable#getStandardName()}. We prefer netCDF standard name instead
+     * than variable name because the former is controlled vocabulary. The use 
of controlled vocabulary for identifiers increases
+     * the chances of stability or consistency between similar products.
+     *
+     * <p>The value set by constructor may be updated by {@link 
#resolveNameCollision(RasterResource, Decoder)},
+     * but should not be modified after that point.</p>
      *
      * @see #getIdentifier()
      */
-    private final GenericName identifier;
+    private GenericName identifier;
 
     /**
      * The grid geometry (size, CRS…) of the {@linkplain #data} cube.
@@ -187,8 +193,9 @@ public final class RasterResource extends 
AbstractGridResource implements Resour
     public static List<Resource> create(final Decoder decoder, final Object 
lock) throws IOException, DataStoreException {
         assert Thread.holdsLock(lock);
         final Variable[]     variables = decoder.getVariables().clone();       
 // Needs a clone because may be modified.
-        final List<Variable> siblings  = new ArrayList<>(4);
-        final List<Resource> resources = new ArrayList<>();
+        final List<Variable> siblings  = new ArrayList<>(4);                   
 // Usually has only 1 element, sometime 2.
+        final List<Resource> resources = new ArrayList<>(variables.length);    
 // The raster resources to be returned.
+        final Map<GenericName,RasterResource> firstOfName = new HashMap<>();   
 // For detecting name collisions.
         for (int i=0; i<variables.length; i++) {
             final Variable variable = variables[i];
             if (variable == null || variable.getRole() != 
VariableRole.COVERAGE) {
@@ -290,13 +297,40 @@ public final class RasterResource extends 
AbstractGridResource implements Resour
                 }
                 numBands = siblings.size();
             }
-            resources.add(new RasterResource(decoder, name.trim(), grid, 
siblings, numBands, bandDimension, lock));
+            final RasterResource r = new RasterResource(decoder, name.trim(), 
grid, siblings, numBands, bandDimension, lock);
+            r.resolveNameCollision(firstOfName.putIfAbsent(r.identifier, r), 
decoder);
+            resources.add(r);
             siblings.clear();
         }
         return resources;
     }
 
     /**
+     * If the given resource is non-null, modifies the name of this resource 
for avoiding name collision.
+     * The {@code other} resource shall be non-null when the caller detected 
that there is a name collision
+     * with that resource.
+     *
+     * @param  other  the other resource for which there is a name collision, 
or {@code null} if no collision.
+     */
+    private void resolveNameCollision(final RasterResource other, final 
Decoder decoder) {
+        if (other != null) {
+            if (identifier.equals(other.identifier)) {
+                other.resolveNameCollision(decoder);
+            }
+            resolveNameCollision(decoder);
+        }
+    }
+
+    /**
+     * Invoked when the name of this resource needs to be changed because it 
collides with the name of another resource.
+     * This method appends the variable name, which should be unique in each 
netCDF file.
+     */
+    private void resolveNameCollision(final Decoder decoder) {
+        String name = identifier + " (" + data[0].getName() + ')';
+        identifier = decoder.nameFactory.createLocalName(decoder.namespace, 
name);
+    }
+
+    /**
      * Returns the variable name as an identifier of this resource.
      */
     @Override
@@ -571,7 +605,7 @@ public final class RasterResource extends 
AbstractGridResource implements Resour
             throw new 
DataStoreContentException(Errors.getResources(getLocale()).getString(Errors.Keys.UnsupportedType_1,
 dataType.name()));
         }
         return new Raster(domain, UnmodifiableArrayList.wrap(bands), 
imageBuffer,
-                rangeIndices.getPixelStride(), bandOffsets, 
first.getStandardName());
+                rangeIndices.getPixelStride(), bandOffsets, 
String.valueOf(identifier));
     }
 
     /**
diff --git 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
index d009902..a0f9737 100644
--- 
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
+++ 
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
@@ -168,9 +168,13 @@ public abstract class Variable extends NamedElement {
 
     /**
      * Returns the standard name if available, or the long name other, or the 
ordinary name otherwise.
-     * May be used as the label of a {@link Raster} as a whole (including all 
bands).
+     * May be used as the {@link RasterResource} label, or the label of a 
{@link Raster} as a whole
+     * (including all bands). Standard name is preferred to variable name when 
controlled vocabulary
+     * is desired, for example for more stable identifier or more consistency 
between similar data.
      *
      * @return the standard name, or a fallback if there is no standard name.
+     *
+     * @see RasterResource#identifier
      */
     public final String getStandardName() {
         String name = getAttributeAsString(CF.STANDARD_NAME);

Reply via email to