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 6f2b61e If a netCDF variable contains "flag_names" or "flag_meanings"
attribute, create categories for enumeration values instead than for the range
of quantitative values.
6f2b61e is described below
commit 6f2b61ef7e549ce2958139dcfa938d0126f2956f
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Thu Apr 18 16:15:53 2019 +0200
If a netCDF variable contains "flag_names" or "flag_meanings" attribute,
create categories for enumeration values instead than for the range of
quantitative values.
---
.../org/apache/sis/internal/netcdf/Convention.java | 8 ++---
.../apache/sis/internal/netcdf/RasterResource.java | 41 ++++++++++++++++++++--
.../org/apache/sis/internal/netcdf/Variable.java | 8 ++---
.../sis/internal/netcdf/impl/VariableInfo.java | 18 +++++-----
.../sis/internal/netcdf/ucar/VariableWrapper.java | 10 +++---
5 files changed, 61 insertions(+), 24 deletions(-)
diff --git
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java
index 17d8877..da1e979 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
@@ -320,7 +320,7 @@ public class Convention {
*
* Whether the returned range is a range of packed values or a range of
real values is ambiguous.
* An heuristic rule is documented in UCAR {@link
ucar.nc2.dataset.EnhanceScaleMissing} interface.
- * If both type of ranges are available, then this method should return
the range of packed value.
+ * If both types of range are available, then this method should return
the range of packed value.
* Otherwise if this method returns the range of real values, then that
range shall be an instance
* of {@link MeasurementRange} for allowing the caller to distinguish the
two cases.
*
@@ -428,9 +428,9 @@ public class Convention {
* The returned function will be a component of the {@link
org.apache.sis.coverage.SampleDimension}
* to be created for each variable.
*
- * <p>This method is invoked only if {@link #validRange(Variable)}
returned a non-null value.
- * Since a transfer function is assumed to exist in such case (even if
that function is identity),
- * this method shall never return {@code null}.</p>
+ * <p>This method is invoked in contexts where a transfer function is
assumed to exist, for example
+ * because {@link #validRange(Variable)} returned a non-null value.
Consequently this method shall
+ * never return {@code null}, but can return the identity function.</p>
*
* @param data the variable from which to determine the transfer
function.
* This is usually a variable containing raster data.
diff --git
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
index e384680..08ffea1 100644
---
a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
+++
b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/RasterResource.java
@@ -37,6 +37,7 @@ import org.apache.sis.coverage.grid.GridExtent;
import org.apache.sis.coverage.grid.GridCoverage;
import org.apache.sis.coverage.grid.GridGeometry;
import org.apache.sis.coverage.grid.GridDerivation;
+import org.apache.sis.storage.netcdf.AttributeNames;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.DataStoreContentException;
import org.apache.sis.storage.DataStoreReferencingException;
@@ -45,6 +46,7 @@ import org.apache.sis.math.MathFunctions;
import org.apache.sis.measure.MeasurementRange;
import org.apache.sis.measure.NumberRange;
import org.apache.sis.util.Numbers;
+import org.apache.sis.util.CharSequences;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.internal.jdk9.JDK9;
@@ -398,8 +400,8 @@ public final class RasterResource extends
AbstractGridResource implements Resour
* is used only as a fallback. We give precedence to the range
computed by Apache SIS instead than the range given
* by UCAR because we need the range of packed values instead than the
range of converted values.
*/
- NumberRange<?> range = band.getValidRange();
- if (range != null) {
+ NumberRange<?> range;
+ if (!createEnumeration(builder, band, index) && (range =
band.getValidRange()) != null) {
final MathTransform1D mt =
band.getTransferFunction().getTransform();
if (!mt.isIdentity() && range instanceof MeasurementRange<?>) {
/*
@@ -490,6 +492,41 @@ public final class RasterResource extends
AbstractGridResource implements Resour
}
/**
+ * Appends qualitative categories in the given builder for {@code
"flag_values"} or {@code "flag_masks"} attribute.
+ *
+ * @param builder the builder to use for creating the sample dimension.
+ * @param band the data for which to create a sample dimension.
+ * @param index index in the variable dimension identified by {@link
#bandDimension}.
+ * @return {@code true} if flag attributes have been found, or {@code
false} otherwise.
+ */
+ private static boolean createEnumeration(final SampleDimension.Builder
builder, final Variable band, final int index) {
+ Object[] names = band.getAttributeValues(AttributeNames.FLAG_NAMES,
false);
+ if (names.length == 0) {
+ names = band.getAttributeValues(AttributeNames.FLAG_MEANINGS,
false);
+ if (names.length == 0) return false;
+ }
+ Object[] values = band.getAttributeValues(AttributeNames.FLAG_VALUES,
true);
+ if (values.length == 0) {
+ values = band.getAttributeValues(AttributeNames.FLAG_MASKS, true);
+ if (values.length == 0) return false;
+ }
+ if (names.length == 1) {
+ names = CharSequences.split((CharSequence) names[0], ' ');
+ }
+ for (int i=0; i<values.length; i++) {
+ final Number value = (Number) values[i];
+ final CharSequence name;
+ if (i < names.length) {
+ name = (CharSequence) names[i];
+ } else {
+ name = Vocabulary.formatInternational(Vocabulary.Keys.Unnamed);
+ }
+ builder.addQualitative(name, value, value);
+ }
+ return true;
+ }
+
+ /**
* Loads a subset of the grid coverage represented by this resource.
*
* @param domain desired grid extent and resolution, or {@code null} for
reading the whole domain.
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 a0f9737..e2d74b8 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
@@ -799,15 +799,15 @@ public abstract class Variable extends NamedElement {
public abstract Collection<String> getAttributeNames();
/**
- * Returns the numeric type of the attribute of the given name, or {@code
null}
- * if the given attribute is not found or its value is not numeric.
+ * Returns the type of the attribute of the given name,
+ * or {@code null} if the given attribute is not found.
*
* @param attributeName the name of the attribute for which to get the
type.
- * @return type of the given attribute, or {@code null} if none or not
numeric.
+ * @return type of the given attribute, or {@code null} if the attribute
does not exist.
*
* @see #getDataType()
*/
- public abstract Class<? extends Number> getAttributeType(String
attributeName);
+ public abstract Class<?> getAttributeType(String attributeName);
/**
* Returns the sequence of values for the given attribute, or an empty
array if none.
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 1d58f8a..40e8fc6 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
@@ -176,6 +176,10 @@ final class VariableInfo extends Variable implements
Comparable<VariableInfo> {
*
* @see #isEnumeration()
* @see #meaning(int)
+ *
+ * @todo Need to be consistent with {@code VariableWrapper}. We could move
this field to {@link FeaturesInfo},
+ * or provides the same functionality in {@code VariableWrapper}.
Whatever solution is chosen,
+ * {@code RasterResource.createEnumeration(…)} needs to use the
mechanism common to both implementations.
*/
private final String[] meanings;
@@ -510,20 +514,16 @@ final class VariableInfo extends Variable implements
Comparable<VariableInfo> {
}
/**
- * Returns the numeric type of the attribute of the given name, or {@code
null}
- * if the given attribute is not found or its value is not numeric.
+ * Returns the type of the attribute of the given name,
+ * or {@code null} if the given attribute is not found.
*/
@Override
- @SuppressWarnings("unchecked")
- public Class<? extends Number> getAttributeType(final String
attributeName) {
+ public Class<?> getAttributeType(final String attributeName) {
final Object value = getAttributeValue(attributeName);
if (value != null) {
- Class<?> type = value.getClass();
+ final Class<?> type = value.getClass();
final Class<?> c = type.getComponentType();
- if (c != null) type = c;
- if (Number.class.isAssignableFrom(type)) {
- return (Class<? extends Number>) type;
- }
+ return (c != null) ? c : type;
}
return null;
}
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 74de8e9..39f25c1 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
@@ -298,13 +298,11 @@ final class VariableWrapper extends Variable {
}
/**
- * Returns the numeric type of the attribute of the given name, or {@code
null}
- * if the given attribute is not found or its value is not numeric.
- *
- * @see #getDataType()
+ * Returns the type of the attribute of the given name,
+ * or {@code null} if the given attribute is not found.
*/
@Override
- public Class<? extends Number> getAttributeType(final String
attributeName) {
+ public Class<?> getAttributeType(final String attributeName) {
final Attribute attribute = raw.findAttributeIgnoreCase(attributeName);
if (attribute != null) {
switch (attribute.getDataType()) {
@@ -314,6 +312,8 @@ final class VariableWrapper extends Variable {
case LONG: return Long.class;
case FLOAT: return Float.class;
case DOUBLE: return Double.class;
+ case STRING: return String.class;
+ default: return Object.class;
}
}
return null;