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 0ee27a9df1 Provide more context in the internal 
`createMapProjection(…)` method. This is needed when the projection needs to 
delegate to another method. This change replaces 
`NormalizedProjection.delegate(…)`.
0ee27a9df1 is described below

commit 0ee27a9df15a5cdcd1e2afd46195770265bae9da
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Apr 24 13:06:36 2024 +0200

    Provide more context in the internal `createMapProjection(…)` method.
    This is needed when the projection needs to delegate to another method.
    This change replaces `NormalizedProjection.delegate(…)`.
---
 .../operation/projection/AlbersEqualArea.java      | 19 +++---
 .../operation/projection/CassiniSoldner.java       | 16 ++---
 .../operation/projection/CylindricalEqualArea.java | 19 +++---
 .../projection/LambertConicConformal.java          | 19 +++---
 .../referencing/operation/projection/Mercator.java | 19 +++---
 .../projection/ModifiedAzimuthalEquidistant.java   | 19 +++---
 .../operation/projection/NormalizedProjection.java | 74 +++++-----------------
 .../operation/projection/ObliqueStereographic.java | 27 ++++----
 .../operation/projection/PolarStereographic.java   | 19 +++---
 .../operation/projection/Polyconic.java            | 19 +++---
 .../operation/projection/SatelliteTracking.java    | 16 ++---
 .../operation/projection/Sinusoidal.java           | 19 +++---
 .../operation/projection/TransverseMercator.java   | 26 +++++---
 .../operation/provider/MapProjection.java          |  2 +-
 .../operation/provider/PolarStereographicA.java    | 19 ++++++
 .../operation/transform/MathTransformProvider.java |  6 +-
 .../projection/LambertAzimuthalEqualAreaTest.java  |  2 +-
 .../projection/MapProjectionTestCase.java          | 26 ++++++++
 .../operation/projection/ObliqueMercatorTest.java  |  3 +-
 .../projection/ObliqueStereographicTest.java       |  4 +-
 20 files changed, 190 insertions(+), 183 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/AlbersEqualArea.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/AlbersEqualArea.java
index 02d52e111b..a4300e7976 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/AlbersEqualArea.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/AlbersEqualArea.java
@@ -21,7 +21,6 @@ import static java.lang.Math.*;
 import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.OperationMethod;
 import org.apache.sis.referencing.privy.Formulas;
@@ -33,6 +32,7 @@ import org.apache.sis.parameter.Parameters;
 import org.apache.sis.referencing.operation.matrix.Matrix2;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
+import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import static org.apache.sis.referencing.operation.provider.AlbersEqualArea.*;
 
 
@@ -186,24 +186,23 @@ public class AlbersEqualArea extends AuthalicConversion {
     }
 
     /**
-     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms
-     * as a whole. The transform returned by this method expects 
(<var>longitude</var>, <var>latitude</var>)
-     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) 
coordinates in <em>metres</em>.
+     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms as a whole.
+     * The transform returned by this method expects (<var>longitude</var>, 
<var>latitude</var>) coordinates
+     * in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates 
in <em>metres</em>.
+     * The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
+     * is spherical. In the latter case, {@code this} transform is replaced by 
a simplified implementation.
      *
-     * <p>The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
-     * is spherical. In the latter case, {@code this} transform may be 
replaced by a simplified implementation.</p>
-     *
-     * @param  factory The factory to use for creating the transform.
+     * @param  parameters  parameters and the factory to use for creating the 
transform.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates.
      * @throws FactoryException if an error occurred while creating a 
transform.
      */
     @Override
