sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: Avoid use of the deprecated `ucar.nc2.dataset.CoordSysBuilder` class. It forces us to register a `ucar.nc2.dataset.spi.CoordSystemBuilderFactory` using Service Provider Interface (SPI), which is a bit unfortunate because it has a global effect on system configuration. But we do this registration only if the `sis-japan-profile` is in the classpath.
Date Fri, 26 Feb 2021 22:43:20 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


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 4658dfb  Avoid use of the deprecated `ucar.nc2.dataset.CoordSysBuilder` class. It
forces us to register a `ucar.nc2.dataset.spi.CoordSystemBuilderFactory` using Service Provider
Interface (SPI), which is a bit unfortunate because it has a global effect on system configuration.
But we do this registration only if the `sis-japan-profile` is in the classpath.
4658dfb is described below

commit 4658dfb9648b8b7da6c990286a720e04f15d060d
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Fri Feb 26 23:39:39 2021 +0100

    Avoid use of the deprecated `ucar.nc2.dataset.CoordSysBuilder` class.
    It forces us to register a `ucar.nc2.dataset.spi.CoordSystemBuilderFactory`
    using Service Provider Interface (SPI), which is a bit unfortunate because
    it has a global effect on system configuration. But we do this registration
    only if the `sis-japan-profile` is in the classpath.
    
    https://github.com/Unidata/netcdf-java/issues/616
---
 ide-project/NetBeans/build.xml                     |  12 ++
 .../sis/internal/earth/netcdf/FactoryForUCAR.java  | 123 +++++++++++++++++++++
 .../apache/sis/internal/earth/netcdf/GCOM_W.java   |  33 +++---
 .../ucar.nc2.dataset.spi.CoordSystemBuilderFactory |   1 +
 .../internal/netcdf/ucar/CSBuilderFallback.java    |  90 ---------------
 .../sis/internal/netcdf/ucar/DecoderWrapper.java   |  20 +---
 .../sis/internal/netcdf/ucar/VariableWrapper.java  |   3 +-
 7 files changed, 163 insertions(+), 119 deletions(-)

diff --git a/ide-project/NetBeans/build.xml b/ide-project/NetBeans/build.xml
index 6cc8993..d17f099 100644
--- a/ide-project/NetBeans/build.xml
+++ b/ide-project/NetBeans/build.xml
@@ -250,8 +250,20 @@
         <include name="*/*/src/main/resources/META-INF/services/org.apache.sis.internal.netcdf.Convention"/>
       </fileset>
     </concat>
+
+
+
+    <!-- ==== Other service providers ==============================================================================
-->
+
+    <!-- NetCDF conventions to be loaded by ServiceLoader. -->
+    <concat destfile="${build.classes.dir}/META-INF/services/ucar.nc2.dataset.spi.CoordSystemBuilderFactory"
encoding="UTF-8" fixlastline="yes">
+      <fileset dir="${project.root}">
+        <include name="*/*/src/main/resources/META-INF/services/ucar.nc2.dataset.spi.CoordSystemBuilderFactory"/>
+      </fileset>
+    </concat>
   </target>
 
+
   <!--
     Called after compilation of test classes in order to copy test files.
   -->
