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 f19ffb083d6471dcd4c99e6f10299e15b11db0f0
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Jan 8 12:13:38 2025 +0100

    Add clarification in documentations related to image operations.
    Update of the link to GeoTIFF specification in metadata, replacing OSGeo 
track by OGC web site.
    Add a `Strings.appendWithHeuristic(…)` internal method for some 
`toString()` implementations.
    The rest of this commit contains some usages of `var` in place of redundant 
type declarations.
---
 .../org/apache/sis/coverage/SampleRangeFormat.java |  6 +--
 .../apache/sis/coverage/grid/GridDerivation.java   | 19 +++----
 .../org/apache/sis/coverage/grid/GridExtent.java   | 30 +++++------
 .../org/apache/sis/coverage/grid/GridGeometry.java | 18 ++++---
 .../main/org/apache/sis/feature/FeatureFormat.java |  9 ++--
 .../main/org/apache/sis/image/ImageProcessor.java  |  5 +-
 .../main/org/apache/sis/metadata/sql/Citations.sql |  2 +-
 .../coverage/MultiResolutionCoverageLoader.java    |  2 +-
 .../sis/referencing/gazetteer/LocationFormat.java  |  7 ++-
 .../org/apache/sis/parameter/ParameterFormat.java  | 41 ++++++++-------
 .../apache/sis/referencing/GeodeticCalculator.java |  6 +--
 .../operation/builder/LinearTransformBuilder.java  | 25 ++++-----
 .../operation/builder/ProjectedTransformTry.java   |  6 +--
 .../sis/referencing/operation/gridded/Tile.java    |  6 +--
 .../projection/MercatorMethodComparison.java       | 10 ++--
 .../operation/transform/MathTransformTestCase.java |  2 +-
 .../sis/test/integration/ConsistencyTest.java      | 12 ++---
 .../sis/storage/geotiff/reader/CRSBuilder.java     |  4 +-
 .../main/org/apache/sis/storage/gpx/Metadata.java  | 10 ++--
 .../main/org/apache/sis/io/stream/Region.java      |  2 +-
 .../apache/sis/storage/GridCoverageResource.java   |  2 +-
 .../aggregate/ConcatenatedGridResource.java        |  2 +-
 .../main/org/apache/sis/io/TableAppender.java      |  7 +--
 .../main/org/apache/sis/io/TabularFormat.java      | 10 ++--
 .../main/org/apache/sis/math/StatisticsFormat.java |  9 ++--
 .../main/org/apache/sis/util/CharSequences.java    | 16 +++---
 .../sis/util/collection/TreeTableFormat.java       | 12 ++---
 .../org/apache/sis/util/privy/AbstractMap.java     |  8 +--
 .../main/org/apache/sis/util/privy/Strings.java    | 61 +++++++++++++++-------
 .../org/apache/sis/test/LogRecordCollector.java    |  2 +-
 .../apache/sis/gui/coverage/CoverageCanvas.java    |  4 +-
 31 files changed, 193 insertions(+), 162 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/SampleRangeFormat.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/SampleRangeFormat.java
