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 6011e9f39f Consolidation in the way to get or create 
`OperationMethod`: - No longer specify the number of dimensions in constructor. 
- Search of predefined instance based only on `MathTransformFactory`,   using a 
convenience method added in `ReferencingFactoryContainer`.
6011e9f39f is described below

commit 6011e9f39f98c535098fd6634c08d3aa29414a67
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Tue Jun 25 18:21:51 2024 +0200

    Consolidation in the way to get or create `OperationMethod`:
    - No longer specify the number of dimensions in constructor.
    - Search of predefined instance based only on `MathTransformFactory`,
      using a convenience method added in `ReferencingFactoryContainer`.
---
 .../apache/sis/io/wkt/GeodeticObjectParser.java    |  7 ++-
 .../org/apache/sis/io/wkt/MathTransformParser.java | 22 +++++-----
 .../operation/CoordinateOperationRegistry.java     |  5 +--
 .../DefaultCoordinateOperationFactory.java         | 20 ++-------
 .../transform/DefaultMathTransformFactory.java     |  7 +--
 .../referencing/privy/CoordinateOperations.java    | 26 ++++++++---
 .../referencing/privy/GeodeticObjectBuilder.java   |  4 +-
 .../privy/ReferencingFactoryContainer.java         | 51 ++++++++++++++++++++--
 .../sis/storage/geotiff/reader/CRSBuilder.java     | 17 ++++++--
 .../apache/sis/storage/netcdf/base/CRSBuilder.java |  9 ++--
 .../apache/sis/storage/netcdf/base/Decoder.java    | 13 +++++-
 .../sis/storage/netcdf/base/GridMapping.java       |  5 ++-
 .../sis/storage/netcdf/classic/ChannelDecoder.java |  4 +-
 .../sis/storage/netcdf/ucar/DecoderWrapper.java    |  2 +-
 .../sis/util/resources/IndexedResourceBundle.java  |  2 +-
 geoapi/snapshot                                    |  2 +-
 16 files changed, 127 insertions(+), 69 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
index 5ba9431ebc..7c1d29de28 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
@@ -1286,15 +1286,14 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
          * not use the identifier.
          */
         FactoryException suppressed = null;
