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

commit cb9d0cfae49be66866f7f35054140b4a02ab9dd6
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Wed Sep 10 19:28:50 2025 +0200

    Adjust the operation method providers for changes in EPSG database.
---
 .../referencing/datum/DefaultDatumEnsemble.java    |  15 +++
 .../factory/ConcurrentAuthorityFactory.java        |   5 +-
 .../referencing/operation/projection/Mercator.java |  11 ++-
 .../operation/provider/AxisOrderReversal.java      |   4 +-
 .../operation/provider/AxisOrderReversal3D.java    |   4 +-
 .../operation/provider/Equirectangular.java        |   2 +-
 .../provider/FranceGeocentricInterpolation.java    |   2 +
 .../operation/provider/GeocentricTranslation.java  |   1 +
 .../provider/GeographicAndVerticalOffsets.java     |   5 +-
 .../operation/provider/LambertConformal1SP.java    |   1 +
 .../operation/provider/LambertConformal2SP.java    |   8 +-
 .../referencing/operation/provider/Mollweide.java  |   2 +-
 .../operation/provider/ObliqueMercator.java        |   2 +
 .../operation/provider/RegionalMercator.java       |  36 ++++++-
 .../provider/ZonedTransverseMercator.java          |   2 +
 .../provider/ParameterNameTableGenerator.java      |  16 +++-
 .../operation/provider/ProvidersTest.java          | 103 ++++++++++++++++++++-
 .../test/org/apache/sis/test/Assertions.java       |  13 ++-
 18 files changed, 194 insertions(+), 38 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java
index 6a216fc196..6d0d482208 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultDatumEnsemble.java
@@ -45,6 +45,7 @@ import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.referencing.privy.WKTKeywords;
 import org.apache.sis.referencing.privy.WKTUtilities;
 import org.apache.sis.referencing.internal.PositionalAccuracyConstant;
+import org.apache.sis.metadata.privy.NameToIdentifier;
 import org.apache.sis.metadata.privy.SecondaryTrait;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.Classes;
@@ -465,6 +466,20 @@ check:  if (it.hasNext()) {
         return value;
     }
 
+    /**
+     * Returns {@code true} if either the {@linkplain #getName() primary name} 
or at least
+     * one {@linkplain #getAlias() alias} matches the given string according 
heuristic rules.
+     * This method performs the comparison documented in the
+     * {@linkplain AbstractDatum#isHeuristicMatchForName(String) datum-class}.
+     *
+     * @param  name  the name to compare.
+     * @return {@code true} if the primary name or at least one alias matches 
the specified {@code name}.
+     */
+    @Override
+    public boolean isHeuristicMatchForName(final String name) {
+        return NameToIdentifier.isHeuristicMatchForName(super.getName(), 
super.getAlias(), name, AbstractDatum.Simplifier.INSTANCE);
+    }
+
     /**
      * Compares the specified object with this ensemble for equality.
      *
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
index 62f0b9b3f7..abe0119030 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
@@ -2010,12 +2010,15 @@ public abstract class ConcurrentAuthorityFactory<DAO 
extends GeodeticAuthorityFa
          * Used in lambda expression and defined as a separated method because 
of generic type.
          * The {@code object} argument is present only for having the required 
method signature.
          *
+         * <p>The array length is {@value #DOMAIN_COUNT} × 2 for whether axes 
are ignored or not,
+         * and ×2 again for whether a singleton is searched instead of the 
collection.</p>
+         *
          * @param  object  the user-specified object which was searched.
          * @return a new array to use as a cache for the specified object.
          */
         @SuppressWarnings({"unchecked", "rawtypes"})            // Generic 
array creation.
         private static Set<IdentifiedObject>[] 
createCacheEntry(IdentifiedObject object) {
-            return new Set[DOMAIN_COUNT * 3];
+            return new Set[DOMAIN_COUNT * 4];
         }
 
         /**
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 6000cc9d50..f14c532a7a 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
@@ -195,8 +195,10 @@ public class Mercator extends ConformalProjection {
          * The "scale factor" is not formally a "Mercator 2SP" argument, but 
we accept it anyway
          * for all Mercator projections because it may be used in some Well 
Known Text (WKT).
          */
