sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 01/04: feat(NetCDF): Allow for custom search paths and attribute names per convention.
Date Thu, 21 Feb 2019 12:04:31 GMT
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 85928b679046f463167c07665adf1f0d29775f76
Author: Alexis Manin <alexis.manin@gmail.com>
AuthorDate: Mon Feb 18 15:39:54 2019 +0100

    feat(NetCDF): Allow for custom search paths and attribute names per convention.
    
    Introduced mechanism is really simple and naive. It will surely be too limited for some
conventions and will have to evoluate. But for now, it allows to start taking into account
other conventions than NetCDF.
---
 .../org/apache/sis/internal/netcdf/Convention.java | 69 +++++++++++++++++++---
 .../sis/internal/netcdf/impl/ChannelDecoder.java   | 10 ++++
 .../sis/internal/netcdf/ucar/DecoderWrapper.java   | 14 ++++-
 .../apache/sis/storage/netcdf/MetadataReader.java  |  9 ---
 4 files changed, 85 insertions(+), 17 deletions(-)

diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java
index 76a80d6..f8c35e8 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java
@@ -16,12 +16,15 @@
  */
 package org.apache.sis.internal.netcdf;
 
+import java.util.Arrays;
 import java.util.Iterator;
 import org.apache.sis.internal.referencing.LazySet;
 import org.apache.sis.referencing.operation.transform.TransferFunction;
 import org.apache.sis.measure.MeasurementRange;
 import org.apache.sis.measure.NumberRange;
+import org.apache.sis.storage.netcdf.AttributeNames;
 import org.apache.sis.util.Numbers;
+import ucar.nc2.constants.ACDD;
 import ucar.nc2.constants.CDM;
 
 
@@ -74,6 +77,14 @@ public class Convention {
     };
 
     /**
+     * Names of groups where to search for metadata, in precedence order.
+     * The {@code null} value stands for global attributes.
+     *
+     * <p>REMINDER: if modified, update class javadoc too.</p>
+     */
+    private static final String[] SEARCH_PATH = {"NCISOMetadata", "CFMetadata", null, "THREDDSMetadata"};
+
+    /**
      * For subclass constructors.
      */
     protected Convention() {
@@ -82,24 +93,55 @@ public class Convention {
     /**
      * Finds the convention to apply to the file opened by the given decoder, or {@code null}
if none.
      */
-    static synchronized Convention find(final Decoder decoder) {
+    static Convention find(final Decoder decoder) {
         final Iterator<Convention> it;
         Convention c;
         synchronized (AVAILABLES) {
             it = AVAILABLES.iterator();
-            if (!it.hasNext()) return DEFAULT;
-            c = it.next();
         }
-        while (!c.isApplicableTo(decoder)) {
+
+        do {
             synchronized (AVAILABLES) {
-                if (!it.hasNext()) return DEFAULT;
-                c = it.next();
+                if (it.hasNext()) {
+                    c = it.next();
+                } else {
+                    decoder.setSearchPath(DEFAULT.getSearchPath());
+                    return DEFAULT;
+                }
             }
-        }
+
+            decoder.setSearchPath(c.getSearchPath());
+
+        } while (!c.isApplicableTo(decoder));
+
         return c;
     }
 
     /**
+     * Specify a list of groups to focus on when searching for attribute values.
+     *
+     * @return Groups we should search in for global data attributes. Never null, never empty,
but can contain null
+     * values to specify root as search path.
+     */
+    public final String[] getSearchPath() {
+        String[] paths = getSearchPathImpl();
+        if (paths == null || paths.length < 1) {
+            return new String[1];
+        }
+
+        return Arrays.copyOf(paths, paths.length);
+    }
+
+    /**
+     * An abstraction over {@link #getSearchPath() }, allowing subclasses to specify their
own groups. The abstraction
+     * is needed as a control mechanism to avoid invalid paths (null or empty).
+     * @return Groups to look at for attribute values.
+     */
+    protected String[] getSearchPathImpl() {
+        return SEARCH_PATH;
+    }
+
+    /**
      * Detects if this set of conventions applies to the given netCDF file.
      *
      * @param  decoder  the netCDF file to test.
@@ -296,4 +338,17 @@ public class Convention {
         if (!Double.isNaN(offset)) tr.setOffset(offset);
         return tr;
     }
+
+    /**
+     * Try to find an equivalent of a given attribute name adapted to this convention. Names
given as parameter will be
+     * CF based, meaning they mostly originate from {@link AttributeNames SIS attribute naming}
or
+     * {@link ACDD UCAR naming} conventions.
+     *
+     * @param name An attribute name to get an equivalent for in the current convention.
    *
+     * @return If no mapping can be found, or if given is null or empty, input text should
be sent back. Otherwise,
+     * the attribute corresponding to queried information for the current convention is returned.
+     */
+    public String mapAttributeName(final String name) {
+        return name;
+    }
 }
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
index f135d66..ac065f0 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
@@ -38,6 +38,7 @@ import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.nio.channels.ReadableByteChannel;
+import java.util.Objects;
 import javax.measure.UnitConverter;
 import javax.measure.IncommensurableException;
 import javax.measure.format.ParserException;
@@ -742,6 +743,15 @@ public final class ChannelDecoder extends Decoder {
                 value = attributeMap.get(lower);
             }
         }
+
+        // Check if a custom convention could be applied.
+        if (value == null && convention() != null) {
+            final String mappedName = convention().mapAttributeName(name);
+            if (!Objects.equals(name, mappedName)) {
+                value = findAttribute(mappedName);
+            }
+        }
+
         return value;
     }
 
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
index f2b264d..6df5a66 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DecoderWrapper.java
@@ -23,6 +23,7 @@ import java.util.EnumSet;
 import java.util.Formatter;
 import java.util.Collection;
 import java.io.IOException;
