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 b0f406a181ce72e5b3a04f558f39f12afa865796
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Wed Aug 20 19:45:32 2025 +0200

    Add "World Mercator" and "Pseudo-Mercator" in the set of CRS that are 
always present.
    There is a high demand for them, and they are needed for passing some tests 
anyway.
---
 .../apache/sis/referencing/AuthorityFactories.java | 29 +++++----
 .../main/org/apache/sis/referencing/CRS.java       |  2 +
 .../main/org/apache/sis/referencing/CommonCRS.java | 14 ++---
 .../sis/referencing/EPSGFactoryFallback.java       | 41 +++++++++----
 .../sis/referencing/StandardDefinitions.java       | 70 ++++++++++++++++++----
 .../operation/provider/Mercator1SP.java            |  7 ++-
 .../operation/provider/PolarStereographicA.java    |  2 +-
 .../operation/provider/PseudoMercator.java         |  7 ++-
 .../operation/provider/TransverseMercator.java     |  2 +-
 .../test/org/apache/sis/referencing/CRSTest.java   |  4 +-
 .../sis/referencing/EPSGFactoryFallbackTest.java   |  2 +-
 .../sis/referencing/StandardDefinitionsTest.java   | 29 +++++++++
 12 files changed, 156 insertions(+), 53 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AuthorityFactories.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AuthorityFactories.java
index 6cebdd68b9..711f3dde50 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AuthorityFactories.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AuthorityFactories.java
@@ -46,10 +46,10 @@ import org.apache.sis.util.logging.Logging;
 
 
 /**
- * Provides the CRS, CS, datum and coordinate operation authority factories.
+ * Provides the <abbr>CRS</abbr>, <abbr>CS</abbr>, datum and coordinate 
operation authority factories.
  * Provides also the system-wide {@link MultiAuthoritiesFactory} instance used 
by {@link CRS#forCode(String)}.
- * Current version handles the EPSG factory in a special way, but we may try 
to avoid doing special cases in a
- * future SIS version (this may require more help from {@link ServiceLoader}).
+ * Current version handles the <abbr>EPSG</abbr> factory in a special way, but 
we may try to avoid doing special
+ * cases in a future <abbr>SIS</abbr> version (this may require more help from 
{@link ServiceLoader}).
  *
  * @author  Martin Desruisseaux (Geomatys)
  */