-        roles.put(ParameterRole.SCALE_FACTOR,     Mercator1SP.SCALE_FACTOR);
-        roles.put(ParameterRole.CENTRAL_MERIDIAN, 
Mercator1SP.LONGITUDE_OF_ORIGIN);
+        roles.put(ParameterRole.SCALE_FACTOR, Mercator1SP.SCALE_FACTOR);
+        roles.put(ParameterRole.CENTRAL_MERIDIAN,
+                (variant == Variant.REGIONAL) ? 
RegionalMercator.LONGITUDE_OF_FALSE_ORIGIN
+                                              : 
Mercator1SP.LONGITUDE_OF_ORIGIN);
         switch (variant) {
             case REGIONAL: {
                 roles.put(ParameterRole.FALSE_EASTING,  
RegionalMercator.EASTING_AT_FALSE_ORIGIN);
@@ -252,8 +254,9 @@ public class Mercator extends ConformalProjection {
          * "Latitude of origin" cannot have a non-zero value, if it still have 
non-zero value we will process as
          * for "Latitude of false origin".
          */
-        final double φ0 = toRadians(initializer.getAndStore((variant == 
Variant.REGIONAL)
-                ? RegionalMercator.LATITUDE_OF_FALSE_ORIGIN : 
Mercator1SP.LATITUDE_OF_ORIGIN));
+        final double φ0 = toRadians(initializer.getAndStore(
+                (variant == Variant.REGIONAL) ? 
RegionalMercator.LATITUDE_OF_FALSE_ORIGIN
+                                              : 
Mercator1SP.LATITUDE_OF_ORIGIN));
         /*
          * In theory, the "Latitude of 1st standard parallel" and the "Scale 
factor at natural origin" parameters
          * are mutually exclusive. The former is for projections of category 
"2SP" (namely variant B and C) while
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal.java
index d7e63bafa9..0e6d254349 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal.java
@@ -27,7 +27,7 @@ import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 
 
 /**
- * The provider for <q>axis order reversal (2D)</q> (EPSG:9843).
+ * The provider for <q>Axis Order Reversal (2D)</q> (EPSG:9843).
  * This is a trivial operation that just swap the two first axes.
  * The inverse operation is this operation itself.
  *
@@ -44,7 +44,7 @@ public class AxisOrderReversal extends AbstractProvider {
      * The group of all parameters expected by this coordinate operation (in 
this case, none).
      */
     private static final ParameterDescriptorGroup PARAMETERS = builder()
-            .addIdentifier("9843").addName("Axis order reversal 
(2D)").createGroup();
+            .addIdentifier("9843").addName("Axis Order Reversal 
(2D)").createGroup();
 
     /**
      * The canonical instance of this operation method.
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal3D.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal3D.java
index eb844247ad..744c9e0499 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal3D.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/AxisOrderReversal3D.java
@@ -21,7 +21,7 @@ import org.opengis.parameter.ParameterDescriptorGroup;
 
 
 /**
- * The provider for <q>axis order reversal (geographic3D horizontal)</q> 
(EPSG:9844).
+ * The provider for <q>Axis Order Reversal (Geographic3D horizontal)</q> 
(EPSG:9844).
  * This is a trivial operation that just swap the two first axes.
  * The inverse operation is this operation itself.
  *
@@ -38,7 +38,7 @@ public final class AxisOrderReversal3D extends 
AxisOrderReversal {
      * The group of all parameters expected by this coordinate operation (in 
this case, none).
      */
     private static final ParameterDescriptorGroup PARAMETERS = builder()
-            .addIdentifier("9844").addName("Axis order reversal (geographic3D 
horizontal)").createGroup();
+            .addIdentifier("9844").addName("Axis Order Reversal (Geographic3D 
horizontal)").createGroup();
 
     /**
      * The canonical instance of this operation method.
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Equirectangular.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Equirectangular.java
index e297bab69d..7a70dae255 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Equirectangular.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Equirectangular.java
@@ -250,9 +250,9 @@ public final class Equirectangular extends AbstractProvider 
{
         // for avoiding confusion with EPSG "Equidistant Cylindrical" 
ellipsoidal projection.
         PARAMETERS = addIdentifierAndLegacy(builder, "1029", "9823")    // 
9823 uses deprecated parameter names.
                 .addName(                   NAME)
-                .addName(                   "Plate Carrée")  // Not formally 
defined by EPSG, but cited in documentation.
                 .addName(Citations.OGC,     "Equirectangular")
                 .addName(Citations.ESRI,    "Plate_Carree")
+                .addName(Citations.SIS,     "Plate Carrée")  // Not formally 
defined by EPSG, but cited in documentation.
                 .createGroupForMapProjection(
                         STANDARD_PARALLEL,
                         LATITUDE_OF_ORIGIN,     // Not formally an 
Equirectangular parameter.
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/FranceGeocentricInterpolation.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/FranceGeocentricInterpolation.java
index 31a06e311f..031ad2931d 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/FranceGeocentricInterpolation.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/FranceGeocentricInterpolation.java
@@ -167,6 +167,7 @@ public final class FranceGeocentricInterpolation extends 
AbstractProvider {
      * <!-- Generated by ParameterNameTableGenerator -->
      * <table class="sis">
      *   <caption>Parameter names</caption>
+     *   <tr><td> EPSG:    </td><td> EPSG code for standard transformation T0 
</td></tr>
      *   <tr><td> EPSG:    </td><td> EPSG code for "standard" CT </td></tr>
      *   <tr><td> EPSG:    </td><td> Standard CT code </td></tr>
      * </table>
@@ -196,6 +197,7 @@ public final class FranceGeocentricInterpolation extends 
AbstractProvider {
                 .create(Integer.class, null);
         STANDARD_CT = builder
                 .addIdentifier("1062")
+                .addName("EPSG code for standard transformation T0")
                 .addName("EPSG code for \"standard\" CT")
                 .addName("Standard CT code")
                 .create(Integer.class, null);
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeocentricTranslation.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeocentricTranslation.java
index d078d711a1..9f5620f5b0 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeocentricTranslation.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeocentricTranslation.java
@@ -42,6 +42,7 @@ public final class GeocentricTranslation extends 
GeocentricAffine {
         PARAMETERS = builder()
                 .addIdentifier("1031")
                 .addName("Geocentric translations (geocentric domain)")
+                .addName("Geocentric translations")
                 .createGroup(TX, TY, TZ);
     }
 
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeographicAndVerticalOffsets.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeographicAndVerticalOffsets.java
index 107d4884b3..20377286c3 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeographicAndVerticalOffsets.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/GeographicAndVerticalOffsets.java
@@ -47,13 +47,14 @@ public final class GeographicAndVerticalOffsets extends 
GeographicOffsets {
     private static final long serialVersionUID = 7822664525013018023L;
 
     /**
-     * The operation parameter descriptor for the <q>Geoid undulation</q> 
parameter value.
+     * The operation parameter descriptor for the <q>Geoid height</q> 
parameter value.
      *
      * @see #TZ
      *
      * <!-- Generated by ParameterNameTableGenerator -->
      * <table class="sis">
      *   <caption>Parameter names</caption>
+     *   <tr><td> EPSG:    </td><td> Geoid height </td></tr>
      *   <tr><td> EPSG:    </td><td> Geoid undulation </td></tr>
      * </table>
      */
@@ -65,7 +66,7 @@ public final class GeographicAndVerticalOffsets extends 
GeographicOffsets {
     private static final ParameterDescriptorGroup PARAMETERS;
     static {
         final ParameterBuilder builder = builder();
-        TH = builder.addIdentifier("8604").addName("Geoid 
undulation").create(0, Units.METRE);
+        TH = builder.addIdentifier("8604").addName("Geoid 
height").addName("Geoid undulation").create(0, Units.METRE);
         PARAMETERS = builder().addIdentifier("9618").addName("Geographic2D 
with Height Offsets").createGroup(TY, TX, TH);
     }
 
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal1SP.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal1SP.java
index b1da184dd3..57444bca81 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal1SP.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal1SP.java
@@ -111,6 +111,7 @@ public final class LambertConformal1SP extends 
AbstractLambert {
         PARAMETERS = builder
                 .addIdentifier(IDENTIFIER)
                 .addName(                    "Lambert Conic Conformal (1SP)")
+                .addName(                    "Lambert Conic Conformal (1SP 
variant A)")
                 .addName(Citations.OGC,      "Lambert_Conformal_Conic_1SP")
                 .addName(Citations.GEOTIFF,  "CT_LambertConfConic_1SP")
                 .addName(Citations.PROJ4,    "lcc")
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal2SP.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal2SP.java
index b73d4e94ad..5669dacdd5 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal2SP.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/LambertConformal2SP.java
@@ -178,12 +178,8 @@ public final class LambertConformal2SP extends 
AbstractLambert {
          * GeoTIFF: FalseOriginLong
          */
         LONGITUDE_OF_FALSE_ORIGIN = createLongitude(builder
-                
.addNamesAndIdentifiers(LambertConformal1SP.LONGITUDE_OF_ORIGIN)
-                .rename(Citations.EPSG, "Longitude of false origin")
-                .rename(Citations.NETCDF, "longitude_of_central_meridian")
-                .rename(Citations.GEOTIFF, "FalseOriginLong")
-                .reidentify(Citations.EPSG, "8822")
-                .reidentify(Citations.GEOTIFF, "3084"));
+                
.addNamesAndIdentifiers(RegionalMercator.LONGITUDE_OF_FALSE_ORIGIN)
+                .rename(Citations.NETCDF, "longitude_of_central_meridian"));
         /*
          * EPSG:    Latitude of 1st standard parallel
          * OGC:     standard_parallel_1
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mollweide.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mollweide.java
index 5a7ba1f070..035d942d08 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mollweide.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mollweide.java
@@ -53,7 +53,7 @@ public final class Mollweide extends MapProjection {
      *   <tr><td> OGC:     </td><td> central_meridian </td></tr>
      *   <tr><td> GeoTIFF: </td><td> CenterLong </td></tr>
      *   <tr><td> Proj4:   </td><td> lon_0 </td></tr>
-     *   <tr><td> EPSG:    </td><td> Longitude of projection centre </td></tr>
+     *   <tr><td> EPSG:    </td><td> Longitude of natural origin </td></tr>
      * </table>
      */
     public static final ParameterDescriptor<Double> CENTRAL_MERIDIAN = 
Sinusoidal.CENTRAL_MERIDIAN;
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ObliqueMercator.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ObliqueMercator.java
index d4674077ae..9d86f93e38 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ObliqueMercator.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ObliqueMercator.java
@@ -94,6 +94,7 @@ public class ObliqueMercator extends AbstractMercator {
      * <table class="sis">
      *   <caption>Parameter names</caption>
      *   <tr><td> EPSG:    </td><td> Azimuth at projection centre </td></tr>
+     *   <tr><td> EPSG:    </td><td> Azimuth of initial line </td></tr>
      *   <tr><td> OGC:     </td><td> azimuth </td></tr>
      *   <tr><td> ESRI:    </td><td> Azimuth </td></tr>
      *   <tr><td> GeoTIFF: </td><td> AzimuthAngle </td></tr>
@@ -140,6 +141,7 @@ public class ObliqueMercator extends AbstractMercator {
      *   <tr><td> ESRI:    </td><td> Scale_Factor </td></tr>
      *   <tr><td> GeoTIFF: </td><td> ScaleAtCenter </td></tr>
      *   <tr><td> Proj4:   </td><td> k </td></tr>
+     *   <tr><td> EPSG:    </td><td> Scale factor on initial line </td></tr>
      * </table>
      */
     public static final ParameterDescriptor<Double> SCALE_FACTOR;
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/RegionalMercator.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/RegionalMercator.java
index 4bddb0107d..a19bf3f2af 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/RegionalMercator.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/RegionalMercator.java
@@ -24,7 +24,7 @@ import org.apache.sis.parameter.ParameterBuilder;
 
 
 /**
- * The provider for <q>Mercator (variant C)</q> projection (EPSG:1044).
+ * The provider for <q>Mercator (variant C)</q> projection (EPSG:1108).
  *
  * <h2>Note on naming</h2>
  * The "Regional Mercator" class name is inspired by MapInfo practice, while 
not exactly the same projection.
@@ -43,7 +43,7 @@ public class RegionalMercator extends AbstractMercator {
     /**
      * The EPSG identifier, to be preferred to the name when available.
      */
-    public static final String IDENTIFIER = "1044";
+    public static final String IDENTIFIER = "1108";
 
     /**
      * The operation parameter descriptor for the <cite>Latitude of false 
origin</cite> (φf) parameter value.
@@ -66,6 +66,24 @@ public class RegionalMercator extends AbstractMercator {
      */
     public static final ParameterDescriptor<Double> LATITUDE_OF_FALSE_ORIGIN;
 
+    /**
+     * The operation parameter descriptor for the <cite>Longitude of false 
origin</cite> (λf) parameter value.
+     * Valid values range is [-180 … 180]° and default value is 0°.
+     *
+     * <!-- Generated by ParameterNameTableGenerator -->
+     * <table class="sis">
+     *   <caption>Parameter names</caption>
+     *   <tr><td> EPSG:    </td><td> Longitude of false origin </td></tr>
+     *   <tr><td> OGC:     </td><td> central_meridian </td></tr>
+     *   <tr><td> ESRI:    </td><td> Central_Meridian </td></tr>
+     *   <tr><td> NetCDF:  </td><td> longitude_of_projection_origin </td></tr>
+     *   <tr><td> GeoTIFF: </td><td> FalseOriginLong </td></tr>
+     *   <tr><td> Proj4:   </td><td> lon_0 </td></tr>
+     *   <tr><td> EPSG:    </td><td> <del>Longitude of natural origin</del> 
</td></tr>
+     * </table>
+     */
+    public static final ParameterDescriptor<Double> LONGITUDE_OF_FALSE_ORIGIN;
+
     /**
      * The operation parameter descriptor for the <cite>Easting at false 
origin</cite> (Ef) parameter value.
      * Valid values range is unrestricted and default value is 0 metre.
@@ -114,6 +132,15 @@ public class RegionalMercator extends AbstractMercator {
                 .reidentify(Citations.EPSG, "8821")
                 .reidentify(Citations.GEOTIFF, "3085"), false);
 
+        LONGITUDE_OF_FALSE_ORIGIN = createLongitude(builder
+                .addNamesAndIdentifiers(Mercator1SP.LONGITUDE_OF_ORIGIN)
+                .rename(Citations.EPSG, "Longitude of false origin")
+                .rename(Citations.GEOTIFF, "FalseOriginLong")
+                .reidentify(Citations.EPSG, "8822")
+                .reidentify(Citations.GEOTIFF, "3084")
+                .setDeprecated(true).addName(Citations.EPSG, "Longitude of 
natural origin")
+                .setDeprecated(false));
+
         EASTING_AT_FALSE_ORIGIN = createShift(builder
                 .addNamesAndIdentifiers(FALSE_EASTING)
                 .rename(Citations.EPSG, "Easting at false origin")
@@ -131,10 +158,11 @@ public class RegionalMercator extends AbstractMercator {
         PARAMETERS = builder
                 .addIdentifier(IDENTIFIER)
                 .addName("Mercator (variant C)")
-                .createGroupForMapProjection(
+                .setDeprecated(true).addIdentifier("1044")  // Legacy 
identifer with "longitude of natural origin".
+                .setDeprecated(false).createGroupForMapProjection(
                         Mercator2SP.STANDARD_PARALLEL,
-                        Mercator1SP.LONGITUDE_OF_ORIGIN,    // Really "natural 
origin", not "false origin".
                         LATITUDE_OF_FALSE_ORIGIN,
+                        LONGITUDE_OF_FALSE_ORIGIN,
                         EASTING_AT_FALSE_ORIGIN,
                         NORTHING_AT_FALSE_ORIGIN);
     }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ZonedTransverseMercator.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ZonedTransverseMercator.java
index 0c63480b63..ab202ef277 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ZonedTransverseMercator.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/ZonedTransverseMercator.java
@@ -89,6 +89,8 @@ public final class ZonedTransverseMercator extends 
AbstractProvider {
         PARAMETERS = builder
                 .addIdentifier("9824")
                 .addName("Transverse Mercator Zoned Grid System")
+                .addName("UTM grid system")
+                .addName("UTM")
                 .createGroupForMapProjection(
                         TransverseMercator.LATITUDE_OF_ORIGIN,
                         INITIAL_LONGITUDE,
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ParameterNameTableGenerator.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ParameterNameTableGenerator.java
index 26a2875e41..d37068740d 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ParameterNameTableGenerator.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ParameterNameTableGenerator.java
@@ -37,6 +37,7 @@ import org.apache.sis.measure.Longitude;
 import org.apache.sis.measure.Range;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.StringBuilders;
+import org.apache.sis.util.Deprecable;
 
 // Test dependencies
 import static org.junit.jupiter.api.Assertions.*;
@@ -99,7 +100,7 @@ public final class ParameterNameTableGenerator extends 
SimpleFileVisitor<Path> {
      * @throws IOException if an error occurred while reading or writing a 
file.
      */
     public static void main(final String[] args) throws IOException {
-        final ParameterNameTableGenerator cg = new 
ParameterNameTableGenerator();
+        final var cg = new ParameterNameTableGenerator();
         Files.walkFileTree(cg.directory, cg);
     }
 
@@ -198,9 +199,10 @@ public final class ParameterNameTableGenerator extends 
SimpleFileVisitor<Path> {
                 write(insertAt++, "<!-- Generated by 
ParameterNameTableGenerator -->");
                 write(insertAt++, "<table class=\"sis\">");
                 write(insertAt++, "  <caption>Parameter names</caption>");
-                write(insertAt++, descriptor.getName());
+                write(insertAt++, descriptor.getName(), false);
                 for (final GenericName alias : descriptor.getAlias()) {
-                    write(insertAt++, (alias instanceof Identifier) ? 
(Identifier) alias : new NamedIdentifier(alias));
+                    write(insertAt++, (alias instanceof Identifier) ? 
(Identifier) alias : new NamedIdentifier(alias),
+                                       alias instanceof Deprecable && 
((Deprecable) alias).isDeprecated());
                 }
                 write(insertAt++, "</table>");
                 /*
@@ -311,12 +313,16 @@ public final class ParameterNameTableGenerator extends 
SimpleFileVisitor<Path> {
      * Appends the given authority and name at the given position. This method 
writes the margin
      * (typically spaces followed by {@code '*'} and a single space) before 
the line.
      */
-    private void write(final int insertAt, final Identifier id) {
+    private void write(final int insertAt, final Identifier id, final boolean 
isDeprecated) {
         final int p = buffer.length();
         final String authority = id.getCodeSpace();
         buffer.append("   <tr><td> ").append(authority).append(':')
               .append(CharSequences.spaces(8 - authority.length()))
-              .append("</td><td> ").append(id.getCode()).append(" </td></tr>");
+              .append("</td><td> ");
+        if (isDeprecated) buffer.append("<del>");
+        buffer.append(id.getCode());
+        if (isDeprecated) buffer.append("</del>");
+        buffer.append(" </td></tr>");
         lines.add(insertAt, buffer.toString());
         buffer.setLength(p);
     }
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java
index 09febc881e..19ba3a4126 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/provider/ProvidersTest.java
@@ -16,18 +16,31 @@
  */
 package org.apache.sis.referencing.operation.provider;
 
+import java.util.Arrays;
+import java.util.List;
 import java.util.Map;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.IdentityHashMap;
 import org.opengis.util.GenericName;
+import org.opengis.util.FactoryException;
 import org.opengis.metadata.Identifier;
+import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.cs.VerticalCS;
+import org.opengis.referencing.operation.OperationMethod;
 import org.opengis.parameter.GeneralParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
+import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.util.privy.Constants;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.factory.sql.EPSGFactory;
 
 // Test dependencies
 import org.junit.jupiter.api.Test;
 import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assumptions.abort;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
 import org.apache.sis.test.TestCase;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
@@ -152,9 +165,9 @@ public final class ProvidersTest extends TestCase {
      */
     @Test
     public void ensureParameterUniqueness() throws 
ReflectiveOperationException {
-        final Map<GeneralParameterDescriptor, String> groupNames = new 
IdentityHashMap<>();
-        final Map<GeneralParameterDescriptor, GeneralParameterDescriptor> 
parameters = new HashMap<>();
-        final Map<Object, Object> namesAndIdentifiers = new HashMap<>();
+        final var groupNames = new IdentityHashMap<GeneralParameterDescriptor, 
String>();
+        final var parameters = new HashMap<GeneralParameterDescriptor, 
GeneralParameterDescriptor>();
+        final var namesAndIdentifiers = new HashMap<Object, Object>();
         for (final Class<?> c : methods()) {
             final AbstractProvider method = instance(c);
             final ParameterDescriptorGroup group = method.getParameters();
@@ -237,4 +250,88 @@ public final class ProvidersTest extends TestCase {
         assertNotEquals(0, SatelliteTracking.SATELLITE_ORBITAL_PERIOD   
.getDescription().orElseThrow().length());
         assertNotEquals(0, SatelliteTracking.ASCENDING_NODE_PERIOD      
.getDescription().orElseThrow().length());
     }
+
+    /**
+     * Compares the method and parameter names against the declarations in the 
<abbr>EPSG</abbr> database.
+     *
+     * @throws ReflectiveOperationException if the instantiation of a service 
provider failed.
+     * @throws FactoryException if an error occurred while using the 
<abbr>EPSG</abbr> database.
+     */
+    @Test
+    public void compareWithEPSG() throws ReflectiveOperationException, 
FactoryException {
+        assumeTrue(RUN_EXTENSIVE_TESTS, "Extensive tests not enabled.");
+        final EPSGFactory factory;
+        try {
+            factory = (EPSGFactory) CRS.getAuthorityFactory(Constants.EPSG);
+        } catch (ClassCastException e) {
+            abort("This test requires the EPSG geodetic dataset.");
+            throw e;
+        }
+        final var methodAliases   = new HashMap<AbstractProvider, 
String[]>(256);
+        final var aliasUsageCount = new HashMap<String, Integer>(256);
+        for (final Class<?> c : methods()) {
+            final AbstractProvider method = instance(c);
+            final Identifier identifier = 
IdentifiedObjects.getIdentifier(method, Citations.EPSG);
+            if (identifier != null) {
+                final OperationMethod authoritative = 
factory.createOperationMethod(identifier.getCode());
+                final String[] aliases = getAliases(authoritative);
+                for (final String alias : aliases) {
+                    aliasUsageCount.merge(alias, 1, Math::addExact);
+                }
+                /*
+                 * Verify that the name of the operation method is identical 
to the name used in the EPSG database.
+                 * Aliases will be checked later, after we know which aliases 
are used multiple times.
+                 */
+                final String classe = c.getName();
+                assertNull(methodAliases.put(method, aliases), classe);
+                assertEquals(authoritative.getName().getCode(), 
method.getName().getCode(), classe);
+                /*
+                 * Verify that all parameters declared in the EPSG database 
are present with an identical name.
+                 * The Apache SIS's method provider may contain additional 
parameters. They will be ignored.
+                 */
+                int index = 0;
+                final List<GeneralParameterDescriptor> parameters = 
method.getParameters().descriptors();
+                for (GeneralParameterDescriptor expected : 
authoritative.getParameters().descriptors()) {
+                    final String name = expected.getName().getCode();
+                    GeneralParameterDescriptor parameter;
+                    do {
+                        if (index >= parameters.size()) {
+                            fail("Parameter \"" + name + "\" not found or not 
in expected order in " + classe);
+                        }
+                        parameter = parameters.get(index++);
+                    } while (!name.equals(parameter.getName().getCode()));
+                }
+            }
+        }
+        /*
+         * AFter we checked all operation methods, execute a second loop for 
checking method aliases.
+         * We need to ignore the aliases that are used by more than one method.
+         */
+        for (final Map.Entry<AbstractProvider, String[]> entry : 
methodAliases.entrySet()) {
+            final AbstractProvider method = entry.getKey();
+            final String classe = method.getClass().getName();
+            final var hardCoded = new 
HashSet<String>(Arrays.asList(getAliases(method)));
+            for (final String alias : entry.getValue()) {
+                if (aliasUsageCount.get(alias) == 1) {
+                    if (!hardCoded.remove(alias)) {
+                        fail("Alias \"" + alias + "\" not found or not in 
expected order in " + classe);
+                    }
+                }
+            }
+            if (!hardCoded.isEmpty()) {
+                fail("Unexpected alias \"" + hardCoded.iterator().next() + "\" 
in " + classe);
+            }
+        }
+    }
+
+    /**
+     * Returns the collection of <abbr>EPSG</abbr> aliases or abbreviations 
for the given object.
+     */
+    private static String[] getAliases(final IdentifiedObject object) {
+        return object.getAlias()
+                .stream()
+                .filter((alias) -> 
alias.scope().name().toString().startsWith(Constants.EPSG))
+                .map(GenericName::toString)
+                .toArray(String[]::new);
+    }
 }
diff --git 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/Assertions.java 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/Assertions.java
index 13c92950c7..ff0b32b86b 100644
--- a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/Assertions.java
+++ b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/Assertions.java
@@ -25,7 +25,6 @@ import java.util.LinkedHashSet;
 import java.util.LinkedHashMap;
 import java.util.stream.Stream;
 import java.util.function.Consumer;
-import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -225,7 +224,7 @@ public final class Assertions extends Static {
      */
     public static <E> void assertParallelStreamEquals(final Iterator<E> 
expected, final Stream<E> actual) {
         final Integer ONE = 1;          // For doing autoboxing only once.
-        final ConcurrentMap<E,Integer> count = new ConcurrentHashMap<>();
+        final var count = new ConcurrentHashMap<E,Integer>();
         while (expected.hasNext()) {
             count.merge(expected.next(), ONE, (old, one) -> old + 1);
         }
@@ -266,7 +265,7 @@ public final class Assertions extends Static {
      */
     public static void assertSetEquals(final Collection<?> expected, final 
Collection<?> actual) {
         if (expected != null && actual != null && !expected.isEmpty()) {
-            final Set<Object> r = new LinkedHashSet<>(expected);
+            final var r = new LinkedHashSet<Object>(expected);
             assertTrue(r.removeAll(actual),   "The two sets are disjoint.");
             assertTrue(r.isEmpty(),           "The set is missing elements: " 
+ r);
             assertTrue(r.addAll(actual),      "The set unexpectedly became 
empty.");
@@ -288,7 +287,7 @@ public final class Assertions extends Static {
      */
     public static void assertMapEquals(final Map<?,?> expected, final Map<?,?> 
actual) {
         if (expected != null && actual != null && !expected.isEmpty()) {
-            final Map<Object,Object> r = new LinkedHashMap<>(expected);
+            final var r = new LinkedHashMap<Object,Object>(expected);
             for (final Map.Entry<?,?> entry : actual.entrySet()) {
                 final Object key = entry.getKey();
                 if (!r.containsKey(key)) {
@@ -337,13 +336,13 @@ public final class Assertions extends Static {
         Objects.requireNonNull(object);
         final Object deserialized;
         try {
-            final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-            try (ObjectOutputStream out = new ObjectOutputStream(buffer)) {
+            final var buffer = new ByteArrayOutputStream();
+            try (var out = new ObjectOutputStream(buffer)) {
                 out.writeObject(object);
             }
             // Now reads the object we just serialized.
             final byte[] data = buffer.toByteArray();
-            try (ObjectInputStream in = new ObjectInputStream(new 
ByteArrayInputStream(data))) {
+            try (var in = new ObjectInputStream(new 
ByteArrayInputStream(data))) {
                 try {
                     deserialized = in.readObject();
                 } catch (ClassNotFoundException e) {


Reply via email to