+import java.util.Objects;
 import ucar.nc2.Group;
 import ucar.nc2.Attribute;
 import ucar.nc2.VariableIF;
@@ -58,6 +59,7 @@ import org.apache.sis.storage.DataStoreException;
  * @module
  */
 public final class DecoderWrapper extends Decoder implements CancelTask {
+
     /**
      * The netCDF file to read.
      * This file is set at construction time.
@@ -234,7 +236,17 @@ public final class DecoderWrapper extends Decoder implements CancelTask
{
      * @return the attribute, or {@code null} if none.
      */
     private Attribute findAttribute(final Group group, final String name) {
-        return (group != null) ? group.findAttributeIgnoreCase(name) : file.findGlobalAttributeIgnoreCase(name);
+        Attribute value = (group != null) ?
+                group.findAttributeIgnoreCase(name) : file.findGlobalAttributeIgnoreCase(name);
+
+        if (value == null && convention() != null) {
+            String mappedName = convention().mapAttributeName(name);
+            if (!Objects.equals(name, mappedName)) {
+                value = findAttribute(group, mappedName);
+            }
+        }
+
+        return value;
     }
 
     /**
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
index bf3e41b..d835802 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/MetadataReader.java
@@ -122,14 +122,6 @@ final class MetadataReader extends MetadataBuilder {
     private static final boolean EXPERIMENTAL = true;
 
     /**
-     * Names of groups where to search for metadata, in precedence order.
-     * The {@code null} value stands for global attributes.
-     *
-     * <p>REMINDER: if modified, update class javadoc too.</p>
-     */
-    private static final String[] SEARCH_PATH = {"NCISOMetadata", "CFMetadata", null, "THREDDSMetadata"};
-
-    /**
      * Names of global attributes identifying services.
      */
     private static final String[] SERVICES = {"wms_service", "wcs_service"};
@@ -194,7 +186,6 @@ final class MetadataReader extends MetadataBuilder {
      */
     MetadataReader(final Decoder decoder) {
         this.decoder = decoder;
-        decoder.setSearchPath(SEARCH_PATH);
         searchPath = decoder.getSearchPath();
     }
 


Mime
View raw message