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 e79df9c2d3 Ensure that recursive method calls to `EPSGFactory` reach
the same factory instance. Opportunistic documentation fixes.
e79df9c2d3 is described below
commit e79df9c2d3f81a6dd6be593795f18b8d41a65873
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Tue Aug 5 11:11:42 2025 +0200
Ensure that recursive method calls to `EPSGFactory` reach the same factory
instance.
Opportunistic documentation fixes.
---
.../apache/sis/coverage/grid/GridDerivation.java | 2 +-
.../main/org/apache/sis/referencing/CRS.java | 22 ++++++++++++-----
.../referencing/factory/sql/EPSGDataAccess.java | 28 ++++++++++++++++++++--
.../internal/ParameterizedTransformBuilder.java | 9 +++++++
4 files changed, 52 insertions(+), 9 deletions(-)
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 a1932913f5..7ad8920b1f 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
@@ -615,7 +615,7 @@ public class GridDerivation {
nowraparound = finder.gridToGrid();
/*
* At this point, the transform between the coordinate systems
of the two grids is known.
- * The `gridToGrid` transform is the main one. If the user did
not specified an AOI for
+ * The `gridToGrid` transform is the main one. If the user did
not specify an AOI for
* all dimensions, then `gridToGrid` is for low coordinates
and `gridToGridHigh` is for
* high coordinates.
*/
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
index 84becac5f3..aa52105478 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
@@ -81,6 +81,7 @@ import
org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory;
import org.apache.sis.referencing.operation.DefaultConversion;
import org.apache.sis.referencing.factory.GeodeticObjectFactory;
import org.apache.sis.referencing.factory.UnavailableFactoryException;
+import org.apache.sis.referencing.internal.ParameterizedTransformBuilder;
import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
import org.apache.sis.metadata.iso.extent.Extents;
import org.apache.sis.util.ArgumentChecks;
@@ -88,6 +89,7 @@ import org.apache.sis.util.OptionalCandidate;
import org.apache.sis.util.Static;
import org.apache.sis.util.Utilities;
import org.apache.sis.util.privy.Numerics;
+import org.apache.sis.util.privy.Constants;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.logging.Logging;
@@ -1564,18 +1566,20 @@ check: while (lower != 0 || upper != dimension) {
}
/**
- * Returns the system-wide authority factory used by {@link
#forCode(String)} and other SIS methods.
+ * Returns the system-wide authority factory used by {@link
#forCode(String)} and other <abbr>SIS</abbr> methods.
* If the given authority is non-null, then this method returns a factory
specifically for that authority.
* Otherwise, this method returns the {@link
org.apache.sis.referencing.factory.MultiAuthoritiesFactory}
* instance that manages all other factories.
*
- * <p>The {@code authority} argument can be {@code "EPSG"}, {@code "OGC"}
or any other authority found
- * on the module path. In the {@code "EPSG"} case, whether the full set of
EPSG codes is supported or not
+ * <p>The {@code authority} argument can be {@code "EPSG"}, {@code "OGC"}
+ * or any other authority found on the module path.
+ * In the {@code "EPSG"} case, whether the full set of <abbr>EPSG</abbr>
codes is supported or not
* depends on whether a {@linkplain org.apache.sis.referencing.factory.sql
connection to the database}
* can be established. If no connection can be established, then this
method returns a small embedded
- * EPSG factory containing at least the CRS defined in the {@link
#forCode(String)} method javadoc.</p>
+ * <abbr>EPSG</abbr> factory containing at least the <abbr>CRS</abbr>s
defined in the
+ * {@link #forCode(String)} method javadoc.</p>
*
- * <p>User-defined authorities can be added to the SIS environment by
creating a {@code CRSAuthorityFactory}
+ * <p>User-defined authorities can be added to the <abbr>SIS</abbr>
environment by creating a {@code CRSAuthorityFactory}
* implementation with a public no-argument constructor or a public static
{@code provider()} method,
* and declaring the name of that class in the {@code module-info.java}
file as a provider of the
* {@code org.opengis.referencing.crs.CRSAuthorityFactory} service.</p>
@@ -1583,7 +1587,7 @@ check: while (lower != 0 || upper != dimension) {
* @param authority the authority of the desired factory (typically
{@code "EPSG"} or {@code "OGC"}),
* or {@code null} for the {@link
org.apache.sis.referencing.factory.MultiAuthoritiesFactory}
* instance that manage all factories.
- * @return the system-wide authority factory used by SIS for the given
authority.
+ * @return the system-wide authority factory used by <abbr>SIS</abbr> for
the given authority.
* @throws FactoryException if no factory can be returned for the given
authority.
*
* @see MultiRegisterOperations
@@ -1594,6 +1598,12 @@ check: while (lower != 0 || upper != dimension) {
if (authority == null) {
return AuthorityFactories.ALL;
}
+ if (authority.equalsIgnoreCase(Constants.EPSG)) {
+ CRSAuthorityFactory factory =
ParameterizedTransformBuilder.CREATOR.get();
+ if (factory != null) {
+ return factory;
+ }
+ }
return
AuthorityFactories.ALL.getAuthorityFactory(CRSAuthorityFactory.class,
authority, null);
}
diff --git
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
index 44aff1352a..59997d0496 100644
---
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
@@ -1505,6 +1505,30 @@ search: try (ResultSet result =
executeMetadataQuery("Deprecation",
R create(F factory, Map<String, Object> properties) throws
FactoryException;
}
+ /**
+ * Invokes the {@code create(…)} method of the given constructor in a
block which ensures that recursive method
+ * calls will be redirected to this factory. This is needed only when the
constructor may indirectly invoke the
+ * {@link org.apache.sis.referencing.CRS#getAuthorityFactory(String)}
method.
+ */
+ private <F extends Factory, R extends IdentifiedObject> R create(
+ final FactoryCall<F, R> constructor,
+ final F factory,
+ final Map<String, Object> properties) throws FactoryException
+ {
+ final ThreadLocal<CRSAuthorityFactory> caller =
ParameterizedTransformBuilder.CREATOR;
+ final CRSAuthorityFactory old = caller.get();
+ caller.set(owner);
+ try {
+ return constructor.create(factory, properties);
+ } finally {
+ if (old != null) {
+ caller.set(old);
+ } else {
+ caller.remove();
+ }
+ }
+ }
+
/**
* Creates an arbitrary coordinate reference system from a code.
* The returned object will typically be an instance of {@link
GeographicCRS}, {@link ProjectedCRS},
@@ -1785,7 +1809,7 @@ search: try (ResultSet result =
executeMetadataQuery("Deprecation",
@SuppressWarnings("LocalVariableHidesMemberVariable")
final Map<String,Object> properties = createProperties(
"Coordinate Reference System", epsg, name, null, area,
scope, remarks, deprecated);
- final CoordinateReferenceSystem crs =
constructor.create(owner.crsFactory, properties);
+ final CoordinateReferenceSystem crs = create(constructor,
owner.crsFactory, properties);
returnValue = ensureSingleton(crs, returnValue, code);
if (result.isClosed()) break; // See createProperties(…) for
explanation.
}
@@ -3316,7 +3340,7 @@ next: while (r.next()) {
properties.put(CoordinateOperation .OPERATION_VERSION_KEY,
version);
properties.put(CoordinateOperation
.COORDINATE_OPERATION_ACCURACY_KEY,
PositionalAccuracyConstant.transformation(accuracy));
- CoordinateOperation operation =
constructor.create(owner.copFactory, properties);
+ CoordinateOperation operation = create(constructor,
owner.copFactory, properties);
returnValue = ensureSingleton(operation, returnValue, code);
if (result.isClosed()) break; // See createProperties(…) for
explanation.
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ParameterizedTransformBuilder.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ParameterizedTransformBuilder.java
index a9b2cda5df..b970f5f415 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ParameterizedTransformBuilder.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/ParameterizedTransformBuilder.java
@@ -39,6 +39,7 @@ import org.opengis.referencing.operation.MathTransformFactory;
import org.opengis.referencing.operation.OperationMethod;
import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.crs.CRSAuthorityFactory;
import org.opengis.util.NoSuchIdentifierException;
import org.opengis.util.FactoryException;
import org.apache.sis.util.ArgumentChecks;
@@ -90,6 +91,14 @@ import org.opengis.util.UnimplementedServiceException;
* @author Martin Desruisseaux (Geomatys)
*/
public class ParameterizedTransformBuilder extends MathTransformBuilder
implements MathTransformProvider.Context {
+ /**
+ * The factory which is creating the coordinate operation.
+ * The value is read indirectly by {@link
#getMatrix(ContextualParameters.MatrixRole)}
+ * when normalizing axes, because it invokes a method that may search for
the authority
+ * codes of normalized coordinate systems.
+ */
+ public static final ThreadLocal<CRSAuthorityFactory> CREATOR = new
ThreadLocal<>();
+
/**
* Minimal precision of ellipsoid semi-major and semi-minor axis lengths,
in metres.
* If the length difference between the axis of two ellipsoids is greater
than this threshold,