This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push: new 6fd7c530f7 Use the SIS-specific `DefaultGeocentricCRS` class in one place where we removed the `GeocentricCRS` interface. This is needed for avoiding an ambiguity when searching codes in an EPSG database. 6fd7c530f7 is described below commit 6fd7c530f7d5181b5dd2fc5bb86af2ba2cc73999 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Tue Apr 16 11:50:09 2024 +0200 Use the SIS-specific `DefaultGeocentricCRS` class in one place where we removed the `GeocentricCRS` interface. This is needed for avoiding an ambiguity when searching codes in an EPSG database. --- .../sis/referencing/crs/DefaultTemporalCRS.java | 1 + .../referencing/factory/AuthorityFactoryProxy.java | 1 + .../factory/ConcurrentAuthorityFactory.java | 2 ++ .../factory/GeodeticAuthorityFactory.java | 2 ++ .../referencing/factory/GeodeticObjectFactory.java | 4 +++ .../factory/MultiAuthoritiesFactory.java | 2 ++ .../referencing/factory/sql/AuthorityCodes.java | 10 ++++--- .../referencing/factory/sql/EPSGCodeFinder.java | 2 +- .../sis/referencing/factory/sql/TableInfo.java | 35 ++++++++++++++++++++-- 9 files changed, 52 insertions(+), 7 deletions(-) diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java index 8a55606a48..3644a65a34 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java @@ -152,6 +152,7 @@ public class DefaultTemporalCRS extends AbstractCRS implements TemporalCRS { * * @see org.apache.sis.referencing.factory.GeodeticObjectFactory#createTemporalCRS(Map, TemporalDatum, TimeCS) */ + @SuppressWarnings("this-escape") public DefaultTemporalCRS(final Map<String,?> properties, final TemporalDatum datum, final TimeCS cs) diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java index 8947411b87..7893b80b77 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/AuthorityFactoryProxy.java @@ -543,6 +543,7 @@ abstract class AuthorityFactoryProxy<T> { static final AuthorityFactoryProxy<?>[] PROXIES = new AuthorityFactoryProxy<?>[] { PROJECTED_CRS, // Special kind of GeneralDerivedCRS. GEOGRAPHIC_CRS, // Special kind of GeodeticCRS. + GEODETIC_CRS, VERTICAL_CRS, TEMPORAL_CRS, ENGINEERING_CRS, diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java index 34e23dddab..f7d6ab7758 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java @@ -937,6 +937,8 @@ public abstract class ConcurrentAuthorityFactory<DAO extends GeodeticAuthorityFa * * @return the coordinate reference system for the given code. * @throws FactoryException if the object creation failed. + * + * @since 1.5 */ @Override public GeodeticCRS createGeodeticCRS(final String code) throws FactoryException { diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java index 4985f629fc..d32f19d9bc 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java @@ -332,6 +332,8 @@ public abstract class GeodeticAuthorityFactory extends AbstractFactory implement * * @see org.apache.sis.referencing.crs.DefaultGeocentricCRS * @see org.apache.sis.referencing.CommonCRS#geocentric() + * + * @since 1.5 */ public GeodeticCRS createGeodeticCRS(final String code) throws NoSuchAuthorityCodeException, FactoryException { return cast(GeodeticCRS.class, createCoordinateReferenceSystem(code), code); diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java index 666eb45942..5ad6bca3f5 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java @@ -342,6 +342,8 @@ public class GeodeticObjectFactory extends AbstractFactory implements CRSFactory * * @see GeodeticAuthorityFactory#createGeodeticCRS(String) * @see DefaultGeocentricCRS#DefaultGeocentricCRS(Map, GeodeticDatum, CartesianCS) + * + * @since 1.5 */ @Override public GeodeticCRS createGeodeticCRS(final Map<String,?> properties, @@ -420,6 +422,8 @@ public class GeodeticObjectFactory extends AbstractFactory implements CRSFactory * * @see DefaultGeocentricCRS#DefaultGeocentricCRS(Map, GeodeticDatum, SphericalCS) * @see GeodeticAuthorityFactory#createGeodeticCRS(String) + * + * @since 1.5 */ @Override public GeodeticCRS createGeodeticCRS(final Map<String,?> properties, diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java index 55fe728fb9..0bcfff9048 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java @@ -956,6 +956,8 @@ public class MultiAuthoritiesFactory extends GeodeticAuthorityFactory implements * * @return the coordinate reference system for the given code. * @throws FactoryException if the object creation failed. + * + * @since 1.5 */ @Override public GeodeticCRS createGeodeticCRS(final String code) throws FactoryException { diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/AuthorityCodes.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/AuthorityCodes.java index a226b0cad9..9fd9585b36 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/AuthorityCodes.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/AuthorityCodes.java @@ -28,6 +28,7 @@ import org.opengis.referencing.operation.Projection; import org.apache.sis.util.collection.BackingStoreException; import org.apache.sis.util.collection.IntegerList; import org.apache.sis.util.privy.AbstractMap; +import org.apache.sis.util.privy.Strings; /** @@ -336,17 +337,18 @@ final class AuthorityCodes extends AbstractMap<String,String> implements Seriali /** * Returns a string representation of this map for debugging purpose. - * This method does not let the default implementation format all entry, since it would be a costly operation. + * This method does not let the default implementation formats all entries, + * because it would be a costly operation. */ @Override public String toString() { - final StringBuilder buffer = new StringBuilder("AuthorityCodes[").append(type.getSimpleName()); + String size = null; synchronized (factory) { if (codes != null) { - buffer.append(", size ").append(results != null ? ">= " : "= ").append(codes.size()); + size = "size " + (results != null ? "≥ " : "= ") + codes.size(); } } - return buffer.append(']').toString(); + return Strings.toString(getClass(), "type", type.getSimpleName(), null, size); } /** diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGCodeFinder.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGCodeFinder.java index 85a92aab3b..04d74233f7 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGCodeFinder.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGCodeFinder.java @@ -420,7 +420,7 @@ crs: if (isInstance(CoordinateReferenceSystem.class, object)) { * It may be absent (typically, only datums or reference frames have that condition). */ buffer.append("SELECT ").append(table.codeColumn).append(" FROM ").append(table.table); - table.where(object.getClass(), buffer); // Unconditionally append a "WHERE" clause. + table.where(object, buffer); // Unconditionally append a "WHERE" clause. boolean isNext = false; for (final Condition filter : filters) { isNext |= filter.appendToWhere(buffer, isNext); diff --git a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/TableInfo.java b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/TableInfo.java index 1b16b321d5..c7ed64c976 100644 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/TableInfo.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/TableInfo.java @@ -21,10 +21,14 @@ import org.opengis.referencing.cs.*; import org.opengis.referencing.crs.*; import org.opengis.referencing.datum.*; import org.opengis.referencing.operation.*; +import org.opengis.referencing.IdentifiedObject; import org.opengis.parameter.ParameterDescriptor; import org.apache.sis.referencing.privy.WKTKeywords; import org.apache.sis.util.CharSequences; +// Specific to the geoapi-4.0 branch: +import org.apache.sis.referencing.crs.DefaultGeocentricCRS; + /** * Information about a specific table. The MS-Access dialect of SQL is assumed; @@ -60,6 +64,12 @@ final class TableInfo { * {@link EPSGDataAccess#createUnit(String)} * * The order is significant: it is the key for a {@code switch} statement. + * + * <h4>Ambiguity</h4> + * As of ISO 19111:2019, we have no standard way to identify the geocentric case from a {@link Class} argument + * because the standard does not provide the {@code GeocentricCRS} interface. This implementation fallbacks on + * the SIS-specific geocentric CRS class, with a {@link #where(IdentifiedObject, StringBuilder)} method which + * will substitute implementation-neutral objects by the Apache SIS class. */ static final TableInfo[] EPSG = { CRS = new TableInfo(CoordinateReferenceSystem.class, @@ -67,7 +77,7 @@ final class TableInfo { "COORD_REF_SYS_CODE", "COORD_REF_SYS_NAME", "COORD_REF_SYS_KIND", - new Class<?>[] { ProjectedCRS.class, GeographicCRS.class, GeodeticCRS.class, + new Class<?>[] { ProjectedCRS.class, GeographicCRS.class, DefaultGeocentricCRS.class, VerticalCRS.class, CompoundCRS.class, EngineeringCRS.class, DerivedCRS.class, TemporalCRS.class, ParametricCRS.class}, // See comment below new String[] {"projected", "geographic", "geocentric", @@ -249,6 +259,27 @@ final class TableInfo { return CharSequences.isAcronymForWords(name, expected); } + /** + * Appends a {@code WHERE} clause together with a condition for searching the specified object. + * This method delegates to {@link #where(Class, StringBuilder)} with the type of the given object, + * except that some object properties may be inspected for resolving ambiguities. + * + * @param object the object to search in the database. + * @param buffer where to append the {@code WHERE} clause. + */ + final void where(final IdentifiedObject object, final StringBuilder buffer) { + Class<?> userType = object.getClass(); + if (object instanceof GeodeticCRS) { + final CoordinateSystem cs = ((GeodeticCRS) object).getCoordinateSystem(); + if (cs instanceof EllipsoidalCS) { + userType = GeographicCRS.class; + } else if (cs instanceof CartesianCS || cs instanceof SphericalCS) { + userType = DefaultGeocentricCRS.class; + } + } + where(userType, buffer); + } + /** * Appends a {@code WHERE} clause together with a condition for searching the most specific subtype, * if such condition can be added. The clause appended by this method looks like the following example @@ -262,7 +293,7 @@ final class TableInfo { * * @param userType the type specified by the user. * @param buffer where to append the {@code WHERE} clause. - * @return the subtype, or {@link #type} if no subtype was found. + * @return the subtype, or {@link #type} if no subtype was found. */ final Class<?> where(final Class<?> userType, final StringBuilder buffer) { buffer.append(" WHERE ");