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 <[email protected]>
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;