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 77c040a6fb43c6b1bb586305804ae4156444bf2f
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Mon Nov 12 19:44:30 2018 +0100
More progress toward decoding the CoordinateSystem from a netCDF file.
A side effect of this work is the introduction of ReferencingFactoryContainer, to be needed by various data store (not just netCDF).
---
.../sis/internal/metadata/AxisDirections.java | 35 ++++--
.../internal/referencing/CoordinateOperations.java | 5 +-
.../referencing/ReferencingFactoryContainer.java | 137 +++++++++++++++++++++
.../sis/internal/metadata/AxisDirectionsTest.java | 26 +++-
.../apache/sis/referencing/cs/HardCodedAxes.java | 2 +-
.../org/apache/sis/storage/geotiff/CRSBuilder.java | 77 ++----------
.../java/org/apache/sis/internal/netcdf/Axis.java | 104 +++++++++++-----
.../apache/sis/internal/netcdf/GridGeometry.java | 19 ++-
.../apache/sis/internal/netcdf/NamedElement.java | 51 +++-----
.../org/apache/sis/internal/netcdf/Resources.java | 6 +
.../sis/internal/netcdf/Resources.properties | 1 +
.../sis/internal/netcdf/Resources_fr.properties | 1 +
.../org/apache/sis/internal/netcdf/Variable.java | 38 +++++-
.../sis/internal/netcdf/impl/ChannelDecoder.java | 33 ++++-
.../sis/internal/netcdf/impl/GridGeometryInfo.java | 8 ++
.../sis/internal/netcdf/impl/VariableInfo.java | 16 +--
.../internal/netcdf/ucar/GridGeometryWrapper.java | 8 ++
.../sis/internal/netcdf/ucar/VariableWrapper.java | 15 +++
18 files changed, 418 insertions(+), 164 deletions(-)
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java
index fdff560..9ec0a20 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java
@@ -18,6 +18,7 @@ package org.apache.sis.internal.metadata;
import java.util.Map;
import java.util.HashMap;
+import java.util.Objects;
import javax.measure.Unit;
import javax.measure.quantity.Angle;
import org.opengis.annotation.UML;
@@ -39,7 +40,7 @@ import static org.apache.sis.util.CharSequences.*;
* Utilities methods related to {@link AxisDirection}.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.0
* @since 0.4
* @module
*/
@@ -485,9 +486,7 @@ public final class AxisDirections extends Static {
return -1;
}
while (--i > 0) { // Intentionally exclude 0.
- if (!absolute(subCS.getAxis(i).getDirection()).equals(
- absolute(cs.getAxis(i + dim).getDirection())))
- {
+ if (!isColinear(subCS.getAxis(i).getDirection(), cs.getAxis(i + dim).getDirection())) {
return -1;
}
}
@@ -496,6 +495,19 @@ public final class AxisDirections extends Static {
}
/**
+ * Returns whether the second axis is colinear with the first axis. This method returns {@code true}
+ * if the {@linkplain #absolute absolute} direction of the given directions are equal.
+ * For example "down" is considered colinear with "up".
+ *
+ * @param d1 the first axis direction to compare.
+ * @param d2 the second axis direction to compare.
+ * @return {@code true} if both directions are colinear.
+ */
+ public static boolean isColinear(final AxisDirection d1, final AxisDirection d2) {
+ return Objects.equals(absolute(d1), absolute(d2));
+ }
+
+ /**
* Searches for an axis direction having the given name in the specified list of directions.
* This method compares the given name with the name of each {@code AxisDirection} in a lenient way:
*
@@ -653,12 +665,12 @@ public final class AxisDirections extends Static {
* use "h" as the fallback for unknown vertical axis.
*/
if (UP.equals(direction)) {
- if (contains(name, "Gravity", false)) return "H";
- if (contains(name, "Elevation", false)) return "φ";
- if (contains(name, "Geocentric", false)) return "r";
- return "h";
+ if (Units.isAngular(unit)) return "α"; // Elevation angle
+ if (contains(name, "Gravity", false)) return "H"; // Gravity-related height
+ if (contains(name, "Geocentric", false)) return "r"; // Geocentric radius
+ return "h"; // Ellipsoidal height
} else if (DOWN.equals(direction)) {
- return "D"; // "Depth"
+ return "D"; // Depth
} else if (isGeocentric(direction)) {
// For GEOCENTRIC_X, GEOCENTRIC_Y or GEOCENTRIC_Z, just take the last letter.
final String dir = direction.name();
@@ -676,7 +688,8 @@ public final class AxisDirections extends Static {
/**
* Returns an axis direction for the given abbreviation. This method is (partially) the converse
* of {@link #suggestAbbreviation(String, AxisDirection, Unit)}. Current implementation does not
- * recognize all abbreviation generated by above method, but only the main ones.
+ * recognize all abbreviation generated by above method, but only the main ones. This method is
+ * defined here for making easier to maintain consistency with {@code suggestAbbreviation(…)}.
*
* @param abbreviation the abbreviation.
* @return axis direction for the given abbreviation, or {@code null} if unrecognized.
@@ -687,6 +700,7 @@ public final class AxisDirections extends Static {
}
final AxisDirection dir;
switch (abbreviation) {
+ default: dir = null; break;
case 'W': dir = AxisDirection.WEST; break;
case 'S': dir = AxisDirection.SOUTH; break;
case 'θ': case 'λ': case 'E': dir = AxisDirection.EAST; break;
@@ -694,7 +708,6 @@ public final class AxisDirections extends Static {
case 'R': case 'H': dir = AxisDirection.UP; break;
case 'D': dir = AxisDirection.DOWN; break;
case 'T': dir = AxisDirection.FUTURE; break;
- default: dir = null; break;
}
return dir;
}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/CoordinateOperations.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/CoordinateOperations.java
index 5bed02e..7d82422 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/CoordinateOperations.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/CoordinateOperations.java
@@ -17,7 +17,6 @@
package org.apache.sis.internal.referencing;
import java.util.Set;
-import java.util.Objects;
import java.util.Collections;
import javax.measure.UnitConverter;
import javax.measure.IncommensurableException;
@@ -229,9 +228,7 @@ compare: for (int i=0; i<dim; i++) {
do {
final long mask = Long.lowestOneBit(candidates);
final CoordinateSystemAxis src = source.getAxis(Long.numberOfTrailingZeros(mask));
- if (Objects.equals(AxisDirections.absolute(src .getDirection()),
- AxisDirections.absolute(axis.getDirection())))
- {
+ if (AxisDirections.isColinear(src.getDirection(), axis.getDirection())) {
try {
final UnitConverter c = src.getUnit().getConverterToAny(axis.getUnit());
final double minimum = axis.getMinimumValue();
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingFactoryContainer.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingFactoryContainer.java
new file mode 100644
index 0000000..470af80
--- /dev/null
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ReferencingFactoryContainer.java
@@ -0,0 +1,137 @@
+/*
+ * 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.referencing;
+
+import org.opengis.referencing.cs.CSFactory;
+import org.opengis.referencing.crs.CRSFactory;
+import org.opengis.referencing.datum.DatumFactory;
+import org.opengis.referencing.operation.MathTransformFactory;
+import org.opengis.referencing.operation.CoordinateOperationFactory;
+import org.apache.sis.internal.system.DefaultFactories;
+
+
+/**
+ * A container of factories frequently used together.
+ * This class may be temporary until we choose a dependency injection framework
+ * See <a href="https://issues.apache.org/jira/browse/SIS-102">SIS-102</a>.
+ *
+ * <p>This class is not thread safe. Synchronization, if needed, is caller's responsibility.</p>
+ *
+ * @author Martin Desruisseaux (IRD, Geomatys)
+ * @version 1.0
+ * @since 1.0
+ * @module
+ */
+public class ReferencingFactoryContainer {
+ /**
+ * The {@linkplain org.opengis.referencing.datum.Datum datum} factory.
+ * If null, then a default factory will be created only when first needed.
+ */
+ private DatumFactory datumFactory;
+
+ /**
+ * The {@linkplain org.opengis.referencing.cs.CoordinateSystem coordinate system} factory.
+ * If null, then a default factory will be created only when first needed.
+ */
+ private CSFactory csFactory;
+
+ /**
+ * The {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem coordinate reference system} factory.
+ * If null, then a default factory will be created only when first needed.
+ */
+ private CRSFactory crsFactory;
+
+ /**
+ * Factory for fetching operation methods and creating defining conversions.
+ * This is needed only for user-defined projected coordinate reference system.
+ */
+ private CoordinateOperationFactory operationFactory;
+
+ /**
+ * The {@linkplain org.opengis.referencing.operation.MathTransform math transform} factory.
+ * If null, then a default factory will be created only when first needed.
+ */
+ private MathTransformFactory mtFactory;
+
+ /**
+ * Creates a new instance for the default factories.
+ */
+ public ReferencingFactoryContainer() {
+ }
+
+ /**
+ * Returns the factory for creating datum, prime meridians and ellipsoids.
+ *
+ * @return the Datum factory (never {@code null}).
+ */
+ public final DatumFactory datumFactory() {
+ if (datumFactory == null) {
+ datumFactory = DefaultFactories.forBuildin(DatumFactory.class);
+ }
+ return datumFactory;
+ }
+
+ /**
+ * Returns the factory for creating coordinate systems and their axes.
+ *
+ * @return the Coordinate System factory (never {@code null}).
+ */
+ public final CSFactory csFactory() {
+ if (csFactory == null) {
+ csFactory = DefaultFactories.forBuildin(CSFactory.class);
+ }
+ return csFactory;
+ }
+
+ /**
+ * Returns the factory for creating coordinate reference systems.
+ *
+ * @return the Coordinate Reference System factory (never {@code null}).
+ */
+ public final CRSFactory crsFactory() {
+ if (crsFactory == null) {
+ crsFactory = DefaultFactories.forBuildin(CRSFactory.class);
+ }
+ return crsFactory;
+ }
+
+ /**
+ * Returns the factory for fetching operation methods and creating defining conversions.
+ * This is needed only for user-defined projected coordinate reference system.
+ * The factory is fetched when first needed.
+ *
+ * @return the Coordinate Operation factory (never {@code null}).
+ */
+ public final CoordinateOperationFactory operationFactory() {
+ if (operationFactory == null) {
+ operationFactory = CoordinateOperations.factory();
+ }
+ return operationFactory;
+ }
+
+ /**
+ * Returns the factory for creating parameterized transforms.
+ *
+ * @return the Math Transform factory (never {@code null}).
+ */
+ public final MathTransformFactory mtFactory() {
+ if (mtFactory == null) {
+ mtFactory = DefaultFactories.forBuildin(MathTransformFactory.class);
+ }
+ return mtFactory;
+ }
+}
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/internal/metadata/AxisDirectionsTest.java b/core/sis-referencing/src/test/java/org/apache/sis/internal/metadata/AxisDirectionsTest.java
index 3ceaad2..74c44d8 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/internal/metadata/AxisDirectionsTest.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/internal/metadata/AxisDirectionsTest.java
@@ -424,7 +424,7 @@ public final strictfp class AxisDirectionsTest extends TestCase {
assertEquals("Ω", AxisDirections.suggestAbbreviation("Spherical latitude", NORTH, Units.DEGREE));
assertEquals("h", AxisDirections.suggestAbbreviation("Ellipsoidal height", UP, Units.METRE));
assertEquals("H", AxisDirections.suggestAbbreviation("Gravity-related height", UP, Units.METRE));
- assertEquals("φ", AxisDirections.suggestAbbreviation("Elevation", UP, Units.METRE));
+ assertEquals("α", AxisDirections.suggestAbbreviation("Elevation", UP, Units.DEGREE));
assertEquals("r", AxisDirections.suggestAbbreviation("Geocentric radius", UP, Units.METRE));
assertEquals("r", AxisDirections.suggestAbbreviation("Distance", AWAY_FROM, Units.METRE));
assertEquals("θ", AxisDirections.suggestAbbreviation("Bearing", CLOCKWISE, Units.DEGREE));
@@ -451,6 +451,30 @@ public final strictfp class AxisDirectionsTest extends TestCase {
}
/**
+ * Tests {@link AxisDirections#fromAbbreviation(char)}.
+ * This tests reuse some of the case tested by {@link #testSuggestAbbreviation()}.
+ * The intent is to ensure that those two methods are consistent with each other.
+ *
+ * @since 1.0
+ */
+ @Test
+ public void testFromAbbreviation() {
+ assertEquals(EAST, AxisDirections.fromAbbreviation('λ'));
+ assertEquals(NORTH, AxisDirections.fromAbbreviation('φ'));
+ assertEquals(EAST, AxisDirections.fromAbbreviation('θ'));
+ assertEquals(NORTH, AxisDirections.fromAbbreviation('Ω'));
+ assertEquals(UP, AxisDirections.fromAbbreviation('h'));
+ assertEquals(UP, AxisDirections.fromAbbreviation('H'));
+ assertEquals(UP, AxisDirections.fromAbbreviation('r'));
+ assertEquals(DOWN, AxisDirections.fromAbbreviation('D'));
+ assertEquals(FUTURE, AxisDirections.fromAbbreviation('t'));
+ assertEquals(NORTH, AxisDirections.fromAbbreviation('N'));
+ assertEquals(SOUTH, AxisDirections.fromAbbreviation('S'));
+ assertEquals(EAST, AxisDirections.fromAbbreviation('E'));
+ assertEquals(WEST, AxisDirections.fromAbbreviation('W'));
+ }
+
+ /**
* Verifies that the abbreviations used in {@link HardCodedAxes} constants are consistent with the abbreviations
* suggested by {@link AxisDirections#suggestAbbreviation(String, AxisDirection, Unit)}. Note that a failure in
* this verification does not necessarily means that {@code suggestAbbreviation(…)} has a bug. It could also be
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/HardCodedAxes.java b/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/HardCodedAxes.java
index 562d740..a577586 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/HardCodedAxes.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/HardCodedAxes.java
@@ -415,7 +415,7 @@ public final strictfp class HardCodedAxes {
* This is part of an engineering spherical coordinate system
* (not to be confused with geodetic spherical coordinate system).
*/
- public static final DefaultCoordinateSystemAxis ELEVATION = create("Elevation", "φ",
+ public static final DefaultCoordinateSystemAxis ELEVATION = create("Elevation", "α",
AxisDirection.UP, Units.DEGREE, -90, +90, RangeMeaning.WRAPAROUND);
/**
diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
index b92011a..a54a54d 100644
--- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
+++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/CRSBuilder.java
@@ -38,7 +38,6 @@ import org.opengis.metadata.spatial.CellGeometry;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.parameter.ParameterNotFoundException;
import org.opengis.referencing.IdentifiedObject;
-import org.opengis.referencing.crs.CRSFactory;
import org.opengis.referencing.crs.GeocentricCRS;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
@@ -53,17 +52,15 @@ import org.opengis.referencing.datum.PrimeMeridian;
import org.opengis.referencing.datum.VerticalDatum;
import org.opengis.referencing.operation.Conversion;
import org.opengis.referencing.operation.CoordinateOperation;
-import org.opengis.referencing.operation.CoordinateOperationFactory;
import org.opengis.referencing.operation.OperationMethod;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.util.FactoryException;
import org.apache.sis.internal.geotiff.Resources;
import org.apache.sis.internal.metadata.WKTKeywords;
-import org.apache.sis.internal.referencing.CoordinateOperations;
import org.apache.sis.internal.referencing.NilReferencingObject;
import org.apache.sis.internal.referencing.ReferencingUtilities;
-import org.apache.sis.internal.system.DefaultFactories;
+import org.apache.sis.internal.referencing.ReferencingFactoryContainer;
import org.apache.sis.internal.util.Constants;
import org.apache.sis.internal.util.Utilities;
import org.apache.sis.internal.util.Numerics;
@@ -77,7 +74,6 @@ import org.apache.sis.referencing.cs.AxesConvention;
import org.apache.sis.referencing.cs.CoordinateSystems;
import org.apache.sis.referencing.crs.DefaultGeographicCRS;
import org.apache.sis.referencing.factory.GeodeticAuthorityFactory;
-import org.apache.sis.referencing.factory.GeodeticObjectFactory;
import org.apache.sis.io.TableAppender;
import org.apache.sis.util.iso.DefaultNameSpace;
import org.apache.sis.util.resources.Errors;
@@ -137,7 +133,7 @@ import static org.apache.sis.util.Utilities.equalsIgnoreMetadata;
* @since 0.8
* @module
*/
-final class CRSBuilder {
+final class CRSBuilder extends ReferencingFactoryContainer {
/**
* Number of {@code short} values in each GeoKey entry.
*/
@@ -217,27 +213,6 @@ final class CRSBuilder {
private GeodeticAuthorityFactory epsgFactory;
/**
- * Factory for creating geodetic objects from their components, or {@code null} if not yet fetched.
- * Constructing a CRS from its components requires parsing many {@link GeoKeys}.
- *
- * <div class="note"><b>Note:</b> we do not yet split this field into 3 separated fields for datums,
- * coordinate systems and coordinate reference systems objects because it is not needed with Apache SIS
- * implementation of those factories. However we may revisit this choice if we want to let the user specify
- * his own factories.</div>
- *
- * @see #objectFactory()
- */
- private GeodeticObjectFactory objectFactory;
-
- /**
- * Factory for fetching operation methods and creating defining conversions.
- * This is needed only for user-defined projected coordinate reference system.
- *
- * @see #operationFactory()
- */
- private CoordinateOperationFactory operationFactory;
-
- /**
* Name of the last object created. This is used by {@link #properties(Object)} for reusing existing instance
* if possible. This is useful in GeoTIFF files since the same name is used for different geodetic components,
* for example the datum and the ellipsoid.
@@ -302,37 +277,9 @@ final class CRSBuilder {
}
/**
- * Returns the factory for creating geodetic objects from their components.
- * The factory is fetched when first needed.
- *
- * @return the object factory (never {@code null}).
- * @see <a href="https://issues.apache.org/jira/browse/SIS-102">SIS-102</a>
- */
- private GeodeticObjectFactory objectFactory() {
- if (objectFactory == null) {
- objectFactory = DefaultFactories.forBuildin(CRSFactory.class, GeodeticObjectFactory.class);
- }
- return objectFactory;
- }
-
- /**
- * Returns the factory for fetching operation methods and creating defining conversions.
- * The factory is fetched when first needed.
- *
- * @return the operation factory (never {@code null}).
- * @see <a href="https://issues.apache.org/jira/browse/SIS-102">SIS-102</a>
- */
- private CoordinateOperationFactory operationFactory() {
- if (operationFactory == null) {
- operationFactory = CoordinateOperations.factory();
- }
- return operationFactory;
- }
-
- /**
* Returns a map with the given name associated to {@value org.opengis.referencing.IdentifiedObject#NAME_KEY}.
* The given name shall be either an instance of {@link String} or {@link Identifier}.
- * This is an helper method for creating geodetic objects with {@link #objectFactory}.
+ * This is an helper method for creating geodetic objects with {@link #crsFactory()}.
*/
private Map<String,?> properties(Object name) {
if (name == null) {
@@ -753,7 +700,7 @@ final class CRSBuilder {
if (crs == null) {
missingValue(GeoKeys.GeographicType);
} else {
- crs = objectFactory().createCompoundCRS(Collections.singletonMap(IdentifiedObject.NAME_KEY, crs.getName()), crs, vertical);
+ crs = crsFactory().createCompoundCRS(Collections.singletonMap(IdentifiedObject.NAME_KEY, crs.getName()), crs, vertical);
}
}
}
@@ -920,7 +867,7 @@ final class CRSBuilder {
* This is because the citation value is for the CRS (e.g. "WGS84") while the prime
* meridian names are very different (e.g. "Paris", "Madrid", etc).
*/
- return objectFactory().createPrimeMeridian(properties(names[PRIMEM]), longitude, unit);
+ return datumFactory().createPrimeMeridian(properties(names[PRIMEM]), longitude, unit);
}
break; // Default to Greenwich.
}
@@ -990,14 +937,14 @@ final class CRSBuilder {
double inverseFlattening = getAsDouble(GeoKeys.InvFlattening);
final Ellipsoid ellipsoid;
if (!Double.isNaN(inverseFlattening)) {
- ellipsoid = objectFactory().createFlattenedSphere(properties, semiMajor, inverseFlattening, unit);
+ ellipsoid = datumFactory().createFlattenedSphere(properties, semiMajor, inverseFlattening, unit);
} else {
/*
* If the inverse flattening factory was not defined, fallback on semi-major axis length.
* This is a less common way to define ellipsoid (the most common way uses flattening).
*/
final double semiMinor = getMandatoryDouble(GeoKeys.SemiMinorAxis);
- ellipsoid = objectFactory().createEllipsoid(properties, semiMajor, semiMinor, unit);
+ ellipsoid = datumFactory().createEllipsoid(properties, semiMajor, semiMinor, unit);
}
lastName = ellipsoid.getName();
return ellipsoid;
@@ -1076,7 +1023,7 @@ final class CRSBuilder {
String name = getOrDefault(names, DATUM);
final Ellipsoid ellipsoid = createEllipsoid(names, linearUnit);
final PrimeMeridian meridian = createPrimeMeridian(names, angularUnit);
- final GeodeticDatum datum = objectFactory().createGeodeticDatum(properties(name), ellipsoid, meridian);
+ final GeodeticDatum datum = datumFactory().createGeodeticDatum(properties(name), ellipsoid, meridian);
name = Utilities.toUpperCase(name, Characters.Filter.LETTERS_AND_DIGITS);
lastName = datum.getName();
try {
@@ -1249,7 +1196,7 @@ final class CRSBuilder {
if (!Units.DEGREE.equals(angularUnit)) {
cs = replaceAngularUnit(cs, angularUnit);
}
- final GeographicCRS crs = objectFactory().createGeographicCRS(properties(getOrDefault(names, GCRS)), datum, cs);
+ final GeographicCRS crs = crsFactory().createGeographicCRS(properties(getOrDefault(names, GCRS)), datum, cs);
lastName = crs.getName();
return crs;
}
@@ -1319,7 +1266,7 @@ final class CRSBuilder {
if (!Units.METRE.equals(linearUnit)) {
cs = replaceLinearUnit(cs, linearUnit);
}
- final GeocentricCRS crs = objectFactory().createGeocentricCRS(properties(getOrDefault(names, GCRS)), datum, cs);
+ final GeocentricCRS crs = crsFactory().createGeocentricCRS(properties(getOrDefault(names, GCRS)), datum, cs);
lastName = crs.getName();
return crs;
}
@@ -1458,7 +1405,7 @@ final class CRSBuilder {
if (!Units.METRE.equals(linearUnit)) {
cs = replaceLinearUnit(cs, linearUnit);
}
- final ProjectedCRS crs = objectFactory().createProjectedCRS(properties(name), baseCRS, projection, cs);
+ final ProjectedCRS crs = crsFactory().createProjectedCRS(properties(name), baseCRS, projection, cs);
lastName = crs.getName();
return crs;
}
@@ -1693,7 +1640,7 @@ final class CRSBuilder {
if (!Units.METRE.equals(unit)) {
cs = (VerticalCS) CoordinateSystems.replaceLinearUnit(cs, unit);
}
- return objectFactory().createVerticalCRS(properties(name), datum, cs);
+ return crsFactory().createVerticalCRS(properties(name), datum, cs);
}
default: {
return epsgFactory().createVerticalCRS(String.valueOf(epsg));
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
index a70e9e6..69ff891 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Axis.java
@@ -23,10 +23,11 @@ import java.util.HashMap;
import java.io.IOException;
import javax.measure.Unit;
import org.opengis.util.GenericName;
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.cs.CSFactory;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.apache.sis.internal.metadata.AxisDirections;
-import org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis;
import org.apache.sis.referencing.NamedIdentifier;
import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.storage.netcdf.AttributeNames;
@@ -51,7 +52,7 @@ import ucar.nc2.constants.CF;
* @since 0.3
* @module
*/
-public final class Axis {
+public final class Axis extends NamedElement {
/**
* The abbreviation, also used as a way to identify the axis type. Possible values are:
* <ul>
@@ -128,45 +129,47 @@ public final class Axis {
* @throws ArithmeticException if the size of an axis exceeds {@link Integer#MAX_VALUE}, or other overflow occurs.
*/
public Axis(final GridGeometry owner, final Variable axis, final AttributeNames.Dimension attributeNames,
- final char abbreviation, final String direction, final int[] sourceDimensions, final int[] sourceSizes)
+ char abbreviation, final String direction, final int[] sourceDimensions, final int[] sourceSizes)
throws IOException, DataStoreException
{
/*
- * Try to get the axis direction from one of the following sources, in preference order:
+ * Try to get the axis direction from one of the following sources,
+ * in preference order (unless an inconsistency is detected):
*
* 1) The "positive" attribute value, which can be "up" or "down".
* 2) The abbreviation, which indirectly tells us the axis type inferred by UCAR library.
* 3) The direction in unit of measurement formatted as "degrees east" or "degrees north".
*
- * Choice #1 is preferred because it tells us the direction of increasing values. By contrast,
- * choice #2 said nothing about that. However if we find an inconsistency between directions
- * inferred in those different ways, we give precedence to choices #2 and #3 in that order.
- * Choice #1 is not considered authoritative because it applies (in principle) to only one of axis.
+ * Choice #1 is preferred because it is the only one telling us the direction of increasing values.
+ * However if we find an inconsistency between directions inferred in those different ways, then we
+ * give precedence to choices #2 and #3 in that order. Choice #1 is not considered authoritative
+ * because it applies (in principle) only to vertical axis.
*/
AxisDirection dir = Types.forCodeName(AxisDirection.class, direction, false);
AxisDirection check = AxisDirections.fromAbbreviation(abbreviation);
- final boolean isSigned = (dir != null); // Whether is specify the direction of positive values.
+ final boolean isSigned = (dir != null); // Whether 'dir' takes in account the direction of positive values.
boolean isConsistent = true;
if (dir == null) {
dir = check;
} else if (check != null) {
- isConsistent = AxisDirections.absolute(dir).equals(check);
+ isConsistent = AxisDirections.isColinear(dir, check);
}
if (isConsistent) {
check = direction(axis.getUnitsString());
if (dir == null) {
dir = check;
} else if (check != null) {
- isConsistent = AxisDirections.absolute(dir).equals(AxisDirections.absolute(check));
+ isConsistent = AxisDirections.isColinear(dir, check);
}
}
if (!isConsistent) {
- // TODO: report a warning here.
+ axis.warning(owner.getClass(), "getAxes", // Caller of this constructor.
+ Resources.Keys.AmbiguousAxisDirection_4, axis.getFilename(), axis.getName(), dir, check);
if (isSigned) {
- dir = check;
- if (AxisDirections.isOpposite(check)) {
- dir = AxisDirections.opposite(dir);
+ if (AxisDirections.isOpposite(dir)) {
+ check = AxisDirections.opposite(check); // Apply the sign of 'dir' on 'check'.
}
+ dir = check;
}
}
this.direction = dir;
@@ -212,30 +215,69 @@ public final class Axis {
return null;
}
- private CoordinateSystemAxis toISO() {
- final String name = coordinates.getName().trim();
- final Map<String,Object> properties = new HashMap<>(4);
- properties.put(CoordinateSystemAxis.NAME_KEY, name);
+ /**
+ * Returns the name of this axis.
+ *
+ * @return the name of this element.
+ */
+ @Override
+ public final String getName() {
+ return coordinates.getName().trim();
+ }
+
+ /**
+ * Creates an ISO 19111 axis from the information stored in this netCDF axis.
+ *
+ * @param factory the factory to use for creating the coordinate system axis.
+ */
+ final CoordinateSystemAxis toISO(final CSFactory factory) throws FactoryException {
/*
- * Aliases (optional property)
+ * The axis name is stored without namespace, because the variable name in a netCDF file can be anything;
+ * this is not controlled vocabulary. However the standard name, if any, is stored with "NetCDF" namespace
+ * because this is controlled vocabulary.
*/
+ final String name = getName();
+ final Map<String,Object> properties = new HashMap<>(4);
+ properties.put(CoordinateSystemAxis.NAME_KEY, name); // Intentionally no namespace.
final List<GenericName> aliases = new ArrayList<>(2);
final String standardName = coordinates.getAttributeString(CF.STANDARD_NAME);
if (standardName != null) {
- aliases.add(new NamedIdentifier(Citations.NETCDF, standardName));
+ final NamedIdentifier std = new NamedIdentifier(Citations.NETCDF, standardName);
+ if (standardName.equals(name)) {
+ properties.put(CoordinateSystemAxis.NAME_KEY, std); // Store as primary name.
+ } else {
+ aliases.add(std); // Store as alias.
+ }
}
+ /*
+ * The long name is stored as an optional description of the primary name.
+ * It is also stored as an alias if not redundant with other names.
+ */
final String alt = coordinates.getAttributeString(CDM.LONG_NAME);
- if (alt != null && !alt.equals(standardName)) {
- aliases.add(new NamedIdentifier(Citations.NETCDF, alt));
+ if (alt != null && !similar(alt, name)) {
+ properties.put(org.opengis.metadata.Identifier.DESCRIPTION_KEY, alt); // Description associated to primary name.
+ if (!similar(alt, standardName)) {
+ aliases.add(new NamedIdentifier(null, alt)); // Additional alias.
+ }
}
- properties.put(CoordinateSystemAxis.ALIAS_KEY, aliases.toArray(new GenericName[aliases.size()]));
-
- String a = Character.toString(abbreviation).intern(); // TODO: need default value is zero.
- AxisDirection dir = direction;
- if (dir == null) {
- dir = AxisDirection.OTHER;
+ if (!aliases.isEmpty()) {
+ properties.put(CoordinateSystemAxis.ALIAS_KEY, aliases.toArray(new GenericName[aliases.size()]));
+ }
+ /*
+ * Axis abbreviation, direction and unit of measurement are mandatory.
+ * If any of them is null, creation of CoordinateSystemAxis is likely
+ * to fail with an InvalidGeodeticParameterException. But we let the
+ * factory to choose, in case users specify their own factory.
+ */
+ final Unit<?> unit = coordinates.getUnit();
+ final String abbr;
+ if (abbreviation != 0) {
+ abbr = Character.toString(abbreviation).intern();
+ } else if (direction != null && unit != null) {
+ abbr = AxisDirections.suggestAbbreviation(name, direction, unit);
+ } else {
+ abbr = null;
}
- Unit<?> unit = coordinates.getUnit(); // TODO: need default value if null.
- return new DefaultCoordinateSystemAxis(properties, a, dir, unit);
+ return factory.createCoordinateSystemAxis(properties, abbr, direction, unit);
}
}
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java
index 76b6518..9a8dc7c 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/GridGeometry.java
@@ -16,7 +16,13 @@
*/
package org.apache.sis.internal.netcdf;
+import java.util.Map;
+import java.util.HashMap;
import java.io.IOException;
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.cs.CSFactory;
+import org.opengis.referencing.cs.CoordinateSystem;
+import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.apache.sis.storage.DataStoreException;
@@ -31,7 +37,7 @@ import org.apache.sis.storage.DataStoreException;
* @since 0.3
* @module
*/
-public abstract class GridGeometry {
+public abstract class GridGeometry extends NamedElement {
/**
* The axes, created when first needed.
*
@@ -108,4 +114,15 @@ public abstract class GridGeometry {
* @throws ArithmeticException if the axis size exceeds {@link Integer#MAX_VALUE}, or other overflow occurs.
*/
protected abstract double coordinateForAxis(Variable axis, int j, int i) throws IOException, DataStoreException;
+
+ final CoordinateSystem createCoordinateSystem(final CSFactory factory) throws IOException, DataStoreException, FactoryException {
+ final Axis[] axes = getAxes();
+ final CoordinateSystemAxis[] csAxes = new CoordinateSystemAxis[axes.length];
+ for (int i=0; i<axes.length; i++) {
+ csAxes[i] = axes[i].toISO(factory);
+ }
+ final Map<String,Object> properties = new HashMap<>(4);
+ properties.put(CoordinateSystem.NAME_KEY, getName());
+ return factory.createEllipsoidalCS(null, csAxes[0], csAxes[1]);
+ }
}
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/NamedElement.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/NamedElement.java
index c11af8d..c835476 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/NamedElement.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/NamedElement.java
@@ -16,13 +16,8 @@
*/
package org.apache.sis.internal.netcdf;
-import java.util.AbstractList;
-import java.util.AbstractMap;
-import java.util.Locale;
-import java.util.Map;
-import org.apache.sis.internal.util.CollectionsExt;
-import org.apache.sis.util.logging.WarningListeners;
-import org.opengis.parameter.InvalidParameterCardinalityException;
+import org.apache.sis.util.Characters;
+import org.apache.sis.util.CharSequences;
/**
@@ -49,41 +44,25 @@ public abstract class NamedElement {
public abstract String getName();
/**
- * Creates a (<cite>name</cite>, <cite>element</cite>) mapping for the given array of elements.
- * If the name of an element is not all lower cases, then this method also adds an entry for the
- * lower cases version of that name in order to allow case-insensitive searches.
+ * Returns {@code true} if the given names are considered equals for the purpose of netCDF decoder.
+ * Two names are considered similar if they are equal ignoring case and characters that are not valid
+ * for an Unicode identifier.
*
- * <p>Code searching in the returned map shall ask for the original (non lower-case) name
- * <strong>before</strong> to ask for the lower-cases version of that name.</p>
- *
- * @param <E> the type of elements.
- * @param elements the elements to store in the map, or {@code null} if none.
- * @param namesLocale the locale to use for creating the "all lower cases" names.
- * @return a (<cite>name</cite>, <cite>element</cite>) mapping with lower cases entries where possible.
- * @throws InvalidParameterCardinalityException if the same name is used for more than one element.
+ * @param s1 the first characters sequence to compare, or {@code null}.
+ * @param s2 the second characters sequence to compare, or {@code null}.
+ * @return whether the two characters sequences are considered similar names.
*/
- public static <E extends NamedElement> Map<String,E> toCaseInsensitiveNameMap(final E[] elements, final Locale namesLocale) {
- return CollectionsExt.toCaseInsensitiveNameMap(new AbstractList<Map.Entry<String,E>>() {
- @Override
- public int size() {
- return elements.length;
- }
-
- @Override
- public Map.Entry<String,E> get(final int index) {
- final E e = elements[index];
- return new AbstractMap.SimpleImmutableEntry<>(e.getName(), e);
- }
- }, namesLocale);
+ protected static boolean similar(final CharSequence s1, final CharSequence s2) {
+ return CharSequences.equalsFiltered(s1, s2, Characters.Filter.UNICODE_IDENTIFIER, true);
}
/**
- * Returns the resources to use for warnings or error messages.
+ * Returns a string representation of this element. Current implementation returns only the element class and name.
*
- * @param listeners where the warnings are sent. Used for inferring the locale.
- * @return the resources for the locales specified by the given argument.
+ * @return string representation of this element for debugging purposes.
*/
- protected static Resources resources(final WarningListeners<?> listeners) {
- return Resources.forLocale(listeners != null ? listeners.getLocale() : null);
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "[\"" + getName() + "\"]";
}
}
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.java
index 7ddb3c8..ba8e2a9 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.java
@@ -59,6 +59,12 @@ public final class Resources extends IndexedResourceBundle {
}
/**
+ * NetCDF file “{0}” provides an ambiguous axis direction for variable “{1}”. It could be
+ * {2} or {3}.
+ */
+ public static final short AmbiguousAxisDirection_4 = 9;
+
+ /**
* Can not compute data location for “{1}” variable in the “{0}” netCDF file.
*/
public static final short CanNotComputeVariablePosition_2 = 6;
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.properties b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.properties
index 92f6c3f..e5e0e0c 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.properties
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.properties
@@ -19,6 +19,7 @@
# Resources in this file are for "sis-netcdf" usage only and should not be used by any other module.
# For resources shared by all modules in the Apache SIS project, see "org.apache.sis.util.resources" package.
#
+AmbiguousAxisDirection_4 = NetCDF file \u201c{0}\u201d provides an ambiguous axis direction for variable \u201c{1}\u201d. It could be {2}\u00a0or {3}.
CanNotComputeVariablePosition_2 = Can not compute data location for \u201c{1}\u201d variable in the \u201c{0}\u201d netCDF file.
CanNotUseUCAR = Can not use UCAR library for netCDF format. Fallback on Apache SIS implementation.
DimensionNotFound_3 = Dimension \u201c{2}\u201d declared by attribute \u201c{1}\u201d is not found in the \u201c{0}\u201d file.
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources_fr.properties b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources_fr.properties
index 78adf94..9731b7d 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources_fr.properties
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources_fr.properties
@@ -24,6 +24,7 @@
# U+202F NARROW NO-BREAK SPACE before ; ! and ?
# U+00A0 NO-BREAK SPACE before :
#
+AmbiguousAxisDirection_4 = Le fichier netCDF \u00ab\u202f{0}\u202f\u00bb fournit une direction d\u2019axe ambigu\u00eb pour la variable \u00ab\u202f{1}\u202f\u00bb. Elle pourrait \u00eatre {2}\u00a0ou {3}.
CanNotComputeVariablePosition_2 = Ne peut pas calculer la position des donn\u00e9es de la variable \u00ab\u202f{1}\u202f\u00bb dans le fichier netCDF \u00ab\u202f{0}\u202f\u00bb.
CanNotUseUCAR = Ne peut pas utiliser la biblioth\u00e8que de l\u2019UCAR pour le format netCDF. L\u2019impl\u00e9mentation de Apache SIS sera utilis\u00e9e \u00e0 la place.
DimensionNotFound_3 = La dimension \u00ab\u202f{2}\u202f\u00bb d\u00e9clar\u00e9e par l\u2019attribut \u00ab\u202f{1}\u202f\u00bb n\u2019a pas \u00e9t\u00e9 trouv\u00e9e dans le fichier \u00ab\u202f{0}\u202f\u00bb.
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 15840a2..3ba3ce4 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
@@ -17,12 +17,15 @@
package org.apache.sis.internal.netcdf;
import java.util.Collection;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
import java.io.IOException;
import java.awt.image.DataBuffer;
import javax.measure.Unit;
import javax.measure.format.ParserException;
import org.apache.sis.math.Vector;
import org.apache.sis.measure.Units;
+import org.apache.sis.internal.system.Modules;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.util.logging.WarningListeners;
import org.apache.sis.util.resources.Errors;
@@ -59,7 +62,7 @@ public abstract class Variable extends NamedElement {
/**
* Where to report warnings, if any.
*/
- protected final WarningListeners<?> listeners;
+ private final WarningListeners<?> listeners;
/**
* Creates a new variable.
@@ -71,6 +74,14 @@ public abstract class Variable extends NamedElement {
}
/**
+ * Returns the name of the netCDF file containing this variable, or {@code null} if unknown.
+ * This is used for information purpose only.
+ *
+ * @return name of the netCDF file containing this variable, or {@code null} if unknown.
+ */
+ public abstract String getFilename();
+
+ /**
* Returns the name of this variable, or {@code null} if none.
*
* @return the name of this variable, or {@code null}.
@@ -297,6 +308,31 @@ public abstract class Variable extends NamedElement {
public abstract Vector read(int[] areaLower, int[] areaUpper, int[] subsampling) throws IOException, DataStoreException;
/**
+ * Returns the resources to use for warnings or error messages.
+ *
+ * @return the resources for the locales specified by the given argument.
+ */
+ protected final Resources resources() {
+ return Resources.forLocale(listeners.getLocale());
+ }
+
+ /**
+ * Reports a warning to the listeners specified at construction time.
+ *
+ * @param caller the caller class to report, preferably a public class.
+ * @param method the caller method to report, preferable a public method.
+ * @param key one or {@link Resources.Keys} constants.
+ * @param arguments values to be formatted in the {@link java.text.MessageFormat} pattern.
+ */
+ protected final void warning(final Class<?> caller, final String method, final short key, final Object... arguments) {
+ final LogRecord record = resources().getLogRecord(Level.WARNING, key, arguments);
+ record.setLoggerName(Modules.NETCDF);
+ record.setSourceClassName(caller.getCanonicalName());
+ record.setSourceMethodName(method);
+ listeners.warning(record);
+ }
+
+ /**
* Returns a string representation of this variable for debugging purpose.
*
* @return a string representation of this variable.
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 d2fab63..47c18b1 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
@@ -36,6 +36,7 @@ import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.channels.ReadableByteChannel;
+import java.util.AbstractList;
import javax.measure.UnitConverter;
import javax.measure.IncommensurableException;
import javax.measure.format.ParserException;
@@ -282,7 +283,35 @@ public final class ChannelDecoder extends Decoder {
}
this.attributeMap = attributes;
this.variables = variables;
- this.variableMap = NamedElement.toCaseInsensitiveNameMap(variables, NAME_LOCALE);
+ this.variableMap = toCaseInsensitiveNameMap(variables);
+ }
+
+ /**
+ * Creates a (<cite>name</cite>, <cite>element</cite>) mapping for the given array of elements.
+ * If the name of an element is not all lower cases, then this method also adds an entry for the
+ * lower cases version of that name in order to allow case-insensitive searches.
+ *
+ * <p>Code searching in the returned map shall ask for the original (non lower-case) name
+ * <strong>before</strong> to ask for the lower-cases version of that name.</p>
+ *
+ * @param <E> the type of elements.
+ * @param elements the elements to store in the map, or {@code null} if none.
+ * @return a (<cite>name</cite>, <cite>element</cite>) mapping with lower cases entries where possible.
+ * @throws InvalidParameterCardinalityException if the same name is used for more than one element.
+ */
+ private static <E extends NamedElement> Map<String,E> toCaseInsensitiveNameMap(final E[] elements) {
+ return CollectionsExt.toCaseInsensitiveNameMap(new AbstractList<Map.Entry<String,E>>() {
+ @Override
+ public int size() {
+ return elements.length;
+ }
+
+ @Override
+ public Map.Entry<String,E> get(final int index) {
+ final E e = elements[index];
+ return new AbstractMap.SimpleImmutableEntry<>(e.getName(), e);
+ }
+ }, NAME_LOCALE);
}
/**
@@ -488,7 +517,7 @@ public final class ChannelDecoder extends Decoder {
}
dimensions[i] = new Dimension(name, length, isUnlimited);
}
- dimensionMap = Dimension.toCaseInsensitiveNameMap(dimensions, NAME_LOCALE);
+ dimensionMap = toCaseInsensitiveNameMap(dimensions);
return dimensions;
}
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridGeometryInfo.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridGeometryInfo.java
index 51df17c..100f8cd 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridGeometryInfo.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/GridGeometryInfo.java
@@ -90,6 +90,14 @@ final class GridGeometryInfo extends GridGeometry {
}
/**
+ * Returns a name for this grid geometry, for information purpose only.
+ */
+ @Override
+ public String getName() {
+ return getFilename();
+ }
+
+ /**
* Returns the number of dimensions of source coordinates in the <cite>"grid to CRS"</cite> conversion.
* This is the number of dimensions of the <em>grid</em>.
*/
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java
index a14bcaf..d11d376 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/VariableInfo.java
@@ -19,8 +19,6 @@ package org.apache.sis.internal.netcdf.impl;
import java.util.Map;
import java.util.Collection;
import java.util.Collections;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
import java.io.IOException;
import java.lang.reflect.Array;
import ucar.nc2.constants.CF;
@@ -29,7 +27,6 @@ import ucar.nc2.constants._Coordinate;
import org.apache.sis.internal.netcdf.DataType;
import org.apache.sis.internal.netcdf.Variable;
import org.apache.sis.internal.netcdf.Resources;
-import org.apache.sis.internal.system.Modules;
import org.apache.sis.internal.storage.io.ChannelDataInput;
import org.apache.sis.internal.storage.io.HyperRectangleReader;
import org.apache.sis.internal.storage.io.Region;
@@ -224,12 +221,8 @@ final class VariableInfo extends Variable implements Comparable<VariableInfo> {
final long actual = Integer.toUnsignedLong(size);
if (actual != expected) {
if (expected != 0) {
- final LogRecord record = resources(listeners).getLogRecord(Level.WARNING,
+ warning(ChannelDecoder.class, "readVariables", // Caller of this constructor.
Resources.Keys.MismatchedVariableSize_3, getFilename(), name, actual - expected);
- record.setLoggerName(Modules.NETCDF);
- record.setSourceClassName(ChannelDecoder.class.getName()); // Caller of this constructor.
- record.setSourceMethodName("readVariables");
- listeners.warning(record);
}
if (actual > offsetToNextRecord) {
offsetToNextRecord = actual;
@@ -317,7 +310,8 @@ final class VariableInfo extends Variable implements Comparable<VariableInfo> {
/**
* Returns the name of the netCDF file containing this variable, or {@code null} if unknown.
*/
- final String getFilename() {
+ @Override
+ public String getFilename() {
return (reader != null) ? reader.filename() : null;
}
@@ -574,7 +568,7 @@ final class VariableInfo extends Variable implements Comparable<VariableInfo> {
if (isUnlimited()) {
final int dataSize = reader.dataSize();
if (offsetToNextRecord < 0 || (offsetToNextRecord % dataSize) != 0) {
- throw new DataStoreContentException(resources(listeners)
+ throw new DataStoreContentException(resources()
.getString(Resources.Keys.CanNotComputeVariablePosition_2, getFilename(), name));
}
region.increaseStride(dimensions.length - 1, offsetToNextRecord / dataSize);
@@ -648,7 +642,7 @@ final class VariableInfo extends Variable implements Comparable<VariableInfo> {
* Returns the error message for an unknown data type.
*/
private String unknownType() {
- return resources(listeners).getString(Resources.Keys.UnsupportedDataType_3, getFilename(), name, dataType);
+ return resources().getString(Resources.Keys.UnsupportedDataType_3, getFilename(), name, dataType);
}
/**
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java
index 22c4324..9087dd3 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/GridGeometryWrapper.java
@@ -66,6 +66,14 @@ final class GridGeometryWrapper extends GridGeometry {
}
/**
+ * Returns a name for this grid geometry, for information purpose only.
+ */
+ @Override
+ public String getName() {
+ return netcdfCS.getName();
+ }
+
+ /**
* Returns the number of dimensions of source coordinates in the <cite>"grid to CRS"</cite> conversion.
* This is the number of dimensions of the <em>grid</em>.
*/
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 079690e..9d2496e 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
@@ -17,6 +17,7 @@
package org.apache.sis.internal.netcdf.ucar;
import java.util.List;
+import java.io.File;
import java.io.IOException;
import java.util.Collection;
import ucar.ma2.Array;
@@ -74,6 +75,20 @@ final class VariableWrapper extends Variable {
}
/**
+ * Returns the name of the netCDF file containing this variable, or {@code null} if unknown.
+ */
+ @Override
+ public String getFilename() {
+ if (variable instanceof ucar.nc2.Variable) {
+ String name = ((ucar.nc2.Variable) variable).getDatasetLocation();
+ if (name != null) {
+ return name.substring(Math.max(name.lastIndexOf('/'), name.lastIndexOf(File.separatorChar)) + 1);
+ }
+ }
+ return null;
+ }
+
+ /**
* Returns the name of this variable, or {@code null} if none.
*/
@Override
|