-        final CoordinateOperationFactory opFactory = 
factories.getCoordinateOperationFactory();
         if (id != null) try {
             // CodeSpace is a mandatory attribute in ID[…] elements, so we do 
not test for null values.
-            return opFactory.getOperationMethod(id.getCodeSpace() + 
Constants.DEFAULT_SEPARATOR + id.getCode());
+            return factories.findOperationMethod(id.getCodeSpace() + 
Constants.DEFAULT_SEPARATOR + id.getCode());
         } catch (FactoryException e) {
             suppressed = e;
         }
         try {
-            return opFactory.getOperationMethod(name);
+            return factories.findOperationMethod(name);
         } catch (FactoryException e) {
             if (suppressed != null) {
                 e.addSuppressed(suppressed);
@@ -2221,7 +2220,7 @@ class GeodeticObjectParser extends MathTransformParser 
implements Comparator<Coo
         }
         final String                    name    = element.pullString("name");
         final MathTransform             toBase  = parseMathTransform(element, 
true);
-        final OperationMethod           method  = getOperationMethod();
+        final OperationMethod           method  = getOperationMethod(element);
         final CoordinateReferenceSystem baseCRS = 
parseCoordinateReferenceSystem(element, true);
         if (!(baseCRS instanceof SingleCRS)) {
             throw new UnparsableObjectException(errorLocale, 
Errors.Keys.UnexpectedValueInElement_2,
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/MathTransformParser.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/MathTransformParser.java
index 0e2c75750f..282575dc0a 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/MathTransformParser.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/MathTransformParser.java
@@ -33,12 +33,10 @@ import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterNotFoundException;
 import org.opengis.parameter.InvalidParameterValueException;
-import org.opengis.referencing.operation.SingleOperation;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.NoninvertibleTransformException;
 import org.opengis.referencing.operation.OperationMethod;
-import org.apache.sis.referencing.privy.CoordinateOperations;
 import org.apache.sis.referencing.privy.ReferencingFactoryContainer;
 import org.apache.sis.referencing.privy.WKTKeywords;
 import org.apache.sis.parameter.DefaultParameterValue;
@@ -120,7 +118,7 @@ class MathTransformParser extends AbstractParser {
     /**
      * The method for the last math transform passed, or {@code null} if none.
      *
-     * @see #getOperationMethod()
+     * @see #getOperationMethod(Element)
      */
     private transient OperationMethod lastMethod;
 
@@ -527,19 +525,23 @@ class MathTransformParser extends AbstractParser {
     }
 
     /**
-     * Returns the operation method for the last math transform parsed. This 
is used by
-     * {@link GeodeticObjectParser} in order to build {@link 
org.opengis.referencing.crs.DerivedCRS}.
+     * Returns the operation method for the last math transform parsed, or 
{@code null} if unspecified.
+     * This is used by {@link GeodeticObjectParser} in order to build {@link 
org.opengis.referencing.crs.DerivedCRS}.
+     *
+     * @param  element  the element being parsed. Used in case an exception 
must be thrown.
+     * @return last operation method used.
+     * @throws ParseException if the last method cannot be obtained.
      */
-    final OperationMethod getOperationMethod() {
+    final OperationMethod getOperationMethod(final Element element) throws 
ParseException {
         if (lastMethod == null) {
             /*
              * Safety in case some MathTransformFactory implementations do not 
support
              * getLastMethod(). Performs a slower and less robust check as a 
fallback.
              */
-            if (classification != null) {
-                final MathTransformFactory mtFactory = 
factories.getMathTransformFactory();
-                lastMethod = CoordinateOperations.getOperationMethod(
-                        mtFactory.getAvailableMethods(SingleOperation.class), 
classification);
+            if (classification != null) try {
+                lastMethod = factories.findOperationMethod(classification);
+            } catch (NoSuchIdentifierException e) {
+                throw element.parseFailed(e);
             }
         }
         return lastMethod;
diff --git 
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
index 85ef73d67a..33c46f35e5 100644
--- 
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
@@ -1340,10 +1340,7 @@ class CoordinateOperationRegistry {
                         method = factory.getOperationMethod(name.getCode());
                     }
                     if (method == null) {
-                        method = factory.createOperationMethod(properties,
-                                sourceCRS.getCoordinateSystem().getDimension(),
-                                targetCRS.getCoordinateSystem().getDimension(),
-                                descriptor);
+                        method = factory.createOperationMethod(properties, 
descriptor);
                     }
                 }
             }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
index 65fbd9cc84..7f72c76705 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
@@ -21,7 +21,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Objects;
 import org.opengis.util.FactoryException;
-import org.opengis.util.NoSuchIdentifierException;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.referencing.AuthorityFactory;
@@ -45,7 +44,6 @@ import org.apache.sis.util.Classes;
 import org.apache.sis.util.Utilities;
 import org.apache.sis.util.Debug;
 import org.apache.sis.util.privy.Constants;
-import org.apache.sis.util.privy.URLs;
 import org.apache.sis.referencing.factory.GeodeticObjectFactory;
 import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
 import org.apache.sis.referencing.operation.transform.AbstractMathTransform;
@@ -278,19 +276,7 @@ public class DefaultCoordinateOperationFactory extends 
AbstractFactory implement
      */
     @Override
     public OperationMethod getOperationMethod(String name) throws 
FactoryException {
-        ArgumentChecks.ensureNonEmpty("name", name = name.strip());
-        @SuppressWarnings("LocalVariableHidesMemberVariable")
-        final MathTransformFactory mtFactory = getMathTransformFactory();
-        if (mtFactory instanceof DefaultMathTransformFactory) {
-            return ((DefaultMathTransformFactory) 
mtFactory).getOperationMethod(name);
-        }
-        final OperationMethod method = CoordinateOperations.getOperationMethod(
-                mtFactory.getAvailableMethods(SingleOperation.class), name);
-        if (method != null) {
-            return method;
-        }
-        throw new 
NoSuchIdentifierException(Resources.forProperties(defaultProperties)
-                .getString(Resources.Keys.NoSuchOperationMethod_2, name, 
URLs.OPERATION_METHODS), name);
+        return new ReferencingFactoryContainer(null, null, null, null, null, 
mtFactory).findOperationMethod(name);
     }
 
     /**
@@ -336,6 +322,7 @@ public class DefaultCoordinateOperationFactory extends 
AbstractFactory implement
      *
      * @since 1.4
      */
+    @Override
     public OperationMethod createOperationMethod(final Map<String,?> 
properties,
             final ParameterDescriptorGroup parameters) throws FactoryException
     {
@@ -351,8 +338,7 @@ public class DefaultCoordinateOperationFactory extends 
AbstractFactory implement
     /**
      * @deprecated The dimensions attributes have been removed in ISO 
19111:2019 revision.
      */
-    @Override
-    @Deprecated(since = "1.4")
+    @Deprecated(since="1.4", forRemoval=true)
     public OperationMethod createOperationMethod(final Map<String,?> 
properties,
             final Integer sourceDimensions, final Integer targetDimensions,
             ParameterDescriptorGroup parameters) throws FactoryException
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
index 8bfa59d5d4..84e54a6232 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
@@ -57,7 +57,6 @@ import org.apache.sis.io.wkt.Parser;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.Classes;
-import org.apache.sis.util.privy.URLs;
 import org.apache.sis.util.privy.Strings;
 import org.apache.sis.util.privy.Constants;
 import org.apache.sis.referencing.IdentifiedObjects;
@@ -464,11 +463,7 @@ public class DefaultMathTransformFactory extends 
AbstractFactory implements Math
         OperationMethod method = methodsByName.get(identifier);
         if (method == null) {
             synchronized (methods) {
-                method = CoordinateOperations.getOperationMethod(methods, 
identifier);
-            }
-            if (method == null) {
-                throw new NoSuchIdentifierException(Resources.format(
-                        Resources.Keys.NoSuchOperationMethod_2, identifier, 
URLs.OPERATION_METHODS), identifier);
+                method = CoordinateOperations.findOperationMethod(methods, 
identifier);
             }
             /*
              * Remember the method we just found, for faster check next time.
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/CoordinateOperations.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/CoordinateOperations.java
index d3e1d13048..a00de5c76d 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/CoordinateOperations.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/CoordinateOperations.java
@@ -22,6 +22,7 @@ import java.util.HashMap;
 import java.util.function.Supplier;
 import javax.measure.UnitConverter;
 import javax.measure.IncommensurableException;
+import org.opengis.util.NoSuchIdentifierException;
 import org.opengis.referencing.ObjectFactory;
 import org.opengis.referencing.cs.CSFactory;
 import org.opengis.referencing.cs.RangeMeaning;
@@ -39,10 +40,12 @@ import 
org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory;
 import 
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.apache.sis.referencing.factory.GeodeticObjectFactory;
 import org.apache.sis.metadata.privy.NameToIdentifier;
+import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.util.Deprecable;
 import org.apache.sis.util.Static;
 import org.apache.sis.util.privy.CollectionsExt;
 import org.apache.sis.util.privy.Numerics;
+import org.apache.sis.util.privy.URLs;
 import org.apache.sis.util.collection.Containers;
 
 // Specific to the geoapi-4.0 branch:
@@ -155,17 +158,26 @@ public final class CoordinateOperations extends Static {
     }
 
     /**
-     * Returns the operation method for the specified name or identifier. The 
given argument shall be either a
-     * method name (e.g. <q>Transverse Mercator</q>) or one of its identifiers 
(e.g. {@code "EPSG:9807"}).
+     * Returns the operation method for the specified name or identifier. The 
given argument shall be either
+     * a method name (e.g. <q>Transverse Mercator</q>) or one of its 
identifiers (e.g. {@code "EPSG:9807"}).
+     * The search is case-insensitive and comparisons against method names can 
be
+     * {@linkplain 
org.apache.sis.referencing.operation.DefaultOperationMethod#isHeuristicMatchForName(String)
 heuristic}.
+     *
+     * <p>If more than one method match the given name, then the first 
(according iteration order)
+     * non-{@linkplain Deprecable#isDeprecated() deprecated} matching method 
is returned.
+     * If all matching methods are deprecated, the first one is returned.</p>
      *
      * @param  methods     the method candidates.
      * @param  identifier  the name or identifier of the operation method to 
search.
-     * @return the coordinate operation method for the given name or 
identifier, or {@code null} if none.
+     * @return the coordinate operation method for the given name or 
identifier.
+     * @throws NoSuchIdentifierException if the requested operation method 
cannot be found.
      *
      * @see 
org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory#getOperationMethod(String)
      * @see 
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory#getOperationMethod(String)
      */
-    public static OperationMethod getOperationMethod(final Iterable<? extends 
OperationMethod> methods, final String identifier) {
+    public static OperationMethod findOperationMethod(final Iterable<? extends 
OperationMethod> methods, final String identifier)
+            throws NoSuchIdentifierException
+    {
         OperationMethod fallback = null;
         for (final OperationMethod method : methods) {
             if (NameToIdentifier.isHeuristicMatchForName(method, identifier) ||
@@ -183,7 +195,11 @@ public final class CoordinateOperations extends Static {
                 }
             }
         }
-        return fallback;
+        if (fallback != null) {
+            return fallback;
+        }
+        throw new NoSuchIdentifierException(Resources.format(
+                Resources.Keys.NoSuchOperationMethod_2, identifier, 
URLs.OPERATION_METHODS), identifier);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/GeodeticObjectBuilder.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/GeodeticObjectBuilder.java
index e02350ff29..287eb6d631 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/GeodeticObjectBuilder.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/GeodeticObjectBuilder.java
@@ -237,7 +237,7 @@ public class GeodeticObjectBuilder extends 
Builder<GeodeticObjectBuilder> {
         if (method != null) {
             throw new 
IllegalStateException(Errors.forLocale(locale).getString(Errors.Keys.ElementAlreadyPresent_1,
 "OperationMethod"));
         }
-        method = 
factories.getCoordinateOperationFactory().getOperationMethod(name);
+        method = factories.findOperationMethod(name);
         parameters = method.getParameters().createValue();
         return this;
     }
@@ -263,7 +263,7 @@ public class GeodeticObjectBuilder extends 
Builder<GeodeticObjectBuilder> {
      * @throws FactoryException if the operation method cannot be obtained.
      */
     public GeodeticObjectBuilder setConversion(final ParameterValueGroup 
parameters) throws FactoryException {
-        method = 
factories.getCoordinateOperationFactory().getOperationMethod(parameters.getDescriptor().getName().getCode());
+        method = 
factories.findOperationMethod(parameters.getDescriptor().getName().getCode());
         this.parameters = parameters;           // Set only if above line 
succeed.
         return this;
     }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/ReferencingFactoryContainer.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/ReferencingFactoryContainer.java
index aa9fbde384..0e949be56f 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/ReferencingFactoryContainer.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/ReferencingFactoryContainer.java
@@ -17,8 +17,10 @@
 package org.apache.sis.referencing.privy;
 
 import java.util.Map;
+import java.util.Locale;
 import org.opengis.util.FactoryException;
 import org.opengis.util.NameFactory;
+import org.opengis.util.NoSuchIdentifierException;
 import org.opengis.referencing.cs.CartesianCS;
 import org.opengis.referencing.cs.CSFactory;
 import org.opengis.referencing.cs.CSAuthorityFactory;
@@ -26,6 +28,8 @@ import org.opengis.referencing.crs.CRSFactory;
 import org.opengis.referencing.crs.CRSAuthorityFactory;
 import org.opengis.referencing.datum.DatumFactory;
 import org.opengis.referencing.datum.DatumAuthorityFactory;
+import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.referencing.operation.SingleOperation;
 import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.CoordinateOperationFactory;
 import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory;
@@ -33,6 +37,9 @@ import org.apache.sis.referencing.CRS;
 import 
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.apache.sis.referencing.factory.NoSuchAuthorityFactoryException;
 import org.apache.sis.referencing.factory.GeodeticObjectFactory;
+import org.apache.sis.referencing.internal.Resources;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.Localized;
 import org.apache.sis.util.privy.Constants;
 import org.apache.sis.util.iso.DefaultNameFactory;
 import org.apache.sis.util.resources.Errors;
@@ -54,7 +61,7 @@ import org.opengis.util.Factory;
  *
  * @see <a href="https://issues.apache.org/jira/browse/SIS-102";>SIS-102</a>
  */
-public class ReferencingFactoryContainer {
+public class ReferencingFactoryContainer implements Localized {
     /**
      * The key for specifying a {@link NameFactory} instance to use for 
geodetic object constructions.
      */
@@ -213,7 +220,7 @@ public class ReferencingFactoryContainer {
         if (type == CRSFactory.class)                 return crsFactory       
!= (crsFactory       = (CRSFactory)                 factory);
         if (type == CoordinateOperationFactory.class) return operationFactory 
!= (operationFactory = (CoordinateOperationFactory) factory);
         if (type == MathTransformFactory.class)       return mtFactory        
!= (mtFactory        = (MathTransformFactory)       factory);
-        throw new 
IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2, 
"type", type));
+        throw new 
IllegalArgumentException(Errors.forLocale(getLocale()).getString(Errors.Keys.IllegalArgumentValue_2,
 "type", type));
     }
 
     /**
@@ -246,7 +253,8 @@ public class ReferencingFactoryContainer {
         else if (type == CoordinateOperationFactory.class) f = 
getCoordinateOperationFactory();
         else if (type == MathTransformFactory.class)       f = 
getMathTransformFactory();
         else {
-            throw new 
IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2, 
"type", type));
+            throw new IllegalArgumentException(Errors.forLocale(getLocale())
+                    .getString(Errors.Keys.IllegalArgumentValue_2, "type", 
type));
         }
         return type.cast(f);
     }
@@ -395,4 +403,41 @@ public class ReferencingFactoryContainer {
     public final CartesianCS getStandardProjectedCS() throws FactoryException {
         return getCSAuthorityFactory().createCartesianCS("4400");
     }
+
+    /**
+     * Returns the locale to use for error messages, or {@code null} if 
unspecified.
+     * In the latter case, the platform default locale will be used.
+     * Subclasses should override if a locale is known.
+     *
+     * @return the locale to use for error messages, or {@code null} if 
unspecified.
+     */
+    @Override
+    public Locale getLocale() {
+        return Resources.getLocale(defaultProperties);
+    }
+
+    /**
+     * Returns the operation method for the specified name or identifier. The 
given argument shall be either
+     * a method name (e.g. <q>Transverse Mercator</q>) or one of its 
identifiers (e.g. {@code "EPSG:9807"}).
+     * The search is case-insensitive and comparisons against method names can 
be
+     * {@linkplain 
org.apache.sis.referencing.operation.DefaultOperationMethod#isHeuristicMatchForName(String)
 heuristic}.
+     *
+     * <p>If more than one method match the given name, then the first 
(according iteration order)
+     * non-{@linkplain org.apache.sis.util.Deprecable#isDeprecated() 
deprecated} matching method is returned.
+     * If all matching methods are deprecated, the first one is returned.</p>
+     *
+     * @param  name  the name of the operation method to fetch.
+     * @return the operation method of the given name.
+     * @throws NoSuchIdentifierException if the requested operation method 
cannot be found.
+     */
+    public final OperationMethod findOperationMethod(String name) throws 
NoSuchIdentifierException {
+        ArgumentChecks.ensureNonEmpty("name", name = name.strip());
+        @SuppressWarnings("LocalVariableHidesMemberVariable")
+        final MathTransformFactory mtFactory = getMathTransformFactory();
+        if (mtFactory instanceof DefaultMathTransformFactory) {
+            return ((DefaultMathTransformFactory) 
mtFactory).getOperationMethod(name);
+        }
+        return CoordinateOperations.findOperationMethod(
+                mtFactory.getAvailableMethods(SingleOperation.class), name);
+    }
 }
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/CRSBuilder.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/CRSBuilder.java
index c508fd5bee..d0fa83779a 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/CRSBuilder.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/CRSBuilder.java
@@ -24,6 +24,7 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.StringJoiner;
 import java.util.NoSuchElementException;
+import java.util.Locale;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
 import java.lang.reflect.Array;
@@ -223,7 +224,7 @@ public final class CRSBuilder extends 
ReferencingFactoryContainer {
      * @see GeoKeysLoader#warning(short, Object...)
      */
     final void warning(final short key, final Object... args) {
-        LogRecord record = 
Resources.forLocale(listeners.getLocale()).getLogRecord(Level.WARNING, key, 
args);
+        LogRecord record = 
Resources.forLocale(getLocale()).getLogRecord(Level.WARNING, key, args);
         // Logger name will be set by listeners.warning(record).
         record.setSourceClassName(GeoTiffStore.class.getName());
         record.setSourceMethodName("getMetadata");
@@ -1383,7 +1384,7 @@ public final class CRSBuilder extends 
ReferencingFactoryContainer {
             case GeoCodes.userDefined: {
                 final Unit<Angle>         azimuthUnit = 
createAngularUnit(UnitKey.AZIMUTH);
                 final String              code        = 
methodCode(getMandatoryString(GeoKeys.ProjMethod));
-                final OperationMethod     method      = 
getCoordinateOperationFactory().getOperationMethod(code);
+                final OperationMethod     method      = 
findOperationMethod(code);
                 final ParameterValueGroup parameters  = 
method.getParameters().createValue();
                 final Map<Integer,String> toNames     = 
ReferencingUtilities.identifierToName(parameters.getDescriptor(), 
Citations.GEOTIFF);
                 final Map<Object,Number>  paramValues = new HashMap<>();    // 
Keys: [String|Short] instances for [known|unknown] parameters.
@@ -1424,7 +1425,7 @@ public final class CRSBuilder extends 
ReferencingFactoryContainer {
                         String paramName = 
toNames.get(Short.toUnsignedInt(key));
                         if (paramName == null) {
                             paramName = GeoKeys.name(key);
-                            throw new 
ParameterNotFoundException(Errors.forLocale(listeners.getLocale())
+                            throw new 
ParameterNotFoundException(Errors.forLocale(getLocale())
                                         
.getString(Errors.Keys.UnexpectedParameter_1, paramName), paramName);
                         }
                         final Number value  = paramValues.get(key);
@@ -1482,7 +1483,7 @@ public final class CRSBuilder extends 
ReferencingFactoryContainer {
                     final String parent = 
IdentifiedObjects.getIdentifierOrName(projection);
                     warning(Resources.Keys.NotTheEpsgValue_5, parent, 
id.getCode(), key, code, "");
                 }
-                method = 
getCoordinateOperationFactory().getOperationMethod(methodCode(code));
+                method = findOperationMethod(methodCode(code));
             }
             /*
              * Compare the parameter values with the ones declared in the EPSG 
geodetic dataset.
@@ -1588,6 +1589,14 @@ public final class CRSBuilder extends 
ReferencingFactoryContainer {
         }
     }
 
+    /**
+     * Returns the locale to use for error messages.
+     */
+    @Override
+    public final Locale getLocale() {
+        return listeners.getLocale();
+    }
+
     /**
      * Returns a string representation of the keys and associated values in 
this {@code CRSBuilder}.
      */
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/CRSBuilder.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/CRSBuilder.java
index e8cdfc64e5..87352f7e20 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/CRSBuilder.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/CRSBuilder.java
@@ -50,6 +50,7 @@ import org.apache.sis.referencing.crs.DefaultGeographicCRS;
 import org.apache.sis.referencing.crs.DefaultGeocentricCRS;
 import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
 import org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory;
+import 
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.apache.sis.referencing.operation.provider.Equirectangular;
 import org.apache.sis.storage.DataStoreContentException;
 import org.apache.sis.storage.DataStoreException;
@@ -59,9 +60,6 @@ import org.apache.sis.util.resources.Errors;
 import org.apache.sis.measure.NumberRange;
 import org.apache.sis.measure.Units;
 
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.referencing.operation.CoordinateOperationFactory;
-
 
 /**
  * Temporary object for building a coordinate reference system from the 
variables in a netCDF file.
@@ -795,10 +793,9 @@ previous:   for (int i=components.size(); --i >= 0;) {
          */
         private static final Conversion UNKNOWN_PROJECTION;
         static {
-            final CoordinateOperationFactory factory = 
DefaultCoordinateOperationFactory.provider();
             try {
-                final OperationMethod method = 
factory.getOperationMethod(Equirectangular.NAME);
-                UNKNOWN_PROJECTION = factory.createDefiningConversion(
+                OperationMethod method = 
DefaultMathTransformFactory.provider().getOperationMethod(Equirectangular.NAME);
+                UNKNOWN_PROJECTION = 
DefaultCoordinateOperationFactory.provider().createDefiningConversion(
                         properties("Not specified (presumed Plate Carrée)"),
                         method, method.getParameters().createValue());
             } catch (FactoryException e) {
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Decoder.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Decoder.java
index e264766e4a..b559329826 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Decoder.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Decoder.java
@@ -531,7 +531,18 @@ public abstract class Decoder extends 
ReferencingFactoryContainer {
      * @return the localized error resource bundle.
      */
     final Resources resources() {
-        return Resources.forLocale(listeners.getLocale());
+        return Resources.forLocale(getLocale());
+    }
+
+    /**
+     * Returns the locale used for error message, or {@code null} if 
unspecified.
+     * In the latter case, the platform default locale will be used.
+     *
+     * @return the locale for messages (typically specified by the data 
store), or {@code null} if unknown.
+     */
+    @Override
+    public final Locale getLocale() {
+        return listeners.getLocale();
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/GridMapping.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/GridMapping.java
index 539f683d17..07133b2cab 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/GridMapping.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/GridMapping.java
@@ -217,8 +217,8 @@ final class GridMapping {
              * than OGC names, but Apache SIS implementations of map 
projections know how to handle them, including
              * the redundant parameters like "inverse_flattening" and 
"earth_radius".
              */
-            final CoordinateOperationFactory opFactory = 
node.decoder.getCoordinateOperationFactory();
-            final OperationMethod method = 
opFactory.getOperationMethod((String) definition.remove(CF.GRID_MAPPING_NAME));
+            final String mappingName = (String) 
definition.remove(CF.GRID_MAPPING_NAME);
+            final OperationMethod method = 
node.decoder.findOperationMethod(mappingName);
             final ParameterValueGroup parameters = 
method.getParameters().createValue();
             for (final Iterator<Map.Entry<String,Object>> it = 
definition.entrySet().iterator(); it.hasNext();) {
                 final Map.Entry<String,Object> entry = it.next();
@@ -267,6 +267,7 @@ final class GridMapping {
                 baseToCRS = MathTransforms.linear(new Matrix3(0, 1, 0, 1, 0, 
0, 0, 0, 1));
                 crs = baseCRS;
             } else {
+                final CoordinateOperationFactory opFactory = 
node.decoder.getCoordinateOperationFactory();
                 Map<String,?> properties = properties(definition, 
Convention.CONVERSION_NAME, node.getName());
                 final Conversion conversion = 
opFactory.createDefiningConversion(properties, method, parameters);
                 final CartesianCS cs = node.decoder.getStandardProjectedCS();
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/ChannelDecoder.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/ChannelDecoder.java
index d0c20df6e4..356bc6f213 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/ChannelDecoder.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/ChannelDecoder.java
@@ -347,7 +347,7 @@ public final class ChannelDecoder extends Decoder {
      * @return the localized error resource bundle.
      */
     final Errors errors() {
-        return Errors.forLocale(listeners.getLocale());
+        return Errors.forLocale(getLocale());
     }
 
     /**
@@ -355,7 +355,7 @@ public final class ChannelDecoder extends Decoder {
      * that the file should be a netCDF one, but we found some inconsistency 
or unknown tags.
      */
     private DataStoreContentException malformedHeader() {
-        return new DataStoreContentException(listeners.getLocale(), 
FORMAT_NAME, getFilename(), null);
+        return new DataStoreContentException(getLocale(), FORMAT_NAME, 
getFilename(), null);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/DecoderWrapper.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/DecoderWrapper.java
index 381d8b1f5c..b62529d2d7 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/DecoderWrapper.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/ucar/DecoderWrapper.java
@@ -433,7 +433,7 @@ public final class DecoderWrapper extends Decoder 
implements CancelTask {
     private FeatureDataset getFeatureDataSet() throws IOException {
         if (features == null && file instanceof NetcdfDataset) {
             features = FeatureDatasetFactoryManager.wrap(null, (NetcdfDataset) 
file, this,
-                    new Formatter(new LogAdapter(listeners), 
listeners.getLocale()));
+                    new Formatter(new LogAdapter(listeners), getLocale()));
         }
         return features;
     }
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/IndexedResourceBundle.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/IndexedResourceBundle.java
index 2bb0bb32ec..5ae36d1d3d 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/IndexedResourceBundle.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/IndexedResourceBundle.java
@@ -754,7 +754,7 @@ public abstract class IndexedResourceBundle extends 
ResourceBundle implements Lo
      * @param  properties  the map of properties, or {@code null} if none.
      * @return the locale found in the given map, or {@code null} if none.
      */
-    protected static Locale getLocale(final Map<?,?> properties) {
+    public static Locale getLocale(final Map<?,?> properties) {
         if (properties != null) {
             final Object candidate = properties.get(LOCALE_KEY);
             if (candidate instanceof Locale) {
diff --git a/geoapi/snapshot b/geoapi/snapshot
index a012f57760..a07e965123 160000
--- a/geoapi/snapshot
+++ b/geoapi/snapshot
@@ -1 +1 @@
-Subproject commit a012f5776018987a7e9aaf5125a8286ded7de414
+Subproject commit a07e965123706be9092d0dc615592c23c8401450


Reply via email to