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 aeaadf2f05 GeoTIFF writer should throw an exception instead of logging
a warning when the CRS or the "grid to CRS" transform cannot be encoded.
aeaadf2f05 is described below
commit aeaadf2f05a610a22af587cc7581adf335f5f404
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Tue Dec 17 16:17:03 2024 +0100
GeoTIFF writer should throw an exception instead of logging a warning
when the CRS or the "grid to CRS" transform cannot be encoded.
---
.../apache/sis/storage/geotiff/GeoTiffStore.java | 6 +-
.../sis/storage/geotiff/writer/GeoEncoder.java | 115 +++++++++++----------
.../sis/storage/IncompatibleResourceException.java | 56 +++++++++-
.../sis/storage/base/WritableAggregateSupport.java | 2 +-
.../storage/base/WritableGridCoverageSupport.java | 6 +-
.../apache/sis/storage/esri/AsciiGridStore.java | 27 ++---
.../org/apache/sis/storage/esri/WritableStore.java | 4 +-
.../apache/sis/storage/image/WritableStore.java | 27 ++---
.../apache/sis/storage/geopackage/GpkgStore.java | 2 +-
9 files changed, 151 insertions(+), 94 deletions(-)
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/GeoTiffStore.java
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/GeoTiffStore.java
index 0c5cd17ce6..5dabda1abe 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/GeoTiffStore.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/GeoTiffStore.java
@@ -683,8 +683,8 @@ public class GeoTiffStore extends DataStore implements
Aggregate {
* @param metadata title, author and other information, or {@code null}
if none.
* @return the effectively added resource. Using this resource may cause
data to be reloaded.
* @throws ReadOnlyStorageException if this data store is read-only.
- * @throws DataStoreException if the given {@code image} has a property
which is not supported by this writer,
- * or if an error occurred while writing to the output stream.
+ * @throws IncompatibleResourceException if the given {@code image} has a
property which is not supported by this writer.
+ * @throws DataStoreException if an error occurred while writing to the
output stream.
*
* @since 1.5
*/
@@ -708,7 +708,7 @@ public class GeoTiffStore extends DataStore implements
Aggregate {
}
index = writer.imageIndex++;
} catch (RasterFormatException | ArithmeticException e) {
- throw new IncompatibleResourceException(cannotWrite(), e);
+ throw new IncompatibleResourceException(cannotWrite(),
e).addAspect("raster");
} catch (IOException e) {
throw new DataStoreException(cannotWrite(), e);
}
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/GeoEncoder.java
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/GeoEncoder.java
index a88c8b21d4..25536bca7b 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/GeoEncoder.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/GeoEncoder.java
@@ -34,6 +34,7 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.GeodeticCRS;
import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.crs.VerticalCRS;
+import org.opengis.referencing.crs.EngineeringCRS;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CartesianCS;
@@ -63,6 +64,7 @@ import org.apache.sis.referencing.privy.WKTKeywords;
import org.apache.sis.coverage.grid.GridGeometry;
import org.apache.sis.coverage.grid.PixelInCell;
import org.apache.sis.coverage.grid.IncompleteGridGeometryException;
+import org.apache.sis.storage.IncompatibleResourceException;
import org.apache.sis.storage.base.MetadataFetcher;
import org.apache.sis.storage.geotiff.base.UnitKey;
import org.apache.sis.storage.geotiff.base.GeoKeys;
@@ -223,26 +225,31 @@ public final class GeoEncoder {
* @throws ArithmeticException if a short value cannot be stored as an
unsigned 16 bits integer.
* @throws IncommensurableException if a measure uses an unexpected unit
of measurement.
* @throws IncompleteGridGeometryException if the grid geometry is
incomplete.
+ * @throws IncompatibleResourceException if the grid geometry cannot be
encoded.
*/
public void write(final GridGeometry grid, final MetadataFetcher<?>
metadata)
- throws FactoryException, IncommensurableException
+ throws FactoryException, IncommensurableException,
IncompatibleResourceException
{
citation = CollectionsExt.first(metadata.transformationDimension);
isPoint = CollectionsExt.first(metadata.cellGeometry) ==
CellGeometry.POINT;
gridToCRS = MathTransforms.getMatrix(grid.getGridToCRS(isPoint ?
PixelInCell.CELL_CENTER : PixelInCell.CELL_CORNER));
if (gridToCRS == null) {
-
warning(resources().getString(Resources.Keys.CanNotEncodeNonLinearModel), null);
+ String message =
resources().getString(Resources.Keys.CanNotEncodeNonLinearModel);
+ throw new
IncompatibleResourceException(message).addAspect("gridToCRS");
}
if (grid.isDefined(GridGeometry.CRS)) {
fullCRS = grid.getCoordinateReferenceSystem();
final CoordinateReferenceSystem crs =
CRS.getHorizontalComponent(fullCRS);
- if ((crs instanceof ProjectedCRS && writeCRS((ProjectedCRS) crs))
||
- (crs instanceof GeodeticCRS && writeCRS((GeodeticCRS) crs,
false)))
- {
+ if (crs instanceof ProjectedCRS) {
+ writeCRS((ProjectedCRS) crs);
writeCRS(CRS.getVerticalComponent(fullCRS, true));
- } else {
- unsupportedType(fullCRS);
+ } else if (crs instanceof GeodeticCRS) {
+ writeCRS((GeodeticCRS) crs, false);
+ writeCRS(CRS.getVerticalComponent(fullCRS, true));
+ } else if (fullCRS instanceof EngineeringCRS &&
ReferencingUtilities.getDimension(fullCRS) == 2) {
writeModelType(GeoCodes.userDefined);
+ } else {
+ throw unsupportedType(fullCRS);
}
} else {
writeModelType(GeoCodes.undefined);
@@ -270,8 +277,9 @@ public final class GeoEncoder {
*
* @param crs the CRS to write, or {@code null} if none.
* @throws FactoryException if an error occurred while fetching an EPSG
code.
+ * @throws IncompatibleResourceException if a unit of measurement cannot
be encoded.
*/
- private void writeCRS(final VerticalCRS crs) throws FactoryException {
+ private void writeCRS(final VerticalCRS crs) throws FactoryException,
IncompatibleResourceException {
if (crs != null) {
hasVerticalAxis = true;
if (writeEPSG(GeoKeys.Vertical, crs)) {
@@ -298,24 +306,25 @@ public final class GeoEncoder {
*
* @param crs the CRS to write.
* @param isBaseCRS whether to write the base CRS of a projected CRS.
- * @return whether this method has been able to write the CRS.
* @throws FactoryException if an error occurred while fetching an EPSG
code.
* @throws IncommensurableException if a measure uses an unexpected unit
of measurement.
+ * @throws IncompatibleResourceException if the <abbr>CRS</abbr> has an
incompatible property.
*/
- private boolean writeCRS(final GeodeticCRS crs, final boolean isBaseCRS)
throws FactoryException, IncommensurableException {
+ private void writeCRS(final GeodeticCRS crs, final boolean isBaseCRS)
+ throws FactoryException, IncommensurableException,
IncompatibleResourceException
+ {
final short type;
final CoordinateSystem cs = crs.getCoordinateSystem();
addUnits(UnitKey.ANGULAR, cs);
if (cs instanceof EllipsoidalCS) {
type = GeoCodes.ModelTypeGeographic;
} else if (isBaseCRS) {
-
warning(resources().getString(Resources.Keys.CanNotEncodeNonGeographicBase),
null);
- return false;
+ String message =
resources().getString(Resources.Keys.CanNotEncodeNonGeographicBase);
+ throw new IncompatibleResourceException(message).addAspect("crs");
} else if (cs instanceof CartesianCS) {
type = GeoCodes.ModelTypeGeocentric;
} else {
- unsupportedType(cs);
- return false;
+ throw unsupportedType(cs);
}
/*
* Start writing GeoTIFF keys for the geodetic CRS, potentially
followed by datum, prime meridian and ellipsoid
@@ -361,7 +370,6 @@ public final class GeoEncoder {
} else if (isBaseCRS) {
writeUnit(UnitKey.ANGULAR); // Map projection parameters
may need this unit.
}
- return true;
}
/**
@@ -371,23 +379,27 @@ public final class GeoEncoder {
* @return whether this method has been able to write the CRS.
* @throws FactoryException if an error occurred while fetching an EPSG or
GeoTIFF code.
* @throws IncommensurableException if a measure uses an unexpected unit
of measurement.
+ * @throws IncompatibleResourceException if the <abbr>CRS</abbr> has an
incompatible property.
*/
- private boolean writeCRS(final ProjectedCRS crs) throws FactoryException,
IncommensurableException {
- if (!writeCRS(crs.getBaseCRS(), true)) {
- return false;
- }
+ private boolean writeCRS(final ProjectedCRS crs)
+ throws FactoryException, IncommensurableException,
IncompatibleResourceException
+ {
+ writeCRS(crs.getBaseCRS(), true);
if (writeEPSG(GeoKeys.ProjectedCRS, crs)) {
writeName(GeoKeys.ProjectedCitation, null, crs);
addUnits(UnitKey.PROJECTED, crs.getCoordinateSystem());
final Conversion projection = crs.getConversionFromBase();
if (writeEPSG(GeoKeys.Projection, projection)) {
final var method = projection.getMethod();
- final short projCode = getGeoCode(method);
+ final short projCode = getGeoCode(0, method);
writeShort(GeoKeys.ProjMethod, projCode);
writeUnit(UnitKey.PROJECTED);
switch (projCode) {
- case GeoCodes.undefined:
missingValue(GeoKeys.ProjMethod); return true;
- case GeoCodes.userDefined: cannotEncode(0, name(method),
null); break;
+ case GeoCodes.userDefined: // Should not happen.
+ case GeoCodes.undefined: {
+ missingValue(GeoKeys.ProjMethod);
+ return true;
+ }
/*
* TODO: GeoTIFF requirement 27.4 said that
ProjectedCitationGeoKey shall be provided,
* But how? Using the same multiple-names convention ("GCS
Name") as for geodetic CRS?
@@ -400,12 +412,12 @@ public final class GeoEncoder {
RuntimeException cause = null;
final var descriptor = p.getDescriptor();
if (p instanceof ParameterValue<?>) {
- final short key = getGeoCode(descriptor);
+ final short key = getGeoCode(1, descriptor);
if (key != GeoCodes.undefined && key !=
GeoCodes.userDefined) {
final var pv = (ParameterValue<?>) p;
final UnitKey type =
UnitKey.ofProjectionParameter(key);
if (type == UnitKey.LINEAR) {
- continue; // Skip the "cannot
encode" warning.
+ continue; // Skip the "cannot
encode" error.
}
if (type != UnitKey.NULL) try {
final Unit<?> unit = units.getOrDefault(type,
type.defaultUnit());
@@ -416,7 +428,7 @@ public final class GeoEncoder {
}
}
}
- cannotEncode(1, name(descriptor), cause);
+ throw cannotEncode(1, name(descriptor), cause);
}
}
return true;
@@ -428,18 +440,20 @@ public final class GeoEncoder {
*
* @param main the main kind of units expected in the coordinate system.
* @param cs the coordinate system to analyze.
+ * @throws IncompatibleResourceException if the unit of measurement cannot
be encoded.
*/
- private void addUnits(final UnitKey main, final CoordinateSystem cs) {
+ private void addUnits(final UnitKey main, final CoordinateSystem cs)
throws IncompatibleResourceException {
for (int i = cs.getDimension(); --i >= 0;) {
final Unit<?> unit = cs.getAxis(i).getUnit();
final UnitKey type = main.validate(unit);
if (type != null) {
final Unit<?> previous = units.putIfAbsent(type, unit);
if (previous != null && !previous.equals(unit)) {
-
warning(errors().getString(Errors.Keys.HeterogynousUnitsIn_1, name(cs)), null);
+ String message =
errors().getString(Errors.Keys.HeterogynousUnitsIn_1, name(cs));
+ throw new
IncompatibleResourceException(message).addAspect("crs");
}
} else {
- cannotEncode(2, unit.toString(), null);
+ throw cannotEncode(2, unit.toString(), null).addAspect("unit");
}
}
}
@@ -449,8 +463,9 @@ public final class GeoEncoder {
* This method should be invoked only once per unit key.
*
* @param key identification of the unit to write.
+ * @throws IncompatibleResourceException if the unit of measurement cannot
be encoded.
*/
- private void writeUnit(final UnitKey key) {
+ private void writeUnit(final UnitKey key) throws
IncompatibleResourceException {
final Unit<?> unit = units.get(key);
if (unit != null) {
final short epsg = toShortEPSG(Units.getEpsgCode(unit,
key.isAxis));
@@ -460,7 +475,7 @@ public final class GeoEncoder {
writeShort(key.codeKey, epsg);
writeDouble(key.scaleKey, Units.toStandardUnit(unit));
} else {
- cannotEncode(2, unit.toString(), null);
+ throw cannotEncode(2, unit.toString(), null).addAspect("unit");
}
}
}
@@ -529,21 +544,26 @@ public final class GeoEncoder {
* Fetches the GeoTIFF code of the given object. If {@code null}, returns
{@link GeoCodes#undefined}.
* If the object has no GeTIFF identifier, returns {@value
GeoCodes#userDefined}.
*
+ * @param type object type: 0 = operation method, 1 = parameter.
* @param object the object for which to get the GeoTIFF code.
* @return the GeoTIFF code, or {@link GeoCodes#undefined} or {@link
GeoCodes#userDefined} if none.
* @throws FactoryException if an error occurred while fetching the
GeoTIFF code.
+ * @throws IncompatibleResourceException if the GeoTIFF identifier cannot
be obtained.
*/
- private short getGeoCode(final IdentifiedObject object) throws
FactoryException {
+ private short getGeoCode(final int type, final IdentifiedObject object)
+ throws FactoryException, IncompatibleResourceException
+ {
if (object == null) {
return GeoCodes.undefined;
}
final Identifier id = IdentifiedObjects.getIdentifier(object,
Citations.GEOTIFF);
+ NumberFormatException cause = null;
if (id != null) try {
return Short.parseShort(id.getCode());
} catch (NumberFormatException e) {
- warning(errors().getString(Errors.Keys.CanNotParse_1,
IdentifiedObjects.toString(id)), e);
+ cause = e;
}
- return GeoCodes.userDefined;
+ throw cannotEncode(type, name(object), cause);
}
/**
@@ -770,38 +790,29 @@ public final class GeoEncoder {
* @param key the GeoKey for which we found no value.
*/
private void missingValue(final short key) {
- warning(resources().getString(Resources.Keys.MissingGeoValue_1,
GeoKeys.name(key)), null);
+
listeners.warning(resources().getString(Resources.Keys.MissingGeoValue_1,
GeoKeys.name(key)));
}
/**
- * Logs a warning saying that the given object cannot be encoded becasuse
of its type.
+ * Prepares an exception saying that the given object cannot be encoded
because of its type.
*
* @param object object that cannot be encoded.
*/
- private void unsupportedType(final IdentifiedObject object) {
- warning(resources().getString(Resources.Keys.CanNotEncodeObjectType_1,
ReferencingUtilities.getInterface(object)), null);
+ private IncompatibleResourceException unsupportedType(final
IdentifiedObject object) {
+ String message =
resources().getString(Resources.Keys.CanNotEncodeObjectType_1,
ReferencingUtilities.getInterface(object));
+ return new IncompatibleResourceException(message).addAspect("crs");
}
/**
- * Logs a warning saying that an object of the given name cannot be
encoded.
+ * Prepares an exception saying that an object of the given name cannot be
encoded.
*
* @param type object type: 0 = operation method, 1 = parameter, 2 =
unit of measurement.
* @param name name of the object that cannot be encoded.
- * @param cause the reason why a warning occurred, or {@code null} if
none.
- */
- private void cannotEncode(final int type, final String name, final
Exception cause) {
-
warning(resources().getString(Resources.Keys.CanNotEncodeNamedObject_2, type,
name), cause);
- }
-
- /**
- * Reports a warning that occurred while analyzing the CRS.
- * This warning may prevent readers to reconstruct the CRS correctly.
- *
- * @param message the warning message.
- * @param cause the reason why a warning occurred, or {@code null} if
none.
+ * @param cause the reason why an error occurred, or {@code null} if
none.
*/
- private void warning(final String message, final Exception cause) {
- listeners.warning(message, cause);
+ private IncompatibleResourceException cannotEncode(final int type, final
String name, final Exception cause) {
+ String message =
resources().getString(Resources.Keys.CanNotEncodeNamedObject_2, type, name);
+ return new IncompatibleResourceException(message,
cause).addAspect("crs");
}
/**
diff --git
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/IncompatibleResourceException.java
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/IncompatibleResourceException.java
index 2c8a9288a0..4540cfe6f6 100644
---
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/IncompatibleResourceException.java
+++
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/IncompatibleResourceException.java
@@ -16,13 +16,18 @@
*/
package org.apache.sis.storage;
+import java.util.Set;
+
/**
* Thrown when a write operation cannot be performed because the resource to
write
* is incompatible with the data store.
+ * For example, the file format may have restrictions that prevent the
encoding of the coordinate
+ * reference system used by the resource. The {@link #getAspects()} method can
help to identify
+ * which aspects (class, <abbr>CRS</abbr>, <i>etc.</i>) are the causes of the
incompatibility.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.5
* @since 1.2
*/
public class IncompatibleResourceException extends DataStoreException {
@@ -31,6 +36,13 @@ public class IncompatibleResourceException extends
DataStoreException {
*/
private static final long serialVersionUID = -1833794980891065300L;
+ /**
+ * Identification of which aspects are incompatible, or {@code null} if
none.
+ * If non-null, this is usually a singleton set.
+ */
+ @SuppressWarnings("serial")
+ private Set<String> aspects;
+
/**
* Creates an exception with no cause and no details message.
*/
@@ -55,4 +67,46 @@ public class IncompatibleResourceException extends
DataStoreException {
public IncompatibleResourceException(String message, Throwable cause) {
super(message, cause);
}
+
+ /**
+ * Adds an identification of the aspect which is the cause of the
incompatibility.
+ * It should be the name of a property such as {@code "crs"} or {@code
"gridToCRS"}.
+ * See {@link #getAspects()} for a list of suggested values.
+ *
+ * @param name an identification of the aspect which is incompatible.
+ * @return {@code this} for method call chaining.
+ * @since 1.5
+ */
+ public IncompatibleResourceException addAspect(final String name) {
+ if (aspects == null) {
+ aspects = Set.of(name);
+ } else {
+ // Inefficient, but rarely used.
+ final int n = aspects.size();
+ String[] names = aspects.toArray(new String[n+1]);
+ names[n] = name;
+ aspects = Set.of(names);
+ }
+ return this;
+ }
+
+ /**
+ * Returns identifications of the aspects which are causes of the
incompatibility.
+ * Some values are:
+ *
+ * <ul>
+ * <li>{@code "class"}: the resources is not an instance of the
class expected by the writer.</li>
+ * <li>{@code "crs"}: the coordinate reference system cannot be
encoded.</li>
+ * <li>{@code "gridToCRS"}: the "grid to <abbr>CRS</abbr>" component
of the grid geometry of a raster cannot be encoded.</li>
+ * <li>{@code "gridGeometry"}: the grid geometry of a raster cannot be
encoded for reason less specific than {@code gridToCRS}.</li>
+ * <li>{@code "raster"}: the raster data cannot be encoded.</li>
+ * <li>{@code "unit"}: the unit of measurement cannot be
encoded.</li>
+ * </ul>
+ *
+ * @return identifications of aspects which are incompatible.
+ * @since 1.5
+ */
+ public Set<String> getAspects() {
+ return (aspects != null) ? aspects : Set.of();
+ }
}
diff --git
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/WritableAggregateSupport.java
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/WritableAggregateSupport.java
index 6e68cd3f6d..2752231cee 100644
---
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/WritableAggregateSupport.java
+++
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/WritableAggregateSupport.java
@@ -93,7 +93,7 @@ public final class WritableAggregateSupport implements
Localized {
if (Objects.requireNonNull(resource) instanceof GridCoverageResource) {
return (GridCoverageResource) resource;
}
- throw new
IncompatibleResourceException(message(GridCoverageResource.class, resource));
+ throw new
IncompatibleResourceException(message(GridCoverageResource.class,
resource)).addAspect("class");
}
/**
diff --git
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/WritableGridCoverageSupport.java
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/WritableGridCoverageSupport.java
index 37ad5a39a8..c9d27905c9 100644
---
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/WritableGridCoverageSupport.java
+++
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/WritableGridCoverageSupport.java
@@ -173,7 +173,7 @@ public final class WritableGridCoverageSupport implements
Localized {
*/
public final GridCoverage update(final GridCoverage coverage) throws
DataStoreException {
final GridCoverage existing = target.read(null, null);
- final CoverageCombiner combiner = new CoverageCombiner(existing);
+ final var combiner = new CoverageCombiner(existing);
try {
if (!combiner.acceptAll(coverage)) {
throw new ReadOnlyStorageException(canNotWrite());
@@ -196,14 +196,14 @@ public final class WritableGridCoverageSupport implements
Localized {
public final AffineTransform getAffineTransform2D(final GridExtent extent,
final MathTransform gridToCRS)
throws DataStoreException
{
- final TransformSeparator s = new TransformSeparator(gridToCRS);
+ final var s = new TransformSeparator(gridToCRS);
try {
s.addSourceDimensions(extent.getSubspaceDimensions(2));
return AffineTransforms2D.castOrCopy(s.separate());
} catch (FactoryException | CannotEvaluateException e) {
throw new DataStoreReferencingException(canNotWrite(), e);
} catch (IllegalArgumentException e) {
- throw new IncompatibleResourceException(canNotWrite(), e);
+ throw new IncompatibleResourceException(canNotWrite(),
e).addAspect("gridToCRS");
}
}
diff --git
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/AsciiGridStore.java
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/AsciiGridStore.java
index 222f869de2..f7de0e522a 100644
---
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/AsciiGridStore.java
+++
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/AsciiGridStore.java
@@ -65,48 +65,39 @@ import org.apache.sis.util.resources.Errors;
* <th>Keyword</th>
* <th>Value type</th>
* <th>Obligation</th>
- * </tr>
- * <tr>
+ * </tr><tr>
* <td>{@code NCOLS}</td>
* <td>{@link java.lang.Integer}</td>
* <td>Mandatory</td>
- * </tr>
- * <tr>
+ * </tr><tr>
* <td>{@code NROWS}</td>
* <td>{@link java.lang.Integer}</td>
* <td>Mandatory</td>
- * </tr>
- * <tr>
+ * </tr><tr>
* <td>{@code XLLCORNER} or {@code XLLCENTER}</td>
* <td>{@link java.lang.Double}</td>
* <td>Mandatory</td>
- * </tr>
- * <tr>
+ * </tr><tr>
* <td>{@code YLLCORNER} or {@code YLLCENTER}</td>
* <td>{@link java.lang.Double}</td>
* <td>Mandatory</td>
- * </tr>
- * <tr>
+ * </tr><tr>
* <td>{@code CELLSIZE}</td>
* <td>{@link java.lang.Double}</td>
* <td>Mandatory, unless an alternative below is present</td>
- * </tr>
- * <tr>
+ * </tr><tr>
* <td>{@code XCELLSIZE} and {@code YCELLSIZE}</td>
* <td>{@link java.lang.Double}</td>
* <td>Non-standard alternative to {@code CELLSIZE}</td>
- * </tr>
- * <tr>
+ * </tr><tr>
* <td>{@code XDIM} and {@code YDIM}</td>
* <td>{@link java.lang.Double}</td>
* <td>Non-standard alternative to {@code CELLSIZE}</td>
- * </tr>
- * <tr>
+ * </tr><tr>
* <td>{@code DX} and {@code DY}</td>
* <td>{@link java.lang.Double}</td>
* <td>Non-standard alternative to {@code CELLSIZE}</td>
- * </tr>
- * <tr>
+ * </tr><tr>
* <td>{@code NODATA_VALUE}</td>
* <td>{@link java.lang.Double}</td>
* <td>Optional</td>
diff --git
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/WritableStore.java
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/WritableStore.java
index 10c0247fa9..66ca6828ea 100644
---
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/WritableStore.java
+++
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/WritableStore.java
@@ -131,7 +131,7 @@ final class WritableStore extends AsciiGridStore implements
WritableGridCoverage
}
final AffineTransform at = h.getAffineTransform2D(gg.getExtent(),
gridToCRS);
if (at.getShearX() != 0 || at.getShearY() != 0) {
- throw new
IncompatibleResourceException(h.rotationNotSupported(AsciiGridStoreProvider.NAME));
+ throw new
IncompatibleResourceException(h.rotationNotSupported(AsciiGridStoreProvider.NAME)).addAspect("gridToCRS");
}
double scaleX = at.getScaleX();
double scaleY = -at.getScaleY();
@@ -144,7 +144,7 @@ final class WritableStore extends AsciiGridStore implements
WritableGridCoverage
* TODO: future version could support other signs, provided that
* we implement `PixelIterator` for other `SequenceType` values.
*/
- throw new IncompatibleResourceException(h.canNotWrite());
+ throw new
IncompatibleResourceException(h.canNotWrite()).addAspect("gridToCRS");
}
header.put(xll, x);
header.put(yll, y);
diff --git
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/WritableStore.java
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/WritableStore.java
index a55ac4c04a..cf94e852c2 100644
---
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/WritableStore.java
+++
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/WritableStore.java
@@ -151,9 +151,9 @@ class WritableStore extends WorldFileStore {
@Override
public String[] getImageFormat(final boolean asMimeType) {
if (writer != null) {
- final ImageWriterSpi provider = writer.getOriginatingProvider();
- if (provider != null) {
- final String[] names = asMimeType ? provider.getMIMETypes() :
provider.getFormatNames();
+ final ImageWriterSpi codec = writer.getOriginatingProvider();
+ if (codec != null) {
+ final String[] names = asMimeType ? codec.getMIMETypes() :
codec.getFormatNames();
if (names != null) {
return names;
}
@@ -223,8 +223,8 @@ class WritableStore extends WorldFileStore {
*/
if (index != MAIN_IMAGE || isMultiImages() > 1) {
if (!getGridGeometry(MAIN_IMAGE).equals(gg,
ComparisonMode.IGNORE_METADATA)) {
- throw new IncompatibleResourceException(
-
resources().getString(Resources.Keys.IncompatibleGridGeometry));
+ String message =
resources().getString(Resources.Keys.IncompatibleGridGeometry);
+ throw new
IncompatibleResourceException(message).addAspect("gridGeometry");
}
}
/*
@@ -236,17 +236,17 @@ class WritableStore extends WorldFileStore {
if (gg.isDefined(GridGeometry.GRID_TO_CRS)) try {
gridToCRS =
AffineTransforms2D.castOrCopy(gg.getGridToCRS(CELL_ANCHOR));
} catch (IllegalArgumentException e) {
- throw new IncompatibleResourceException(e.getLocalizedMessage(),
e);
+ throw new IncompatibleResourceException(e.getLocalizedMessage(),
e).addAspect("gridToCRS");
}
- final String suffix = super.setGridGeometry(index, gg); // May
throw `ArithmeticException`.
+ final String suffixWLD = super.setGridGeometry(index, gg); // May
throw `ArithmeticException`.
/*
* If the image is the main one, overwrite (possibly with same
content) the previous auxiliary files.
* Otherwise above checks should have ensured that the existing
auxiliary files are applicable.
*/
- if (suffix != null) {
+ if (suffixWLD != null) {
if (gridToCRS == null) {
- deleteAuxiliaryFile(suffix);
- } else try (BufferedWriter out = writeAuxiliaryFile(suffix)) {
+ deleteAuxiliaryFile(suffixWLD);
+ } else try (BufferedWriter out = writeAuxiliaryFile(suffixWLD)) {
writeCoeffs: for (int i=0;; i++) {
final double c;
switch (i) {
@@ -264,7 +264,7 @@ writeCoeffs: for (int i=0;; i++) {
}
writePRJ();
}
- return suffix;
+ return suffixWLD;
}
/**
@@ -311,7 +311,7 @@ writeCoeffs: for (int i=0;; i++) {
if (domain == null) {
domain = coverage.getGridGeometry(); // We are adding
the first image.
}
- final WritableResource image = new WritableResource(this,
listeners, numImages, domain);
+ final var image = new WritableResource(this, listeners, numImages,
domain);
image.write(coverage);
components.added(image); // Must be invoked only after
above succeeded.
numImages++;
@@ -335,7 +335,7 @@ writeCoeffs: for (int i=0;; i++) {
public synchronized void remove(final Resource resource) throws
DataStoreException {
Exception cause = null;
if (resource instanceof WritableResource) {
- final WritableResource image = (WritableResource) resource;
+ final var image = (WritableResource) resource;
if (image.store() == this) try {
final int imageIndex = image.getImageIndex();
writer().removeImage(imageIndex);
@@ -376,6 +376,7 @@ writeCoeffs: for (int i=0;; i++) {
*/
@Override
ImageReader prepareReader(ImageReader current) throws IOException {
+ @SuppressWarnings("LocalVariableHidesMemberVariable")
final ImageWriter writer = this.writer;
if (writer != null) {
final Object output = writer.getOutput();
diff --git
a/incubator/src/org.apache.sis.storage.geopackage/main/org/apache/sis/storage/geopackage/GpkgStore.java
b/incubator/src/org.apache.sis.storage.geopackage/main/org/apache/sis/storage/geopackage/GpkgStore.java
index ea4db47c69..dc3f7b2eaa 100644
---
a/incubator/src/org.apache.sis.storage.geopackage/main/org/apache/sis/storage/geopackage/GpkgStore.java
+++
b/incubator/src/org.apache.sis.storage.geopackage/main/org/apache/sis/storage/geopackage/GpkgStore.java
@@ -371,7 +371,7 @@ public class GpkgStore extends SQLStore implements
WritableAggregate {
* Note: Geopackage requires that each feature table has exactly one
geometry column,
* while SQLStore accepts any number of geometry columns (including
zero).
*/
- throw new IncompatibleResourceException("Unsupported resource type");
+ throw new IncompatibleResourceException("Unsupported resource
type").addAspect("class");
}
/**