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 d73cf32be86..0fd1d733614 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 @@ -280,7 +280,7 @@ public VariableRole roleOf(final Variable variable) { * * @param data the variable for which the list of axis variables are desired, in CRS order. * @return names of the variables containing axis values, or {@code null} if this - * method performs applies no special convention for the given variable. + * method applies no special convention for the given variable. */ public String[] namesOfAxisVariables(Variable data) { return null; diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Dimension.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Dimension.java index daece51d0e2..26caff74c4d 100644 --- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Dimension.java +++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Dimension.java @@ -45,8 +45,9 @@ protected Dimension() { /** * Returns the name of this netCDF dimension. + * Note that dimensions in HDF5 files may be unnamed. * - * @return the name of this netCDF dimension. + * @return the name of this netCDF dimension, or {@code null} if unnamed. */ @Override public abstract String getName(); 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 9ac2622246e..2a0c9cb0b66 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 @@ -45,8 +45,9 @@ protected NamedElement() { /** * Returns the dimension, variable or attribute name. + * Note that dimensions in HDF5 files may be unnamed. * - * @return the name of this element. + * @return the name of this element, or {@code null} if unnamed. */ public abstract String getName(); 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 720b880d71f..bdb30934aca 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 @@ -58,7 +58,7 @@ * Provides netCDF decoding services based on the netCDF library. * * @author Martin Desruisseaux (Geomatys) - * @version 1.1 + * @version 1.2 * @since 0.3 * @module */ @@ -498,7 +498,7 @@ public Grid[] getGrids() throws IOException { @Override protected Dimension findDimension(final String dimName) { final ucar.nc2.Dimension dimension = file.findDimension(dimName); - return (dimension != null) ? new DimensionWrapper(dimension) : null; + return (dimension != null) ? new DimensionWrapper(dimension, -1) : null; } /** diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DimensionWrapper.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DimensionWrapper.java index fde99e45aa4..caa7c54f992 100644 --- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DimensionWrapper.java +++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/DimensionWrapper.java @@ -18,7 +18,8 @@ import java.util.List; import java.util.Collection; -import java.util.stream.Collectors; +import org.apache.sis.internal.util.UnmodifiableArrayList; +import org.apache.sis.util.ArraysExt; import ucar.nc2.Dimension; @@ -29,7 +30,7 @@ * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 1.1 + * @version 1.2 * @since 1.0 * @module */ @@ -38,7 +39,13 @@ final class DimensionWrapper extends org.apache.sis.internal.netcdf.Dimension { * Wraps all given dimensions. */ static List wrap(final Collection dimensions) { - return dimensions.stream().map(DimensionWrapper::new).collect(Collectors.toList()); + final DimensionWrapper[] wrappers = new DimensionWrapper[dimensions.size()]; + int i = 0; + for (final Dimension dim : dimensions) { + wrappers[i] = new DimensionWrapper(dim, i); + i++; + } + return UnmodifiableArrayList.wrap(ArraysExt.resize(wrappers, i)); } /** @@ -57,15 +64,27 @@ static Dimension[] unwrap(final org.apache.sis.internal.netcdf.Dimension[] dimen */ private final Dimension netcdf; + /** + * Index of the dimension in the variable, or -1 if unknown. Used during comparisons of + * dimensions that are private to a variable, because those dimensions may be unnamed. + * Consequently value -1 should be used only for shared dimensions. + * + * Issue #951 on netcdf-java + */ + private final int index; + /** * Wraps the given netCDF dimension object. */ - DimensionWrapper(final Dimension netcdf) { + DimensionWrapper(final Dimension netcdf, final int index) { this.netcdf = netcdf; + this.index = index; } /** - * Returns the name of this netCDF dimension. + * Returns the name of this netCDF dimension, or {@code null} if none. + * Should always be non-null if {@link Dimension#isShared()} is {@code true}, + * but may be null for non-shared dimensions (i.e. dimensions private to a variable). */ @Override public String getName() { @@ -91,22 +110,38 @@ protected boolean isUnlimited() { /** * Returns {@code true} if the given object represents the same dimension than this object. + * If the dimension is shared, then it has a unique name and {@link Dimension#equals(Object)} + * can distinguish dimensions based on their name. But if the dimension is private to a variable, + * then the dimension name can be null and the only remaining discriminant is the dimension length. + * A problem is that the length may by coincidence be the same for different dimensions. + * Consequently for non-shared dimensions we need to add {@link #index} in the comparison. * - * @param other the other object to compare with this dimension. + * @param obj the other object to compare with this dimension. * @return whether the other object wraps the same netCDF dimension than this object. */ @Override - public boolean equals(final Object other) { - return (other instanceof DimensionWrapper) && netcdf.equals(((DimensionWrapper) other).netcdf); + public boolean equals(final Object obj) { + if (obj instanceof DimensionWrapper) { + final DimensionWrapper other = (DimensionWrapper) obj; + if (netcdf.equals(other.netcdf)) { + return netcdf.isShared() || other.index == index; + } + } + return false; } /** * Returns a hash code value for this dimension. + * See {@link #equals(Object)} for a discussion about the use of {@link #index}. * * @return a hash code value. */ @Override public int hashCode() { - return ~netcdf.hashCode(); + int code = ~netcdf.hashCode(); + if (!netcdf.isShared()) { + code += 37 * index; + } + return code; } } diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/package-info.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/package-info.java index 105353e0405..533a1150d07 100644 --- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/package-info.java +++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/package-info.java @@ -20,7 +20,7 @@ * as wrappers around the UCAR netCDF library. * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 1.1 + * @version 1.2 * @since 0.3 * @module */