diff --git a/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/FactoryForUCAR.java
b/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/FactoryForUCAR.java
new file mode 100644
index 0000000..26a238c
--- /dev/null
+++ b/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/FactoryForUCAR.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.earth.netcdf;
+
+import ucar.nc2.Attribute;
+import ucar.nc2.NetcdfFile;
+import ucar.nc2.constants.AxisType;
+import ucar.nc2.dataset.VariableDS;
+import ucar.nc2.dataset.NetcdfDataset;
+import ucar.nc2.dataset.spi.CoordSystemBuilderFactory;
+import ucar.nc2.internal.dataset.CoordSystemBuilder;
+import org.apache.sis.util.CharSequences;
+
+
+/**
+ * Factories to be registered as service providers to the UCAR netCDF library.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.1
+ * @since   1.1
+ * @module
+ */
+public final class FactoryForUCAR implements CoordSystemBuilderFactory {
+    /**
+     * Creates a new factory.
+     */
+    public FactoryForUCAR() {
+    }
+
+    /**
+     * Returns a name for the convention recognized by this package.
+     * This name may change in any future version.
+     *
+     * @return a name for the convention recognized by this package.
+     */
+    @Override
+    public String getConventionName() {
+        return "GCOM";
+    }
+
+    /**
+     * Returns whether the given file seems to be a GCOM-W file.
+     *
+     * @param  file  the file to test.
+     * @return whether the file seems supported by this factory.
+     */
+    @Override
+    public boolean isMine(final NetcdfFile file) {
+        final Attribute at = file.findGlobalAttributeIgnoreCase(GCOM_W.SENTINEL_ATTRIBUTE);
+        if (at != null) {
+            final String s = at.getStringValue();
+            if (s != null) {
+                return GCOM_W.SENTINEL_VALUE.matcher(s).matches();
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Creates a coordinate system builder for the given dataset builder.
+     *
+     * @param  dsb  the dataset builder.
+     * @return the coordinate system builder for the given dataset.
+     */
+    @Override
+    public CoordSystemBuilder open(NetcdfDataset.Builder dsb) {         // TODO: add <?>
with UCAR netCDF 6.
+        return new CSBuilder(dsb);
+    }
+
+    /**
+     * A UCAR coordinate system builder for GCOM-W data.
+     */
+    private static final class CSBuilder extends CoordSystemBuilder {
+        /**
+         * Creates a new UCAR coordinate system builder.
+         */
+        CSBuilder(final NetcdfDataset.Builder<?> dsb) {
+            super(dsb);
+        }
+
+        /**
+         * Applies {@link GCOM_W#roleOf GCOM-W} rules for determining which variables are
axes.
+         */
+        @Override
+        protected void identifyCoordinateAxes() {
+            for (final VarProcess vp : varList) {
+                if (!vp.isCoordinateVariable) {
+                    vp.isCoordinateVariable = GCOM_W.isCoordinateAxis(vp.vb.shortName);
+                }
+            }
+            super.identifyCoordinateAxes();
+        }
+
+        /**
+         * Identifies what kind of axis the given variable is.
+         * Only called for variables already identified as Coordinate Axes.
+         */
+        @Override
+        protected AxisType getAxisType(final VariableDS.Builder variable) {       // TODO:
add <?> with UCAR netCDF 6.
+            final AxisType type = super.getAxisType(variable);
+            if (type == null) {
+                final String name = variable.shortName;
+                if (CharSequences.startsWith(name, GCOM_W.LONGITUDE, true)) return AxisType.Lon;
+                if (CharSequences.startsWith(name, GCOM_W.LATITUDE,  true)) return AxisType.Lat;
+            }
+            return type;
+        }
+    }
+}
diff --git a/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/GCOM_W.java
b/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/GCOM_W.java
index 3410a54..b129195 100644
--- a/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/GCOM_W.java
+++ b/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/GCOM_W.java
@@ -32,6 +32,7 @@ import org.apache.sis.internal.netcdf.VariableRole;
 import org.apache.sis.internal.netcdf.Linearizer;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.operation.transform.TransferFunction;
+import org.apache.sis.util.CharSequences;
 
 
 /**
@@ -79,9 +80,14 @@ import org.apache.sis.referencing.operation.transform.TransferFunction;
  */
 public final class GCOM_W extends Convention {
     /**
+     * Name of the attribute to read for checking the sentinel value.
+     */
+    static final String SENTINEL_ATTRIBUTE = "PlatformShortName";
+
+    /**
      * Sentinel value to search in the {@code "PlatformShortName"} attribute for determining
if GCOM-W conventions apply.
      */
-    private static final Pattern SENTINEL_VALUE = Pattern.compile(".*\\bGCOM-W1\\b.*");
+    static final Pattern SENTINEL_VALUE = Pattern.compile(".*\\bGCOM-W1\\b.*");
 
     /**
      * Mapping from ACDD or CF-Convention attribute names to names of attributes used by
GCOM-W.
@@ -106,10 +112,7 @@ public final class GCOM_W extends Convention {
     /**
      * Names of variables to use as axes (first word only).
      */
-    private static final String[] AXES = {
-        "Latitude",
-        "Longitude"
-    };
+    static final String LATITUDE = "Latitude", LONGITUDE = "Longitude";
 
     /**
      * "No data" value to use when not specified in the file.
@@ -135,7 +138,7 @@ public final class GCOM_W extends Convention {
      */
     @Override
     protected boolean isApplicableTo(final Decoder decoder) {
-        final String s = decoder.stringValue("PlatformShortName");
+        final String s = decoder.stringValue(SENTINEL_ATTRIBUTE);
         return (s != null) && SENTINEL_VALUE.matcher(s).matches();
     }
 
@@ -153,6 +156,14 @@ public final class GCOM_W extends Convention {
     }
 
     /**
+     * Returns {@code true} if a variable of the given name is a coordinate axis.
+     */
+    static boolean isCoordinateAxis(final String name) {
+        return CharSequences.startsWith(name, LATITUDE,  true)
+            || CharSequences.startsWith(name, LONGITUDE, true);
+    }
+
+    /**
      * Returns whether the given variable is used as a coordinate system axis, a coverage
or something else.
      *
      * @param  variable  the variable for which to get the role, or {@code null}.
@@ -160,14 +171,10 @@ public final class GCOM_W extends Convention {
      */
     @Override
     public VariableRole roleOf(final Variable variable) {
-        VariableRole role = super.roleOf(variable);
+        final VariableRole role = super.roleOf(variable);
         if (role == VariableRole.COVERAGE) {
-            final String name = variable.getName();
-            for (final String c : AXES) {
-                if (name.regionMatches(true, 0, c, 0, c.length())) {
-                    role = VariableRole.AXIS;
-                    break;
-                }
+            if (isCoordinateAxis(variable.getName())) {
+                return VariableRole.AXIS;
             }
         }
         return role;
diff --git a/profiles/sis-japan-profile/src/main/resources/META-INF/services/ucar.nc2.dataset.spi.CoordSystemBuilderFactory
b/profiles/sis-japan-profile/src/main/resources/META-INF/services/ucar.nc2.dataset.spi.CoordSystemBuilderFactory
new file mode 100644
index 0000000..5922dbb
--- /dev/null
+++ b/profiles/sis-japan-profile/src/main/resources/META-INF/services/ucar.nc2.dataset.spi.CoordSystemBuilderFactory
@@ -0,0 +1 @@
+org.apache.sis.internal.earth.netcdf.FactoryForUCAR
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/CSBuilderFallback.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/CSBuilderFallback.java
deleted file mode 100644
index 581304e..0000000
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/CSBuilderFallback.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.internal.netcdf.ucar;
-
-import ucar.nc2.constants.AxisType;
-import ucar.nc2.dataset.NetcdfDataset;
-import ucar.nc2.dataset.CoordSysBuilder;
-import ucar.nc2.dataset.VariableEnhanced;
-import org.apache.sis.internal.netcdf.Convention;
-import org.apache.sis.internal.netcdf.Variable;
-import org.apache.sis.internal.netcdf.VariableRole;
-import org.apache.sis.util.CharSequences;
-
-
-/**
- * A UCAR coordinate system builder which uses Apache SIS mechanism for identifying
- * which variable may be an axis variable.
- *
- * <div class="note"><b>Note:</b>
- * this could could be registered as a {@link ucar.nc2.dataset.CoordSysBuilderIF} service
- * and automatically loaded by the UCAR library using {@link java.util.ServiceLoader}.
- * The UCAR library then invoke the following method by reflection:
- *
- * {@preformat java
- *     public static boolean isMine(NetcdfFile file) {…}
- * }
- *
- * However we rather create instances of this class explicitly when required in order to
- * avoid interfering with UCAR global configuration (users want to apply their own settings)
- * and because we need to specify the {@link DecoderWrapper}.</div>
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
- * @since   1.0
- * @module
- */
-final class CSBuilderFallback extends CoordSysBuilder {
-    /**
-     * The decoder for which to apply this fallback.
-     */
-    private final DecoderWrapper decoder;
-
-    /**
-     * Creates a new UCAR coordinate system builder for the given decoder.
-     */
-    CSBuilderFallback(final DecoderWrapper decoder) {
-        this.decoder = decoder;
-    }
-
-    /**
-     * Delegates to {@link Convention#roleOf(Variable)} in order to determine which variables
are axes.
-     */
-    @Override
-    protected void findCoordinateAxes(final NetcdfDataset ds) {
-        for (final VarProcess vp : varList) {
-            if (!vp.isCoordinateVariable) {
-                final VariableWrapper variable = decoder.getWrapperFor(vp.v);
-                if (variable.getRole() == VariableRole.AXIS) {
-                    vp.isCoordinateVariable = true;
-                }
-            }
-        }
-        super.findCoordinateAxes(ds);
-    }
-
-    /**
-     * Identifies what kind of axis the given variable is.
-     */
-    @Override
-    protected AxisType getAxisType(final NetcdfDataset ds, final VariableEnhanced variable)
{
-        final String name = variable.getShortName();
-        if (CharSequences.startsWith(name, "Longitude", true)) return AxisType.Lon;
-        if (CharSequences.startsWith(name, "Latitude",  true)) return AxisType.Lat;
-        return super.getAxisType(ds, variable);
-    }
-}
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 5a35fd3..720b880 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
@@ -43,7 +43,6 @@ import ucar.nc2.ft.DsgFeatureCollection;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.collection.TreeTable;
 import org.apache.sis.util.collection.TableColumn;
-import org.apache.sis.internal.netcdf.Convention;
 import org.apache.sis.internal.netcdf.Decoder;
 import org.apache.sis.internal.netcdf.Variable;
 import org.apache.sis.internal.netcdf.Dimension;
@@ -416,6 +415,9 @@ public final class DecoderWrapper extends Decoder implements CancelTask
{
     /**
      * Returns the Apache SIS wrapper for the given UCAR variable. The given variable shall
be non-null
      * and should be one of the variables wrapped by the instances returned by {@link #getVariables()}.
+     *
+     * @param  variable  the netCDF variable.
+     * @return the SIS variable wrapping the given netCDF variable.
      */
     final VariableWrapper getWrapperFor(final ucar.nc2.Variable variable) {
         for (VariableWrapper c : (VariableWrapper[]) getVariables()) {
@@ -470,25 +472,15 @@ public final class DecoderWrapper extends Decoder implements CancelTask
{
      * @throws IOException if an I/O operation was necessary but failed.
      */
     @Override
-    @SuppressWarnings({"ReturnOfCollectionOrArrayField", "null"})
+    @SuppressWarnings({"ReturnOfCollectionOrArrayField"})
     public Grid[] getGrids() throws IOException {
         if (geometries == null) {
-            List<CoordinateSystem> systems = null;
+            List<CoordinateSystem> systems = Collections.emptyList();
             if (file instanceof NetcdfDataset) {
                 final NetcdfDataset ds = (NetcdfDataset) file;
                 systems = ds.getCoordinateSystems();
-                /*
-                 * If the UCAR library does not see any coordinate system in the file, verify
if there is
-                 * a custom convention recognizing the axes. CSBuilderFallback uses the mechanism
defined
-                 * by Apache SIS for determining variable role.
-                 */
-                if (systems.isEmpty() && convention() != Convention.DEFAULT) {
-                    final CSBuilderFallback builder = new CSBuilderFallback(this);
-                    builder.buildCoordinateSystems(ds);
-                    systems = ds.getCoordinateSystems();
-                }
             }
-            geometries = new Grid[(systems != null) ? systems.size() : 0];
+            geometries = new Grid[systems.size()];
             for (int i=0; i<geometries.length; i++) {
                 geometries[i] = new GridWrapper(systems.get(i));
             }
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
index 0308091..805e00c 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/VariableWrapper.java
@@ -272,12 +272,11 @@ final class VariableWrapper extends org.apache.sis.internal.netcdf.Variable
{
          * the file. Note that those coordinate systems may have been set by the user.
          */
         if (variable instanceof VariableDS) {
-            final Grid[] grids = decoder.getGrids();    // Must be first for forcing some
UCAR CS constructions.
             final List<CoordinateSystem> systems = ((VariableDS) variable).getCoordinateSystems();
             if (!systems.isEmpty()) {
                 GridWrapper grid = null;
                 final String[] axisNames = decoder.convention().namesOfAxisVariables(this);
-                for (final Grid candidate : grids) {
+                for (final Grid candidate : decoder.getGrids()) {
                     final GridWrapper ordered = ((GridWrapper) candidate).forVariable(variable,
systems, axisNames);
                     if (ordered != null && (grid == null || ordered.getSourceDimensions()
> grid.getSourceDimensions())) {
                         grid = ordered;


Mime
View raw message