@@ -134,7 +134,7 @@ final class AuthorityFactories<T extends AuthorityFactory> 
extends LazySet<T> {
     @Override
     @SuppressWarnings("unchecked")
     protected T[] initialValues() {
-        return (T[]) new GeodeticAuthorityFactory[] {getEPSG()};
+        return (T[]) new GeodeticAuthorityFactory[] {getEPSG(true)};
     }
 
     /**
@@ -162,16 +162,19 @@ final class AuthorityFactories<T extends 
AuthorityFactory> extends LazySet<T> {
     }
 
     /**
-     * Returns the factory connected to the EPSG geodetic dataset if possible, 
or the EPSG fallback otherwise.
-     * If an EPSG data source has been found, then this method returns an 
instance of {@link EPSGFactory}, but
-     * there is no guarantee that attempts to use that factory will succeed. 
For example, maybe the EPSG schema
-     * does not exist. Callers should be prepared to either receive an {@link 
EPSGFactoryFallback} directly if
-     * the EPSG data source does not exist, or replace the {@code EPSGFactory} 
by a {@code EPSGFactoryFallback}
-     * later if attempt to use the returned factory fails.
+     * Returns the factory connected to the <abbr>EPSG</abbr> geodetic dataset 
if possible, or the fallback otherwise.
+     * If an <abbr>EPSG</abbr> data source has been found, then this method 
returns an instance of {@link EPSGFactory}.
+     * But unless {@code test} is {@code true}, there is no guarantee that 
attempts to use that factory will succeed.
+     * For example, maybe the {@code EPSG} schema does not exist and no 
installation scripts are available on the module-path.
+     * Callers should be prepared to either receive an {@link 
EPSGFactoryFallback} directly if the EPSG data source does not exist,
+     * or replace the {@code EPSGFactory} by a {@code EPSGFactoryFallback} 
later if attempt to use the returned factory fails.
      */
-    static synchronized GeodeticAuthorityFactory getEPSG() {
+    static synchronized GeodeticAuthorityFactory getEPSG(final boolean test) {
         if (EPSG == null) try {
             EPSG = new EPSGFactory(null);
+            if (test) {
+                EPSG.createPrimeMeridian(StandardDefinitions.GREENWICH);
+            }
         } catch (FactoryException e) {
             log(e, false);
             EPSG = EPSGFactoryFallback.INSTANCE;
@@ -231,7 +234,7 @@ final class AuthorityFactories<T extends AuthorityFactory> 
extends LazySet<T> {
 
     /**
      * Logs the given exception at the given level. This method pretends that 
the logging come from
-     * {@link CRS#getAuthorityFactory(String)}, which is the public facade for 
{@link #getEPSG()}.
+     * {@link CRS#getAuthorityFactory(String)}, which is the public facade for 
{@link #getEPSG(boolean)}.
      */
     private static void log(final Exception e, final boolean isWarning) {
         String message = e.getMessage();        // Prefer the locale of system 
administrator.
@@ -253,7 +256,7 @@ final class AuthorityFactories<T extends AuthorityFactory> 
extends LazySet<T> {
      * @throws FactoryException if the finder cannot be created.
      */
     static IdentifiedObjectFinder finderForEPSG() throws FactoryException {
-        final GeodeticAuthorityFactory factory = getEPSG();
+        final GeodeticAuthorityFactory factory = getEPSG(false);
         if (factory instanceof EPSGFactoryFallback) {
             return ((EPSGFactoryFallback) factory).newIdentifiedObjectFinder();
         }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
index aa52105478..d098c91904 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
@@ -179,6 +179,8 @@ public final class CRS extends Static {
      *   <tr><td>CRS:83</td>        <td>{@link CommonCRS#NAD83  NAD83}</td>  
<td>Geographic</td>      <td>Like EPSG:4269 except for (<var>longitude</var>, 
<var>latitude</var>) axis order</td></tr>
      *   <tr><td>CRS:84</td>        <td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Geographic</td>      <td>Like EPSG:4326 except for (<var>longitude</var>, 
<var>latitude</var>) axis order</td></tr>
      *   <tr><td>CRS:88</td>        <td>{@link CommonCRS.Vertical#NAVD88 
NAVD88}</td><td>Vertical</td><td>North American Vertical Datum 1988 
height</td></tr>
+     *   <tr><td>EPSG:3395</td>     <td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Projected</td>       <td>WGS 84 / World Mercator</td></tr>
+     *   <tr><td>EPSG:3857</td>     <td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Projected</td>       <td>WGS 84 / Pseudo-Mercator</td></tr>
      *   <tr><td>EPSG:4230</td>     <td>{@link CommonCRS#ED50   ED50}</td>   
<td>Geographic</td>      <td>European Datum 1950</td></tr>
      *   <tr><td>EPSG:4258</td>     <td>{@link CommonCRS#ETRS89 ETRS89}</td> 
<td>Geographic</td>      <td>European Terrestrial Reference System 
1989</td></tr>
      *   <tr><td>EPSG:4267</td>     <td>{@link CommonCRS#NAD27  NAD27}</td>  
<td>Geographic</td>      <td>North American Datum 1927</td></tr>
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
index 404beba383..003bce6e6e 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
@@ -1149,9 +1149,10 @@ public enum CommonCRS {
             if (cs == null) {
                 if (this != DEFAULT) {
                     cs = DEFAULT.universal(latitude, 
longitude).getCoordinateSystem();
+                } else if (isUTM) {
+                    cs = StandardDefinitions.defaultCartesianCS();
                 } else {
                     cs = (CartesianCS) 
StandardDefinitions.createCoordinateSystem(
-                            isUTM   ? StandardDefinitions.CARTESIAN_2D :
                             isSouth ? StandardDefinitions.UPS_SOUTH
                                     : StandardDefinitions.UPS_NORTH, true);
                 }
@@ -2055,17 +2056,12 @@ public enum CommonCRS {
     }
 
     /**
-     * Returns the EPSG factory to use for creating CRS, or {@code null} if 
none.
+     * Returns the <abbr>EPSG</abbr> factory to use for creating 
<abbr>CRS</abbr>s, or {@code null} if none.
      * If this method returns {@code null}, then the caller will silently 
fallback on hard-coded values.
      */
     private static GeodeticAuthorityFactory factory() {
-        if (!EPSGFactoryFallback.FORCE_HARDCODED) {
-            final GeodeticAuthorityFactory factory = 
AuthorityFactories.getEPSG();
-            if (!(factory instanceof EPSGFactoryFallback)) {
-                return factory;
-            }
-        }
-        return null;
+        final GeodeticAuthorityFactory factory = 
AuthorityFactories.getEPSG(false);
+        return (factory instanceof EPSGFactoryFallback) ? null : factory;
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/EPSGFactoryFallback.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/EPSGFactoryFallback.java
index 10eac1745b..9fc223597c 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/EPSGFactoryFallback.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/EPSGFactoryFallback.java
@@ -45,7 +45,6 @@ import 
org.apache.sis.referencing.operation.provider.TransverseMercator;
 import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.system.Fallback;
 import org.apache.sis.util.CharSequences;
-import org.apache.sis.util.Debug;
 import org.apache.sis.util.privy.MetadataServices;
 import org.apache.sis.util.privy.Constants;
 import org.apache.sis.util.privy.URLs;
@@ -70,14 +69,6 @@ import org.opengis.referencing.crs.GeodeticCRS;
 final class EPSGFactoryFallback extends GeodeticAuthorityFactory
         implements CRSAuthorityFactory, CSAuthorityFactory, 
DatumAuthorityFactory
 {
-    /**
-     * Whether to disallow {@code CommonCRS} to use {@link 
org.apache.sis.referencing.factory.sql.EPSGFactory}
-     * (in which case {@code CommonCRS} will fallback on hard-coded values).
-     * This field should always be {@code false}, except for debugging 
purposes.
-     */
-    @Debug
-    static final boolean FORCE_HARDCODED = false;
-
     /**
      * The singleton instance.
      */
@@ -92,10 +83,16 @@ final class EPSGFactoryFallback extends 
GeodeticAuthorityFactory
      */
     private String installationURL;
 
+    /**
+     * Cache of <abbr>CRS</abbr>s other than the one cached by {@link 
CommonCRS}.
+     */
+    private final ProjectedCRS[] cache;
+
     /**
      * Constructor for the singleton instance.
      */
     private EPSGFactoryFallback() {
+        cache = new ProjectedCRS[2];
     }
 
     /**
@@ -135,7 +132,7 @@ final class EPSGFactoryFallback extends 
GeodeticAuthorityFactory
         final boolean geographic = type.isAssignableFrom(GeographicCRS.class);
         final boolean geodetic   = type.isAssignableFrom(GeodeticCRS  .class);
         final boolean projected  = type.isAssignableFrom(ProjectedCRS .class);
-        final Set<String> codes = new LinkedHashSet<>();
+        final var codes = new LinkedHashSet<String>();
         if (pm) codes.add(StandardDefinitions.GREENWICH);
         for (final CommonCRS crs : CommonCRS.values()) {
             if (ellipsoid) add(codes, crs.ellipsoid);
@@ -291,6 +288,30 @@ final class EPSGFactoryFallback extends 
GeodeticAuthorityFactory
             final int s = 
Math.max(code.lastIndexOf(Constants.DEFAULT_SEPARATOR), code.lastIndexOf('#'));
             code = CharSequences.trimWhitespaces(code, s + 1, 
code.length()).toString();
             final short n = Short.parseShort(code);
+            /*
+             * Special case for CRSs which do not have a convenience method in 
`CommonCRS`.
+             * The absence of convenience method is because those projections 
may not be reasonable with all datums.
+             * For example, Pseudo-Mercator is used with WGS 84 only. While it 
would be technically possible to apply
+             * it on any datum, this is not something that we want to 
encourage.
+             */
+            if ((kind & CRS) != 0) {
+                final boolean pseudo = (n == 3857);     // Pseudo-Mercator
+                if (pseudo || n == 3395) {              // or World Mercator
+                    final int index = pseudo ? 1 : 0;
+                    ProjectedCRS crs;
+                    synchronized (cache) {
+                        crs = cache[index];
+                        if (crs == null) {
+                            crs = StandardDefinitions.createMercator(n, 
CommonCRS.WGS84.geographic(), pseudo);
+                            cache[index] = crs;
+                        }
+                    }
+                    return crs;
+                }
+            }
+            /*
+             * Cases that we can delegate to `CommonCRS`. That enumeration 
have its own cache.
+             */
             if ((kind & (ELLIPSOID | DATUM | CRS)) != 0) {
                 for (final CommonCRS crs : CommonCRS.values()) {
                     /*
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/StandardDefinitions.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/StandardDefinitions.java
index ac942698a4..92fc9c85b7 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/StandardDefinitions.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/StandardDefinitions.java
@@ -18,6 +18,7 @@ package org.apache.sis.referencing;
 
 import java.util.Map;
 import java.util.HashMap;
+import java.util.function.Function;
 import javax.measure.Unit;
 import javax.measure.quantity.Length;
 import org.opengis.util.InternationalString;
@@ -48,6 +49,8 @@ import org.apache.sis.util.privy.Constants;
 import org.apache.sis.metadata.privy.AxisNames;
 import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.referencing.operation.DefaultConversion;
+import org.apache.sis.referencing.operation.provider.Mercator1SP;
+import org.apache.sis.referencing.operation.provider.PseudoMercator;
 import org.apache.sis.referencing.operation.provider.TransverseMercator;
 import org.apache.sis.referencing.operation.provider.PolarStereographicA;
 import org.apache.sis.util.resources.Vocabulary;
@@ -93,10 +96,10 @@ final class StandardDefinitions {
      * We refer to latest version of the 9.x series instead of more recent
      * data because the fallback CRS does not use datum ensemble.
      */
-    static final String VERSION = "9.9.1";
+    private static final String VERSION = "9.9.1";
 
     /**
-     * The EPSG code for Greenwich meridian.
+     * The <abbr>EPSG</abbr> code for Greenwich meridian.
      *
      * @see org.apache.sis.util.privy.Constants#EPSG_GREENWICH
      */
@@ -170,11 +173,20 @@ final class StandardDefinitions {
         });
     }
 
+    /**
+     * Creates a Mercator projection using the Apache <abbr>SIS</abbr> factory 
implementation.
+     *
+     * @param  pseudo  whether to create the pseudo-Mercator projection.
+     */
+    static ProjectedCRS createMercator(final int code, final GeographicCRS 
baseCRS, final boolean pseudo) {
+        return createProjectedCRS(code, baseCRS, defaultCartesianCS(), pseudo 
? PseudoMercator.NAME : Mercator1SP.NAME, (parameters) -> {
+            return pseudo ? "Pseudo-Mercator" : "World Mercator";
+        });
+    }
+
     /**
      * Creates a Universal Transverse Mercator (UTM) or a Universal Polar 
Stereographic (UPS) projected CRS
-     * using the Apache SIS factory implementation. This method restricts the 
factory to SIS implementation
-     * instead of arbitrary factory in order to met the contract saying that 
{@link CommonCRS} methods
-     * should never fail.
+     * using the Apache <abbr>SIS</abbr> factory implementation.
      *
      * @param code       the EPSG code, or 0 if none.
      * @param baseCRS    the geographic CRS on which the projected CRS is 
based.
@@ -185,19 +197,36 @@ final class StandardDefinitions {
      */
     static ProjectedCRS createUniversal(final int code, final GeographicCRS 
baseCRS, final boolean isUTM,
             final double latitude, final double longitude, final CartesianCS 
derivedCS)
+    {
+        return createProjectedCRS(code, baseCRS, derivedCS, isUTM ? 
TransverseMercator.NAME : PolarStereographicA.NAME, (parameters) -> {
+            return isUTM ? 
TransverseMercator.Zoner.UTM.setParameters(parameters, latitude, longitude)
+                         : PolarStereographicA.setParameters(parameters, 
latitude >= 0);
+        });
+    }
+
+    /**
+     * Creates a projected CRS from hard-coded values for the given code.
+     * This method restricts the factory to the <abbr>SIS</abbr> 
implementation instead of arbitrary factory
+     * in order to met the contract saying that {@link CommonCRS} methods 
should never fail.
+     *
+     * @param code        the EPSG code, or 0 if none.
+     * @param baseCRS     the geographic CRS on which the projected CRS is 
based.
+     * @param derivedCS   the projected coordinate system.
+     * @param methodName  name of the operation method to apply.
+     * @param setup       a function which setup the parameter values and 
returns the name of the conversion.
+     */
+    private static ProjectedCRS createProjectedCRS(final int code, final 
GeographicCRS baseCRS, final CartesianCS derivedCS,
+            final String methodName, final Function<ParameterValueGroup, 
String> setup)
     {
         final OperationMethod method;
         try {
-            method = DefaultMathTransformFactory.provider()
-                     .getOperationMethod(isUTM ? TransverseMercator.NAME : 
PolarStereographicA.NAME);
+            method = 
DefaultMathTransformFactory.provider().getOperationMethod(methodName);
         } catch (NoSuchIdentifierException e) {
             throw new IllegalStateException(e);                     // Should 
not happen with SIS implementation.
         }
         final ParameterValueGroup parameters = 
method.getParameters().createValue();
-        String name = isUTM ? 
TransverseMercator.Zoner.UTM.setParameters(parameters, latitude, longitude)
-                            : PolarStereographicA.setParameters(parameters, 
latitude >= 0);
+        String name = setup.apply(parameters);
         final var conversion = new DefaultConversion(properties(0, name, null, 
false), method, null, parameters);
-
         name = baseCRS.getName().getCode() + " / " + name;
         return new DefaultProjectedCRS(properties(code, name, null, false), 
baseCRS, conversion, derivedCS);
     }
@@ -363,6 +392,21 @@ final class StandardDefinitions {
                        UPS_NORTH      = (short) 1026,
                        UPS_SOUTH      = (short) 1027;
 
+    /**
+     * The default coordinate system for projected <abbr>CRS</abbr>, created 
when first requested.
+     */
+    private static CartesianCS DEFAULT_CS;
+
+    /**
+     * Returns the default coordinate system for projected <abbr>CRS</abbr>.
+     */
+    static synchronized CartesianCS defaultCartesianCS() {
+        if (DEFAULT_CS == null) {
+            DEFAULT_CS = (CartesianCS) createCoordinateSystem(CARTESIAN_2D, 
true);
+        }
+        return DEFAULT_CS;
+    }
+
     /**
      * Creates a coordinate system from hard-coded values for the given code.
      * The coordinate system names used by this method contains only the first
@@ -383,9 +427,9 @@ final class StandardDefinitions {
             case ELLIPSOIDAL_3D: name = "Ellipsoidal 3D";  type = 2; dim = 3; 
axisCode =  111; break;
             case SPHERICAL:      name = "Spherical";       type = 1; dim = 3; 
axisCode =   63; break;
             case EARTH_CENTRED:  name = "Cartesian 3D (geocentric)"; dim = 3; 
axisCode =  118; break;
-            case CARTESIAN_2D:   name = "Cartesian 2D";                      
axisCode =    3; break;
-            case UPS_NORTH:      name = "Cartesian 2D for UPS north";        
axisCode = 1067; break;
-            case UPS_SOUTH:      name = "Cartesian 2D for UPS south";        
axisCode = 1059; break;
+            case CARTESIAN_2D:   name = "Cartesian 2D";                       
axisCode =    3; break;
+            case UPS_NORTH:      name = "Cartesian 2D for UPS north";         
axisCode = 1067; break;
+            case UPS_SOUTH:      name = "Cartesian 2D for UPS south";         
axisCode = 1059; break;
             default:   if (!mandatory) return null;
                        throw new AssertionError(code);
         }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mercator1SP.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mercator1SP.java
index 0f8ffa58e0..b46d138e33 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mercator1SP.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/Mercator1SP.java
@@ -45,6 +45,11 @@ public final class Mercator1SP extends AbstractMercator {
      */
     public static final String IDENTIFIER = "9804";
 
+    /**
+     * The {@value} string, which is the <abbr>EPSG</abbr> name for this 
projection.
+     */
+    public static final String NAME = "Mercator (variant A)";
+
     /**
      * The operation parameter descriptor for the <cite>Latitude of natural 
origin</cite> (φ₀) parameter value.
      * In theory, this parameter should not be used and its value should be 0 
in all cases.
@@ -128,7 +133,7 @@ public final class Mercator1SP extends AbstractMercator {
 
         PARAMETERS = builder
                 .addIdentifier(              IDENTIFIER)                    // 
The ellipsoidal case
-                .addName(                    "Mercator (variant A)")        // 
Starting from EPSG version 7.6
+                .addName(                    NAME)                          // 
Starting from EPSG version 7.6
                 .addName(                    "Mercator (1SP)")              // 
Prior to EPSG version 7.6
                 .addName(Citations.OGC,      "Mercator_1SP")
                 .addName(Citations.GEOTIFF,  "CT_Mercator")
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 5676b80cfd..e2de3ea7fa 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
@@ -47,7 +47,7 @@ public final class PolarStereographicA extends 
AbstractStereographic {
     private static final long serialVersionUID = 538262714055500925L;
 
     /**
-     * The EPSG name for this projection.
+     * The {@value} string, which is the <abbr>EPSG</abbr> name for this 
projection.
      */
     public static final String NAME = "Polar Stereographic (variant A)";
 
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/PseudoMercator.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/PseudoMercator.java
index c1d377690e..e705d6a588 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/PseudoMercator.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/PseudoMercator.java
@@ -39,6 +39,11 @@ public final class PseudoMercator extends AbstractMercator {
      */
     public static final String IDENTIFIER = "1024";
 
+    /**
+     * The {@value} string, which is the <abbr>EPSG</abbr> name for this 
projection.
+     */
+    public static final String NAME = "Popular Visualisation Pseudo Mercator";
+
     /**
      * The group of all parameters expected by this coordinate operation.
      */
@@ -46,7 +51,7 @@ public final class PseudoMercator extends AbstractMercator {
     static {
         PARAMETERS = builder()
                 .addIdentifier(IDENTIFIER)
-                .addName("Popular Visualisation Pseudo Mercator")
+                .addName(NAME)
                 
.createGroupForMapProjection(toArray(MercatorSpherical.PARAMETERS.descriptors(),
 0));
     }
 
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/TransverseMercator.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/TransverseMercator.java
index 1874bc60d6..749c22e34e 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/TransverseMercator.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/provider/TransverseMercator.java
@@ -48,7 +48,7 @@ public final class TransverseMercator extends 
AbstractMercator {
     private static final long serialVersionUID = -3386587506686432398L;
 
     /**
-     * The {@value} string, which is also the EPSG name for this projection.
+     * The {@value} string, which is the <abbr>EPSG</abbr> name for this 
projection.
      */
     public static final String NAME = "Transverse Mercator";
 
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CRSTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CRSTest.java
index 72fc601c50..c03e0ad1c1 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CRSTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CRSTest.java
@@ -81,9 +81,7 @@ public final class CRSTest extends TestCaseWithLogs {
     private static void verifyForCode(final SingleCRS expected, final String 
code) throws FactoryException {
         final CoordinateReferenceSystem actual = CRS.forCode(code);
         assertTrue(Utilities.deepEquals(expected, actual, 
ComparisonMode.DEBUG), code);
-        if (!EPSGFactoryFallback.FORCE_HARDCODED) {
-            assertSame(expected, actual, code);
-        }
+        assertSame(expected, actual, code);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/EPSGFactoryFallbackTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/EPSGFactoryFallbackTest.java
index 69bac5ec7d..b22c338826 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/EPSGFactoryFallbackTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/EPSGFactoryFallbackTest.java
@@ -256,7 +256,7 @@ public final class EPSGFactoryFallbackTest extends 
TestCaseWithLogs {
      */
     @Test
     public void compareAllCodes() throws FactoryException {
-        final GeodeticAuthorityFactory EPSG = AuthorityFactories.getEPSG();
+        final GeodeticAuthorityFactory EPSG = 
AuthorityFactories.getEPSG(false);
         try {
             setEPSGFactory(EPSGFactoryFallback.INSTANCE);
             final var codes = new 
ArrayList<String>(EPSGFactoryFallback.INSTANCE.getAuthorityCodes(CoordinateReferenceSystem.class));
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/StandardDefinitionsTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/StandardDefinitionsTest.java
index 2c15a96290..1e77145a0c 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/StandardDefinitionsTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/StandardDefinitionsTest.java
@@ -79,6 +79,35 @@ public final class StandardDefinitionsTest extends 
EPSGDependentTestCase {
         assertEquals(AxisDirection.NORTH, cs.getAxis(1).getDirection());
     }
 
+    /**
+     * Tests {@link StandardDefinitions#createMercator(int, GeographicCRS, 
boolean)} for World Mercator.
+     */
+    @Test
+    public void testCreateWorldMercator() {
+        final ProjectedCRS crs = StandardDefinitions.createMercator(3395, 
HardCodedCRS.WGS84, false);
+        assertEquals("WGS 84 / World Mercator", crs.getName().getCode());
+        final ParameterValueGroup pg = 
crs.getConversionFromBase().getParameterValues();
+        assertEquals(0, 
pg.parameter(Constants.LATITUDE_OF_ORIGIN).doubleValue(), 
Constants.LATITUDE_OF_ORIGIN);
+        assertEquals(0, pg.parameter(Constants.CENTRAL_MERIDIAN)  
.doubleValue(), Constants.CENTRAL_MERIDIAN);
+        assertEquals(1, pg.parameter(Constants.SCALE_FACTOR)      
.doubleValue(), Constants.SCALE_FACTOR);
+        assertEquals(0, pg.parameter(Constants.FALSE_EASTING)     
.doubleValue(), Constants.FALSE_EASTING);
+        assertEquals(0, pg.parameter(Constants.FALSE_NORTHING)    
.doubleValue(), Constants.FALSE_NORTHING);
+    }
+
+    /**
+     * Tests {@link StandardDefinitions#createMercator(int, GeographicCRS, 
boolean)} for pseudo-Mercator.
+     */
+    @Test
+    public void testCreatePseudoMercator() {
+        final ProjectedCRS crs = StandardDefinitions.createMercator(3857, 
HardCodedCRS.WGS84, true);
+        assertEquals("WGS 84 / Pseudo-Mercator", crs.getName().getCode());
+        final ParameterValueGroup pg = 
crs.getConversionFromBase().getParameterValues();
+        assertEquals(0, 
pg.parameter(Constants.LATITUDE_OF_ORIGIN).doubleValue(), 
Constants.LATITUDE_OF_ORIGIN);
+        assertEquals(0, pg.parameter(Constants.CENTRAL_MERIDIAN)  
.doubleValue(), Constants.CENTRAL_MERIDIAN);
+        assertEquals(0, pg.parameter(Constants.FALSE_EASTING)     
.doubleValue(), Constants.FALSE_EASTING);
+        assertEquals(0, pg.parameter(Constants.FALSE_NORTHING)    
.doubleValue(), Constants.FALSE_NORTHING);
+    }
+
     /**
      * Tests {@link StandardDefinitions#createUniversal(int, GeographicCRS, 
boolean, double, double, CartesianCS)}
      * for a Universal Transverse Mercator (UTM) projection.

Reply via email to