index 0ffe6c4c12..bc7b36226e 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/SampleRangeFormat.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/SampleRangeFormat.java
@@ -171,7 +171,7 @@ final class SampleRangeFormat extends RangeFormat {
      * @return the range to write, or {@code null} if the given {@code range} 
argument was null.
      */
     private String formatMeasure(final Range<?> range) {
-        final NumberFormat nf = (NumberFormat) elementFormat;
+        final var nf  = (NumberFormat) elementFormat;
         final int min = nf.getMinimumFractionDigits();
         final int max = nf.getMaximumFractionDigits();
         final int ndigits = numFractionDigits[currentIndex];
@@ -206,8 +206,8 @@ final class SampleRangeFormat extends RangeFormat {
         /*
          * Write table header: │ Values │ Measures │ name │
          */
-        final StringBuilder buffer = new StringBuilder(800);
-        final TableAppender table = new TableAppender(buffer, " │ ");
+        final var buffer = new StringBuilder(800);
+        final var table = new TableAppender(buffer, " │ ");
         table.setMultiLinesCells(true);
         table.appendHorizontalSeparator();
         table.setCellAlignment(TableAppender.ALIGN_CENTER);
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridDerivation.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridDerivation.java
index 6d93ce4ea9..e7aae75227 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridDerivation.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridDerivation.java
@@ -433,13 +433,14 @@ public class GridDerivation {
 
     /**
      * Adapts the base grid for the geographic area and resolution of the 
given grid geometry.
-     * The new grid geometry will cover the spatiotemporal region given by 
{@code areaOfInterest} envelope
-     * (coordinate operations are applied as needed if the Coordinate 
Reference Systems are not the same).
-     * The new grid geometry resolution will be integer multiples of the 
{@link #base} grid geometry resolution.
+     * The new grid geometry will cover the intersection of the {@linkplain 
#base} grid geometry
+     * and the spatiotemporal region given by {@code areaOfInterest} envelope.
+     * Coordinate operations are applied as needed if the Coordinate Reference 
Systems are not the same.
+     * The new grid geometry resolution will be integer multiples of the 
{@linkplain #base} grid geometry resolution.
      *
      * <p>If {@code gridExtent} contains only an envelope, then this method 
delegates to {@link #subgrid(Envelope, double...)}.
-     * Otherwise if {@code gridExtent} contains only an extent, then this 
method delegates to {@link #subgrid(GridExtent, long...)}.
-     * Otherwise the following information are mandatory:</p>
+     * Otherwise, if {@code gridExtent} contains only an extent, then this 
method delegates to {@link #subgrid(GridExtent, long...)}.
+     * Otherwise, the following information are mandatory:</p>
      * <ul>
      *   <li>{@linkplain GridGeometry#getExtent() Extent} in {@code 
areaOfInterest}.</li>
      *   <li>{@linkplain GridGeometry#getGridToCRS(PixelInCell) Grid to CRS} 
conversion in {@code areaOfInterest}.</li>
@@ -571,10 +572,10 @@ public class GridDerivation {
 
     /**
      * Requests a grid geometry over a sub-envelope and optionally with a 
coarser resolution.
-     * The given envelope does not need to be expressed in the same coordinate 
reference system (CRS)
-     * than {@linkplain GridGeometry#getCoordinateReferenceSystem() the CRS of 
the base grid geometry};
-     * coordinate conversions or transformations will be applied as needed.
-     * That envelope CRS may have fewer dimensions than the base grid geometry 
CRS,
+     * The given envelope does not need to be expressed in the same coordinate 
reference system (<abbr>CRS</abbr>)
+     * than {@linkplain GridGeometry#getCoordinateReferenceSystem() the CRS} 
of the {@linkplain #base} grid geometry.
+     * Coordinate conversions or transformations will be applied as needed.
+     * That envelope <abbr>CRS</abbr> may have less dimensions than the 
<abbr>CRS</abbr> of the base grid geometry,
      * in which case grid dimensions not mapped to envelope dimensions will be 
returned unchanged.
      * The target resolution, if provided, shall be in same units and same 
order as the given envelope axes.
      * If the length of {@code resolution} array is less than the number of 
dimensions of {@code areaOfInterest},
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java
index a29bfa0ed6..52e333c2f2 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridExtent.java
@@ -976,7 +976,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
      * @since 1.3
      */
     public SortedMap<Integer,Long> getSliceCoordinates() {
-        final TreeMap<Integer,Long> slice = new TreeMap<>();
+        final var slice = new TreeMap<Integer,Long>();
         final int dimension = getDimension();
         for (int i=0; i<dimension; i++) {
             final long value = coordinates[i];
@@ -1214,7 +1214,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
             throw new IllegalArgumentException(Resources.format(
                     Resources.Keys.IllegalGridEnvelope_3, 
getAxisIdentification(index, index), low, high));
         }
-        final GridExtent copy = new GridExtent(this);
+        final var copy = new GridExtent(this);
         copy.coordinates[index] = low;
         copy.coordinates[ih] = high;
         return copy;
@@ -1275,7 +1275,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
      */
     final GeneralEnvelope toEnvelope() {
         final int dimension = getDimension();
-        final GeneralEnvelope envelope = new GeneralEnvelope(dimension);
+        final var envelope = new GeneralEnvelope(dimension);
         for (int i=0; i<dimension; i++) {
             long high = coordinates[i + dimension];
             if (high != Long.MAX_VALUE) high++;             // Make the 
coordinate exclusive before cast.
@@ -1432,7 +1432,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
             }
             axisTypes[index] = axisType;
         }
-        final GridExtent ex = new GridExtent(newDim, axisTypes);
+        final var ex = new GridExtent(newDim, axisTypes);
         System.arraycopy(coordinates, 0,                 ex.coordinates, 0,    
              index);
         System.arraycopy(coordinates, index,             ex.coordinates, index 
+ 1,          dimension - index);
         System.arraycopy(coordinates, dimension,         ex.coordinates, 
newDim,             index);
@@ -1506,7 +1506,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
                 tt[i] = types[indices[i]];
             }
         }
-        final GridExtent sub = new GridExtent(td, tt);
+        final var sub = new GridExtent(td, tt);
         for (int i=0; i<td; i++) {
             final int j = indices[i];
             sub.coordinates[i]    = coordinates[j];
@@ -1538,7 +1538,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
         if (isZero(margins, length)) {
             return this;
         }
-        final GridExtent resized = new GridExtent(this);
+        final var resized = new GridExtent(this);
         final long[] c = resized.coordinates;
         for (int i=0; i<length; i++) {
             final long p = margins[i];
@@ -1568,7 +1568,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
          */
         final int m = getDimension();
         final int length = Math.min(m, sizes.length);
-        final GridExtent resized = new GridExtent(this);
+        final var resized = new GridExtent(this);
         final long[] c = resized.coordinates;
         for (int i=0; i<length; i++) {
             final int s = sizes[i];
@@ -1606,7 +1606,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
     public GridExtent resize(final long... sizes) {
         final int m = getDimension();
         final int length = Math.min(m, sizes.length);
-        final GridExtent resize = new GridExtent(this);
+        final var resize = new GridExtent(this);
         final long[] c = resize.coordinates;
         for (int i=0; i<length; i++) {
             final long size = sizes[i];
@@ -1664,7 +1664,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
     public GridExtent subsample(final long... periods) {
         final int m = getDimension();
         final int length = Math.min(m, periods.length);
-        final GridExtent sub = new GridExtent(this);
+        final var sub = new GridExtent(this);
         for (int i=0; i<length; i++) {
             final long s = periods[i];
             if (s > 1) {
@@ -1725,7 +1725,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
     public GridExtent upsample(final long... periods) {
         final int m = getDimension();
         final int length = Math.min(m, periods.length);
-        final GridExtent sub = new GridExtent(this);
+        final var sub = new GridExtent(this);
         for (int i=0; i<length; i++) {
             final long s = periods[i];
             if (s > 1) {
@@ -1794,7 +1794,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
      * @throws PointOutsideCoverageException if the given point is outside the 
grid extent.
      */
     final GridExtent slice(final DirectPosition slicePoint, final int[] 
modifiedDimensions) {
-        final GridExtent slice = new GridExtent(this);
+        final var slice = new GridExtent(this);
         final int n = slicePoint.getDimension();
         final int m = getDimension();
         for (int k=0; k<n; k++) {
@@ -1807,7 +1807,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
                 if (c >= low && c <= high) {
                     slice.coordinates[i + m] = slice.coordinates[i] = c;
                 } else {
-                    final StringBuilder b = new StringBuilder();
+                    final var b = new StringBuilder();
                     for (int j=0; j<n; j++) {
                         if (j != 0) b.append(", ");
                         p = slicePoint.getCoordinate(j);
@@ -1890,7 +1890,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
         if (isZero(translation, length)) {
             return this;
         }
-        final GridExtent translated = new GridExtent(this);
+        final var translated = new GridExtent(this);
         final long[] c = translated.coordinates;
         for (int i=0; i < length; i++) {
             final int  j = i + m;
@@ -2110,7 +2110,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
      */
     @Override
     public String toString() {
-        final StringBuilder out = new StringBuilder(256);
+        final var out = new StringBuilder(256);
         try {
             appendTo(out, Vocabulary.forLocale(null));
         } catch (IOException e) {
@@ -2127,7 +2127,7 @@ public class GridExtent implements GridEnvelope, 
LenientComparable, Serializable
      * @param vocabulary  resources for some words.
      */
     final void appendTo(final Appendable out, final Vocabulary vocabulary) 
throws IOException {
-        final TableAppender table = new TableAppender(out, "");
+        final var table = new TableAppender(out, "");
         final int dimension = getDimension();
         for (int i=0; i<dimension; i++) {
             String name = null;
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
index 0d93ede5cf..e1160a4b26 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridGeometry.java
@@ -394,8 +394,10 @@ public class GridGeometry implements LenientComparable, 
Serializable {
          */
         @SuppressWarnings("LocalVariableHidesMemberVariable")
         ImmutableEnvelope envelope = other.envelope;            // We will 
share the same instance if possible.
-        ImmutableEnvelope computed = computeEnvelope(gridToCRS, 
getCoordinateReferenceSystem(envelope),
-                                                     toOther == null ? null : 
envelope);       // Clip.
+        ImmutableEnvelope computed = computeEnvelope(
+                gridToCRS,
+                getCoordinateReferenceSystem(envelope),
+                toOther == null ? null : envelope);             // Clip.
         if (computed == null || !computed.equals(envelope)) {
             envelope = computed;
         }
@@ -1826,7 +1828,7 @@ public class GridGeometry implements LenientComparable, 
Serializable {
             return true;
         }
         if (object instanceof GridGeometry) {
-            final GridGeometry that = (GridGeometry) object;
+            final var that = (GridGeometry) object;
             if ((mode != ComparisonMode.STRICT || 
getClass().equals(object.getClass()))
                     && Utilities.deepEquals(extent,    that.extent,    mode)
                     && Utilities.deepEquals(gridToCRS, that.gridToCRS, mode))
@@ -1853,7 +1855,7 @@ public class GridGeometry implements LenientComparable, 
Serializable {
      */
     final boolean equalsApproximately(final ImmutableEnvelope othenv) {
         if (envelope != null) {
-            for (int i=envelope.getDimension(); --i >= 0;) {
+            for (int i = envelope.getDimension(); --i >= 0;) {
                 // Arbitrary threshold of ½ pixel.
                 final double ε = (resolution != null) ? resolution[i] * 0.5 : 
0;
                 if (!MathFunctions.epsilonEqual(envelope.getLower(i), 
othenv.getLower(i), ε) ||
@@ -1927,7 +1929,7 @@ public class GridGeometry implements LenientComparable, 
Serializable {
     @Debug
     public TreeTable toTree(final Locale locale, final int bitmask) {
         ArgumentChecks.ensureNonNull("locale", locale);
-        final TreeTable tree = new DefaultTreeTable(TableColumn.VALUE_AS_TEXT);
+        final var tree = new DefaultTreeTable(TableColumn.VALUE_AS_TEXT);
         final TreeTable.Node root = tree.getRoot();
         root.setValue(TableColumn.VALUE_AS_TEXT, 
Classes.getShortClassName(this));
         formatTo(locale, Vocabulary.forLocale(locale), bitmask, root);
@@ -2051,8 +2053,8 @@ public class GridGeometry implements LenientComparable, 
Serializable {
             if (section(GEOGRAPHIC_EXTENT, Vocabulary.Keys.GeographicExtent, 
false, false) ||
                 section(TEMPORAL_EXTENT,   Vocabulary.Keys.TemporalExtent, 
false, false))
             {
-                final TableAppender table = new TableAppender(buffer, "  ");
-                final AngleFormat nf = new AngleFormat("DD°MM′SS″", locale);
+                final var table = new TableAppender(buffer, "  ");
+                final var nf = new AngleFormat("DD°MM′SS″", locale);
                 final GeographicBoundingBox bbox = ((bitmask & 
GEOGRAPHIC_EXTENT) != 0) ? geographicBBox() : null;
                 double westBoundLongitude = Double.NaN;
                 double eastBoundLongitude = Double.NaN;
@@ -2102,7 +2104,7 @@ public class GridGeometry implements LenientComparable, 
Serializable {
              */
             if (section(ENVELOPE, Vocabulary.Keys.Envelope, true, false)) {
                 final boolean appendResolution = (bitmask & RESOLUTION) != 0 
&& (resolution != null);
-                final TableAppender table = new TableAppender(buffer, "");
+                final var table = new TableAppender(buffer, "");
                 final int dimension = envelope.getDimension();
                 final NumberFormat nf = numberFormat();
                 for (int i=0; i<dimension; i++) {
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureFormat.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureFormat.java
index e9dcaebf52..a5e392d5c2 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureFormat.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureFormat.java
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.feature;
 
-import java.util.List;
 import java.util.ArrayList;
 import java.util.Set;
 import java.util.EnumSet;
@@ -374,7 +373,7 @@ public class FeatureFormat extends TabularFormat<Object> {
          * Create a table and format the header. Columns will be shown in 
Column enumeration order.
          */
         final Vocabulary resources = Vocabulary.forLocale(displayLocale);
-        final TableAppender table = new TableAppender(toAppendTo, 
columnSeparator);
+        final var table = new TableAppender(toAppendTo, columnSeparator);
         table.setMultiLinesCells(true);
         table.nextLine('─');
         boolean isFirstColumn = true;
@@ -396,9 +395,9 @@ public class FeatureFormat extends TabularFormat<Object> {
          * a row has no value, it will be skipped if and only if that row is 
optional (minimum occurrence
          * of zero).
          */
-        final StringBuffer  buffer  = new StringBuffer();
-        final FieldPosition dummyFP = new FieldPosition(-1);
-        final List<String>  remarks = new ArrayList<>();
+        final var buffer  = new StringBuffer();
+        final var dummyFP = new FieldPosition(-1);
+        final var remarks = new ArrayList<String>();
         for (final PropertyType propertyType : 
featureType.getProperties(true)) {
             Object value = null;
             int cardinality = -1;
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageProcessor.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageProcessor.java
index 75c8916030..d3cef1538e 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageProcessor.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageProcessor.java
@@ -1058,11 +1058,14 @@ public class ImageProcessor implements Cloneable {
     /**
      * Reformats the given image with a different sample model.
      * This operation <em>copies</em> the pixel values in a new image.
-     * Despite the copies being done on a tile-by-tile basis when each tile is 
 first requested,
+     * Despite the copies being done on a tile-by-tile basis when each tile is 
first requested,
      * this is still a relatively costly operation compared to the usual 
Apache <abbr>SIS</abbr>
      * approach of creating views as much as possible. Therefore, this method 
should be used only
      * when necessary.
      *
+     * <h4>Preconditions</h4>
+     * The new sample model shall have the same number of bands as in the 
given image.
+     *
      * <h4>Properties used</h4>
      * This operation uses the following properties in addition to method 
parameters:
      * <ul>
diff --git 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/Citations.sql
 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/Citations.sql
index 7dd4abb1c4..d0c3f8e541 100644
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/Citations.sql
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/Citations.sql
@@ -37,7 +37,7 @@ INSERT INTO metadata."OnlineResource" ("ID", "linkage") VALUES
   ('EPSG',    'https://epsg.org/'),
   ('ESRI',    'https://www.esri.com/'),
   ('GDAL',    'https://gdal.org/'),
-  ('GeoTIFF', 'https://trac.osgeo.org/geotiff/'),
+  ('GeoTIFF', 'https://www.ogc.org/publications/standard/geotiff/'),
   ('IHO',     'https://www.iho.int/'),
   ('IOGP',    'https://www.iogp.org/'),
   ('ISBN',    'https://www.isbn-international.org/'),
diff --git 
a/endorsed/src/org.apache.sis.portrayal/main/org/apache/sis/map/coverage/MultiResolutionCoverageLoader.java
 
b/endorsed/src/org.apache.sis.portrayal/main/org/apache/sis/map/coverage/MultiResolutionCoverageLoader.java
index a3737c7c36..2fda32ee32 100644
--- 
a/endorsed/src/org.apache.sis.portrayal/main/org/apache/sis/map/coverage/MultiResolutionCoverageLoader.java
+++ 
b/endorsed/src/org.apache.sis.portrayal/main/org/apache/sis/map/coverage/MultiResolutionCoverageLoader.java
@@ -350,7 +350,7 @@ dimensions: for (int j=0; j<tgtDim; j++) {
         final NumberFormat f = NumberFormat.getInstance();
         f.setMinimumFractionDigits(n);
         f.setMaximumFractionDigits(n);
-        final TableAppender table = new TableAppender("  ");
+        final var table = new TableAppender("  ");
         table.setCellAlignment(TableAppender.ALIGN_RIGHT);
         for (int level=0; level <= count; level++) {
             final double[] rs = resolutionSquared[level];
diff --git 
a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/LocationFormat.java
 
b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/LocationFormat.java
index e4185ab075..8b41065610 100644
--- 
a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/LocationFormat.java
+++ 
b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/LocationFormat.java
@@ -35,7 +35,6 @@ import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.metadata.extent.GeographicBoundingBox;
-import org.opengis.metadata.extent.Extent;
 import org.opengis.geometry.Envelope;
 import org.opengis.geometry.DirectPosition;
 import org.apache.sis.io.TabularFormat;
@@ -198,7 +197,7 @@ public class LocationFormat extends TabularFormat<Location> 
{
         ArgumentChecks.ensureNonNull("location", location);
         final Locale locale = getLocale(Locale.Category.DISPLAY);
         final Vocabulary vocabulary = Vocabulary.forLocale(locale);
-        final TableAppender table = new TableAppender(toAppendTo, "│ ", 
columnSeparator, " │");
+        final var table = new TableAppender(toAppendTo, "│ ", columnSeparator, 
" │");
         table.setMultiLinesCells(true);
         /*
          * Location type.
@@ -233,7 +232,7 @@ public class LocationFormat extends TabularFormat<Location> 
{
          * We may also need to change axis order (but not unit) of the 
envelope in order to match
          * the axis order of the geographic bounding box.
          */
-        final Extent extent = new DefaultExtent(null, 
location.getGeographicExtent(), null, location.getTemporalExtent());
+        final var extent = new DefaultExtent(null, 
location.getGeographicExtent(), null, location.getTemporalExtent());
         final Range<Date> time = Extents.getTimeRange(extent);
         if (time != null) {
             append(table, vocabulary, Vocabulary.Keys.StartDate, 
toString(time.getMinValue()));
@@ -429,7 +428,7 @@ public class LocationFormat extends TabularFormat<Location> 
{
     protected Format createFormat(final Class<?> valueType) {
         final Format f = super.createFormat(valueType);
         if (f instanceof NumberFormat) {
-            final NumberFormat nf = (NumberFormat) f;
+            final var nf = (NumberFormat) f;
             nf.setMinimumFractionDigits(0);
             nf.setMaximumFractionDigits(0);                     // 1 metre 
accuracy, assuming lengths in metres.
         } else if (f instanceof AngleFormat) {
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java
index 4192edc783..84c9f1c988 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/ParameterFormat.java
@@ -447,13 +447,14 @@ public class ParameterFormat extends 
TabularFormat<Object> {
     private void format(final String name, final ParameterDescriptorGroup 
group,
             final ParameterValueGroup values, final Appendable out) throws 
IOException
     {
-        final boolean             isBrief        = (contentLevel == 
ContentLevel.BRIEF);
-        final boolean             showObligation = !isBrief || (values == 
null);
-        final boolean             hasColors      = (colors != null);
-        final String              lineSeparator  = this.lineSeparator;
-        final Map<String,Integer> remarks        = new LinkedHashMap<>();
-        final ParameterTableRow   header         = new 
ParameterTableRow(group, displayLocale, preferredCodespaces, remarks, isBrief);
-        final String              groupCodespace = header.getCodeSpace();
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
+        final String  lineSeparator  = this.lineSeparator;
+        final boolean isBrief        = (contentLevel == ContentLevel.BRIEF);
+        final boolean showObligation = !isBrief || (values == null);
+        final boolean hasColors      = (colors != null);
+        final var     remarks        = new LinkedHashMap<String,Integer>();
+        final var     header         = new ParameterTableRow(group, 
displayLocale, preferredCodespaces, remarks, isBrief);
+        final String  groupCodespace = header.getCodeSpace();
         /*
          * Prepares the information to be printed later as table rows. We scan 
all rows before to print them
          * in order to compute the width of codespaces. During this process, 
we split the objects to be printed
@@ -462,7 +463,7 @@ public class ParameterFormat extends TabularFormat<Object> {
          */
         int codespaceWidth = 0;
         final Collection<?> elements = (values != null) ? values.values() : 
group.descriptors();
-        final Map<GeneralParameterDescriptor, ParameterTableRow> 
descriptorValues = JDK19.newLinkedHashMap(elements.size());
+        final var descriptorValues = JDK19.<GeneralParameterDescriptor, 
ParameterTableRow>newLinkedHashMap(elements.size());
         List<Object> deferredGroups = null;                 // To be created 
only if needed (it is usually not).
         for (final Object element : elements) {
             final GeneralParameterValue parameter;
@@ -489,11 +490,11 @@ public class ParameterFormat extends 
TabularFormat<Object> {
             Object value = null;
             Unit<?> unit = null;
             if (parameter instanceof ParameterValue<?>) {
-                final ParameterValue<?> p = (ParameterValue<?>) parameter;
+                final var p = (ParameterValue<?>) parameter;
                 value = p.getValue();
                 unit  = p.getUnit();
             } else if (descriptor instanceof ParameterDescriptor<?>) {
-                final ParameterDescriptor<?> p = (ParameterDescriptor<?>) 
descriptor;
+                final var p = (ParameterDescriptor<?>) descriptor;
                 value = p.getDefaultValue();
                 unit  = p.getUnit();
             }
@@ -515,11 +516,11 @@ public class ParameterFormat extends 
TabularFormat<Object> {
          *   - Value domains are formatted.
          *   - Position of the character on which to do the alignment are 
remembered.
          */
-        int     unitWidth             = 0;
-        int     valueDomainAlignment  = 0;
-        boolean writeCodespaces       = (groupCodespace == null);
-        final   StringBuffer  buffer  = new StringBuffer();
-        final   FieldPosition dummyFP = new FieldPosition(-1);
+        int unitWidth            = 0;
+        int valueDomainAlignment = 0;
+        boolean writeCodespaces  = (groupCodespace == null);
+        final var buffer  = new StringBuffer();
+        final var dummyFP = new FieldPosition(-1);
         for (final Map.Entry<GeneralParameterDescriptor,ParameterTableRow> 
entry : descriptorValues.entrySet()) {
             final GeneralParameterDescriptor descriptor = entry.getKey();
             if (descriptor instanceof ParameterDescriptor<?>) {
@@ -639,10 +640,10 @@ public class ParameterFormat extends 
TabularFormat<Object> {
             nextColumn(table);
             final GeneralParameterDescriptor generalDescriptor = 
entry.getKey();
             if (generalDescriptor instanceof ParameterDescriptor<?>) {
+                final var descriptor = (ParameterDescriptor<?>) 
generalDescriptor;
                 /*
                  * Writes value type.
                  */
-                final ParameterDescriptor<?> descriptor = 
(ParameterDescriptor<?>) generalDescriptor;
                 final Class<?> valueClass = descriptor.getValueClass();
                 if (valueClass != null) {  // Should never be null, but let be 
safe.
                     table.append(getFormat(Class.class).format(valueClass, 
buffer, dummyFP).toString());
@@ -825,8 +826,8 @@ public class ParameterFormat extends TabularFormat<Object> {
          * the scope of some alias to be processed below.
          */
         boolean hasIdentifiers = false;
-        final List<String[]> rows = new ArrayList<>();
-        final Map<String,Integer> columnIndices = new LinkedHashMap<>();
+        final var rows = new ArrayList<String[]>();
+        final var columnIndices = new LinkedHashMap<String,Integer>();
         columnIndices.put(null, 0);                 // See above comment for 
the meaning of "null" here.
         if (preferredCodespaces != null) {
             for (final String codespace : preferredCodespaces) {
@@ -902,7 +903,7 @@ public class ParameterFormat extends TabularFormat<Object> {
          * on the user list, then those codespaces will be written in the 
order we found them.
          */
         final boolean hasColors = (colors != null);
-        final TableAppender table = new TableAppender(out, columnSeparator);
+        final var table = new TableAppender(out, columnSeparator);
         table.setMultiLinesCells(true);
         table.appendHorizontalSeparator();
         for (String codespace : columnIndices.keySet()) {
@@ -1028,7 +1029,7 @@ public class ParameterFormat extends 
TabularFormat<Object> {
      */
     @Override
     public ParameterFormat clone() {
-        final ParameterFormat clone = (ParameterFormat) super.clone();
+        final var clone = (ParameterFormat) super.clone();
         // No need to clone 'preferredCodespaces'.
         clone.colors = clone.colors.clone();
         return clone;
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/GeodeticCalculator.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/GeodeticCalculator.java
index 1662fe842b..20adac574c 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/GeodeticCalculator.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/GeodeticCalculator.java
@@ -1236,12 +1236,12 @@ public class GeodeticCalculator {
              */
             if ((validity & (START_POINT | STARTING_AZIMUTH | END_POINT | 
ENDING_AZIMUTH)) != 0) {
                 final String[] axes = 
ReferencingUtilities.getShortAxisNames(resources, crs);
-                final AngleFormat    azimuthFormat = new 
AngleFormat("DD°MM′SS″", locale);
-                final CoordinateFormat pointFormat = new 
CoordinateFormat(locale, null);
+                final var azimuthFormat = new AngleFormat("DD°MM′SS″", locale);
+                final var pointFormat = new CoordinateFormat(locale, null);
                 pointFormat.setSeparator("\t");      // For distributing 
coordinate values on different columns.
                 pointFormat.setDefaultCRS(crs);
                 
pointFormat.setGroundPrecision(Quantities.create(Formulas.LINEAR_TOLERANCE, 
Units.METRE));
-                final TableAppender table = new TableAppender(buffer, " │ ");
+                final var table = new TableAppender(buffer, " │ ");
                 table.setCellAlignment(TableAppender.ALIGN_CENTER);
                 table.appendHorizontalSeparator();
                 for (final String axis : axes) {
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
index ea18879478..849014bcd7 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/LinearTransformBuilder.java
@@ -18,7 +18,6 @@ package org.apache.sis.referencing.operation.builder;
 
 import java.util.Map;
 import java.util.List;
-import java.util.Queue;
 import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.ArrayDeque;
@@ -500,7 +499,7 @@ search: for (int j=numPoints; --j >= 0;) {
     public Envelope getSourceEnvelope() {
         if (gridSize != null) {
             final int dim = gridSize.length;
-            final GeneralEnvelope envelope = new GeneralEnvelope(dim);
+            final var envelope = new GeneralEnvelope(dim);
             for (int i=0; i <dim; i++) {
                 envelope.setRange(i, 0, gridSize[i] - 1);
             }
@@ -533,7 +532,7 @@ search: for (int j=numPoints; --j >= 0;) {
             throw new IllegalStateException(noData());
         }
         final int dim = points.length;
-        final GeneralEnvelope envelope = new GeneralEnvelope(dim);
+        final var envelope = new GeneralEnvelope(dim);
         for (int i=0; i<dim; i++) {
             final double[] values = points[i];
             double lower = Double.POSITIVE_INFINITY;
@@ -741,7 +740,7 @@ search: for (int j=numPoints; --j >= 0;) {
                 case 1: return new DirectPosition1D(data[0][offset]);
                 case 2: return new DirectPosition2D(data[0][offset], 
data[1][offset]);
             }
-            final GeneralDirectPosition pos = new 
GeneralDirectPosition(data.length);
+            final var pos = new GeneralDirectPosition(data.length);
             for (int i=0; i<data.length; i++) pos.setCoordinate(i, 
data[i][offset]);
             return pos;
         }
@@ -886,7 +885,7 @@ search:         for (int j=domain(); --j >= 0;) {
                 @Override protected DirectPosition getKey() {
                     final int[] gridSize = 
LinearTransformBuilder.this.gridSize;
                     final int dim = gridSize.length;
-                    final GeneralDirectPosition pos = new 
GeneralDirectPosition(dim);
+                    final var pos = new GeneralDirectPosition(dim);
                     int offset = index;
                     for (int i=0; i<dim; i++) {
                         final int size = gridSize[i];
@@ -1406,8 +1405,9 @@ search:         for (int j=domain(); --j >= 0;) {
                  * `double[]` arrays may be large (e.g. megabytes) and we want 
to avoid creating new arrays of
                  * such size for each projection to try.
                  */
-                final Queue<double[]> pool = new ArrayDeque<>();
-                final LinearTransformBuilder tmp = new 
LinearTransformBuilder(this);
+                final var pool = new ArrayDeque<double[]>();
+                final var tmp = new LinearTransformBuilder(this);
+                @SuppressWarnings("LocalVariableHidesMemberVariable")
                 final int numPoints = (gridLength != 0) ? gridLength : 
this.numPoints;
                 boolean needTargetReplace = false;
                 for (final ProjectedTransformTry alt : linearizers) {
@@ -1482,8 +1482,9 @@ search:         for (int j=domain(); --j >= 0;) {
      * that depend on affine transform assumption.</p>
      */
     private MatrixSIS fit() throws FactoryException {
-        final double[][] sources = this.sources;                    // Protect 
from changes.
-        final double[][] targets = this.targets;
+        // Protect `sources` and `targets` against accidental changes.
+        @SuppressWarnings("LocalVariableHidesMemberVariable") final double[][] 
sources = this.sources;
+        @SuppressWarnings("LocalVariableHidesMemberVariable") final double[][] 
targets = this.targets;
         if (targets == null) {
             throw new InvalidGeodeticParameterException(noData());
         }
@@ -1635,7 +1636,7 @@ search:         for (int j=domain(); --j >= 0;) {
      */
     @Override
     public String toString() {
-        final StringBuilder buffer = new StringBuilder(400);
+        final var buffer = new StringBuilder(400);
         final String lineSeparator;
         try {
             lineSeparator = appendTo(buffer, getClass(), null, 
Vocabulary.Keys.Result);
@@ -1686,7 +1687,7 @@ search:         for (int j=domain(); --j >= 0;) {
             vocabulary.appendLabel(Vocabulary.Keys.Preprocessing, buffer);
             buffer.append(lineSeparator);
             NumberFormat nf = null;
-            final TableAppender table = new TableAppender(buffer, " │ ");
+            final var table = new TableAppender(buffer, " │ ");
             table.appendHorizontalSeparator();
             
table.append(vocabulary.getString(Vocabulary.Keys.Conversion)).nextColumn();
             
table.append(vocabulary.getString(Vocabulary.Keys.Correlation)).nextLine();
@@ -1710,7 +1711,7 @@ search:         for (int j=domain(); --j >= 0;) {
             buffer.append(Strings.CONTINUATION_ITEM);
             vocabulary.appendLabel(resultKey, buffer);
             buffer.append(lineSeparator);
-            final TableAppender table = new TableAppender(buffer, " ");
+            final var table = new TableAppender(buffer, " ");
             table.setMultiLinesCells(true);
             
table.append(Matrices.toString(transform.getMatrix())).nextColumn();
             table.append(lineSeparator).append("  ")
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/ProjectedTransformTry.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/ProjectedTransformTry.java
index cfe429ed60..cc2356183b 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/ProjectedTransformTry.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/builder/ProjectedTransformTry.java
@@ -358,7 +358,7 @@ final class ProjectedTransformTry implements 
Comparable<ProjectedTransformTry>,
         transform = transform.clone();
         for (int j=0; j<projToGrid.length; j++) {
             final int d = projToGrid[j];
-            for (int i=transform.getNumCol(); --i >= 0;) {
+            for (int i = transform.getNumCol(); --i >= 0;) {
                 transform.setNumber(d, i, newValues.getNumber(j, i));
             }
         }
@@ -403,7 +403,7 @@ final class ProjectedTransformTry implements 
Comparable<ProjectedTransformTry>,
     @Override
     public boolean equals(final Object obj) {
         if (obj instanceof Map.Entry<?,?>) {
-            final Map.Entry<?,?> other = (Map.Entry<?,?>) obj;
+            final var other = (Map.Entry<?,?>) obj;
             return name.equals(other.getKey()) && 
projection.equals(other.getValue());
         }
         return false;
@@ -455,7 +455,7 @@ final class ProjectedTransformTry implements 
Comparable<ProjectedTransformTry>,
      */
     @Override
     public String toString() {
-        final TableAppender buffer = new TableAppender("  ");
+        final var buffer = new TableAppender("  ");
         summarize(buffer, null, null);
         return buffer.toString();
     }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/gridded/Tile.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/gridded/Tile.java
index 85f6d3a8c9..743992db50 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/gridded/Tile.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/gridded/Tile.java
@@ -521,7 +521,7 @@ public class Tile implements Serializable {
      */
     @Override
     public String toString() {
-        final StringBuilder buffer = new 
StringBuilder(Classes.getShortClassName(this)).append('[');
+        final var buffer = new 
StringBuilder(Classes.getShortClassName(this)).append('[');
         if ((xSubsampling | ySubsampling) != 0) {
             buffer.append("location=(");
             if (width == 0 && height == 0) {
@@ -571,7 +571,7 @@ public class Tile implements Serializable {
      * @return a string representation of the given tiles as a table.
      */
     static String toString(final Collection<Tile> tiles, final int maximum) {
-        final StringWriter writer = new StringWriter();
+        final var writer = new StringWriter();
         try {
             writeTable(tiles, writer, maximum);
         } catch (IOException e) {
@@ -594,7 +594,7 @@ public class Tile implements Serializable {
      */
     public static void writeTable(final Collection<Tile> tiles, final Writer 
out, final int maximum) throws IOException {
         int remaining = maximum;
-        final TableAppender table = new TableAppender(out);
+        final var table = new TableAppender(out);
         table.setMultiLinesCells(false);
         table.nextLine('═');
         table.append("Format\tInput\tindex\tx\ty\twidth\theight\tdx\tdy\n");
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java
index d83bdc2496..8e899ab77c 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java
@@ -166,10 +166,10 @@ public final class MercatorMethodComparison {
      * optionally with a comparison with {@link ConformalProjection}.
      */
     private void compare(final int numSamples, final TableAppender summarize) 
throws ProjectionException {
-        final Statistics iterativeMethodErrors = new Statistics("Iterative 
method error");
-        final Statistics seriesExpansionErrors = new Statistics("Series 
expansion error");
-        final Statistics implementationErrors  = new 
Statistics("Implementation error");
-        final Random random = new Random();
+        final var iterativeMethodErrors = new Statistics("Iterative method 
error");
+        final var seriesExpansionErrors = new Statistics("Series expansion 
error");
+        final var implementationErrors  = new Statistics("Implementation 
error");
+        final var random = new Random();
         for (int i=0; i<numSamples; i++) {
             final double φ = random.nextDouble() * PI - PI/2;
             final double t = 1 / expΨ(φ);
@@ -227,7 +227,7 @@ public final class MercatorMethodComparison {
      * @throws ProjectionException if an error occurred in {@link 
ConformalProjection#φ(double)}.
      */
     public static void printErrorForExcentricities(final double min, final 
double max) throws ProjectionException {
-        final TableAppender table = new TableAppender(out);
+        final var table = new TableAppender(out);
         table.appendHorizontalSeparator();
         table.append("Eccentricity");            table.nextColumn();
         table.append("Mean iterative error");    table.nextColumn();
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/MathTransformTestCase.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/MathTransformTestCase.java
index 68e675f990..c4d73a07b1 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/MathTransformTestCase.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/transform/MathTransformTestCase.java
@@ -420,7 +420,7 @@ public abstract class MathTransformTestCase extends 
TransformTestCase {
     @Debug
     protected final void printInternalWKT() {
         @SuppressWarnings("UseOfSystemOutOrSystemErr")
-        final TableAppender table = new TableAppender(System.out);
+        final var table = new TableAppender(System.out);
         table.setMultiLinesCells(true);
         table.appendHorizontalSeparator();
         table.append("WKT of “").append(getName()).append('”').nextColumn();
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/ConsistencyTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/ConsistencyTest.java
index fe62d84896..714b681bb9 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/ConsistencyTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/ConsistencyTest.java
@@ -96,7 +96,7 @@ public final class ConsistencyTest extends TestCase {
     public void debug() throws FactoryException {
         final String code = "EPSG::29871";
         final CoordinateReferenceSystem crs = CRS.forCode(code);
-        final WKTFormat format = new WKTFormat();
+        final var format = new WKTFormat();
         format.setConvention(Convention.WKT2);
         lookup(parseAndFormat(format, code, crs), crs);
     }
@@ -110,10 +110,10 @@ public final class ConsistencyTest extends TestCase {
     @Tag(TAG_SLOW)
     public void testCoordinateReferenceSystems() throws FactoryException {
         assumeTrue(RUN_EXTENSIVE_TESTS, "Extensive tests not enabled.");
-        final WKTFormat v1  = new WKTFormat();
-        final WKTFormat v1c = new WKTFormat();
-        final WKTFormat v2  = new WKTFormat();
-        final WKTFormat v2s = new WKTFormat();
+        final var v1  = new WKTFormat();
+        final var v1c = new WKTFormat();
+        final var v2  = new WKTFormat();
+        final var v2s = new WKTFormat();
         v1 .setConvention(Convention.WKT1);
         v1c.setConvention(Convention.WKT1_COMMON_UNITS);
         v2 .setConvention(Convention.WKT2);
@@ -230,7 +230,7 @@ public final class ConsistencyTest extends TestCase {
             }
         } catch (AssertionError e) {
             print(code, "ERROR", "WKT are not equal.");
-            final TableAppender table = new TableAppender();
+            final var table = new TableAppender();
             table.nextLine('═');
             table.setMultiLinesCells(true);
             table.append("Original WKT:");
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/CRSBuilder.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/CRSBuilder.java
index 83f7e53fdf..652d409b24 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/CRSBuilder.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/CRSBuilder.java
@@ -1613,9 +1613,9 @@ public final class CRSBuilder extends 
ReferencingFactoryContainer {
      */
     @Override
     public final String toString() {
-        final StringBuilder buffer = new StringBuilder("GeoTIFF keys 
").append(majorRevision).append('.')
+        final var buffer = new StringBuilder("GeoTIFF keys 
").append(majorRevision).append('.')
                 .append(minorRevision).append(" in 
").append(listeners.getSourceName()).append(System.lineSeparator());
-        final TableAppender table = new TableAppender(buffer, " ");
+        final var table = new TableAppender(buffer, " ");
         for (Map.Entry<Short,Object> entry : geoKeys.entrySet()) {
             final short key = entry.getKey();
             table.append(String.valueOf(key)).nextColumn();
diff --git 
a/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/gpx/Metadata.java
 
b/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/gpx/Metadata.java
index ffd54b805e..9a84519b8f 100644
--- 
a/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/gpx/Metadata.java
+++ 
b/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/gpx/Metadata.java
@@ -315,7 +315,7 @@ public final class Metadata extends SimpleMetadata {
     @Override
     public Collection<Responsibility> getPointOfContacts() {
         if (creator != null) {
-            final Person p = new Person(creator);
+            final var p = new Person(creator);
             return (author != null) ? UnmodifiableArrayList.wrap(new 
Responsibility[] {p, author})
                                     : Collections.singletonList(author);
         }
@@ -389,6 +389,7 @@ public final class Metadata extends SimpleMetadata {
      */
     @Override
     public Collection<ContentInformation> getContentInfo() {
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         final Store store = this.store;
         return (store != null) ? store.types.metadata : 
Collections.emptyList();
     }
@@ -401,6 +402,7 @@ public final class Metadata extends SimpleMetadata {
      */
     @Override
     public Collection<Format> getResourceFormats() {
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         final Store store = this.store;
         if (store != null) {
             Format f;
@@ -436,7 +438,7 @@ public final class Metadata extends SimpleMetadata {
             return true;
         }
         if (obj instanceof Metadata) {
-            final Metadata that = (Metadata) obj;
+            final var that = (Metadata) obj;
             return Objects.equals(this.creator,     that.creator)     &&
                    Objects.equals(this.name,        that.name)        &&
                    Objects.equals(this.description, that.description) &&
@@ -467,9 +469,9 @@ public final class Metadata extends SimpleMetadata {
      */
     @Override
     public String toString() {
-        final StringBuilder buffer = new StringBuilder();
+        final var buffer = new StringBuilder();
         buffer.append("GPX metadata").append(System.lineSeparator());
-        final TableAppender table = new TableAppender(buffer);
+        final var table = new TableAppender(buffer);
         table.setMultiLinesCells(true);
         table.appendHorizontalSeparator();
         append(table, "Creator",     creator);
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/Region.java 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/Region.java
index 4c87cfe96b..db2039b775 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/Region.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/Region.java
@@ -293,7 +293,7 @@ public final class Region {
      */
     @Override
     public String toString() {
-        final TableAppender table = new TableAppender(" ");
+        final var table = new TableAppender(" ");
         table.setCellAlignment(TableAppender.ALIGN_RIGHT);
         table.append("size").nextColumn();
         table.append("skip").nextLine();
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/GridCoverageResource.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/GridCoverageResource.java
index 1b6665083d..71da17224c 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/GridCoverageResource.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/GridCoverageResource.java
@@ -205,7 +205,7 @@ public interface GridCoverageResource extends DataSet {
      * then this method will try to return a grid coverage matching the given 
grid geometry on a best-effort basis;
      * the coverage actually returned may have a different resolution, cover a 
different area in a different CRS,
      * <i>etc</i>. The general contract is that the returned coverage should 
not contain less data than a coverage
-     * matching exactly the given geometry.
+     * matching exactly the given geometry, ignoring the areas outside the 
resource domain.
      *
      * <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 ranges).
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridResource.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridResource.java
index c4cf932d90..a8daffe35f 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridResource.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridResource.java
@@ -412,7 +412,7 @@ final class ConcatenatedGridResource extends 
AbstractGridCoverageResource implem
     @Override
     public GridCoverage read(GridGeometry domain, int... ranges) throws 
DataStoreException {
         /*
-         * Validate arguments.
+         * Validate arguments. The slices to read will be from `lower` 
inclusive to `upper` exclusive.
          */
         if (ranges != null) {
             ranges = RangeArgument.validate(sampleDimensions.size(), ranges, 
listeners).getSelectedBands();
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/TableAppender.java 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/TableAppender.java
index 7a3309d134..0e00aff212 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/TableAppender.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/TableAppender.java
@@ -43,7 +43,7 @@ import static 
org.apache.sis.util.Characters.isLineOrParagraphSeparator;
  * <p>For example, the following code:</p>
  *
  * {@snippet lang="java" :
- *     TableAppender table = new TableAppender(System.out);
+ *     var table = new TableAppender(System.out);
  *     table.nextLine('═');
  *     table.append("English\tFrench\tr.e.d.\n");
  *     table.nextLine('-');
@@ -702,9 +702,10 @@ public class TableAppender extends Appender implements 
Flushable {
      * repeated.
      */
     private void writeTable() throws IOException {
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
         final String columnSeparator = this.columnSeparator;
-        final Cell[]     currentLine = new Cell[maximalColumnWidths.length];
-        final int          cellCount = cells.size();
+        final Cell[] currentLine     = new Cell[maximalColumnWidths.length];
+        final int    cellCount       = cells.size();
         for (int cellIndex=0; cellIndex<cellCount; cellIndex++) {
             /*
              * Copies in `currentLine` every cells to write in the current 
table row.
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/TabularFormat.java 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/TabularFormat.java
index c3e7738758..fa2cdc28e3 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/TabularFormat.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/TabularFormat.java
@@ -45,7 +45,7 @@ import org.apache.sis.util.resources.Errors;
  *
  * <p><b>Formatting table without border:</b></p>
  * {@snippet lang="java" :
- *     TableAppender table = new TableAppender(out, "");
+ *     var table = new TableAppender(out, "");
  *     // ... do some work, then add a column separator:
  *     table.append(beforeFill);
  *     table.nextColumn(fillCharacter);
@@ -54,7 +54,7 @@ import org.apache.sis.util.resources.Errors;
  *
  * <p><b>Formatting table with a border:</b></p>
  * {@snippet lang="java" :
- *     TableAppender table = new TableAppender(out, columnSeparator);
+ *     var table = new TableAppender(out, columnSeparator);
  *     // ... do some work, then add a column separator:
  *     table.append(beforeFill);
  *     table.nextColumn(fillCharacter);
@@ -168,7 +168,7 @@ public abstract class TabularFormat<T> extends 
CompoundFormat<T> {
      * @return the pattern of the current column separator.
      */
     public String getColumnSeparatorPattern() {
-        final StringBuilder buffer = new StringBuilder(8);
+        final var buffer = new StringBuilder(8);
         buffer.append(beforeFill).append('\uFFFF').append(columnSeparator);
         StringBuilders.replace(buffer, "\\", "\\\\");
         StringBuilders.replace(buffer, "?",  "\\?");
@@ -229,7 +229,7 @@ public abstract class TabularFormat<T> extends 
CompoundFormat<T> {
     public void setColumnSeparatorPattern(final String pattern) throws 
IllegalArgumentException {
         ArgumentChecks.ensureNonEmpty("pattern", pattern);
         final int length = pattern.length();
-        final StringBuilder buffer = new StringBuilder(length);
+        final var buffer = new StringBuilder(length);
         boolean escape  = false;
         boolean trim    = false;
         String  prefix  = null;
@@ -317,7 +317,7 @@ scan:   for (int i=0; i<length; i++) {
      */
     protected Matcher getColumnSeparatorMatcher(final CharSequence text) {
         if (parsePattern == null) {
-            final StringBuilder pattern = new 
StringBuilder(beforeFill).append(fillCharacter);
+            final var pattern = new 
StringBuilder(beforeFill).append(fillCharacter);
             String tmp = pattern.toString();
             pattern.setLength(0);
             pattern.append(Pattern.quote(tmp)).append('*');
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/StatisticsFormat.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/StatisticsFormat.java
index 81cb0278c5..1f84f8b0ee 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/StatisticsFormat.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/math/StatisticsFormat.java
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.math;
 
-import java.util.List;
 import java.util.ArrayList;
 import java.util.Locale;
 import java.util.TimeZone;
@@ -264,7 +263,7 @@ public class StatisticsFormat extends 
TabularFormat<Statistics> {
      */
     @Override
     public void format(Statistics stats, final Appendable toAppendTo) throws 
IOException {
-        final List<Statistics> list = new ArrayList<>(3);
+        final var list = new ArrayList<Statistics>(3);
         while (stats != null) {
             list.add(stats);
             stats = stats.differences();
@@ -304,7 +303,7 @@ public class StatisticsFormat extends 
TabularFormat<Statistics> {
             case 1: horizontalLine = '─'; separator += "│ "; break;
             case 2: horizontalLine = '═'; separator += "║ "; break;
         }
-        final TableAppender table = new TableAppender(toAppendTo, separator);
+        final var table = new TableAppender(toAppendTo, separator);
         final Vocabulary resources = Vocabulary.forLocale(headerLocale);
         /*
          * If there is a header for at least one statistics, write the full 
headers row.
@@ -401,7 +400,7 @@ public class StatisticsFormat extends 
TabularFormat<Statistics> {
     private static Format configure(final Format format, final Statistics 
stats, final boolean clone) {
         int multiplier = 1;
         if (format instanceof DecimalFormat) {
-            DecimalFormat df = (DecimalFormat) format;
+            var df = (DecimalFormat) format;
             multiplier = df.getMultiplier();
             /*
              * Check for scientific notation: the threshold below is high so 
that geocentric and projected
@@ -439,7 +438,7 @@ public class StatisticsFormat extends 
TabularFormat<Statistics> {
             int digits = Numerics.suggestFractionDigits(stats);
             digits -= DecimalFunctions.floorLog10(multiplier);
             digits = Math.max(0, digits);
-            NumberFormat nf = (NumberFormat) format;
+            var nf = (NumberFormat) format;
             if (digits != nf.getMinimumFractionDigits() ||
                 digits != nf.getMaximumFractionDigits())
             {
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/CharSequences.java 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/CharSequences.java
index 8e307a8d12..c68e32c10d 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/CharSequences.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/CharSequences.java
@@ -209,7 +209,7 @@ public final class CharSequences extends Static {
         if (text instanceof StringBuilder) return ((StringBuilder) 
text).codePointCount(fromIndex, toIndex);
         if (text instanceof StringBuffer)  return ((StringBuffer)  
text).codePointCount(fromIndex, toIndex);
         if (text instanceof CharBuffer) {
-            final CharBuffer buffer = (CharBuffer) text;
+            final var buffer = (CharBuffer) text;
             if (buffer.hasArray() && !buffer.isReadOnly()) {
                 final int position = buffer.position();
                 return Character.codePointCount(buffer.array(), position + 
fromIndex, position + toIndex);
@@ -259,7 +259,7 @@ public final class CharSequences extends Static {
         int n = 0;
         if (text != null) {
             if (text instanceof String) {
-                final String s = (String) text;
+                final var s = (String) text;
                 for (int i=s.indexOf(toSearch); ++i != 0; 
i=s.indexOf(toSearch, i)) {
                     n++;
                 }
@@ -1039,7 +1039,7 @@ search:     for (; fromIndex <= toIndex; fromIndex++) {
                      * (a more efficient approach would be to perform bulk 
appends). However, we presume
                      * that this block will be rarely executed, so it is not 
worth to optimize it.
                      */
-                    final StringBuilder buffer = new StringBuilder(length - 
n).append(text, 0, i);
+                    final var buffer = new StringBuilder(length - 
n).append(text, 0, i);
                     while ((i += n) < length) {
                         c = codePointAt(text, i);
                         n = Character.charCount(c);
@@ -1218,7 +1218,7 @@ searchWordBreak:    while (true) {
         if (identifier == null) {
             return null;
         }
-        final StringBuilder buffer = new StringBuilder(identifier.length());
+        final var buffer = new StringBuilder(identifier.length());
         final int length = identifier.length();
         for (int i=0; i<length;) {
             int c = codePointAt(identifier, i);
@@ -1320,7 +1320,7 @@ searchWordBreak:    while (true) {
          * this method to unconditionally returns a new StringBuilder.
          */
         final int length = identifier.length();
-        final StringBuilder buffer = new StringBuilder(length + 8);
+        final var buffer = new StringBuilder(length + 8);
         final int lastIndex = (length != 0) ? length - 
charCount(codePointBefore(identifier, length)) : 0;
         int last = 0;
         for (int i=1; i<=length;) {
@@ -1379,7 +1379,7 @@ searchWordBreak:    while (true) {
         text = trimWhitespaces(text);
         if (text != null && !isAcronym(text)) {
             final int length = text.length();
-            final StringBuilder buffer = new StringBuilder(8);              // 
Acronyms are usually short.
+            final var buffer = new StringBuilder(8);        // Acronyms are 
usually short.
             boolean wantChar = true;
             for (int i=0; i<length;) {
                 final int c = codePointAt(text, i);
@@ -2106,7 +2106,7 @@ cmp:    while (ia < lga) {
          * All special cases have been examined. Return the concatenation of 
(possibly shortened)
          * common prefix and suffix.
          */
-        final StringBuilder buffer = new StringBuilder(prefixLength + 
suffixLength).append(prefix);
+        final var buffer = new StringBuilder(prefixLength + 
suffixLength).append(prefix);
         final int c1 = codePointBefore(prefix, prefixLength);
         final int c2 = codePointAt(suffix, suffixStart);
         if (isLetterOrDigit(c1) && isLetterOrDigit(c2)) {
@@ -2232,7 +2232,7 @@ cmp:    while (ia < lga) {
             if (i >= 0) {
                 int p = 0;
                 final int sl = toSearch.length();
-                final StringBuilder buffer = new StringBuilder(length + 
(replaceBy.length() - sl));
+                final var buffer = new StringBuilder(length + 
(replaceBy.length() - sl));
                 do {
                     buffer.append(text, p, i).append(replaceBy);
                     i = indexOf(text, toSearch, p = i + sl, length);
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/TreeTableFormat.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/TreeTableFormat.java
index 1387c5bbe2..de0ad1883e 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/TreeTableFormat.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/collection/TreeTableFormat.java
@@ -354,7 +354,7 @@ public class TreeTableFormat extends 
TabularFormat<TreeTable> {
      *         contains values of an unsupported type.
      */
     final Format[] getFormats(final TableColumn<?>[] columns, final boolean 
mandatory) throws IllegalStateException {
-        final Format[] formats = new Format[columns.length];
+        final var formats = new Format[columns.length];
         for (int i=0; i<formats.length; i++) {
             final Class<?> valueType = columns[i].getElementType();
             if ((formats[i] = getFormat(valueType)) == null) {
@@ -414,7 +414,7 @@ public class TreeTableFormat extends 
TabularFormat<TreeTable> {
         int[] indentations      = new int[16];      // Number of spaces 
(ignoring drawing characters) for each level.
         TreeTable.Node lastNode = null;             // Last parsed node, 
having `indentation[level]` characters before its content.
         TreeTable.Node root     = null;             // First node found while 
parsing.
-        final DefaultTreeTable table = new DefaultTreeTable(columnIndices != 
null ? columnIndices : TableColumn.NAME_MAP);
+        final var table = new DefaultTreeTable(columnIndices != null ? 
columnIndices : TableColumn.NAME_MAP);
         final TableColumn<?>[] columns = 
DefaultTreeTable.getColumns(table.columnIndices);
         final Format[] formats = getFormats(columns, true);
         do {
@@ -457,7 +457,7 @@ public class TreeTableFormat extends 
TabularFormat<TreeTable> {
              * (without parent for now) and parse the values for each column. 
Columns with empty
              * text are not parsed (the value is left to null).
              */
-            final TreeTable.Node node = new DefaultTreeTable.Node(table);
+            final var node = new DefaultTreeTable.Node(table);
             matcher.region(indexOfValue, endOfLine);
             for (int ci=0; ci<columns.length; ci++) {
                 final boolean found = matcher.find();
@@ -685,7 +685,7 @@ public class TreeTableFormat extends 
TabularFormat<TreeTable> {
             @SuppressWarnings("LocalVariableHidesMemberVariable")   // To be 
stored in the field if successful.
             Predicate<TreeTable.Node> filter = nodeFilter;
             if (tree instanceof TreeFormatCustomization) {
-                final TreeFormatCustomization custom = 
(TreeFormatCustomization) tree;
+                final var custom = (TreeFormatCustomization) tree;
                 final Predicate<TreeTable.Node> more = custom.filter();
                 if (more != null) {
                     filter = (filter != null) ? more.and(filter) : more;
@@ -886,7 +886,7 @@ public class TreeTableFormat extends 
TabularFormat<TreeTable> {
             recursionGuard = new HashSet<>();
         }
         try {
-            final Writer out = new Writer(toAppendTo, tree, columns, 
recursionGuard);
+            final var out = new Writer(toAppendTo, tree, columns, 
recursionGuard);
             out.format(tree.getRoot(), 0);
             out.flush();
         } finally {
@@ -959,7 +959,7 @@ public class TreeTableFormat extends 
TabularFormat<TreeTable> {
      */
     @Override
     public TreeTableFormat clone() {
-        final TreeTableFormat c = (TreeTableFormat) super.clone();
+        final var c = (TreeTableFormat) super.clone();
         c.recursionGuard = null;
         return c;
     }
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/AbstractMap.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/AbstractMap.java
index fda6c3c8f4..4b6fe8e40f 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/AbstractMap.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/AbstractMap.java
@@ -498,7 +498,7 @@ public abstract class AbstractMap<K,V> implements Map<K,V> {
             /** Returns {@code true} if the map contains the given (key, 
value) pair. */
             @Override public boolean contains(final Object e) {
                 if (e instanceof Entry<?,?>) {
-                    final Entry<?,?> entry = (Entry<?,?>) e;
+                    final var entry = (Entry<?,?>) e;
                     final Object value = get(entry.getKey());
                     if (value != null) {
                         return value.equals(entry.getValue());
@@ -521,7 +521,7 @@ public abstract class AbstractMap<K,V> implements Map<K,V> {
                 if (!(object instanceof Set<?>)) {
                     return false;
                 }
-                final Set<?> that = (Set<?>) object;
+                final var that = (Set<?>) object;
                 final EntryIterator<K,V> it = entryIterator();
                 if (it == null) {
                     return that.isEmpty();
@@ -651,7 +651,7 @@ public abstract class AbstractMap<K,V> implements Map<K,V> {
         if (!(object instanceof Map<?,?>)) {
             return false;
         }
-        final Map<?,?> that = (Map<?,?>) object;
+        final var that = (Map<?,?>) object;
         final EntryIterator<K,V> it = entryIterator();
         if (it == null) {
             return that.isEmpty();
@@ -695,7 +695,7 @@ public abstract class AbstractMap<K,V> implements Map<K,V> {
      */
     @Override
     public String toString() {
-        final TableAppender buffer = new TableAppender(" = ");
+        final var buffer = new TableAppender(" = ");
         buffer.setMultiLinesCells(true);
         final EntryIterator<K,V> it = entryIterator();
         if (it != null) while (it.next()) {
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/Strings.java 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/Strings.java
index 8a62a55846..c72193a321 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/Strings.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/Strings.java
@@ -313,12 +313,14 @@ public final class Strings extends Static {
      * the whole entry is omitted. If a key is {@code null}, the value is 
written without the {@code "key="}
      * part. The latter happens typically when the first value is the object 
name.</p>
      *
+     * <p>If a value is an array, elements will be formatted up to an 
arbitrary string length limit.</p>
+     *
      * @param  classe      the class to format.
      * @param  properties  the (<var>key</var>=<var>value</var>) pairs.
      * @return a string representation of an instance of the given class 
having the given properties.
      */
     public static String toString(final Class<?> classe, final Object... 
properties) {
-        final StringBuilder buffer = new 
StringBuilder(32).append(Classes.getShortName(classe)).append('[');
+        final var buffer = new 
StringBuilder(80).append(Classes.getShortName(classe)).append('[');
         boolean isNext = false;
         for (int i=0; i<properties.length; i++) {
             final Object value = properties[++i];
@@ -330,17 +332,7 @@ public final class Strings extends Static {
                 if (name != null) {
                     buffer.append(name).append('=');
                 }
-                if (value.getClass().isArray()) {
-                    final int n = Array.getLength(value);
-                    if (n != 1) buffer.append('{');
-                    for (int j=0; j<n; j++) {
-                        if (j != 0) buffer.append(", ");
-                        append(Array.get(value, j), buffer);
-                    }
-                    if (n != 1) buffer.append('}');
-                } else {
-                    append(value, buffer);
-                }
+                appendWithHeuristic(value, buffer);
                 isNext = true;
             }
         }
@@ -348,13 +340,44 @@ public final class Strings extends Static {
     }
 
     /**
-     * Appends the given value in the given buffer, using quotes if the value 
is a character sequence.
+     * Appends the given value in the given buffer with the application of 
some heuristic rules.
+     * Those rules are aimed to produce representations of class property 
values with some hints
+     * about their types and some safety against values too long.
+     *
+     * <ul>
+     *   <li>If the value is an array, then the first array elements are 
appended up to an arbitrary limit.</li>
+     *   <li>Otherwise, if the value is a character sequence, then the value 
is appended as a quoted text.</li>
+     *   <li>Otherwise, the unquoted value (potentially the {@code "null"} 
string) is appended.</li>
+     * </ul>
+     *
+     * Those rules may change in any future <abbr>SIS</abbr> version.
+     *
+     * @param  value   the object or array to format.
+     * @param  buffer  the destination where to append the object or array 
elements.
      */
-    private static void append(final Object value, final StringBuilder buffer) 
{
-        final boolean isText = (value instanceof CharSequence);
-        if (isText) buffer.append('“');
-        buffer.append(value);
-        if (isText) buffer.append('”');
+    public static void appendWithHeuristic(final Object value, final 
StringBuilder buffer) {
+        if (value.getClass().isArray()) {
+            final int limit = buffer.length() + 80;
+            final int n = Array.getLength(value);
+            if (n != 1) buffer.append('{');
+            for (int j=0; j<n; j++) {
+                if (j != 0) buffer.append(", ");
+                if (buffer.length() > limit) {
+                    int remaining = n - j;
+                    if (remaining > 1) {
+                        buffer.append(remaining).append(" more…");
+                        break;
+                    }
+                }
+                buffer.append(Array.get(value, j));
+            }
+            if (n != 1) buffer.append('}');
+        } else {
+            final boolean isText = (value instanceof CharSequence);
+            if (isText) buffer.append('“');
+            buffer.append(value);
+            if (isText) buffer.append('”');
+        }
     }
 
     /**
@@ -394,7 +417,7 @@ public final class Strings extends Static {
                         value = "";
                     } else {
                         length = (i -= n) + 1;
-                        final StringBuilder buffer = new StringBuilder(length);
+                        final var buffer = new StringBuilder(length);
                         value = buffer.append(value, 0, 
i).append('…').toString();
                     }
                     break;
diff --git 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/LogRecordCollector.java
 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/LogRecordCollector.java
index 1a00e02a39..9953c740c8 100644
--- 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/LogRecordCollector.java
+++ 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/LogRecordCollector.java
@@ -186,7 +186,7 @@ final class LogRecordCollector extends Handler implements 
Runnable {
                 out.append(lineSeparator)
                    .append("The following tests have logged messages at level 
INFO or higher:").append(lineSeparator)
                    .append("See 'org.apache.sis.test.LoggingWatcher' for 
information about logging during tests.").append(lineSeparator);
-                final TableAppender table = new TableAppender(out);
+                final var table = new TableAppender(out);
                 table.setMultiLinesCells(false);
                 table.nextLine('═');
                 table.append("Test class");    table.nextColumn();
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
index e49060e054..bdf4c9a529 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
@@ -1199,8 +1199,8 @@ public class CoverageCanvas extends MapCanvasAWT {
             return super.toString();
         }
         final String lineSeparator = System.lineSeparator();
-        final StringBuilder buffer = new StringBuilder(1000);
-        final TableAppender table  = new TableAppender(buffer);
+        final var buffer = new StringBuilder(1000);
+        final var table  = new TableAppender(buffer);
         table.setMultiLinesCells(true);
         try {
             table.nextLine('═');

Reply via email to