This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits 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 d8c7b14aa1 Use more complete identifier (including code name) for grid 
CRS in the GUI. Opportunistic javadoc and code consolidation relative to datum 
comparisons.
d8c7b14aa1 is described below

commit d8c7b14aa13e1cbe82679e2d4b8e16db29fee1ec
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Sun May 3 01:15:01 2026 +0200

    Use more complete identifier (including code name) for grid CRS in the GUI.
    Opportunistic javadoc and code consolidation relative to datum comparisons.
---
 .../main/org/apache/sis/feature/Validator.java     |  3 +-
 .../builder/AssociationRoleBuilderTest.java        |  7 ++--
 .../metadata/internal/shared/NameToIdentifier.java | 10 ++++-
 .../gazetteer/MilitaryGridReferenceSystem.java     |  4 +-
 .../sis/referencing/AbstractIdentifiedObject.java  | 16 ++++----
 .../main/org/apache/sis/referencing/Builder.java   | 14 ++-----
 .../apache/sis/referencing/IdentifiedObjects.java  |  4 +-
 .../apache/sis/referencing/NamedIdentifier.java    | 44 ++++++++++++++++++++--
 .../sis/referencing/datum/AbstractDatum.java       | 14 ++++---
 .../referencing/datum/DefaultDatumEnsemble.java    |  4 +-
 .../referencing/datum/DefaultGeodeticDatum.java    | 10 +++--
 .../internal/shared/ReferencingUtilities.java      |  8 ++--
 .../sis/referencing/legacy/DefaultImageDatum.java  |  2 +-
 .../operation/CoordinateOperationFinder.java       |  2 +-
 .../apache/sis/parameter/ParameterFormatTest.java  |  3 +-
 .../internal/shared/DefinitionVerifierTest.java    |  3 +-
 .../provider/ParameterNameTableGenerator.java      |  4 +-
 .../org/apache/sis/storage/netcdf/base/Axis.java   |  7 ++--
 .../apache/sis/storage/base/MetadataBuilder.java   |  6 +--
 .../apache/sis/gui/coverage/CoverageCanvas.java    | 14 ++++---
 .../apache/sis/gui/coverage/CoverageExplorer.java  |  5 ++-
 .../org/apache/sis/gui/coverage/GridControls.java  |  2 +-
 .../main/org/apache/sis/gui/coverage/GridView.java |  2 +-
 .../org/apache/sis/gui/coverage/ImageRequest.java  | 23 +++++++++--
 .../apache/sis/gui/referencing/FilterByDatum.java  |  2 +-
 .../org/apache/sis/gui/referencing/MenuSync.java   | 13 ++++---
 .../gui/referencing/RecentReferenceSystems.java    | 13 +++----
 27 files changed, 151 insertions(+), 88 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/Validator.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/Validator.java
index fcf8007ccd..b6de086038 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/Validator.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/Validator.java
@@ -20,7 +20,6 @@ import java.util.Collection;
 import java.util.Collections;
 import org.opengis.util.GenericName;
 import org.opengis.util.InternationalString;
-import org.opengis.metadata.Identifier;
 import org.opengis.metadata.maintenance.ScopeCode;
 import org.opengis.metadata.quality.DataQuality;
 import org.opengis.metadata.quality.EvaluationMethodType;
@@ -94,7 +93,7 @@ final class Validator {
             final GenericName name = type.getName();
             report = new DefaultDomainConsistency();
             // Do not invoke 
report.setMeasureDescription(type.getDescription()) - see above javadoc.
-            report.setMeasureIdentification(name instanceof Identifier ? 
(Identifier) name : new NamedIdentifier(name));
+            
report.setMeasureIdentification(NamedIdentifier.toIdentifier(name));
             
report.setEvaluationMethodType(EvaluationMethodType.DIRECT_INTERNAL);
             quality.getReports().add(report);
         }
diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/feature/builder/AssociationRoleBuilderTest.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/feature/builder/AssociationRoleBuilderTest.java
index d90e1d783b..1f76ed852c 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/feature/builder/AssociationRoleBuilderTest.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/feature/builder/AssociationRoleBuilderTest.java
@@ -30,6 +30,7 @@ import org.apache.sis.test.TestCase;
  *
  * @author  Michael Hausegger
  */
