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
