This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/sis.git

commit eaee561ab0b55921e2ad277faf82a9ed008f9bdc
Merge: 499c98d8e1 c912771e82
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Mon Sep 22 17:20:38 2025 +0200

    Merge branch 'geoapi-3.1'

 .../sis/coverage/privy/SampleDimensions.java       |   3 +-
 .../sis/feature/builder/OperationWrapper.java      |   2 +-
 .../sis/feature/privy/AttributeConvention.java     |   3 +-
 .../feature/privy/FeatureProjectionBuilder.java    |  33 +-
 .../org/apache/sis/filter/ConvertFunction.java     |   2 +-
 .../sis/filter/internal/GeometryFromFeature.java   |   2 +-
 .../main/org/apache/sis/filter/internal/Node.java  |   8 +
 .../org/apache/sis/filter/privy/FunctionNames.java |   3 +-
 .../apache/sis/filter/sqlmm/SpatialFunction.java   |   6 +-
 .../org/apache/sis/geometry/wrapper/jts/JTS.java   |   3 +-
 .../org/apache/sis/image/privy/ImageUtilities.java |   3 +-
 .../org/apache/sis/image/privy/RasterFactory.java  |   3 +-
 .../test/org/apache/sis/feature/Assertions.java    |   3 +-
 .../iso/extent/DefaultGeographicDescription.java   |  20 +-
 .../apache/sis/metadata/iso/extent/Extents.java    |  44 +-
 .../org/apache/sis/metadata/privy/Identifiers.java |   3 +-
 .../sis/metadata/privy/ImplementationHelper.java   |   3 +-
 .../org/apache/sis/metadata/privy/NameMeaning.java |   3 +-
 .../sis/metadata/sql/privy/SQLUtilities.java       |   3 +-
 .../main/org/apache/sis/xml/InputFactory.java      |   3 +-
 .../main/org/apache/sis/xml/OutputFactory.java     |   3 +-
 .../test/org/apache/sis/metadata/Assertions.java   |   3 +-
 .../apache/sis/metadata/MetadataCopierTest.java    |  16 +-
 .../metadata/iso/citation/HardCodedCitations.java  |   3 +-
 .../sis/metadata/iso/extent/ExtentsTest.java       |  11 +-
 .../sis/openoffice/ReferencingFunctions.java       |   4 +-
 .../org/apache/sis/openoffice/package-info.java    |   2 +-
 .../main/org/apache/sis/geometry/Envelopes.java    |   2 +-
 .../main/org/apache/sis/io/wkt/AbstractParser.java |  18 +-
 .../main/org/apache/sis/io/wkt/Formatter.java      |   2 +-
 .../apache/sis/io/wkt/GeodeticObjectParser.java    |  92 +-
 .../org/apache/sis/io/wkt/MathTransformParser.java |   6 +-
 .../main/org/apache/sis/referencing/Builder.java   |   2 +-
 .../sis/referencing/ImmutableIdentifier.java       |   4 +-
 .../sis/referencing/datum/AbstractDatum.java       |  34 +-
 .../org/apache/sis/referencing/datum/SubTypes.java |  81 --
 .../referencing/factory/sql/EPSGDataAccess.java    | 111 ++-
 .../sis/referencing/internal/DeprecatedCode.java   |  45 +-
 .../operation/AbstractCoordinateOperation.java     |  54 +-
 .../operation/CoordinateOperationFinder.java       |   4 +-
 .../operation/CoordinateOperationRegistry.java     |   6 +-
 .../apache/sis/referencing/operation/SubTypes.java |  85 --
 .../sis/referencing/operation/provider/ESRI.java   |   3 +-
 .../provider/FranceGeocentricInterpolation.java    |   5 +-
 .../sis/referencing/operation/provider/NADCON.java |   1 +
 .../sis/referencing/operation/provider/NTv1.java   |   1 +
 .../sis/referencing/operation/provider/NTv2.java   |   1 +
 .../sis/referencing/privy/AxisDirections.java      |   3 +-
 .../referencing/privy/CoordinateOperations.java    |   3 +-
 .../org/apache/sis/referencing/privy/Formulas.java |   3 +-
 .../referencing/privy/ReferencingUtilities.java    |   3 +-
 .../sis/referencing/privy/ShapeUtilities.java      |   3 +-
 .../apache/sis/referencing/privy/WKTKeywords.java  |   3 +-
 .../apache/sis/referencing/privy/WKTUtilities.java |  46 +-
 .../sis/io/wkt/GeodeticObjectParserTest.java       |  77 +-
 .../org/apache/sis/referencing/Assertions.java     |   3 +-
 .../operation/provider/ProvidersTest.java          |  10 +-
 .../sis/storage/geotiff/CompressedSubset.java      |  14 +-
 .../org/apache/sis/storage/geotiff/DataSubset.java |  15 +-
 .../apache/sis/storage/netcdf/MetadataReader.java  |   3 +-
 .../org/apache/sis/storage/netcdf/base/Axis.java   |   2 +-
 .../apache/sis/storage/netcdf/base/AxisType.java   |  32 +-
 .../apache/sis/storage/netcdf/base/FeatureSet.java |   2 +-
 .../storage/netcdf/base/VariableTransformer.java   |   2 +-
 .../sis/storage/netcdf/classic/GridInfo.java       |   2 +-
 .../sis/storage/netcdf/ucar/GridWrapper.java       |   2 +-
 .../sis/storage/netcdf/ucar/VariableWrapper.java   |   6 +-
 .../sis/storage/sql/postgis/PostgresTest.java      |  84 +-
 .../org/apache/sis/storage/gpx/Attributes.java     |   4 +-
 .../main/org/apache/sis/storage/gpx/Tags.java      |   4 +-
 .../main/org/apache/sis/io/stream/IOUtilities.java |   3 +-
 .../main/org/apache/sis/storage/FeatureQuery.java  |  49 +-
 .../apache/sis/storage/base/MetadataBuilder.java   |  17 +-
 .../apache/sis/storage/base/StoreUtilities.java    |   3 +-
 .../org/apache/sis/measure/UnitAliases.properties  |   8 +-
 .../main/org/apache/sis/measure/UnitFormat.java    |  44 +-
 .../apache/sis/measure/UnitNames_en_US.properties  |   3 +
 .../main/org/apache/sis/util/Locales.java          |   5 +-
 .../main/org/apache/sis/util/Printable.java        |   2 +-
 .../main/org/apache/sis/util/Static.java           |   3 +
 .../org/apache/sis/util/privy/CollectionsExt.java  |   3 +-
 .../main/org/apache/sis/util/privy/Constants.java  |   4 +-
 .../main/org/apache/sis/util/privy/Numerics.java   |   3 +-
 .../main/org/apache/sis/util/privy/Strings.java    |   3 +-
 .../main/org/apache/sis/util/privy/URLs.java       |   4 +-
 .../main/org/apache/sis/util/privy/Unsafe.java     |   3 +-
 .../org/apache/sis/util/resources/Vocabulary.java  |   5 +
 .../sis/util/resources/Vocabulary.properties       |   1 +
 .../sis/util/resources/Vocabulary_fr.properties    |   1 +
 .../org/apache/sis/measure/UnitFormatTest.java     |  66 +-
 .../test/org/apache/sis/test/Assertions.java       |   3 +-
 .../org/apache/sis/test/TestConfiguration.java     |   4 +-
 .../test/org/apache/sis/test/TestUtilities.java    |   3 +-
 .../sis/storage/shapefile/ShapefileStore.java      |   6 +-
 .../apache/sis/storage/shapefile/cpg/CpgFiles.java |   3 +-
 netbeans-project/ivy.xml                           |   2 +-
 netbeans-project/nbproject/project.xml             |   1 +
 .../org/apache/sis/gui/controls/ColorCell.java     |   2 +-
 .../sis/gui/controls/ColorColumnHandler.java       |   2 +-
 .../org/apache/sis/gui/controls/ColorRamp.java     |   2 +-
 .../org/apache/sis/gui/controls/TabularWidget.java |   8 +-
 .../org/apache/sis/gui/coverage/CellFormat.java    |  68 +-
 .../apache/sis/gui/coverage/CoverageStyling.java   |  73 +-
 .../main/org/apache/sis/gui/coverage/GridCell.java |  70 --
 .../org/apache/sis/gui/coverage/GridControls.java  |   8 +-
 .../org/apache/sis/gui/coverage/GridError.java     |  19 +-
 .../main/org/apache/sis/gui/coverage/GridRow.java  | 110 ---
 .../org/apache/sis/gui/coverage/GridRowSkin.java   | 136 ---
 .../main/org/apache/sis/gui/coverage/GridTile.java |  43 +-
 .../main/org/apache/sis/gui/coverage/GridView.java | 253 +++---
 .../org/apache/sis/gui/coverage/GridViewSkin.java  | 944 +++++++++++----------
 .../main/org/apache/sis/gui/internal/FontGIS.java  |   5 +-
 .../org/apache/sis/gui/internal/GUIUtilities.java  |   3 +-
 .../main/org/apache/sis/gui/internal/Styles.java   |  20 +-
 .../apache/sis/gui/metadata/MetadataSummary.java   |  19 +-
 .../sis/gui/metadata/RepresentationInfo.java       |  15 +-
 .../org/apache/sis/gui/coverage/GridViewApp.java   |   6 +-
 .../sis/referencing/factory/sql/epsg/Clear.sql     |  31 +
 .../sis/referencing/factory/sql/epsg/README.md     |   3 +-
 settings.gradle.kts                                |   2 +-
 120 files changed, 1615 insertions(+), 1557 deletions(-)

diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/internal/GeometryFromFeature.java
index c221faf617,07244202f4..ac05d62d3d
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/internal/GeometryFromFeature.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/internal/GeometryFromFeature.java
@@@ -94,9 -95,9 +94,9 @@@ final class GeometryFromFeature<G> exte
       * @throws InvalidFilterValueException if the expression result is not an 
instance of a supported type.
       */
      @Override
 -    public GeometryWrapper apply(final Feature input) {
 +    public GeometryWrapper apply(final AbstractFeature input) {
          final GeometryWrapper wrapper = super.apply(input);
-         if (wrapper.getCoordinateReferenceSystem() == null) {
+         if (wrapper != null && wrapper.getCoordinateReferenceSystem() == 
null) {
              final CoordinateReferenceSystem crs = 
AttributeConvention.getCRSCharacteristic(input, propertyName);
              if (crs != null) {
                  wrapper.setCoordinateReferenceSystem(crs);
diff --cc 
endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/privy/FunctionNames.java
index ad709c9195,cd225b2019..fcd81f756a
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/privy/FunctionNames.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/privy/FunctionNames.java
@@@ -26,14 -25,14 +25,14 @@@ import org.apache.sis.filter.sqlmm.SQLM
   *
   * @author  Martin Desruisseaux (Geomatys)
   */
- public final class FunctionNames extends Static {
+ public final class FunctionNames {
 -    /** Value of {@link org.opengis.filter.NullOperator#getOperatorType()}. */
 +    /** Value of {@code NullOperator.getOperatorType()}. */
      public static final String PROPERTY_IS_NULL = "PROPERTY_IS_NULL";
  
 -    /** Value of {@link org.opengis.filter.NilOperator#getOperatorType()}. */
 +    /** Value of {@code NilOperator.getOperatorType()}. */
      public static final String PROPERTY_IS_NIL = "PROPERTY_IS_NIL";
  
 -    /** Value of {@link org.opengis.filter.LikeOperator#getOperatorType()}. */
 +    /** Value of {@code LikeOperator.getOperatorType()}. */
      public static final String PROPERTY_IS_LIKE = "PROPERTY_IS_LIKE";
  
      /** Value of {@link 
org.opengis.filter.BetweenComparisonOperator#getOperatorType()}. */
diff --cc 
endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/MetadataCopierTest.java
index 2384d256a4,61bfc965b1..09f1385c27
--- 
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/MetadataCopierTest.java
+++ 
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/MetadataCopierTest.java
@@@ -109,11 -109,11 +109,11 @@@ public final class MetadataCopierTest e
       */
      @Test
      public void testLocaleAndCharsets() {
-         final MetadataCopier copier = new 
MetadataCopier(MetadataStandard.ISO_19115);
-         final DefaultMetadata original = new DefaultMetadata();
+         final var copier = new MetadataCopier(MetadataStandard.ISO_19115);
+         final var original = new DefaultMetadata();
          original.getLocalesAndCharsets().put(Locale.FRENCH,   
StandardCharsets.UTF_8);
          original.getLocalesAndCharsets().put(Locale.JAPANESE, 
StandardCharsets.UTF_16);
 -        final Metadata copy = copier.copy(Metadata.class, original);
 +        final DefaultMetadata copy = (DefaultMetadata) 
copier.copy(Metadata.class, original);
          final Map<Locale,Charset> lc = copy.getLocalesAndCharsets();
          assertEquals(StandardCharsets.UTF_8,  lc.get(Locale.FRENCH));
          assertEquals(StandardCharsets.UTF_16, lc.get(Locale.JAPANESE));
diff --cc 
endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/extent/ExtentsTest.java
index 708ee86690,6a19364377..1990731a75
--- 
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/extent/ExtentsTest.java
+++ 
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/extent/ExtentsTest.java
@@@ -198,10 -207,10 +207,10 @@@ public final class ExtentsTest extends 
       * because it has a dependency to a referencing implementation class.
       */
      public static void testCentroid() {
-         final DefaultGeographicBoundingBox bbox = new 
DefaultGeographicBoundingBox(140, 160, 30, 50);
+         final var bbox = new DefaultGeographicBoundingBox(140, 160, 30, 50);
          DirectPosition pos = Extents.centroid(bbox);
 -        assertEquals(150, pos.getCoordinate(0), "longitude");
 -        assertEquals( 40, pos.getCoordinate(1), "latitude");
 +        assertEquals(150, pos.getOrdinate(0), "longitude");
 +        assertEquals( 40, pos.getOrdinate(1), "latitude");
          /*
           * Test crossing anti-meridian.
           */
diff --cc 
endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java
index ad6c648d21,3303bcbf70..788e1f9c6d
--- 
a/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java
+++ 
b/endorsed/src/org.apache.sis.openoffice/main/org/apache/sis/openoffice/ReferencingFunctions.java
@@@ -205,10 -197,9 +206,9 @@@ public class ReferencingFunctions exten
       */
      @Override
      public String getScope(final String codeOrPath) {
-         final Object value;
          try {
              final IdentifiedObject object = getIdentifiedObject(codeOrPath, 
null);
 -            for (final ObjectDomain domain : object.getDomains()) {
 +            for (final DefaultObjectDomain domain : 
Legacy.getDomains(object)) {
                  InternationalString scope = domain.getScope();
                  if (scope != null) {
                      return scope.toString(getJavaLocale());
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
index f6585af5e3,60fb930645..dc807bd6aa
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
@@@ -49,11 -53,14 +53,14 @@@ import org.apache.sis.io.wkt.ElementKin
  import org.apache.sis.io.wkt.Formatter;
  import static org.apache.sis.util.Utilities.deepEquals;
  
 -// Specific to the main and geoapi-3.1 branches:
 -import org.opengis.referencing.datum.ImageDatum;
 +// Specific to the main branch:
 +import org.opengis.referencing.ReferenceIdentifier;
 +import org.opengis.metadata.extent.Extent;
 +import org.apache.sis.referencing.internal.Legacy;
  
+ // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.metadata.Identifier;
 -import org.opengis.referencing.datum.DatumEnsemble;
 -import org.opengis.referencing.datum.DynamicReferenceFrame;
++import org.opengis.referencing.datum.ImageDatum;
+ 
  
  /**
   * Specifies the relationship of a Coordinate System to the earth.
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
index 356e26f71e,9f829213a4..fc4d2532b3
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
@@@ -127,13 -128,9 +128,14 @@@ import org.apache.sis.measure.NumberRan
  import org.apache.sis.measure.Units;
  import org.apache.sis.pending.jdk.JDK16;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.metadata.Identifier;
 -import org.opengis.referencing.ObjectDomain;
 +// Specific to the main branch:
 +import org.opengis.referencing.ObjectFactory;
++import org.opengis.referencing.ReferenceIdentifier;
 +import org.apache.sis.referencing.cs.DefaultParametricCS;
 +import org.apache.sis.referencing.datum.AbstractDatum;
 +import org.apache.sis.referencing.datum.DefaultParametricDatum;
 +import org.apache.sis.referencing.factory.GeodeticObjectFactory;
 +import org.apache.sis.temporal.TemporalDate;
  
  
  /**
@@@ -1237,7 -1234,43 +1239,43 @@@ search: try (ResultSet result = execute
      }
  
      /**
-      * Returns the name and aliases for the {@link IdentifiedObject} to 
construct.
+      * Returns the identifier for the {@link IdentifiedObject} to construct.
+      *
+      * @param  source       information about the table on which a query has 
been executed.
+      * @param  code         the <abbr>EPSG</abbr> code of the object to 
construct.
+      * @param  identifier   the code to assign to the identifier, usually 
{@code code.toString()}.
+      * @param  description  a description associated with the identifier. May 
be {@code null}.
+      * @param  deprecated   {@code true} if the object to create is 
deprecated.
+      * @return an identifier for the object to create.
+      */
 -    private Identifier createIdentifier(final TableInfo source, final int 
code, final String identifier,
++    private ReferenceIdentifier createIdentifier(final TableInfo source, 
final int code, final String identifier,
+             final InternationalString description, final Locale locale, final 
boolean deprecated)
+             throws SQLException, FactoryException
+     {
+         final Citation authority = owner.getAuthority();
+         final String version = Types.toString(authority.getEdition(), locale);
+         if (deprecated) {
+             final String replacedBy = getReplacement(source, code, locale);
+             return new DeprecatedCode(
+                     authority,
+                     Constants.EPSG,
+                     identifier,
+                     version,
+                     description,
+                     Character.isDigit(replacedBy.charAt(0)) ? replacedBy : 
null,
+                     
Vocabulary.formatInternational(Vocabulary.Keys.SupersededBy_1, replacedBy));
+         } else {
+             return new ImmutableIdentifier(
+                     authority,
+                     Constants.EPSG,
+                     identifier,
+                     version,
+                     description);
+         }
+     }
+ 
+     /**
+      * Returns the identifier, name and aliases for the {@link 
IdentifiedObject} to construct.
       *
       * <h4>Possible recursive calls</h4>
       * Invoking this method may cause a recursive call to {@link 
#createCoordinateReferenceSystem(String)}
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
index 110d6d8016,ea03bcfd57..6b330753ca
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
@@@ -482,17 -518,14 +523,14 @@@ check:      for (int isTarget=0; ; isTa
      }
  
      /**
-      * Returns {@code true} if this coordinate operation is for the 
definition of a
-      * {@linkplain org.apache.sis.referencing.crs.DefaultDerivedCRS derived} 
or
-      * {@linkplain org.apache.sis.referencing.crs.DefaultProjectedCRS 
projected CRS}.
-      * The standard (ISO 19111) approach constructs <i>defining conversion</i>
-      * as an operation of type {@link 
org.opengis.referencing.operation.Conversion}
-      * with null {@linkplain #getSourceCRS() source} and {@linkplain 
#getTargetCRS() target CRS}.
-      * But SIS supports also defining conversions with non-null CRS provided 
that:
+      * Returns whether this coordinate operation is for the definition of a 
derived or projected <abbr>CRS</abbr>.
+      * The <abbr>ISO</abbr> 19111 approach constructs <dfn>defining 
conversion</dfn> as an operation of type
+      * {@link Conversion} with null {@linkplain #getSourceCRS() source} and 
{@linkplain #getTargetCRS() target CRS}.
+      * But <abbr>SIS</abbr> supports also defining conversions with non-null 
<abbr>CRS</abbrr> provided that:
       *
       * <ul>
 -     *   <li>{@link DerivedCRS#getBaseCRS()} is the {@linkplain 
#getSourceCRS() source CRS} of this operation, and</li>
 -     *   <li>{@link DerivedCRS#getConversionFromBase()} is this operation 
instance.</li>
 +     *   <li>{@link GeneralDerivedCRS#getBaseCRS()} is the {@linkplain 
#getSourceCRS() source CRS} of this operation, and</li>
 +     *   <li>{@link GeneralDerivedCRS#getConversionFromBase()} is this 
operation instance.</li>
       * </ul>
       *
       * When this method returns {@code true}, the source and target CRS are 
not marshalled in XML documents.
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
index 8f1582cbd9,60778fc91d..3cf2c1ea83
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
@@@ -1154,10 -1152,10 +1154,10 @@@ class CoordinateOperationRegistry 
               */
              Matrix matrix = MathTransforms.getMatrix(op.getMathTransform());
              if (matrix == null) {
-                 if (SubTypes.isSingleOperation(op)) {
+                 if (AbstractCoordinateOperation.isSingleOperation(op)) {
                      if (forward) sourceCRS = toGeodetic3D(sourceCRS, 
source3D);
                      else         targetCRS = toGeodetic3D(targetCRS, 
target3D);
 -                    final MathTransform.Builder builder;
 +                    final MathTransformBuilder builder;
                      final MathTransform mt;
                      try {
                          final var parameters = ((SingleOperation) 
op).getParameterValues();
diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTUtilities.java
index 55f71871c0,9b4c150fea..93bfbecbd6
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTUtilities.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTUtilities.java
@@@ -468,4 -471,38 +474,40 @@@ fill:   for (;;) 
          }
          return numbers;
      }
+ 
+     /**
+      * Returns a description of the given extent. If the description is too 
long, tries to find a shorter one.
+      * In the particular case of extents created by {@link 
org.apache.sis.referencing.factory.sql.EPSGDataAccess},
+      * a shorter name is available as a geographic identifier in the 
<abbr>EPSG</abbr> namespace.
+      * This is a name similar to the name of an {@link IdentifiedObject}, 
which is also an {@link Identifier}.
+      * In the latter case, this method checks that the first character is a 
letter for avoiding to return a
+      * numerical <abbr>EPSG</abbr> code.
+      *
+      * @param  extent  the extent from which to get a description.
+      * @return description of medium length for the given extent, or {@code 
null} if none.
+      */
+     public static InternationalString descriptionOfMediumLength(final Extent 
extent) {
+         InternationalString description = extent.getDescription();
+         if (description != null && description.length() > 255) {    // 255 is 
the limit recommended by ISO 19162:2019.
+             if (Extents.isWorld(extent)) {
+                 description = Extents.WORLD.getDescription();
+             } else {
+                 for (GeographicExtent element : 
extent.getGeographicElements()) {
+                     if (element instanceof GeographicDescription) {
+                         Identifier id = ((GeographicDescription) 
element).getGeographicIdentifier();
 -                        if (id != null && 
Constants.EPSG.equalsIgnoreCase(id.getCodeSpace())) {
++                        if (id instanceof ReferenceIdentifier &&
++                                
Constants.EPSG.equalsIgnoreCase(((ReferenceIdentifier) id).getCodeSpace()))
++                        {
+                             String name = id.getCode();
+                             if (name != null && !name.isEmpty() && 
Character.isLetter(name.codePointAt(0))) {
+                                 description = new 
SimpleInternationalString(name);
+                                 break;
+                             }
+                         }
+                     }
+                 }
+             }
+         }
+         return description;
+     }
  }
diff --cc 
endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/postgis/PostgresTest.java
index 29d315030b,927b7fe9d4..16ea0d6487
--- 
a/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/postgis/PostgresTest.java
+++ 
b/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/postgis/PostgresTest.java
@@@ -67,9 -69,8 +69,10 @@@ import org.apache.sis.test.TestUtilitie
  import org.apache.sis.metadata.sql.TestDatabase;
  import org.apache.sis.referencing.crs.HardCodedCRS;
  
 -// Specific to the geoapi-3.1 and geoapi-4.0 branches:
 -import org.opengis.feature.Feature;
 +// Specific to the main branch:
 +import org.apache.sis.feature.AbstractFeature;
++import org.apache.sis.pending.geoapi.filter.Literal;
 +import org.apache.sis.metadata.iso.identification.AbstractIdentification;
  
  
  /**
@@@ -265,6 -266,61 +269,61 @@@ public final class PostgresTest extend
          }
      }
  
+     /**
+      * Tests the {@code ST_Transform} <abbr>SQLMM</abbr> operation.
+      *
+      * @param  resource  the set of all features.
+      */
+     private static void testGeometryTransform(final FeatureSet resource) 
throws Exception {
+         final var factory   = DefaultFilterFactory.forFeatures();
 -        final var targetCRS = 
factory.literal(GeometryGetterTest.getExpectedCRS(4326));
++        final var targetCRS = (Literal<AbstractFeature,?>) 
factory.literal(GeometryGetterTest.getExpectedCRS(4326));
+         final var geometry  = factory.function("ST_Transform", 
factory.property("geometry"), targetCRS);
+         final var alias     = factory.function("ST_Transform", 
factory.property(AttributeConvention.GEOMETRY), targetCRS);
+         final var query     = new FeatureQuery();
+         query.setProjection(new 
FeatureQuery.NamedExpression(factory.property("filename")),
+                             new FeatureQuery.NamedExpression(geometry, 
"transformed"),
+                             new FeatureQuery.NamedExpression(alias),
+                             new 
FeatureQuery.NamedExpression(factory.property("image")));
+         final FeatureSet subset = resource.subset(query);
+         assertNull(getCRSCharacteristic(resource, "geometry"), "Expected no 
CRS because it is not the same for all rows.");
+         assertNull(getCRSCharacteristic(resource, 
AttributeConvention.GEOMETRY));
+         assertEquals(targetCRS.getValue(), getCRSCharacteristic(subset, 
"transformed"));
+         assertEquals(targetCRS.getValue(), getCRSCharacteristic(subset, 
AttributeConvention.GEOMETRY));
+         subset.features(false).forEach(PostgresTest::validateTransformed);
+     }
+ 
+     /**
+      * Invoked for each feature instances which is expected to have been 
transformed to WGS84.
+      */
 -    private static void validateTransformed(final Feature feature) {
++    private static void validateTransformed(final AbstractFeature feature) {
+         final Geometry geometry;
+         switch (feature.getPropertyValue("filename").toString()) {
+             case "point-prj": {
+                 final var p = (Point) feature.getPropertyValue("transformed");
+                 assertEquals(1.79663056824E-5, p.getX(), 1E-14);
+                 assertEquals(2.71310843105E-5, p.getY(), 1E-14);
+                 geometry = p;
+                 break;
+             }
+             case "polygon-prj": {
+                 geometry = (Geometry) feature.getPropertyValue("transformed");
+                 final var envelope = geometry.getEnvelopeInternal();
+                 // Tolerance is specified even if zero in order to ignore the 
sign of zero.
+                 assertEquals(0, envelope.getMinX(), 0);
+                 assertEquals(0, envelope.getMinY(), 0);
+                 assertEquals(8.983152841195214E-6, envelope.getMaxX(), 1E-14);
+                 assertEquals(9.043694770179478E-6, envelope.getMaxY(), 1E-14);
+                 break;
+             }
+             default: {
+                 validate(feature);
+                 return;
+             }
+         }
+         verifySRID(4326, geometry);
+         assertEquals(geometry, 
feature.getPropertyValue(AttributeConvention.GEOMETRY));
+     }
+ 
      /**
       * Invoked for each feature instances for performing some checks on the 
feature.
       * This method performs only a superficial verification of geometries.
diff --cc 
endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/FeatureQuery.java
index a0a15a293b,83ff095436..0d4d665fd4
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/FeatureQuery.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/FeatureQuery.java
@@@ -550,9 -550,12 +551,12 @@@ public class FeatureQuery extends Quer
          /**
           * The literal, value reference or more complex expression to be 
retrieved by a {@code Query}.
           * Never {@code null}.
+          *
+          * @deprecated Replaced by {@link #expression()} in preparation for 
making {@code NamedExpression} a record.
           */
+         @Deprecated(since = "1.5")
          @SuppressWarnings("serial")
 -        public final Expression<? super Feature, ?> expression;
 +        public final Expression<? super AbstractFeature, ?> expression;
  
          /**
           * The name to assign to the expression result, or {@code null} if 
unspecified.
@@@ -562,12 -568,15 +569,15 @@@
  
          /**
           * Whether the expression result should be stored or evaluated every 
times that it is requested.
 -         * A stored value will exist as a feature {@link Attribute}, while a 
virtual value will exist as
 -         * a feature {@link Operation}. The latter are commonly called 
"computed fields" and are equivalent
 +         * A stored value will exist as a feature {@link AbstractAttribute}, 
while a virtual value will exist as
 +         * a feature {@link AbstractOperation}. The latter are commonly 
called "computed fields" and are equivalent
           * to SQL {@code GENERATED ALWAYS} keyword for columns.
           *
+          * @deprecated Replaced by {@link #type()} in preparation for making 
{@code NamedExpression} a record.
+          *
           * @since 1.4
           */
+         @Deprecated(since = "1.5")
          public final ProjectionType type;
  
          /**
@@@ -639,6 -648,37 +649,37 @@@
              return false;
          }
  
+         /**
+          * The literal, value reference or more complex expression to be 
retrieved by a {@code Query}.
+          * Never {@code null}.
+          *
+          * @since 1.5
+          */
 -        public Expression<? super Feature, ?> expression() {
++        public Expression<? super AbstractFeature, ?> expression() {
+             return expression;
+         }
+ 
+         /**
+          * The name to assign to the expression result, or {@code null} if 
unspecified.
+          *
+          * @since 1.5
+          */
+         public GenericName alias() {
+             return alias;
+         }
+ 
+         /**
+          * Whether the expression result should be stored or evaluated every 
times that it is requested.
+          * A stored value will exist as a feature {@link Attribute}, while a 
virtual value will exist as
+          * a feature {@link Operation}. The latter are commonly called 
"computed fields" and are equivalent
+          * to SQL {@code GENERATED ALWAYS} keyword for columns.
+          *
+          * @since 1.5
+          */
+         public ProjectionType type() {
+             return type;
+         }
+ 
          /**
           * Returns a hash code value for this column.
           *
@@@ -764,8 -804,8 +805,8 @@@
          for (int column = 0; column < projection.length; column++) {
              final NamedExpression item = projection[column];
              if (!item.addTo(builder)) {
-                 final var name = 
item.expression.getFunctionName().toInternationalString();
+                 final var name = 
item.expression().getFunctionName().toInternationalString();
 -                throw new 
InvalidFilterValueException(Resources.forLocale(locale)
 +                throw new IllegalArgumentException(Resources.forLocale(locale)
                              .getString(Resources.Keys.InvalidExpression_2, 
column, name));
              }
          }
diff --cc 
optional/src/org.apache.sis.referencing.epsg/test/org/apache/sis/referencing/factory/sql/epsg/README.md
index a01089249f,63331bd775..c1955a0588
--- 
a/optional/src/org.apache.sis.referencing.epsg/test/org/apache/sis/referencing/factory/sql/epsg/README.md
+++ 
b/optional/src/org.apache.sis.referencing.epsg/test/org/apache/sis/referencing/factory/sql/epsg/README.md
@@@ -113,8 -113,9 +113,9 @@@ Adjust version numbers as needed in th
  cd _<path to SIS project directory>_
  gradle clean test jar
  export 
CLASSPATH=~/.m2/repository/org/apache/derby/derby/10.14.2.0/derby-10.14.2.0.jar
+ export 
CLASSPATH=~/.m2/repository/org/postgresql/postgresql/42.7.7/postgresql-42.7.7.jar:$CLASSPATH
  export 
CLASSPATH=~/.m2/repository/javax/measure/unit-api/2.1.3/unit-api-2.1.3.jar:$CLASSPATH
 -export 
CLASSPATH=$PWD/geoapi/snapshot/geoapi/target/geoapi-3.1-SNAPSHOT.jar:$CLASSPATH
 +export 
CLASSPATH=$PWD/geoapi/snapshot/geoapi/target/geoapi-3.0.2.jar:$CLASSPATH
  export 
CLASSPATH=$PWD/endorsed/build/libs/org.apache.sis.referencing.jar:$CLASSPATH
  export 
CLASSPATH=$PWD/endorsed/build/libs/org.apache.sis.metadata.jar:$CLASSPATH
  export CLASSPATH=$PWD/endorsed/build/libs/org.apache.sis.util.jar:$CLASSPATH

Reply via email to