+@SuppressWarnings("exports")
 public final class AssociationRoleBuilderTest extends TestCase {
     /**
      * Creates a new test case.
@@ -42,9 +43,9 @@ public final class AssociationRoleBuilderTest extends 
TestCase {
      */
     @Test
     public void testMetadata() {
-        final FeatureTypeBuilder ftb = new 
FeatureTypeBuilder().setName("Highway");
-        final NamedIdentifier target = new NamedIdentifier(null, "Bridge");
-        final AssociationRoleBuilder builder = new AssociationRoleBuilder(ftb, 
null, target)
+        final var ftb     = new FeatureTypeBuilder().setName("Highway");
+        final var target  = new NamedIdentifier(null, "Bridge");
+        final var builder = new AssociationRoleBuilder(ftb, null, target)
                 .setDescription("Bridges on the highway")
                 .setDefinition("A definition")
                 .setDesignation("A designation")
diff --git 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/shared/NameToIdentifier.java
 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/shared/NameToIdentifier.java
index 3b52eb98ed..531e9a6225 100644
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/shared/NameToIdentifier.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/internal/shared/NameToIdentifier.java
@@ -37,7 +37,7 @@ import static 
org.apache.sis.util.Characters.Filter.LETTERS_AND_DIGITS;
  * method since that method involves a mix of names and identifiers.
  *
  * <h2>Limitations</h2>
- * Current version does not yet work with URN or HTTP syntax.
+ * Current version does not yet work with <abbr>URN</abbr> or 
<abbr>HTTP</abbr> syntax.
  *
  * @author  Martin Desruisseaux (Geomatys)
  */
@@ -45,7 +45,7 @@ public final class NameToIdentifier implements Identifier {
     /**
      * The name from which to infer the identifier attributes.
      */
-    private final GenericName name;
+    public final GenericName name;
 
     /**
      * Infers the attributes from the given name.
@@ -104,6 +104,8 @@ public final class NameToIdentifier implements Identifier {
 
     /**
      * Takes everything except the tip as the code space.
+     *
+     * @return the path before the tip, or {@code null} if none.
      */
     @Override
     public String getCodeSpace() {
@@ -112,6 +114,8 @@ public final class NameToIdentifier implements Identifier {
 
     /**
      * Takes the last element as the code.
+     *
+     * @return the name tip, interpreted as identifier code.
      */
     @Override
     public String getCode() {
@@ -120,6 +124,8 @@ public final class NameToIdentifier implements Identifier {
 
     /**
      * Returns a hash code value for this object.
+     *
+     * @return hash code for this object.
      */
     @Override
     public int hashCode() {
diff --git 
a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java
 
b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java
index 53160a9e22..6917ee93f9 100644
--- 
a/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java
+++ 
b/endorsed/src/org.apache.sis.referencing.gazetteer/main/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java
@@ -301,7 +301,7 @@ public class MilitaryGridReferenceSystem extends 
ReferencingByIdentifiers {
             party = null;
             Logging.unexpectedException(LOGGER, 
MilitaryGridReferenceSystem.class, "<init>", e);
         }
-        NamedIdentifier name = new NamedIdentifier(null, "NATO", 
Resources.formatInternational(Resources.Keys.MGRS), null, null);
+        var name = new NamedIdentifier(null, "NATO", 
Resources.formatInternational(Resources.Keys.MGRS), null, null);
         return properties(name, IDENTIFIER, party);
     }
 
@@ -410,7 +410,7 @@ public class MilitaryGridReferenceSystem extends 
ReferencingByIdentifiers {
         /**
          * Cached information needed for building a MGRS reference from a 
direct position in the given CRS.
          */
-        private final Map<CoordinateReferenceSystem,Encoder> encoders;
+        private final Map<CoordinateReferenceSystem, Encoder> encoders;
 
         /**
          * Temporary positions used for encoding. References are kept for 
avoiding
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
index 0547a1ba72..51cc305d86 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
@@ -637,13 +637,13 @@ public class AbstractIdentifiedObject extends 
FormattableObject implements Ident
      *   <li>Some Latin diacritical signs (e.g. {@code "Réunion"} and {@code 
"Reunion"} are considered equal).</li>
      *   <li>All characters that are not {@linkplain 
Character#isLetterOrDigit(int) letters or digits}
      *       (e.g. {@code "Mercator (1SP)"} and {@code "Mercator_1SP"} are 
considered equal).</li>
-     *   <li>Namespaces or scopes, because this method is typically invoked 
with either the value of another
-     *       <code>IdentifiedObject.getName().getCode()</code> or with the 
<i>Well Known Text</i> (WKT)
+     *   <li>Namespaces or scopes, because this method is typically invoked 
with either the value of another call
+     *       to {@code IdentifiedObject.getName().getCode()} or with the 
<i>Well Known Text</i> (<abbr>WKT</abbr>)
      *       projection or parameter name.</li>
      * </ul>
      *
      * <h4>Usage</h4>
-     * This method is invoked by SIS when comparing in {@link 
ComparisonMode#IGNORE_METADATA IGNORE_METADATA} mode
+     * This method is invoked by <abbr>SIS</abbr> when comparing with {@link 
ComparisonMode#IGNORE_METADATA}
      * two objects that can be differentiated only by some identifier (name or 
alias), like
      * {@linkplain org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis 
coordinate system axes},
      * {@linkplain org.apache.sis.referencing.datum.AbstractDatum datum},
@@ -653,8 +653,8 @@ public class AbstractIdentifiedObject extends 
FormattableObject implements Ident
      *
      * <p>This method is also invoked when searching a parameter or operation 
method for a given name.
      * For example, the same projection is known as {@code "Mercator (variant 
A)"} (the primary name according EPSG)
-     * and {@code "Mercator (1SP)"} (the legacy name prior EPSG 7.6). Since 
the latter is still in frequent use, SIS
-     * accepts it as an alias of the <cite>Mercator (variant A)</cite> 
projection.</p>
+     * and {@code "Mercator (1SP)"} (the legacy name prior EPSG 7.6). Since 
the latter is still in frequent use,
+     * <abbr>SIS</abbr> accepts it as an alias of the <cite>Mercator (variant 
A)</cite> projection.</p>
      *
      * <h4>Overriding by subclasses</h4>
      * Some subclasses add more flexibility to the comparisons:
@@ -673,8 +673,8 @@ public class AbstractIdentifiedObject extends 
FormattableObject implements Ident
      * <h4>Future evolutions</h4>
      * This method implements recommendations from the <abbr>WKT</abbr> 2 
specification,
      * together with heuristic rules learned from experience while trying to 
provide inter-operability
-     * with different data producers. Those rules may be adjusted in any 
future SIS version according experience
-     * gained while working with more data producers.
+     * with different data producers. Those rules may be adjusted in any 
future <abbr>SIS</abbr> version
+     * according experience gained while working with more data producers.
      *
      * @param  name  the name to compare with the object name or aliases.
      * @return {@code true} if the primary name or at least one alias matches 
the specified {@code name}.
@@ -1149,7 +1149,7 @@ public class AbstractIdentifiedObject extends 
FormattableObject implements Ident
                  * Our Code and RS_Identifier implementations should always 
create NamedIdentifier instance,
                  * so the `instanceof` check should not be necessary. But we 
do a paranoiac check anyway.
                  */
-                final GenericName n = id instanceof GenericName ? 
(GenericName) id : new NamedIdentifier(id);
+                final GenericName n = NamedIdentifier.toGenericName(id);
                 if (alias == null) {
                     alias = Collections.singleton(n);
                 } else {
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/Builder.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/Builder.java
index b10504c51a..a66a30b765 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/Builder.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/Builder.java
@@ -349,14 +349,6 @@ public abstract class Builder<B extends Builder<B>> {
         }
     }
 
-    /**
-     * Converts the given name into an identifier. Note that {@link 
NamedIdentifier}
-     * implements both {@link GenericName} and {@link Identifier} interfaces.
-     */
-    private static Identifier toIdentifier(final GenericName name) {
-        return (name instanceof Identifier) ? (Identifier) name : new 
NamedIdentifier(name);
-    }
-
     /**
      * Sets the property value for the given key, if a change is still 
possible. The check for change permission
      * is needed for all keys defined in the {@link Identifier} interface. 
This check is not needed for other keys,
@@ -582,7 +574,7 @@ public abstract class Builder<B extends Builder<B>> {
     public B addName(final Identifier name) {
         if (properties.putIfAbsent(IdentifiedObject.NAME_KEY, 
Objects.requireNonNull(name)) != null) {
             // A primary name is already present. Add the given name as an 
alias instead.
-            aliases.add(name instanceof GenericName ? (GenericName) name : new 
NamedIdentifier(name));
+            aliases.add(NamedIdentifier.toGenericName(name));
         }
         return self();
     }
@@ -607,7 +599,7 @@ public abstract class Builder<B extends Builder<B>> {
     public B addName(final GenericName name) {
         Objects.requireNonNull(name);
         if (properties.get(IdentifiedObject.NAME_KEY) == null) {
-            properties.put(IdentifiedObject.NAME_KEY, toIdentifier(name));
+            properties.put(IdentifiedObject.NAME_KEY, 
NamedIdentifier.toIdentifier(name));
         } else {
             aliases.add(name);
         }
@@ -838,7 +830,7 @@ public abstract class Builder<B extends Builder<B>> {
          * take the first alias as the new primary name.
          */
         if (properties.get(IdentifiedObject.NAME_KEY) == null && 
!aliases.isEmpty()) {
-            properties.put(IdentifiedObject.NAME_KEY, 
toIdentifier(aliases.remove(0)));
+            properties.put(IdentifiedObject.NAME_KEY, 
NamedIdentifier.toIdentifier(aliases.remove(0)));
         }
         return self();
     }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/IdentifiedObjects.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/IdentifiedObjects.java
index 7bfa858c13..cabc1040d9 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/IdentifiedObjects.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/IdentifiedObjects.java
@@ -742,8 +742,8 @@ public final class IdentifiedObjects {
      *   <li>Some Latin diacritical signs (e.g. {@code "Réunion"} and {@code 
"Reunion"} are considered equal).</li>
      *   <li>All characters that are not {@linkplain 
Character#isLetterOrDigit(int) letters or digits}
      *       (e.g. {@code "Mercator (1SP)"} and {@code "Mercator_1SP"} are 
considered equal).</li>
-     *   <li>Namespaces or scopes, because this method is typically invoked 
with either the value of another
-     *       <code>IdentifiedObject.getName().getCode()</code> or with the 
<i>Well Known Text</i> (WKT)
+     *   <li>Namespaces or scopes, because this method is typically invoked 
with either the value of another call
+     *       to {@code IdentifiedObject.getName().getCode()} or with the 
<i>Well Known Text</i> (<abbr>WKT</abbr>)
      *       projection or parameter name.</li>
      * </ul>
      *
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/NamedIdentifier.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/NamedIdentifier.java
index 956bf79950..6fc54e9b88 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/NamedIdentifier.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/NamedIdentifier.java
@@ -83,7 +83,7 @@ import org.apache.sis.util.iso.DefaultNameFactory;
  * any public {@code NamedIdentifier} state.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.7
  *
  * @see org.apache.sis.metadata.iso.DefaultIdentifier
  * @see org.apache.sis.util.iso.AbstractName
@@ -123,10 +123,14 @@ public class NamedIdentifier extends ImmutableIdentifier 
implements GenericName
      */
     public NamedIdentifier(final Identifier identifier) {
         super(identifier);
-        if (identifier instanceof GenericName) {
+        if (identifier instanceof NameToIdentifier) {
+            name = ((NameToIdentifier) identifier).name;
+        } else if (identifier instanceof GenericName) {
             name = (GenericName) identifier;
-            isNameSupplied = true;
+        } else {
+            return;
         }
+        isNameSupplied = true;
     }
 
     /**
@@ -339,6 +343,8 @@ public class NamedIdentifier extends ImmutableIdentifier 
implements GenericName
      * @return a SIS implementation containing the values of the given object 
(may be the
      *         given object itself), or {@code null} if the argument was null.
      *
+     * @see #toGenericName(Identifier)
+     *
      * @since 1.0
      */
     public static NamedIdentifier castOrCopy(final Identifier object) {
@@ -366,6 +372,8 @@ public class NamedIdentifier extends ImmutableIdentifier 
implements GenericName
      * @return a SIS implementation containing the values of the given object 
(may be the
      *         given object itself), or {@code null} if the argument was null.
      *
+     * @see #toIdentifier(GenericName)
+     *
      * @since 1.0
      */
     public static NamedIdentifier castOrCopy(final GenericName object) {
@@ -375,6 +383,36 @@ public class NamedIdentifier extends ImmutableIdentifier 
implements GenericName
         return new NamedIdentifier(object);
     }
 
+    /**
+     * Returns the given identifier as a name. This method is similar to 
{@link #castOrCopy(Identifier)}
+     * except that it does not require the given {@code object} to be a {@code 
NamedIdentifier} instance.
+     *
+     * @param  object  the object to get as a name, or {@code nulk}.
+     * @return the given object as a name, or {@code null} if the argument was 
null.
+     * @since  1.7
+     */
+    public static GenericName toGenericName(final Identifier object) {
+        if (object == null || object instanceof GenericName) {
+            return (GenericName) object;
+        }
+        return new NamedIdentifier(object);
+    }
+
+    /**
+     * Returns the given name as an identifier. This method is similar to 
{@link #castOrCopy(GenericName)}
+     * except that it does not require the given {@code object} to be a {@code 
NamedIdentifier} instance.
+     *
+     * @param  object  the object to get as an identifier, or {@code nulk}.
+     * @return the given object as an identifier, or {@code null} if the 
argument was null.
+     * @since  1.7
+     */
+    public static Identifier toIdentifier(final GenericName object) {
+        if (object == null || object instanceof Identifier) {
+            return (Identifier) object;
+        }
+        return new NamedIdentifier(object);
+    }
+
     /**
      * The last element in the sequence of {@linkplain #getParsedNames() 
parsed names}.
      * By default, this is the same value as the {@linkplain #getCode() code} 
provided as a local name.
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
index a28ed3df72..94d71198d1 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
@@ -391,17 +391,21 @@ public class AbstractDatum extends 
AbstractIdentifiedObject implements Datum {
      *       be ignored.</li>
      * </ul>
      *
+     * Note that the comparison ignores {@linkplain Identifier#getCodeSpace() 
code spaces}
+     * and {@linkplain GenericName#scope() scopes}.
+     *
      * <h4>Future evolutions</h4>
-     * This method implements heuristic rules learned from experience while 
trying to provide inter-operability
-     * with different data producers. Those rules may be adjusted in any 
future SIS version according experience
-     * gained while working with more data producers.
+     * This method implements recommendations from the <abbr>WKT</abbr> 2 
specification,
+     * together with heuristic rules learned from experience while trying to 
provide inter-operability
+     * with different data producers. Those rules may be adjusted in any 
future <abbr>SIS</abbr> version
+     * according experience gained while working with more data producers.
      *
      * @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, Simplifier.INSTANCE);
+        return NameToIdentifier.isHeuristicMatchForName(super.getName(), 
super.getAlias(), name, Simplifier.FOR_DATUM);
     }
 
     /**
@@ -413,7 +417,7 @@ public class AbstractDatum extends AbstractIdentifiedObject 
implements Datum {
      */
     static class Simplifier extends NameToIdentifier.Simplifier {
         /** The singleton simplifier for non-geodetic datum. */
-        static final Simplifier INSTANCE = new Simplifier();
+        static final Simplifier FOR_DATUM = new Simplifier();
 
         /** For subclasses and default instance only. */
         Simplifier() {}
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 72b0d08d80..e733eb37e6 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
@@ -470,14 +470,14 @@ check:  if (it.hasNext()) {
      * 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}.
+     * {@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);
+        return NameToIdentifier.isHeuristicMatchForName(super.getName(), 
super.getAlias(), name, AbstractDatum.Simplifier.FOR_DATUM);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
index 49c7f16835..23d0277e64 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultGeodeticDatum.java
@@ -632,14 +632,18 @@ public class DefaultGeodeticDatum extends AbstractDatum 
implements GeodeticDatum
      * The meridian can be safely ignored in the datum name because the {@link 
PrimeMeridian} object is already
      * compared by the {@link #equals(Object)} method.
      *
+     * <p>Note that the comparison ignores {@linkplain 
Identifier#getCodeSpace() code spaces}
+     * and {@linkplain GenericName#scope() scopes}.</p>
+     *
      * <h4>Example</h4>
      * If the datum name is <q>Nouvelle Triangulation Française (Paris)</q> 
and the prime meridian name is
      * <q>Paris</q>, then this method compares only the <q>Nouvelle 
Triangulation Française</q> part.
      *
      * <h4>Future evolutions</h4>
-     * This method implements heuristic rules learned from experience while 
trying to provide inter-operability
-     * with different data producers. Those rules may be adjusted in any 
future SIS version according experience
-     * gained while working with more data producers.
+     * This method implements recommendations from the <abbr>WKT</abbr> 2 
specification,
+     * together with heuristic rules learned from experience while trying to 
provide inter-operability
+     * with different data producers. Those rules may be adjusted in any 
future <abbr>SIS</abbr> version
+     * according experience gained while working with more data producers.
      *
      * @param  name  the name to compare.
      * @return {@code true} if the primary name or at least one alias matches 
the specified {@code name}.
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/shared/ReferencingUtilities.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/shared/ReferencingUtilities.java
index ca414ebb1f..e865f265ed 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/shared/ReferencingUtilities.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/shared/ReferencingUtilities.java
@@ -303,7 +303,7 @@ public final class ReferencingUtilities {
         if (keepName && overwrite == null) {
             return properties;
         }
-        final var copy = new HashMap<String,Object>(properties);
+        final var copy = new HashMap<String, Object>(properties);
         if (!keepName) {
             copy.put(IdentifiedObject.NAME_KEY, new NamedIdentifier(null, 
name.getCode()));
         }
@@ -357,7 +357,7 @@ public final class ReferencingUtilities {
                         }
                         name = CharSequences.trimWhitespaces(name, 0, 
i).toString();
                         if (!name.isEmpty()) {
-                            final Map<String,Object> copy = new 
HashMap<>(properties);
+                            final var copy = new HashMap<String, 
Object>(properties);
                             copy.put(IdentifiedObject.NAME_KEY, name);
                             return copy;
                         }
@@ -433,8 +433,8 @@ public final class ReferencingUtilities {
      * @throws NumberFormatException if a parameter identifier of the given 
authority is not numeric.
      * @throws IllegalArgumentException if the same identifier is used for two 
or more parameters.
      */
-    public static Map<Integer,String> identifierToName(final 
ParameterDescriptorGroup parameters, final Citation authority) {
-        final Map<Integer,String> mapping = new HashMap<>();
+    public static Map<Integer, String> identifierToName(final 
ParameterDescriptorGroup parameters, final Citation authority) {
+        final var mapping = new HashMap<Integer, String>();
         for (final GeneralParameterDescriptor descriptor : 
parameters.descriptors()) {
             final Identifier id = IdentifiedObjects.getIdentifier(descriptor, 
authority);
             if (id != null) {
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/legacy/DefaultImageDatum.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/legacy/DefaultImageDatum.java
index 5a742311d5..e8568f24e3 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/legacy/DefaultImageDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/legacy/DefaultImageDatum.java
@@ -147,7 +147,7 @@ public final class DefaultImageDatum extends AbstractDatum {
         if (object == this) {
             return true;        // Slight optimization.
         }
-        return (object instanceof DefaultImageDatum) &&
+        return (super.equals(object, mode) && object instanceof 
DefaultImageDatum) &&
                 Objects.equals(pixelInCell, ((DefaultImageDatum) 
object).pixelInCell);
     }
 
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
index be099c5216..53fc23a90d 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
@@ -1240,7 +1240,7 @@ public class CoordinateOperationFinder extends 
CoordinateOperationRegistry {
             p = identifierOfStepCRS.get(oldID);
         }
         final int count = (p != null) ? (Integer) p + 1 : 1;
-        final Identifier newID = new NamedIdentifier(Citations.SIS, 
oldID.getCode() + " (step " + count + ')');
+        final var newID = new NamedIdentifier(Citations.SIS, oldID.getCode() + 
" (step " + count + ')');
         identifierOfStepCRS.put(newID, oldID);
         identifierOfStepCRS.put(oldID, count);
 
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/parameter/ParameterFormatTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/parameter/ParameterFormatTest.java
index 32123058d2..23947e6486 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/parameter/ParameterFormatTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/parameter/ParameterFormatTest.java
@@ -43,6 +43,7 @@ import static 
org.apache.sis.test.Assertions.assertMultilinesEquals;
  *
  * @author  Martin Desruisseaux (Geomatys)
  */
+@SuppressWarnings("exports")
 @Execution(ExecutionMode.CONCURRENT)
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 public final class ParameterFormatTest extends TestCase {
@@ -66,7 +67,7 @@ public final class ParameterFormatTest extends TestCase {
      * The default values are not part of EPSG definitions. They are added 
here only for testing purpose.
      */
     static ParameterDescriptorGroup createMercatorParameters() {
-        ParameterBuilder builder = new ParameterBuilder();
+        final var builder = new ParameterBuilder();
         builder.setCodeSpace(EPSG, "EPSG").setRequired(true);
         ParameterDescriptor<?>[] parameters = {
             builder.addIdentifier("8801").addName("Latitude of natural 
origin").addName(OGC, "latitude_of_origin")
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/shared/DefinitionVerifierTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/shared/DefinitionVerifierTest.java
index 103b18a2b2..442dd3aa94 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/shared/DefinitionVerifierTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/shared/DefinitionVerifierTest.java
@@ -16,7 +16,6 @@
  */
 package org.apache.sis.referencing.internal.shared;
 
-import java.util.Map;
 import java.util.HashMap;
 import java.util.logging.LogRecord;
 import java.util.logging.SimpleFormatter;
@@ -83,7 +82,7 @@ public final class DefinitionVerifierTest extends TestCase {
      */
     @Test
     public void testDifferentAxisOrder() throws FactoryException {
-        final Map<String,Object> properties = new HashMap<>(4);
+        final var properties = new HashMap<String, Object>(4);
         properties.put(DefaultGeographicCRS.NAME_KEY, "WGS 84");
         properties.put(DefaultGeographicCRS.IDENTIFIERS_KEY, new 
NamedIdentifier(HardCodedCitations.EPSG, "4326"));
         DefaultGeographicCRS crs = HardCodedCRS.WGS84;
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 cde607ddb8..f08a1197e3 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
@@ -201,8 +201,8 @@ public final class ParameterNameTableGenerator extends 
SimpleFileVisitor<Path> {
                 write(insertAt++, "  <caption>Parameter names</caption>");
                 write(insertAt++, descriptor.getName(), false);
                 for (final GenericName alias : descriptor.getAlias()) {
-                    write(insertAt++, (alias instanceof Identifier) ? 
(Identifier) alias : new NamedIdentifier(alias),
-                                       alias instanceof Deprecable && 
((Deprecable) alias).isDeprecated());
+                    write(insertAt++, NamedIdentifier.toIdentifier(alias),
+                          alias instanceof Deprecable && ((Deprecable) 
alias).isDeprecated());
                 }
                 write(insertAt++, "</table>");
                 /*
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java
index 3c907574e1..9e63a7741d 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Axis.java
@@ -19,7 +19,6 @@ package org.apache.sis.storage.netcdf.base;
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Set;
-import java.util.Map;
 import java.util.HashMap;
 import java.util.Arrays;
 import java.util.OptionalLong;
@@ -565,12 +564,12 @@ public final class Axis extends NamedElement {
          * because this is controlled vocabulary.
          */
         final String name = getName();
-        final Map<String,Object> properties = new HashMap<>(4);
+        final var properties = new HashMap<String, Object>(4);
         properties.put(CoordinateSystemAxis.NAME_KEY, name);                   
     // Intentionally no namespace.
-        final List<GenericName> aliases = new ArrayList<>(2);
+        final var aliases = new ArrayList<GenericName>(2);
         final String standardName = 
coordinates.getAttributeAsString(CF.STANDARD_NAME);
         if (standardName != null) {
-            final NamedIdentifier std = new NamedIdentifier(Citations.NETCDF, 
standardName);
+            final var std = new NamedIdentifier(Citations.NETCDF, 
standardName);
             if (standardName.equals(name)) {
                 properties.put(CoordinateSystemAxis.NAME_KEY, std);            
     // Store as primary name.
             } else {
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
index 177724488b..46039d1a7d 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
@@ -992,7 +992,7 @@ public class MetadataBuilder {
      */
     public final void addIdentifier(final GenericName id, final Scope scope) {
         if (id != null) {
-            addIdentifier((id instanceof Identifier) ? (Identifier) id : new 
NamedIdentifier(id), scope);
+            addIdentifier(NamedIdentifier.toIdentifier(id), scope);
         }
     }
 
@@ -1736,8 +1736,8 @@ public class MetadataBuilder {
      *   <li>{@code 
metadata/identificationInfo/extent/geographicElement/identifier}</li>
      * </ul>
      *
-     * @param authority  the authority of the identifier code, or {@code null} 
if none.
-     * @param code       the identifier code used to represent a geographic 
area, or {@code null} if none.
+     * @param  authority   the authority of the identifier code, or {@code 
null} if none.
+     * @param  identifier  the identifier code used to represent a geographic 
area, or {@code null} if none.
      */
     public final void addExtent(final Citation authority, final String 
identifier) {
         if (authority != null || identifier != null) {
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
index e1ce2e3f95..039ca62293 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
@@ -881,14 +881,16 @@ public class CoverageCanvas extends MapCanvasAWT {
 
     /**
      * Return a name of the grid <abbr>CRS</abbr>, derived from the resource 
identifier.
-     * This method never return {@code null}.
+     * This method returns {@code null} if no worker has read the resource 
identifier yet.
+     * It may happen randomly depending on thread execution order.
+     *
+     * <p>Note: do not fallback on an artificial name if the name is {@code 
null}.
+     * This method is used for building a grid <abbr>CRS</abbr> for cell 
indices.
+     * If this method returns an artificial name, it would cause an unusable 
menu
+     * item to appear in the menu that offers different <abbr>CRS</abbr>.</p>
      */
     final Identifier gridCrsName() {
-        Identifier name = data.gridCrsName;
-        if (name == null) {
-            name = CommonCRS.Engineering.GRID.datum().getName();
-        }
-        return name;
+        return data.gridCrsName;
     }
 
     /**
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
index 57a02f40cd..58ac7e3dd0 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
@@ -607,14 +607,15 @@ public class CoverageExplorer extends Widget {
      * {@link #coverageProperty}. In the latter case, the {@code resource} and 
{@code coverage} arguments
      * given to this method may be the value that the properties already 
have.</p>
      *
-     * @param  name      an identifier for the grid <abbr>CRS</abbr>. Can be 
null only if {@code coverage} is null.
+     * @param  name      value of {@link CoverageCanvas#gridCrsName()} or 
equivalent.
      * @param  resource  the new source of coverage, or {@code null} if none.
      * @param  coverage  the new coverage, or {@code null} if none.
      */
     final void notifyDataChanged(final Identifier name, final 
GridCoverageResource resource, final GridCoverage coverage) {
         if (coverage != null) {
             BackgroundThreads.execute(() -> {
-                referenceSystems.setGridReferencing(true, Map.of(name, 
coverage.getGridGeometry()));
+                referenceSystems.setGridReferencing(true,
+                        (name == null) ? Map.of() : Map.of(name, 
coverage.getGridGeometry()));
             });
         }
         /*
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridControls.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridControls.java
index 78b2eec27d..4ccccfeed1 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridControls.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridControls.java
@@ -104,7 +104,7 @@ final class GridControls extends ViewAndControls {
      * Invoked after {@link GridView#setImage(ImageRequest)} for updating the 
table of sample
      * dimensions when information become available. This method is invoked in 
JavaFX thread.
      *
-     * @param  name      an identifier for the grid <abbr>CRS</abbr>. Can be 
null only if {@code coverage} is null.
+     * @param  name      value of {@link CoverageCanvas#gridCrsName()}.
      * @param  resource  the new source of coverage, or {@code null} if none.
      * @param  coverage  the new coverage, or {@code null} if none.
      */
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java
index 15d7a7cfe3..7503c841dd 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java
@@ -321,7 +321,7 @@ public class GridView extends Control {
     /**
      * Invoked after the image has been loaded or after failure.
      *
-     * @param  name      an identifier for the grid <abbr>CRS</abbr>. Can be 
null only if {@code coverage} is null.
+     * @param  name      value equivalent to {@link 
CoverageCanvas#gridCrsName()}.
      * @param  resource  the new source of coverage, or {@code null} if none.
      * @param  coverage  the new coverage, or {@code null} if none.
      * @param  image     the loaded image, or {@code null} on failure.
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ImageRequest.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ImageRequest.java
index 7cf1e6ba85..29691a0d8e 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ImageRequest.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ImageRequest.java
@@ -18,12 +18,14 @@ package org.apache.sis.gui.coverage;
 
 import java.util.Objects;
 import java.util.Optional;
+import org.opengis.util.NameSpace;
+import org.opengis.util.GenericName;
 import org.opengis.metadata.Identifier;
 import org.apache.sis.coverage.grid.GridCoverage;
 import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.referencing.CommonCRS;
-import org.apache.sis.referencing.NamedIdentifier;
+import org.apache.sis.referencing.ImmutableIdentifier;
 import org.apache.sis.storage.GridCoverageResource;
 import org.apache.sis.storage.DataStoreException;
 
@@ -179,9 +181,24 @@ public class ImageRequest {
             throws DataStoreException
     {
         if (resource != null) {
-            final Identifier name = 
NamedIdentifier.castOrCopy(resource.getIdentifier().orElse(null));
+            final GenericName name = resource.getIdentifier().orElse(null);
             if (name != null) {
-                return name;
+                if (name instanceof Identifier) {
+                    return (Identifier) name;
+                }
+                /*
+                 * Do not use `NamedIdentifier` because we want the full name 
as identifier code.
+                 * By contrast, `NamedIdentifier` takes only the tip (because 
it is better suited
+                 * to datum names or projection parameter names). In the 
context of resource, the
+                 * tip alone is not sufficient because it is often only an 
image number in a file
+                 * specified by the name component before the tip.
+                 */
+                String codeSpace = null;
+                final NameSpace scope = name.scope();
+                if (scope != null && !scope.isGlobal()) {
+                    codeSpace = scope.name().toString();
+                }
+                return new ImmutableIdentifier(null, codeSpace, 
name.toString());
             }
         }
         return (domain.isDefined(GridGeometry.GRID_TO_CRS)
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/FilterByDatum.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/FilterByDatum.java
index 625cf397cd..dfec44608c 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/FilterByDatum.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/FilterByDatum.java
@@ -86,7 +86,7 @@ final class FilterByDatum implements 
Predicate<ReferenceSystem> {
             }
         }
         types.remove(null);
-        if (types.isEmpty()) {
+        if (instances.isEmpty() && types.equals(Set.of(Datum.class))) {
             return null;
         }
         return new FilterByDatum(types.toArray(Class[]::new), 
instances.toArray(EngineeringDatum[]::new));
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/MenuSync.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/MenuSync.java
index df64435a15..ca03c8a102 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/MenuSync.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/MenuSync.java
@@ -158,7 +158,7 @@ final class MenuSync extends 
SimpleObjectProperty<ReferenceSystem> implements Ev
         if (derived != null) {
             final Menu menu = new 
Menu(Resources.forLocale(locale).getString(Resources.Keys.ReferenceByCellIndices));
             cellIndicesMenus = menu.getItems();
-            updateCellIndicesMenus(locale);
+            updateCellIndicesMenus();
             rootMenus.add(menu);
         } else {
             cellIndicesMenus = null;
@@ -225,10 +225,8 @@ final class MenuSync extends 
SimpleObjectProperty<ReferenceSystem> implements Ev
      * Updates the {@link #cellIndicesMenus} list with current content of 
{@link #cellIndicesSystems}.
      * This method recycles existing menu items, creates new ones if needed 
and discards the ones that
      * are no longer in use.
-     *
-     * @param  systems  all CRS for grid indices to show in the "Referencing 
by cell indices" sub-menu.
      */
-    private void updateCellIndicesMenus(final Locale locale) {
+    private void updateCellIndicesMenus() {
         final int n = cellIndicesSystems.size();
         for (int i=0; i<n; i++) {
             final CoordinateReferenceSystem crs = cellIndicesSystems.get(i);
@@ -242,7 +240,10 @@ final class MenuSync extends 
SimpleObjectProperty<ReferenceSystem> implements Ev
                 cellIndicesMenus.add(item);
             }
             if (item.getProperties().put(REFERENCE_SYSTEM_KEY, crs) != crs) {
-                item.setText(IdentifiedObjects.getDisplayName(crs, locale));
+                item.setText(IdentifiedObjects.toString(crs.getName()));
+                // Note: use `toString(…)` instead of `getDisplayName(…)`
+                // because we are better to show the code space, since it
+                // is often the name of the file of the grid.
             }
         }
         for (int i = cellIndicesMenus.size(); --i >= n;) {
@@ -355,7 +356,7 @@ final class MenuSync extends 
SimpleObjectProperty<ReferenceSystem> implements Ev
             initialize();
         }
         if (cellIndicesSystems != null) {
-            updateCellIndicesMenus(locale);
+            updateCellIndicesMenus();
         }
     }
 
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java
index 6ef9dc5307..10cc7bdaba 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java
@@ -366,14 +366,13 @@ public class RecentReferenceSystems {
                 final boolean old = isAdjusting;
                 try {
                     isAdjusting = true;
-                    final CoordinateReferenceSystem preferred = refsys[0];
-                    if (preferred != null) {
+                    if (refsys.length != 0) {
+                        setPreferred(replaceByAuthoritativeDefinition, 
refsys[0]);
                         refsys[0] = null;
-                        setPreferred(replaceByAuthoritativeDefinition, 
preferred);
                         addAlternatives(replaceByAuthoritativeDefinition, 
refsys);  // Null elements are ignored.
-                        cellIndiceSystems.clear();
-                        cellIndiceSystems.addAll(cellCRS);
                     }
+                    cellIndiceSystems.clear();
+                    cellIndiceSystems.addAll(cellCRS);
                     filterByDatum = filter;
                     areaOfInterest.set(aoi);
                 } finally {
@@ -727,7 +726,7 @@ public class RecentReferenceSystems {
             final int n = referenceSystems.size();
             for (int j=0; j<values.length; j++) {
                 ReferenceSystem system = values[j];
-                if (system != null) {                   // See comment about 
empty `referenceSystems` list.
+                if (system != null) {
                     for (int i=0; i<n; i++) {
                         final ReferenceSystem candidate = 
referenceSystems.get(i);
                         if (Utilities.deepEquals(candidate, system, mode)) {
@@ -821,7 +820,7 @@ public class RecentReferenceSystems {
                     if (!found) {
                         if (count >= NUM_SHOWN_ITEMS) {
                             final List<ReferenceSystem> selected = 
getSelectedItems();
-                            for (int i=count; --i >= NUM_CORE_ITEMS;) {
+                            for (int i = count; --i >= NUM_CORE_ITEMS;) {
                                 if (!selected.contains(items.get(i))) {        
 // Do not remove selected items.
                                     items.remove(i);                           
 // Remove an item before `OTHER`.
                                     if (--count < NUM_SHOWN_ITEMS) break;

Reply via email to