-    public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
+    public MathTransform createMapProjection(final 
MathTransformProvider.Context parameters) throws FactoryException {
         AlbersEqualArea kernel = this;
         if (eccentricity == 0) {
             kernel = new Spherical(this);
         }
-        return kernel.completeWithWraparound(factory);
+        return kernel.completeWithWraparound(parameters);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/CassiniSoldner.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/CassiniSoldner.java
index ea77cbb804..2fb4d233d2 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/CassiniSoldner.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/CassiniSoldner.java
@@ -22,12 +22,12 @@ import static java.lang.Math.*;
 import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.OperationMethod;
 import org.apache.sis.referencing.operation.matrix.Matrix2;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
+import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import org.apache.sis.referencing.operation.provider.HyperbolicCassiniSoldner;
 import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.parameter.Parameters;
@@ -209,23 +209,23 @@ public class CassiniSoldner extends MeridianArcBased {
     }
 
     /**
-     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms
-     * as a whole. The transform returned by this method expects 
(<var>longitude</var>, <var>latitude</var>)
-     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) 
coordinates in <em>metres</em>.
+     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms as a whole.
+     * The transform returned by this method expects (<var>longitude</var>, 
<var>latitude</var>) coordinates
+     * in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates 
in <em>metres</em>.
      * The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
-     * is spherical. In the latter case, {@code this} transform may be 
replaced by a simplified implementation.
+     * is spherical. In the latter case, {@code this} transform is replaced by 
a simplified implementation.
      *
-     * @param  factory  the factory to use for creating the transform.
+     * @param  parameters  parameters and the factory to use for creating the 
transform.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates.
      * @throws FactoryException if an error occurred while creating a 
transform.
      */
     @Override
-    public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
+    public MathTransform createMapProjection(final 
MathTransformProvider.Context parameters) throws FactoryException {
         CassiniSoldner kernel = this;
         if (eccentricity == 0 && variant == null) {
             kernel = new Spherical(this);
         }
-        return context.completeTransform(factory, kernel);
+        return context.completeTransform(parameters.getFactory(), kernel);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/CylindricalEqualArea.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/CylindricalEqualArea.java
index 2404ba7fdb..e27c23a72f 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/CylindricalEqualArea.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/CylindricalEqualArea.java
@@ -21,7 +21,6 @@ import java.util.regex.Pattern;
 import static java.lang.Math.*;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.TransformException;
@@ -34,6 +33,7 @@ import org.apache.sis.parameter.Parameters;
 import org.apache.sis.referencing.operation.matrix.Matrix2;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
+import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import static 
org.apache.sis.referencing.operation.provider.LambertCylindricalEqualArea.*;
 
 
@@ -194,24 +194,23 @@ public class CylindricalEqualArea extends 
AuthalicConversion {
     }
 
     /**
-     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms
-     * as a whole. The transform returned by this method expects 
(<var>longitude</var>, <var>latitude</var>)
-     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) 
coordinates in <em>metres</em>.
+     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms as a whole.
+     * The transform returned by this method expects (<var>longitude</var>, 
<var>latitude</var>) coordinates
+     * in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates 
in <em>metres</em>.
+     * The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
+     * is spherical. In the latter case, {@code this} transform is replaced by 
a simplified implementation.
      *
-     * <p>The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
-     * is spherical. In the latter case, {@code this} transform may be 
replaced by a simplified implementation.</p>
-     *
-     * @param  factory  the factory to use for creating the transform.
+     * @param  parameters  parameters and the factory to use for creating the 
transform.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates.
      * @throws FactoryException if an error occurred while creating a 
transform.
      */
     @Override
-    public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
+    public MathTransform createMapProjection(final 
MathTransformProvider.Context parameters) throws FactoryException {
         CylindricalEqualArea kernel = this;
         if (variant == Variant.SPHERICAL || eccentricity == 0) {
             kernel = new Spherical(this);
         }
-        return context.completeTransform(factory, kernel);
+        return context.completeTransform(parameters.getFactory(), kernel);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
index d6a6074bdb..7428ce5a6a 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/LambertConicConformal.java
@@ -25,7 +25,6 @@ import org.opengis.geometry.Envelope;
 import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.Matrix;
 import org.apache.sis.measure.Latitude;
@@ -35,6 +34,7 @@ import org.apache.sis.referencing.operation.matrix.Matrix2;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.transform.DomainDefinition;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
+import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import org.apache.sis.referencing.operation.provider.LambertConformal1SP;
 import org.apache.sis.referencing.operation.provider.LambertConformal2SP;
 import org.apache.sis.referencing.operation.provider.LambertConformalWest;
@@ -384,24 +384,23 @@ public class LambertConicConformal extends 
ConformalProjection {
     }
 
     /**
-     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms
-     * as a whole. The transform returned by this method expects 
(<var>longitude</var>, <var>latitude</var>)
-     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) 
coordinates in <em>metres</em>.
+     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms as a whole.
+     * The transform returned by this method expects (<var>longitude</var>, 
<var>latitude</var>) coordinates
+     * in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates 
in <em>metres</em>.
+     * The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
+     * is spherical. In the latter case, {@code this} transform is replaced by 
a simplified implementation.
      *
-     * <p>The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
-     * is spherical. In the latter case, {@code this} transform may be 
replaced by a simplified implementation.</p>
-     *
-     * @param  factory  the factory to use for creating the transform.
+     * @param  parameters  parameters and the factory to use for creating the 
transform.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates.
      * @throws FactoryException if an error occurred while creating a 
transform.
      */
     @Override
-    public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
+    public MathTransform createMapProjection(final 
MathTransformProvider.Context parameters) throws FactoryException {
         LambertConicConformal kernel = this;
         if (eccentricity == 0) {
             kernel = new Spherical(this);
         }
-        return kernel.completeWithWraparound(factory);
+        return kernel.completeWithWraparound(parameters);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Mercator.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Mercator.java
index 55a1b96a7c..29452d770e 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Mercator.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Mercator.java
@@ -26,7 +26,6 @@ import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.geometry.Envelope2D;
@@ -43,6 +42,7 @@ import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.referencing.operation.transform.DomainDefinition;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
+import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import org.apache.sis.parameter.Parameters;
 import org.apache.sis.util.resources.Errors;
 import static org.apache.sis.math.MathFunctions.isPositive;
@@ -334,19 +334,18 @@ public class Mercator extends ConformalProjection {
     }
 
     /**
-     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms
-     * as a whole. The transform returned by this method expects 
(<var>longitude</var>, <var>latitude</var>)
-     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) 
coordinates in <em>metres</em>.
+     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms as a whole.
+     * The transform returned by this method expects (<var>longitude</var>, 
<var>latitude</var>) coordinates
+     * in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates 
in <em>metres</em>.
+     * The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
+     * is spherical. In the latter case, {@code this} transform is replaced by 
a simplified implementation.
      *
-     * <p>The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
-     * is spherical. In the latter case, {@code this} transform may be 
replaced by a simplified implementation.</p>
-     *
-     * @param  factory  the factory to use for creating the transform.
+     * @param  parameters  parameters and the factory to use for creating the 
transform.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates.
      * @throws FactoryException if an error occurred while creating a 
transform.
      */
     @Override
-    public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
+    public MathTransform createMapProjection(final 
MathTransformProvider.Context parameters) throws FactoryException {
         NormalizedProjection kernel = this;
 subst:  if (variant.spherical || eccentricity == 0) {
             if (variant == Variant.AUXILIARY && eccentricity != 0) {
@@ -358,7 +357,7 @@ subst:  if (variant.spherical || eccentricity == 0) {
             }
             kernel = new Spherical(this);
         }
-        return kernel.completeWithWraparound(factory);
+        return kernel.completeWithWraparound(parameters);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/ModifiedAzimuthalEquidistant.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/ModifiedAzimuthalEquidistant.java
index 5741659cd6..897efef1c9 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/ModifiedAzimuthalEquidistant.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/ModifiedAzimuthalEquidistant.java
@@ -21,11 +21,11 @@ import static java.lang.Math.*;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.parameter.ParameterDescriptor;
 import org.apache.sis.parameter.Parameters;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
+import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.util.Workaround;
 import static 
org.apache.sis.referencing.operation.provider.ModifiedAzimuthalEquidistant.*;
@@ -127,24 +127,23 @@ public class ModifiedAzimuthalEquidistant extends 
AzimuthalEquidistant {
     }
 
     /**
-     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms
-     * as a whole. The transform returned by this method expects 
(<var>longitude</var>, <var>latitude</var>)
-     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) 
coordinates in <em>metres</em>.
+     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms as a whole.
+     * The transform returned by this method expects (<var>longitude</var>, 
<var>latitude</var>) coordinates
+     * in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates 
in <em>metres</em>.
+     * The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
+     * is spherical. In the latter case, {@code this} transform is replaced by 
a simplified implementation.
      *
-     * <p>The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
-     * is spherical. In the latter case, {@code this} transform may be 
replaced by a simplified implementation.</p>
-     *
-     * @param  factory  the factory to use for creating the transform.
+     * @param  parameters  parameters and the factory to use for creating the 
transform.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates.
      * @throws FactoryException if an error occurred while creating a 
transform.
      */
     @Override
-    public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
+    public MathTransform createMapProjection(final 
MathTransformProvider.Context parameters) throws FactoryException {
         AzimuthalEquidistant kernel = this;
         if (eccentricity == 0) {
             kernel = new AzimuthalEquidistant(this);
         }
-        return context.completeTransform(factory, kernel);
+        return context.completeTransform(parameters.getFactory(), kernel);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
index dc6906976b..8b22d9f146 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
@@ -20,7 +20,6 @@ import java.util.Arrays;
 import java.util.Map;
 import java.util.HashMap;
 import java.util.Objects;
-import java.util.OptionalInt;
 import java.util.regex.Pattern;
 import java.io.Serializable;
 import java.lang.reflect.Modifier;
@@ -31,7 +30,6 @@ import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransform2D;
-import org.opengis.referencing.operation.SingleOperation;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.referencing.operation.MathTransformFactory;
@@ -46,16 +44,13 @@ import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.transform.AbstractMathTransform2D;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
-import 
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import org.apache.sis.referencing.operation.transform.DomainDefinition;
 import org.apache.sis.referencing.operation.provider.MapProjection;
-import org.apache.sis.referencing.privy.CoordinateOperations;
 import org.apache.sis.referencing.privy.Formulas;
 import org.apache.sis.system.Modules;
 import org.apache.sis.util.privy.Constants;
 import org.apache.sis.util.privy.Numerics;
-import org.apache.sis.util.resources.Errors;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.metadata.Identifier;
@@ -198,8 +193,8 @@ public abstract class NormalizedProjection extends 
AbstractMathTransform2D imple
 
     /**
      * The parameters used for creating this projection. They are used for 
formatting <i>Well Known Text</i> (WKT)
-     * and error messages. Subclasses shall not use the values defined in this 
object for computation purpose, except at
-     * construction time.
+     * and error messages. Subclasses shall not use the values defined in this 
object for computation purpose,
+     * except at construction time.
      *
      * @see #getContextualParameters()
      */
@@ -493,29 +488,29 @@ public abstract class NormalizedProjection extends 
AbstractMathTransform2D imple
     }
 
     /**
-     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms
-     * as a whole. The transform returned by this method expects 
(<var>longitude</var>, <var>latitude</var>)
-     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) 
coordinates in <em>metres</em>.
+     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms as a whole.
+     * The transform returned by this method expects (<var>longitude</var>, 
<var>latitude</var>) coordinates
+     * in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates 
in <em>metres</em>.
      * Conversion to other units and {@linkplain 
org.apache.sis.referencing.cs.CoordinateSystems#swapAndScaleAxes
      * changes in axis order} are <strong>not</strong> managed by the returned 
transform.
      *
      * <p>The default implementation is as below:</p>
      * {@snippet lang="java" :
-     *     return getContextualParameters().completeTransform(factory, this);
+     *     return 
getContextualParameters().completeTransform(parameters.getFactory(), this);
      *     }
      *
      * Subclasses can override this method if they wish to use alternative 
implementations under some circumstances.
-     * For example, many subclasses will replace {@code this} by a specialized 
implementation if they detect that the
-     * ellipsoid is actually spherical.
+     * For example, many subclasses will replace {@code this} by a simplified 
implementation if they detect that
+     * the ellipsoid is actually spherical.
      *
-     * @param  factory  the factory to use for creating the transform.
+     * @param  parameters  parameters and the factory to use for creating the 
transform.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates.
      * @throws FactoryException if an error occurred while creating a 
transform.
      *
      * @see ContextualParameters#completeTransform(MathTransformFactory, 
MathTransform)
      */
-    public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
-        return context.completeTransform(factory, this);
+    public MathTransform createMapProjection(final 
MathTransformProvider.Context parameters) throws FactoryException {
+        return context.completeTransform(parameters.getFactory(), this);
     }
 
     /**
@@ -543,13 +538,13 @@ public abstract class NormalizedProjection extends 
AbstractMathTransform2D imple
      * by some factor before to be used in trigonometric functions, then that 
implicit wraparound is not the
      * one we expect. The map projection code needs to perform explicit 
wraparound in such cases.
      *
-     * @param  factory  the factory to use for completing the transform with 
normalization/denormalization steps.
+     * @param  parameters  parameters and the factory to use for creating the 
normalization/denormalization steps.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates with wraparound if needed.
      * @throws FactoryException if an error occurred while creating a 
transform.
      *
      * @see <a href="https://issues.apache.org/jira/browse/SIS-486";>SIS-486</a>
      */
-    final MathTransform completeWithWraparound(final MathTransformFactory 
factory) throws FactoryException {
+    final MathTransform completeWithWraparound(final 
MathTransformProvider.Context parameters) throws FactoryException {
         MathTransform kernel = this;
         final MatrixSIS normalize = 
context.getMatrix(ContextualParameters.MatrixRole.NORMALIZATION);
         final double rotation = normalize.getElement(0, DIMENSION);
@@ -557,46 +552,7 @@ public abstract class NormalizedProjection extends 
AbstractMathTransform2D imple
             kernel = new LongitudeWraparound(this,
                     LongitudeWraparound.boundOfScaledLongitude(normalize, 
rotation < 0), rotation);
         }
-        return context.completeTransform(factory, kernel);
-    }
-
-    /**
-     * If this map projection cannot handle the parameters given by the user 
but another projection could, delegates
-     * to the other projection. This method can be invoked by some {@link 
#createMapProjection(MathTransformFactory)}
-     * implementations when the other projection can be seen as a special case.
-     *
-     * <div class="note"><b>Example:</b>
-     * the {@link ObliqueStereographic} formulas do not work anymore when the 
latitude of origin is 90°N or 90°S,
-     * because some internal coefficients become infinite. However, the {@link 
PolarStereographic} implementation
-     * is designed especially for those special cases. So the {@code 
ObliqueStereographic.createMapProjection(…)}
-     * method can redirect to {@code 
PolarStereographic.createMapProjection(…)} when it detects such cases.</div>
-     *
-     * It is caller's responsibility to choose an alternative method that can 
understand the parameters which were
-     * given to this original projection.
-     *
-     * @param  factory  the factory given to {@link 
#createMapProjection(MathTransformFactory)}.
-     * @param  name     the name of the alternative map projection to use.
-     * @return the alternative projection.
-     * @throws FactoryException if an error occurred while creating the 
alternative projection.
-     */
-    final MathTransform delegate(final MathTransformFactory factory, final 
String name) throws FactoryException {
-        final OperationMethod method;
-        if (factory instanceof DefaultMathTransformFactory) {
-            method = ((DefaultMathTransformFactory) 
factory).getOperationMethod(name);
-        } else {
-            method = 
CoordinateOperations.getOperationMethod(factory.getAvailableMethods(SingleOperation.class),
 name);
-        }
-        if (method instanceof MathTransformProvider) {
-            return ((MathTransformProvider) method).createMathTransform(new 
MathTransformProvider.Context() {
-                @Override public MathTransformFactory getFactory() {return 
factory;}
-                @Override public OptionalInt getSourceDimensions() {return 
OptionalInt.of(DIMENSION);}
-                @Override public OptionalInt getTargetDimensions() {return 
OptionalInt.of(DIMENSION);}
-                @Override public ParameterValueGroup getCompletedParameters() 
{return context;}
-            });
-        } else {
-            throw new 
FactoryException(Errors.format(Errors.Keys.UnsupportedImplementation_1,
-                    (method != null ? method : factory).getClass()));
-        }
+        return context.completeTransform(parameters.getFactory(), kernel);
     }
 
     /**
@@ -670,7 +626,7 @@ public abstract class NormalizedProjection extends 
AbstractMathTransform2D imple
                     builder.setCodeSpace(Citations.SIS, Constants.SIS);
                 }
                 final String[] names = getInternalParameterNames();
-                final ParameterDescriptor<?>[] parameters = new 
ParameterDescriptor<?>[names.length + 1];
+                final var parameters = new ParameterDescriptor<?>[names.length 
+ 1];
                 parameters[0] = MapProjection.ECCENTRICITY;
                 for (int i=1; i<parameters.length; i++) {
                     parameters[i] = 
builder.addName(names[i-1]).create(Double.class, null);
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/ObliqueStereographic.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/ObliqueStereographic.java
index 23543d00d9..7f2374945c 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/ObliqueStereographic.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/ObliqueStereographic.java
@@ -22,12 +22,12 @@ import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.util.FactoryException;
 import org.apache.sis.parameter.Parameters;
 import org.apache.sis.referencing.operation.matrix.Matrix2;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
+import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import org.apache.sis.referencing.operation.provider.PolarStereographicA;
 import org.apache.sis.referencing.privy.Formulas;
 import org.apache.sis.referencing.internal.Resources;
@@ -210,34 +210,37 @@ public class ObliqueStereographic extends 
NormalizedProjection {
     }
 
     /**
-     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms
-     * as a whole. The transform returned by this method expects 
(<var>longitude</var>, <var>latitude</var>)
-     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) 
coordinates in <em>metres</em>.
+     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms as a whole.
+     * The transform returned by this method expects (<var>longitude</var>, 
<var>latitude</var>) coordinates
+     * in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates 
in <em>metres</em>.
+     * The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
+     * is spherical. In the latter case, {@code this} transform is replaced by 
a simplified implementation.
      *
-     * <p>The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
-     * is spherical. In the latter case, {@code this} transform may be 
replaced by a simplified implementation.</p>
-     *
-     * @param  factory  the factory to use for creating the transform.
+     * @param  parameters  parameters and the factory to use for creating the 
transform.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates.
      * @throws FactoryException if an error occurred while creating a 
transform.
      */
     @Override
-    public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
+    public MathTransform createMapProjection(final 
MathTransformProvider.Context parameters) throws FactoryException {
         if (Double.isNaN(χ0)) {
             /*
              * The oblique stereographic formulas cannot handle the polar case.
              * If the user gave us a latitude of origin of ±90°, delegate to 
the
              * polar stereographic which is designed especially for those 
cases.
+             *
+             * Note: the GeoTIFF parameter name and code for the central 
meridian is different.
+             * But the delegation should still work if EPSG, ESRI or OGC names 
are also present.
+             * It should be the case if the parameter descriptor group was 
provided by SIS.
              */
             final Double φ0 = context.getValue(LATITUDE_OF_ORIGIN);
             if (φ0 != null && abs(abs(φ0) - 90) < Formulas.ANGULAR_TOLERANCE) {
-                return delegate(factory, PolarStereographicA.NAME);
+                return 
PolarStereographicA.provider().createMathTransform(parameters);
             }
         }
         if (eccentricity == 0) {
-            return context.completeTransform(factory, new Spherical(this));
+            return context.completeTransform(parameters.getFactory(), new 
Spherical(this));
         }
-        return completeWithWraparound(factory);
+        return completeWithWraparound(parameters);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/PolarStereographic.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/PolarStereographic.java
index 2570839bb2..62573b1b42 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/PolarStereographic.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/PolarStereographic.java
@@ -24,7 +24,6 @@ import org.opengis.geometry.Envelope;
 import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.Matrix;
 import org.apache.sis.geometry.Envelope2D;
@@ -32,6 +31,7 @@ import org.apache.sis.referencing.operation.matrix.Matrix2;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.transform.DomainDefinition;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
+import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import org.apache.sis.referencing.operation.provider.PolarStereographicA;
 import org.apache.sis.referencing.operation.provider.PolarStereographicB;
 import org.apache.sis.referencing.operation.provider.PolarStereographicC;
@@ -278,24 +278,23 @@ public class PolarStereographic extends 
ConformalProjection {
     }
 
     /**
-     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms
-     * as a whole. The transform returned by this method expects 
(<var>longitude</var>, <var>latitude</var>)
-     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) 
coordinates in <em>metres</em>.
+     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms as a whole.
+     * The transform returned by this method expects (<var>longitude</var>, 
<var>latitude</var>) coordinates
+     * in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates 
in <em>metres</em>.
+     * The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
+     * is spherical. In the latter case, {@code this} transform is replaced by 
a simplified implementation.
      *
-     * <p>The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
-     * is spherical. In the latter case, {@code this} transform may be 
replaced by a simplified implementation.</p>
-     *
-     * @param  factory  the factory to use for creating the transform.
+     * @param  parameters  parameters and the factory to use for creating the 
transform.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates.
      * @throws FactoryException if an error occurred while creating a 
transform.
      */
     @Override
-    public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
+    public MathTransform createMapProjection(final 
MathTransformProvider.Context parameters) throws FactoryException {
         PolarStereographic kernel = this;
         if (eccentricity == 0) {
             kernel = new Spherical(this);
         }
-        return context.completeTransform(factory, kernel);
+        return context.completeTransform(parameters.getFactory(), kernel);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Polyconic.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Polyconic.java
index ba83f9ea60..fd079ce026 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Polyconic.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Polyconic.java
@@ -23,10 +23,10 @@ import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
 import org.apache.sis.referencing.operation.matrix.Matrix2;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
+import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.parameter.Parameters;
 import org.apache.sis.util.Workaround;
@@ -141,24 +141,23 @@ public class Polyconic extends MeridianArcBased {
     }
 
     /**
-     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms
-     * as a whole. The transform returned by this method expects 
(<var>longitude</var>, <var>latitude</var>)
-     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) 
coordinates in <em>metres</em>.
+     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms as a whole.
+     * The transform returned by this method expects (<var>longitude</var>, 
<var>latitude</var>) coordinates
+     * in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates 
in <em>metres</em>.
+     * The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
+     * is spherical. In the latter case, {@code this} transform is replaced by 
a simplified implementation.
      *
-     * <p>The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
-     * is spherical. In the latter case, {@code this} transform may be 
replaced by a simplified implementation.</p>
-     *
-     * @param  factory  the factory to use for creating the transform.
+     * @param  parameters  parameters and the factory to use for creating the 
transform.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates.
      * @throws FactoryException if an error occurred while creating a 
transform.
      */
     @Override
-    public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
+    public MathTransform createMapProjection(final 
MathTransformProvider.Context parameters) throws FactoryException {
         Polyconic kernel = this;
         if (eccentricity == 0) {
             kernel = new Spherical(this);
         }
-        return context.completeTransform(factory, kernel);
+        return context.completeTransform(parameters.getFactory(), kernel);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/SatelliteTracking.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/SatelliteTracking.java
index 207b74d87c..f58370efe3 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/SatelliteTracking.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/SatelliteTracking.java
@@ -23,13 +23,13 @@ import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.InvalidParameterValueException;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.OperationMethod;
 import org.apache.sis.referencing.privy.Formulas;
 import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.referencing.operation.matrix.Matrix2;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
+import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import org.apache.sis.parameter.Parameters;
 import org.apache.sis.measure.Latitude;
 import org.apache.sis.util.Workaround;
@@ -215,20 +215,20 @@ public class SatelliteTracking extends 
NormalizedProjection {
     }
 
     /**
-     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms
-     * as a whole. The transform returned by this method expects 
(<var>longitude</var>, <var>latitude</var>)
-     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) 
coordinates in <em>metres</em>.
+     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms as a whole.
+     * The transform returned by this method expects (<var>longitude</var>, 
<var>latitude</var>) coordinates
+     * in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates 
in <em>metres</em>.
      *
-     * @param  factory The factory to use for creating the transform.
+     * @param  parameters  parameters and the factory to use for creating the 
transform.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates.
      * @throws FactoryException if an error occurred while creating a 
transform.
      */
     @Override
-    public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
+    public MathTransform createMapProjection(final 
MathTransformProvider.Context parameters) throws FactoryException {
         if (isConic) {
-            return completeWithWraparound(factory);
+            return completeWithWraparound(parameters);
         } else {
-            return super.createMapProjection(factory);
+            return super.createMapProjection(parameters);
         }
     }
 
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Sinusoidal.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Sinusoidal.java
index 0b8952bd6b..00123d060a 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Sinusoidal.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/Sinusoidal.java
@@ -24,9 +24,9 @@ import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.referencing.operation.matrix.Matrix2;
+import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import org.apache.sis.parameter.Parameters;
 import org.apache.sis.util.Workaround;
 import static org.apache.sis.referencing.operation.provider.Sinusoidal.*;
@@ -139,24 +139,23 @@ public class Sinusoidal extends MeridianArcBased {
     }
 
     /**
-     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms
-     * as a whole. The transform returned by this method expects 
(<var>longitude</var>, <var>latitude</var>)
-     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) 
coordinates in <em>metres</em>.
+     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms as a whole.
+     * The transform returned by this method expects (<var>longitude</var>, 
<var>latitude</var>) coordinates
+     * in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates 
in <em>metres</em>.
+     * The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
+     * is spherical. In the latter case, {@code this} transform is replaced by 
a simplified implementation.
      *
-     * <p>The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
-     * is spherical. In the latter case, {@code this} transform may be 
replaced by a simplified implementation.</p>
-     *
-     * @param  factory  the factory to use for creating the transform.
+     * @param  parameters  parameters and the factory to use for creating the 
transform.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates.
      * @throws FactoryException if an error occurred while creating a 
transform.
      */
     @Override
-    public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
+    public MathTransform createMapProjection(final 
MathTransformProvider.Context parameters) throws FactoryException {
         Sinusoidal kernel = this;
         if (eccentricity == 0 || variant == Variant.PSEUDO) {
             kernel = new Spherical(this);
         }
-        return context.completeTransform(factory, kernel);
+        return context.completeTransform(parameters.getFactory(), kernel);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/TransverseMercator.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/TransverseMercator.java
index ec6a7222f3..be6579a88a 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/TransverseMercator.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/TransverseMercator.java
@@ -32,6 +32,7 @@ import org.apache.sis.referencing.operation.matrix.Matrix2;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.transform.DomainDefinition;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
+import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import org.apache.sis.referencing.operation.provider.TransverseMercatorSouth;
 import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.util.Workaround;
@@ -342,19 +343,28 @@ public class TransverseMercator extends 
NormalizedProjection {
     }
 
     /**
-     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms
-     * as a whole. The transform returned by this method expects 
(<var>longitude</var>, <var>latitude</var>)
-     * coordinates in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) 
coordinates in <em>metres</em>.
+     * Returns the sequence of <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms as a whole.
+     * The transform returned by this method expects (<var>longitude</var>, 
<var>latitude</var>) coordinates
+     * in <em>degrees</em> and returns (<var>x</var>,<var>y</var>) coordinates 
in <em>metres</em>.
+     * The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
+     * is spherical. In the latter case, {@code this} transform is replaced by 
a simplified implementation.
      *
-     * <p>The non-linear part of the returned transform will be {@code this} 
transform, except if the ellipsoid
-     * is spherical. In the latter case, {@code this} transform may be 
replaced by a simplified implementation.</p>
-     *
-     * @param  factory  the factory to use for creating the transform.
+     * @param  parameters  parameters and the factory to use for creating the 
transform.
      * @return the map projection from (λ,φ) to (<var>x</var>,<var>y</var>) 
coordinates.
      * @throws FactoryException if an error occurred while creating a 
transform.
      */
     @Override
-    public MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
+    public MathTransform createMapProjection(final 
MathTransformProvider.Context parameters) throws FactoryException {
+        return createMapProjection(parameters.getFactory());
+    }
+
+    /**
+     * Creates the <i>normalization</i> → {@code this} → 
<i>denormalization</i> transforms.
+     * This method is defined for {@link ZonedGridSystem} implementation.
+     *
+     * @param  factory  the factory to use for creating the transform.
+     */
+    final MathTransform createMapProjection(final MathTransformFactory 
factory) throws FactoryException {
         TransverseMercator kernel = this;
         if (eccentricity == 0) {
             kernel = new Spherical(this);
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/MapProjection.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/MapProjection.java
index 114fe3e8a4..b76d237aa5 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/MapProjection.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/MapProjection.java
@@ -231,7 +231,7 @@ public abstract class MapProjection extends 
AbstractProvider {
     @Override
     public final MathTransform createMathTransform(final Context context) 
throws FactoryException {
         return maybe3D(context, 
createProjection(Parameters.castOrWrap(context.getCompletedParameters()))
-                               .createMapProjection(context.getFactory()));
+                               .createMapProjection(context));
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/PolarStereographicA.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/PolarStereographicA.java
index d2322a848c..5676b80cfd 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/PolarStereographicA.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/PolarStereographicA.java
@@ -139,8 +139,27 @@ public final class PolarStereographicA extends 
AbstractStereographic {
                         FALSE_NORTHING);
     }
 
+    /**
+     * The canonical instance of this map projection.
+     *
+     * @see #provider()
+     */
+    private static final PolarStereographicA INSTANCE = new 
PolarStereographicA();
+
+    /**
+     * Returns the canonical instance of this map projection.
+     * This method is invoked by {@link java.util.ServiceLoader} using 
reflection.
+     *
+     * @return the canonical instance of this map projection.
+     */
+    public static PolarStereographicA provider() {
+        return INSTANCE;
+    }
+
     /**
      * Constructs a new provider.
+     *
+     * @todo Make this constructor private after we stop class-path support.
      */
     public PolarStereographicA() {
         super(PARAMETERS);
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransformProvider.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransformProvider.java
index 5086e9df40..a215ab8718 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransformProvider.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/MathTransformProvider.java
@@ -158,9 +158,13 @@ public interface MathTransformProvider {
          * This is often the factory which is invoking the {@link 
#createMathTransform(Context)} method,
          * but not necessarily.
          *
+         * <p>The default implementation returns the {@link 
DefaultMathTransformFactory}.</p>
+         *
          * @return the factory to use if the provider needs to create other 
math transforms.
          */
-        MathTransformFactory getFactory();
+        default MathTransformFactory getFactory() {
+            return DefaultMathTransformFactory.provider();
+        }
 
         /**
          * Returns the desired number of source dimensions.
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/LambertAzimuthalEqualAreaTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/LambertAzimuthalEqualAreaTest.java
index 84569f636e..d58e2954f0 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/LambertAzimuthalEqualAreaTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/LambertAzimuthalEqualAreaTest.java
@@ -78,7 +78,7 @@ public final class LambertAzimuthalEqualAreaTest extends 
MapProjectionTestCase {
         parameters.parameter("latitude_of_origin").setValue(latitudeOfOrigin);
         LambertAzimuthalEqualArea projection = new 
LambertAzimuthalEqualArea(provider, parameters);
         if (complete) {
-            transform = projection.createMapProjection(new 
MathTransformFactoryMock(provider));
+            transform = projection.createMapProjection(context(new 
MathTransformFactoryMock(provider), parameters));
         } else {
             transform = projection;
         }
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
index c748170c3e..83aebfe4e1 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java
@@ -23,12 +23,15 @@ import org.opengis.util.FactoryException;
 import org.opengis.referencing.datum.Ellipsoid;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
+import org.opengis.referencing.operation.MathTransformFactory;
+import org.opengis.parameter.ParameterValueGroup;
 import org.apache.sis.parameter.Parameters;
 import org.apache.sis.util.privy.Constants;
 import org.apache.sis.referencing.operation.DefaultOperationMethod;
 import org.apache.sis.referencing.operation.provider.MapProjection;
 import org.apache.sis.referencing.operation.transform.CoordinateDomain;
 import org.apache.sis.referencing.operation.transform.MathTransformFactoryMock;
+import org.apache.sis.referencing.operation.transform.MathTransformProvider;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
 import org.apache.sis.referencing.datum.GeodeticDatumMock;
 
@@ -101,6 +104,29 @@ abstract class MapProjectionTestCase extends 
MathTransformTestCase {
         return new Tester(provider);
     }
 
+    /**
+     * Creates a context with the given factory and parameters, used for map 
projection construction.
+     * The given parameters should not be {@code null}, but this method 
nevertheless accepts null when
+     * the caller knows that the tested code will not use parameters.
+     *
+     * @param  factory     the factory to use, or {@code null} for the default 
one.
+     * @param  parameters  the parameters. Should not be null, but null is 
nevertheless accepted for testing purposes.
+     * @return the context to use in map projection construction.
+     */
+    static MathTransformProvider.Context context(final MathTransformFactory 
factory, final ParameterValueGroup parameters) {
+        return new MathTransformProvider.Context() {
+            /** Returns the specified factory, or the default one if none. */
+            @Override public MathTransformFactory getFactory() {
+                return (factory != null) ? factory : 
MathTransformProvider.Context.super.getFactory();
+            }
+
+            /** Returns the specified parameters (possible null). */
+            @Override public ParameterValueGroup getCompletedParameters() {
+                return parameters;
+            }
+        };
+    }
+
     /**
      * Returns the parameters to use for instantiating the projection to test.
      * The parameters are initialized with the ellipse semi-axis lengths.
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ObliqueMercatorTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ObliqueMercatorTest.java
index b74a70b6a6..8438d9af2a 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ObliqueMercatorTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ObliqueMercatorTest.java
@@ -29,7 +29,6 @@ import org.junit.jupiter.api.Test;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.util.FactoryException;
-import 
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.opengis.test.ToleranceModifier;
 
 
@@ -113,7 +112,7 @@ public final class ObliqueMercatorTest extends 
MapProjectionTestCase {
     @Test
     public void testPole() throws TransformException, FactoryException {
         tolerance = 0.01;
-        transform = create(179.8, 89.8, 
-174).createMapProjection(DefaultMathTransformFactory.provider());
+        transform = create(179.8, 89.8, 
-174).createMapProjection(context(null, null));
         transform = transform.inverse();
         validate();
         /*
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ObliqueStereographicTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ObliqueStereographicTest.java
index 147efdcc44..fb792d08e5 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ObliqueStereographicTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ObliqueStereographicTest.java
@@ -23,7 +23,6 @@ import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.util.FactoryException;
 import org.apache.sis.parameter.Parameters;
-import 
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.apache.sis.referencing.operation.transform.ContextualParameters;
 import org.apache.sis.referencing.privy.Formulas;
 import org.apache.sis.measure.Units;
@@ -147,8 +146,7 @@ public final class ObliqueStereographicTest extends 
MapProjectionTestCase {
      * created by above {@link #createNormalizedProjection(boolean)} method.
      */
     private void createCompleteTransform(final OperationMethod op, final 
ParameterValueGroup p) throws FactoryException {
-        transform = new ObliqueStereographic(op, (Parameters) 
p).createMapProjection(
-                DefaultMathTransformFactory.provider());
+        transform = new ObliqueStereographic(op, (Parameters) 
p).createMapProjection(context(null, p));
     }
 
     /**

Reply via email to