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 edaef36 Prepare netCDF RasterResource to handle variables having
bands.
edaef36 is described below
commit edaef369de17532c0f0dd3e39762f84300fb4c3c
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Wed Mar 20 21:05:51 2019 +0100
Prepare netCDF RasterResource to handle variables having bands.
---
.../org/apache/sis/coverage/grid/GridExtent.java | 29 +++++++++-------
.../apache/sis/coverage/grid/GridExtentTest.java | 30 ++++++++++++----
.../main/java/org/apache/sis/util/ArraysExt.java | 30 ++++++++++------
.../java/org/apache/sis/internal/netcdf/Axis.java | 2 +-
.../org/apache/sis/internal/netcdf/Convention.java | 7 ++--
.../apache/sis/internal/netcdf/RasterResource.java | 40 +++++++++-------------
.../org/apache/sis/internal/netcdf/Variable.java | 28 ++++++++++++++-
.../sis/internal/storage/AbstractGridResource.java | 26 ++++++++++++--
.../org/apache/sis/internal/storage/Resources.java | 7 +++-
.../sis/internal/storage/Resources.properties | 5 +--
.../sis/internal/storage/Resources_fr.properties | 1 +
.../apache/sis/storage/GridCoverageResource.java | 7 ++--
12 files changed, 145 insertions(+), 67 deletions(-)
diff --git
a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
index 722623c..04af16a 100644
--- a/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
+++ b/core/sis-raster/src/main/java/org/apache/sis/coverage/grid/GridExtent.java
@@ -267,7 +267,7 @@ public class GridExtent implements Serializable {
*
* @see #getLow()
* @see #getHigh()
- * @see #append(DimensionNameType, long, long, boolean)
+ * @see #insert(int, DimensionNameType, long, long, boolean)
*/
public GridExtent(final DimensionNameType[] axisTypes, final long[] low,
final long[] high, final boolean isHighIncluded) {
ArgumentChecks.ensureNonNull("high", high);
@@ -824,8 +824,10 @@ public class GridExtent implements Serializable {
}
/**
- * Returns a new grid envelope with the specified dimension added after
this grid envelope dimensions.
+ * Returns a new grid envelope with the specified dimension inserted at
the given index in this grid envelope.
+ * To append a new dimension after all existing dimensions, set {@code
offset} to {@link #getDimension()}.
*
+ * @param offset where to insert the new dimension, from 0 to
{@link #getDimension()} inclusive.
* @param axisType the type of the grid axis to add, or {@code
null} if unspecified.
* @param low the valid minimum grid coordinate (always
inclusive).
* @param high the valid maximum grid coordinate, inclusive or
exclusive depending on the next argument.
@@ -835,26 +837,29 @@ public class GridExtent implements Serializable {
* @return a new grid envelope with the specified dimension added.
* @throws IllegalArgumentException if the low coordinate value is greater
than the high coordinate value.
*/
- public GridExtent append(final DimensionNameType axisType, final long low,
long high, final boolean isHighIncluded) {
+ public GridExtent insert(final int offset, final DimensionNameType
axisType, final long low, long high, final boolean isHighIncluded) {
+ final int dimension = getDimension();
+ ArgumentChecks.ensureBetween("offset", 0, dimension, offset);
if (!isHighIncluded) {
high = Math.decrementExact(high);
}
- final int dimension = getDimension();
- final int newDim = dimension + 1;
+ final int newDim = dimension + 1;
DimensionNameType[] axisTypes = null;
if (types != null || axisType != null) {
if (types != null) {
- axisTypes = Arrays.copyOf(types, newDim);
+ axisTypes = ArraysExt.insert(types, offset, 1);
} else {
axisTypes = new DimensionNameType[newDim];
}
- axisTypes[dimension] = axisType;
+ axisTypes[offset] = axisType;
}
final GridExtent ex = new GridExtent(newDim, axisTypes);
- System.arraycopy(coordinates, 0, ex.coordinates, 0,
dimension);
- System.arraycopy(coordinates, dimension, ex.coordinates, newDim,
dimension);
- ex.coordinates[dimension] = low;
- ex.coordinates[dimension + newDim] = high;
+ System.arraycopy(coordinates, 0, ex.coordinates, 0,
offset);
+ System.arraycopy(coordinates, offset, ex.coordinates,
offset + 1, dimension - offset);
+ System.arraycopy(coordinates, dimension, ex.coordinates,
newDim, offset);
+ System.arraycopy(coordinates, dimension + offset, ex.coordinates,
newDim + offset + 1, dimension - offset);
+ ex.coordinates[offset] = low;
+ ex.coordinates[offset + newDim] = high;
ex.validateCoordinates();
return ex;
}
@@ -935,7 +940,7 @@ public class GridExtent implements Serializable {
* The number of dimensions of the sub grid envelope will be {@code
dimensions.length}.
*
* <p>This method performs a <cite>dimensionality reduction</cite> and can
be used as the
- * converse of {@link #append(DimensionNameType, long, long, boolean)}.
+ * converse of {@link #insert(int, DimensionNameType, long, long,
boolean)}.
* This method can not be used for changing dimension order.</p>
*
* @param dimensions the dimensions to select, in strictly increasing
order.
diff --git
a/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridExtentTest.java
b/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridExtentTest.java
index 8d63d52..6687c45 100644
---
a/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridExtentTest.java
+++
b/core/sis-raster/src/test/java/org/apache/sis/coverage/grid/GridExtentTest.java
@@ -106,20 +106,36 @@ public final strictfp class GridExtentTest extends
TestCase {
}
/**
- * Tests {@link GridExtent#append(DimensionNameType, long, long, boolean)}.
+ * Tests {@link GridExtent#insert(int, DimensionNameType, long, long,
boolean)}
+ * with {@code offset} set to {@link GridExtent#getDimension()}.
*/
@Test
public void testAppend() {
+ appendOrInsert(2, 1);
+ }
+
+ /**
+ * Tests {@link GridExtent#insert(int, DimensionNameType, long, long,
boolean)}.
+ */
+ @Test
+ public void testInsert() {
+ appendOrInsert(1, 2);
+ }
+
+ /**
+ * Implementation of {@link #testAppend()} and {@link #testInsert()}.
+ */
+ private void appendOrInsert(final int offset, final int rowIndex) {
GridExtent extent = new GridExtent(new DimensionNameType[]
{DimensionNameType.COLUMN, DimensionNameType.ROW},
new long[] {100, 200}, new long[]
{500, 800}, true);
- extent = extent.append(DimensionNameType.TIME, 40, 50, false);
+ extent = extent.insert(offset, DimensionNameType.TIME, 40, 50, false);
assertEquals("dimension", 3, extent.getDimension());
- assertExtentEquals(extent, 0, 100, 500);
- assertExtentEquals(extent, 1, 200, 800);
- assertExtentEquals(extent, 2, 40, 49);
+ assertExtentEquals(extent, 0, 100, 500);
+ assertExtentEquals(extent, rowIndex, 200, 800);
+ assertExtentEquals(extent, offset, 40, 49);
assertEquals(DimensionNameType.COLUMN, extent.getAxisType(0).get());
- assertEquals(DimensionNameType.ROW, extent.getAxisType(1).get());
- assertEquals(DimensionNameType.TIME, extent.getAxisType(2).get());
+ assertEquals(DimensionNameType.ROW,
extent.getAxisType(rowIndex).get());
+ assertEquals(DimensionNameType.TIME,
extent.getAxisType(offset).get());
}
/**
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java
b/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java
index 0bfb01f..063e217 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/ArraysExt.java
@@ -628,8 +628,9 @@ public final class ArraysExt extends Static {
*
* @param <T> the array type.
* @param array array in which to insert spaces. Can be {@code null}
only if {@code length} is 0.
- * @param first index where the first space should be inserted. All
{@code array} elements
+ * @param first index where the first space will be inserted. All
{@code array} elements
* having an index equal to or higher than {@code index}
will be moved forward.
+ * Can be {@code array.length} for inserting spaces at the
end of the array.
* @param length number of spaces to insert.
* @return array containing the {@code array} elements with the additional
space inserted,
* or {@code array} (which may be null) if {@code length} is 0.
@@ -645,8 +646,9 @@ public final class ArraysExt extends Static {
return array; // May be null
}
ArgumentChecks.ensureNonNull ("array", array);
- ArgumentChecks.ensurePositive("length", length);
final int arrayLength = Array.getLength(array);
+ ArgumentChecks.ensureBetween("first", 0, arrayLength, first);
+ ArgumentChecks.ensurePositive("length", length);
@SuppressWarnings("unchecked")
final T newArray = (T)
Array.newInstance(array.getClass().getComponentType(), arrayLength + length);
System.arraycopy(array, 0, newArray, 0, first
);
@@ -662,8 +664,9 @@ public final class ArraysExt extends Static {
*
* @param <E> the type of array elements.
* @param array array in which to insert spaces. Can be {@code null}
only if {@code length} is 0.
- * @param first index where the first space should be inserted. All
{@code array} elements
+ * @param first index where the first space will be inserted. All
{@code array} elements
* having an index equal to or higher than {@code index}
will be moved forward.
+ * Can be {@code array.length} for inserting spaces at the
end of the array.
* @param length number of spaces to insert.
* @return array containing the {@code array} elements with the additional
space inserted,
* or {@code array} (which may be null) if {@code length} is 0.
@@ -687,8 +690,9 @@ public final class ArraysExt extends Static {
* Otherwise this method creates a new array. In every cases, the given
array is never modified.
*
* @param array array in which to insert spaces. Can be {@code null}
only if {@code length} is 0.
- * @param first index where the first space should be inserted. All
{@code array} elements
+ * @param first index where the first space will be inserted. All
{@code array} elements
* having an index equal to or higher than {@code index}
will be moved forward.
+ * Can be {@code array.length} for inserting spaces at the
end of the array.
* @param length number of spaces to insert.
* @return array containing the {@code array} elements with the additional
space inserted,
* or {@code array} (which may be null) if {@code length} is 0.
@@ -712,8 +716,9 @@ public final class ArraysExt extends Static {
* Otherwise this method creates a new array. In every cases, the given
array is never modified.
*
* @param array array in which to insert spaces. Can be {@code null}
only if {@code length} is 0.
- * @param first index where the first space should be inserted. All
{@code array} elements
+ * @param first index where the first space will be inserted. All
{@code array} elements
* having an index equal to or higher than {@code index}
will be moved forward.
+ * Can be {@code array.length} for inserting spaces at the
end of the array.
* @param length number of spaces to insert.
* @return array containing the {@code array} elements with the additional
space inserted,
* or {@code array} (which may be null) if {@code length} is 0.
@@ -737,8 +742,9 @@ public final class ArraysExt extends Static {
* Otherwise this method creates a new array. In every cases, the given
array is never modified.
*
* @param array array in which to insert spaces. Can be {@code null}
only if {@code length} is 0.
- * @param first index where the first space should be inserted. All
{@code array} elements
+ * @param first index where the first space will be inserted. All
{@code array} elements
* having an index equal to or higher than {@code index}
will be moved forward.
+ * Can be {@code array.length} for inserting spaces at the
end of the array.
* @param length number of spaces to insert.
* @return array containing the {@code array} elements with the additional
space inserted,
* or {@code array} (which may be null) if {@code length} is 0.
@@ -762,8 +768,9 @@ public final class ArraysExt extends Static {
* Otherwise this method creates a new array. In every cases, the given
array is never modified.
*
* @param array array in which to insert spaces. Can be {@code null}
only if {@code length} is 0.
- * @param first index where the first space should be inserted. All
{@code array} elements
+ * @param first index where the first space will be inserted. All
{@code array} elements
* having an index equal to or higher than {@code index}
will be moved forward.
+ * Can be {@code array.length} for inserting spaces at the
end of the array.
* @param length number of spaces to insert.
* @return array containing the {@code array} elements with the additional
space inserted,
* or {@code array} (which may be null) if {@code length} is 0.
@@ -812,8 +819,9 @@ public final class ArraysExt extends Static {
* Otherwise this method creates a new array. In every cases, the given
array is never modified.
*
* @param array array in which to insert spaces. Can be {@code null}
only if {@code length} is 0.
- * @param first index where the first space should be inserted. All
{@code array} elements
+ * @param first index where the first space will be inserted. All
{@code array} elements
* having an index equal to or higher than {@code index}
will be moved forward.
+ * Can be {@code array.length} for inserting spaces at the
end of the array.
* @param length number of spaces to insert.
* @return array containing the {@code array} elements with the additional
space inserted,
* or {@code array} (which may be null) if {@code length} is 0.
@@ -837,8 +845,9 @@ public final class ArraysExt extends Static {
* Otherwise this method creates a new array. In every cases, the given
array is never modified.
*
* @param array array in which to insert spaces. Can be {@code null}
only if {@code length} is 0.
- * @param first index where the first space should be inserted. All
{@code array} elements
+ * @param first index where the first space will be inserted. All
{@code array} elements
* having an index equal to or higher than {@code index}
will be moved forward.
+ * Can be {@code array.length} for inserting spaces at the
end of the array.
* @param length number of spaces to insert.
* @return array containing the {@code array} elements with the additional
space inserted,
* or {@code array} (which may be null) if {@code length} is 0.
@@ -862,8 +871,9 @@ public final class ArraysExt extends Static {
* Otherwise this method creates a new array. In every cases, the given
array is never modified.
*
* @param array array in which to insert spaces. Can be {@code null}
only if {@code length} is 0.
- * @param first index where the first space should be inserted. All
{@code array} elements
+ * @param first index where the first space will be inserted. All
{@code array} elements
* having an index equal to or higher than {@code index}
will be moved forward.
+ * Can be {@code array.length} for inserting spaces at the
end of the array.
* @param length number of spaces to insert.
* @return array containing the {@code array} elements with the additional
space inserted,
* or {@code array} (which may be null) if {@code length} is 0.
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 ca282a3..094f194 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
@@ -712,7 +712,7 @@ main: switch (getDimension()) {
* @throws DataStoreException if a logical error occurred.
*/
final Vector read() throws IOException, DataStoreException {
- final TransferFunction tr =
coordinates.decoder.convention().transferFunction(coordinates);
+ final TransferFunction tr = coordinates.getTransferFunction();
if (TransferFunctionType.LINEAR.equals(tr.getType())) {
Vector data = coordinates.read();
data = data.subList(0, getSizeProduct(0)); //
Trim trailing NaN values.
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 0dfac3b..d5f7625 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
@@ -195,13 +195,10 @@ public class Convention {
* to confuse them with images.</li>
* </ul>
*
- * @param variable the variable for which to get the role, or {@code
null}.
- * @return role of the given variable, or {@code null} if the given
variable was null.
+ * @param variable the variable for which to get the role.
+ * @return role of the given variable.
*/
public VariableRole roleOf(final Variable variable) {
- if (variable == null) {
- return null;
- }
if (variable.isCoordinateSystemAxis()) {
return VariableRole.AXIS;
}
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 fbbd463..dfeadf5 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
@@ -109,10 +109,17 @@ public final class RasterResource extends
AbstractGridResource implements Resour
/**
* The netCDF variable wrapped by this resource.
+ * The same variable may be repeated if one of its dimension shall be
interpreted as bands.
*/
private final Variable[] data;
/**
+ * If one of {@link #data} dimension provides values for different bands,
that dimension index.
+ * Otherwise -1.
+ */
+ private final int bandDimension;
+
+ /**
* Path to the netCDF file for information purpose, or {@code null} if
unknown.
*
* @see #getComponentFiles()
@@ -120,12 +127,6 @@ public final class RasterResource extends
AbstractGridResource implements Resour
private final Path location;
/**
- * Allows to fetch referencing information from source variables. It's
mostly useful for handling netCDF files
- * structured in ways different than CF-convention (for example GCOM,
<i>etc.</i>).
- */
- private final Convention convention;
-
- /**
* Creates a new resource. All variables in the {@code data} list shall
have the same domain and the same grid geometry.
*
* @param decoder the implementation used for decoding the netCDF file.
@@ -141,8 +142,8 @@ public final class RasterResource extends
AbstractGridResource implements Resour
ranges = new SampleDimension[data.length];
identifier = decoder.nameFactory.createLocalName(decoder.namespace,
name);
location = decoder.location;
- convention = decoder.convention();
gridGeometry = grid;
+ bandDimension = -1;
}
/**
@@ -159,7 +160,7 @@ public final class RasterResource extends
AbstractGridResource implements Resour
final List<Resource> resources = new ArrayList<>();
for (int i=0; i<variables.length; i++) {
final Variable variable = variables[i];
- if (decoder.convention().roleOf(variable) !=
VariableRole.COVERAGE) { // Variable may be null.
+ if (variable == null || variable.getRole() !=
VariableRole.COVERAGE) {
continue; //
Skip variables that are not grid coverages.
}
final GridGeometry grid = variable.getGridGeometry();
@@ -187,7 +188,7 @@ public final class RasterResource extends
AbstractGridResource implements Resour
int suffixLength = name.length() - suffixStart;
for (int j=i; ++j < variables.length;) {
final Variable candidate = variables[j];
- if (decoder.convention().roleOf(candidate) !=
VariableRole.COVERAGE) { // Variable may be null.
+ if (candidate == null || candidate.getRole() !=
VariableRole.COVERAGE) {
variables[j] = null;
// For avoiding to revisit that variable again.
continue;
}
@@ -287,12 +288,9 @@ 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 = convention.validRange(band);
- if (range == null) {
- range = band.getRangeFallback(); //
Fallback to UCAR library may happen here.
- }
+ NumberRange<?> range = band.getValidRange();
if (range != null) {
- final MathTransform1D mt =
convention.transferFunction(band).getTransform();
+ final MathTransform1D mt =
band.getTransferFunction().getTransform();
if (!mt.isIdentity() && range instanceof MeasurementRange<?>) {
/*
* Heuristic rule defined in UCAR documentation (see
EnhanceScaleMissing interface):
@@ -382,7 +380,7 @@ public final class RasterResource extends
AbstractGridResource implements Resour
*/
@Override
public GridCoverage read(GridGeometry domain, int... range) throws
DataStoreException {
- range = validateRangeArgument(data.length, range);
+ range = validateRangeArgument(ranges.length, range);
if (domain == null) {
domain = gridGeometry;
}
@@ -405,19 +403,15 @@ public final class RasterResource extends
AbstractGridResource implements Resour
/*
* Iterate over netCDF variables in the order they appear in the
file, not in the order requested
* by the 'range' argument. The intent is to perform sequential
I/O as much as possible, without
- * seeking backward.
+ * seeking backward. A side effect is that even if the same sample
dimension were requested many
+ * times, the data would still be loaded at most once.
*/
for (int i=0; i<data.length; i++) {
final Variable variable = data[i];
SampleDimension def = ranges[i];
Buffer values = null;
for (int j=0; j<range.length; j++) {
- /*
- * Check if the current variable is a sample dimension
specified in the 'range' argument.
- * Note that the same sample dimension may be requested an
arbitrary amount of time, but
- * the data will be loaded at most once.
- */
- if (range[j] == i) {
+ if (range[j] == i) { // Search sample
dimensions specified in the 'range' argument.
if (def == null) {
if (builder == null) builder = new
SampleDimension.Builder();
ranges[i] = def = createSampleDimension(builder,
variable);
@@ -448,7 +442,7 @@ public final class RasterResource extends
AbstractGridResource implements Resour
if (imageBuffer == null) {
throw new
DataStoreContentException(Errors.format(Errors.Keys.UnsupportedType_1,
dataType.name()));
}
- return new Raster(domain, UnmodifiableArrayList.wrap(selected),
imageBuffer, first.getName());
+ return new Raster(domain, UnmodifiableArrayList.wrap(selected),
imageBuffer, first.getStandardName());
}
/**
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 2d328cc..e28037b 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
@@ -29,6 +29,7 @@ import java.io.IOException;
import java.time.Instant;
import javax.measure.Unit;
import org.opengis.referencing.operation.Matrix;
+import org.apache.sis.referencing.operation.transform.TransferFunction;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.InternalDataStoreException;
import org.apache.sis.coverage.grid.GridGeometry;
@@ -149,7 +150,7 @@ public abstract class Variable extends NamedElement {
}
/**
- * Returns the name of this variable.
+ * Returns the name of this variable. May be used as sample dimension name
in a raster.
*
* @return the name of this variable.
*/
@@ -158,6 +159,7 @@ public abstract class Variable extends NamedElement {
/**
* Returns the standard name if available, or the long name other, or the
ordinary name otherwise.
+ * May be used as the label of a {@link Raster} as a whole (including all
bands).
*
* @return the standard name, or a fallback if there is no standard name.
*/
@@ -174,6 +176,7 @@ public abstract class Variable extends NamedElement {
/**
* Returns the description of this variable, or {@code null} if none.
+ * May be used as a category name in a sample dimension of a {@link
Raster}.
* This information may be encoded in different attributes like {@code
"description"}, {@code "title"},
* {@code "long_name"} or {@code "standard_name"}. If the return value is
non-null, then it should also
* be non-empty.
@@ -832,6 +835,22 @@ public abstract class Variable extends NamedElement {
}
/**
+ * Returns the range of valid values, or {@code null} if unknown. This is
a shortcut for
+ * {@link Convention#validRange(Variable)} with a fallback on {@link
#getRangeFallback()}.
+ *
+ * @return the range of valid values, or {@code null} if unknown.
+ *
+ * @see Convention#validRange(Variable)
+ */
+ final NumberRange<?> getValidRange() {
+ NumberRange<?> range = decoder.convention().validRange(this);
+ if (range == null) {
+ range = getRangeFallback();
+ }
+ return range;
+ }
+
+ /**
* Returns the range of values as determined by the data type or other
means, or {@code null} if unknown.
* This method is invoked only as a fallback if {@link
Convention#validRange(Variable)} did not found a
* range of values by application of CF conventions. The returned range
may be a range of packed values
@@ -908,6 +927,13 @@ public abstract class Variable extends NamedElement {
}
/**
+ * Builds the function converting values from their packed formats in the
variable to "real" values.
+ */
+ final TransferFunction getTransferFunction() {
+ return decoder.convention().transferFunction(this);
+ }
+
+ /**
* Reads all the data for this variable and returns them as an array of a
Java primitive type.
* Multi-dimensional variables are flattened as a one-dimensional array
(wrapped in a vector).
* Example:
diff --git
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractGridResource.java
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractGridResource.java
index 9d5cd02..1355db9 100644
---
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractGridResource.java
+++
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractGridResource.java
@@ -16,6 +16,7 @@
*/
package org.apache.sis.internal.storage;
+import java.util.BitSet;
import org.opengis.geometry.Envelope;
import org.apache.sis.storage.DataStore;
import org.apache.sis.storage.DataStoreException;
@@ -91,8 +92,12 @@ public abstract class AbstractGridResource extends
AbstractResource implements G
/**
* Validate the {@code range} argument given to {@link #read(GridGeometry,
int...)}.
- * This method verifies that all indices are between 0 and {@code
numSampleDimensions},
- * but does not verify if there is duplicated indices since such
duplication is allowed.
+ * This method verifies that all indices are between 0 and {@code
numSampleDimensions}
+ * and that there is no duplicated index.
+ *
+ * <p>On success, this method always returns a non-null array with the
same content than the user argument.
+ * The user specified array is not returned directly in order to allow the
caller to perform modifications,
+ * and also as a paranoiac safety against concurrent changes.</p>
*
* @param numSampleDimensions number of sample dimensions.
* @param range the {@code range} argument given by the user. May be
null or empty.
@@ -105,12 +110,29 @@ public abstract class AbstractGridResource extends
AbstractResource implements G
return ArraysExt.range(0, numSampleDimensions);
}
range = range.clone();
+ long previous = 0; // Cheap way to remember
previous dimensions.
+ BitSet extra = null; // Used only if there is
more than 64 dimensions.
for (int i=0; i<range.length; i++) {
final int r = range[i];
if (r < 0 || r >= numSampleDimensions) {
throw new
IllegalArgumentException(Resources.forLocale(getLocale()).getString(
Resources.Keys.InvalidSampleDimensionIndex_2, i,
numSampleDimensions - 1));
}
+ final boolean duplicated;
+ if (r < Long.SIZE) {
+ duplicated = (previous == (previous |= (1L << r)));
+ } else {
+ if (extra == null) {
+ extra = new BitSet();
+ }
+ final int j = r - Long.SIZE;
+ duplicated = extra.get(j);
+ extra.set(j);
+ }
+ if (duplicated) {
+ throw new
IllegalArgumentException(Resources.forLocale(getLocale()).getString(
+ Resources.Keys.DuplicatedSampleDimensionIndex_1, i));
+ }
}
return range;
}
diff --git
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java
index b3d2cb6..1fa0c5e 100644
---
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java
+++
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java
@@ -142,7 +142,7 @@ public final class Resources extends IndexedResourceBundle {
public static final short DataStoreEncoding = 29;
/**
- * Formating conventions of dates and numbers.
+ * Formatting conventions of dates and numbers.
*/
public static final short DataStoreLocale = 30;
@@ -167,6 +167,11 @@ public final class Resources extends IndexedResourceBundle
{
public static final short DirectoryContent_1 = 35;
/**
+ * Sample dimension index {0} is duplicated.
+ */
+ public static final short DuplicatedSampleDimensionIndex_1 = 53;
+
+ /**
* Character string in the “{0}” file is too long. The string has {2}
characters while the
* limit is {1}.
*/
diff --git
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties
index 616f8e9..3730a42 100644
---
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties
+++
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties
@@ -35,17 +35,18 @@ ConcurrentRead_1 = One or more read
operations are in progress
ConcurrentWrite_1 = A write operation is in progress in the
\u201c{0}\u201d data store.
DataStoreCreate = Whether to allow new data store creation
if the source to open does not already exist.
DataStoreEncoding = Character encoding used by the data store.
-DataStoreLocale = Formating conventions of dates and numbers.
+DataStoreLocale = Formatting conventions of dates and
numbers.
DataStoreLocation = Data store location as a file or URL.
DataStoreTimeZone = Timezone of dates in the data store.
DirectoryContent_1 = Content of \u201c{0}\u201d directory.
DirectoryContentFormatName = Name of the format to use for reading or
writing the directory content.
+DuplicatedSampleDimensionIndex_1 = Sample dimension index {0} is duplicated.
+ExcessiveStringSize_3 = Character string in the \u201c{0}\u201d
file is too long. The string has {2} characters while the limit is {1}.
FeatureAlreadyPresent_2 = A feature named \u201c{1}\u201d is already
present in the \u201c{0}\u201d data store.
FeatureNotFound_2 = Feature \u201c{1}\u201d has not been found
in the \u201c{0}\u201d data store.
FileAlreadyExists_2 = A {1,choice,0#file|1#directory} already
exists at \u201c{0}\u201d.
FileIsNotAResourceDirectory_1 = The \u201c{0}\u201d file is not a
directory of resources.
FoliationRepresentation = Whether to assemble trajectory fragments
(lines in CSV file) in a single feature instance.
-ExcessiveStringSize_3 = Character string in the \u201c{0}\u201d
file is too long. The string has {2} characters while the limit is {1}.
IllegalFeatureType_2 = The {0} data store does not accept
features of type \u201c{1}\u201d.
IllegalInputTypeForReader_2 = The {0} reader does not accept inputs of
type \u2018{1}\u2019.
IllegalOutputTypeForWriter_2 = The {0} writer does not accept outputs of
type \u2018{1}\u2019.
diff --git
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties
index f5f3739..f87a2d8 100644
---
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties
+++
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties
@@ -45,6 +45,7 @@ DataStoreLocation = Chemin (fichier ou URL)
vers la source de do
DataStoreTimeZone = Fuseau horaire des dates dans les
donn\u00e9es.
DirectoryContent_1 = Contenu du r\u00e9pertoire
\u00ab\u202f{0}\u202f\u00bb.
DirectoryContentFormatName = Nom du format ou de la source de
donn\u00e9es \u00e0 utiliser pour lire ou \u00e9crire le contenu du
r\u00e9pertoire.
+DuplicatedSampleDimensionIndex_1 = L\u2019index de dimension
d\u2019\u00e9chantillonnage {0} est r\u00e9p\u00e9t\u00e9.
ExcessiveStringSize_3 = La cha\u00eene de caract\u00e8res dans le
fichier \u00ab\u202f{0}\u202f\u00bb est trop longue. La cha\u00eene fait {2}
caract\u00e8res alors que la limite est {1}.
FeatureAlreadyPresent_2 = Une entit\u00e9 nomm\u00e9e
\u00ab\u202f{1}\u202f\u00bb est d\u00e9j\u00e0 pr\u00e9sente dans les
donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb.
FeatureNotFound_2 = L\u2019entit\u00e9
\u00ab\u202f{1}\u202f\u00bb n\u2019a pas \u00e9t\u00e9 trouv\u00e9e dans les
donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb.
diff --git
a/storage/sis-storage/src/main/java/org/apache/sis/storage/GridCoverageResource.java
b/storage/sis-storage/src/main/java/org/apache/sis/storage/GridCoverageResource.java
index fc632bd..b9f273b 100644
---
a/storage/sis-storage/src/main/java/org/apache/sis/storage/GridCoverageResource.java
+++
b/storage/sis-storage/src/main/java/org/apache/sis/storage/GridCoverageResource.java
@@ -90,9 +90,10 @@ public interface GridCoverageResource extends DataSet {
* <i>etc</i>. The general contract is that the returned coverage should
not contain less data than a coverage
* matching exactly the given geometry.
*
- * <p>The returned coverage shall contain the exact set of sample
dimensions specified by the {@code range}
- * argument, in the specified order. The "best-effort basis" flexibility
applies only to the grid geometry,
- * not to the range.</p>
+ * <p>The returned coverage shall contain the exact set of sample
dimensions specified by the {@code range} argument,
+ * in the specified order (the "best-effort basis" flexibility applies
only to the grid geometry, not to the range).
+ * All {@code range} values shall be between 0 inclusive and
<code>{@linkplain #getSampleDimensions()}.size()</code>
+ * exclusive, without duplicated values.</p>
*
* <p>While this method name suggests an immediate reading, some
implementations may defer the actual reading
* at a later stage.</p>