Merge branch 'geoapi-4.0' into geoapi-3.1: removal of deprecated methods.
diff --git a/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java b/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java
index bb227ba..29ed49a 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java
@@ -551,15 +551,6 @@
     }
 
     /**
-     * @deprecated Renamed {@link #setDefaultMultiplicity(int, int)}. A cardinality is the actual number of elements
-     * in a set, while multiplicity is the range of cardinality that a set can have.
-     */
-    @Deprecated
-    public FeatureTypeBuilder setDefaultCardinality(final int minimumOccurs, final int maximumOccurs) {
-        return setDefaultMultiplicity(minimumOccurs, maximumOccurs);
-    }
-
-    /**
      * Sets the default minimum and maximum number of next attributes and associations to add.
      * Those defaults will applied to newly created attributes or associations,
      * for example in next calls to {@link #addAttribute(Class)}.
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/Context.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/Context.java
index a4af9cf..4483329 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/Context.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/Context.java
@@ -181,7 +181,7 @@
     /**
      * The object to inform about warnings, or {@code null} if none.
      */
-    private final Filter warningListener;
+    private final Filter logFilter;
 
     /**
      * The {@code <gml:*PropertyType>} which is wrapping the {@code <gml:*Type>} object to (un)marshal, or
@@ -222,7 +222,7 @@
      * @param  versionMetadata  the metadata version, or {@code null}.
      * @param  resolver         the resolver in use.
      * @param  converter        the converter in use.
-     * @param  warningListener  the object to inform about warnings.
+     * @param  logFilter        the object to inform about warnings.
      */
     @SuppressWarnings("ThisEscapedInObjectConstruction")
     public Context(int                      bitMasks,
@@ -233,7 +233,7 @@
                    final Version            versionMetadata,
                    final ReferenceResolver  resolver,
                    final ValueConverter     converter,
-                   final Filter             warningListener)
+                   final Filter             logFilter)
     {
         if (versionMetadata != null && versionMetadata.compareTo(LegacyNamespaces.VERSION_2014) < 0) {
             bitMasks |= LEGACY_METADATA;
@@ -244,7 +244,7 @@
         this.versionGML        = versionGML;
         this.resolver          = resolver;
         this.converter         = converter;
-        this.warningListener   = warningListener;
+        this.logFilter         = logFilter;
         this.identifiers       = new HashMap<>();
         this.identifiedObjects = new IdentityHashMap<>();
         if (locale != null) {
@@ -621,10 +621,10 @@
         record.setSourceMethodName(method);
         record.setLoggerName(Loggers.XML);
         if (context != null) {
-            final Filter warningListener = context.warningListener;
-            if (warningListener != null) {
+            final Filter logFilter = context.logFilter;
+            if (logFilter != null) {
                 record.setThrown(exception);
-                if (!warningListener.isLoggable(record)) {
+                if (!logFilter.isLoggable(record)) {
                     return;
                 }
             }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Identifiers.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Identifiers.java
index 46f7f1f..1fb8556 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Identifiers.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Identifiers.java
@@ -91,10 +91,10 @@
      * <ul>
      *   <li>For information purpose (e.g. some {@code toString()} methods), use {@code getIdentifier(…, false)}.</li>
      *   <li>For WKT formatting, use {@code getIdentifier(…, true)} in order to preserve formatting characters.</li>
-     *   <li>For assigning a value to a {@code codeSpace} field, use {@link Citations#getUnicodeIdentifier(Citation)}.</li>
+     *   <li>For assigning a value to a {@code codeSpace} field, use {@link Citations#toCodeSpace(Citation)}.</li>
      * </ul>
      *
-     * Use {@code getUnicodeIdentifier(…)} method when assigning values to be returned by methods like
+     * Use {@code toCodeSpace(…)} method when assigning values to be returned by methods like
      * {@link Identifier#getCodeSpace()}, since those values are likely to be compared without special
      * care about ignorable identifier characters. But if the intent is to format a more complex string
      * like WKT or {@code toString()}, then we suggest to use {@code getIdentifier(citation, true)} instead,
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Resources.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Resources.java
index f2badce..660a727 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Resources.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Resources.java
@@ -81,7 +81,7 @@
         public static final short ElementsOmitted_1 = 4;
 
         /**
-         * `{1}` is an implementation class. Specify the `{0}` interface instead.
+         * Illegal class `{1}`. Specify the `{0}` interface instead.
          */
         public static final short ExpectedInterface_2 = 5;
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Resources.properties b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Resources.properties
index 0e80c25..8ab6976 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Resources.properties
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Resources.properties
@@ -23,5 +23,5 @@
 ConnectionAlreadyInitialized_1    = Connection to \u201c{0}\u201d database is already initialized.
 ElementAlreadyInitialized_1       = This metadata element is already initialized with value \u201c{0}\u201d.
 ElementsOmitted_1                 = \u2026 {0} elements omitted \u2026
-ExpectedInterface_2               = `{1}` is an implementation class. Specify the `{0}` interface instead.
+ExpectedInterface_2               = Illegal class `{1}`. Specify the `{0}` interface instead.
 UnmodifiableMetadata              = This metadata is not modifiable.
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Resources_fr.properties b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Resources_fr.properties
index c8eefe5..8359aaa 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Resources_fr.properties
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/Resources_fr.properties
@@ -28,5 +28,5 @@
 ConnectionAlreadyInitialized_1    = La connexion \u00e0 la base de donn\u00e9es \u00ab\u202f{0}\u202f\u00bb est d\u00e9j\u00e0 initialis\u00e9e.
 ElementAlreadyInitialized_1       = Cet \u00e9l\u00e9ment de m\u00e9ta-donn\u00e9e est d\u00e9j\u00e0 initialis\u00e9 avec la valeur \u00ab\u202f{0}\u202f\u00bb.
 ElementsOmitted_1                 = \u2026 {0} \u00e9l\u00e9ments omis \u2026
-ExpectedInterface_2               = `{1}` est une classe d\u2019impl\u00e9mentation. Sp\u00e9cifiez l\u2019interface `{0}` \u00e0 la place.
+ExpectedInterface_2               = La classe `{1}` est ill\u00e9gale. Sp\u00e9cifiez l\u2019interface `{0}` \u00e0 la place.
 UnmodifiableMetadata              = Cette m\u00e9ta-donn\u00e9e n\u2019est pas modifiable.
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataCopier.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataCopier.java
index a99df1a..1e34396 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataCopier.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataCopier.java
@@ -155,7 +155,7 @@
         ArgumentChecks.ensureNonNull("type", type);
         if (metadata instanceof AbstractMetadata) {
             final Class<?> interfaceType = ((AbstractMetadata) metadata).getInterface();
-            if (type != interfaceType) {
+            if (!type.isAssignableFrom(interfaceType)) {
                 /*
                  * In case the user specified an implementation despite the documentation warning.
                  * We could replace `type` by `interfaceType` and it would work most of the time,
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
index a6a196f..f9c3b78 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
@@ -133,16 +133,6 @@
     private transient byte state;
 
     /**
-     * An unmodifiable copy of this metadata, created only when first needed.
-     * If {@code null}, then no unmodifiable entity is available.
-     * If {@code this}, then this entity is itself unmodifiable.
-     *
-     * @deprecated to be deleted after the removal of {@link #unmodifiable()}.
-     */
-    @Deprecated
-    private transient ModifiableMetadata unmodifiable;
-
-    /**
      * Constructs an initially empty metadata.
      * The initial state is {@link State#EDITABLE}.
      */
@@ -297,112 +287,6 @@
     }
 
     /**
-     * Returns {@code true} if this metadata is modifiable. This method returns
-     * {@code false} if {@link #freeze()} has been invoked on this object.
-     *
-     * @return {@code true} if this metadata is modifiable.
-     *
-     * @see #freeze()
-     * @see #checkWritePermission()
-     *
-     * @deprecated Replaced by <code>{@linkplain #state()} != State.FINAL</code>.
-     *             See <a href="https://issues.apache.org/jira/browse/SIS-81">SIS-81</a>.
-     */
-    @Deprecated
-    public final boolean isModifiable() {
-        return state <= STAGED;
-    }
-
-    /**
-     * Returns an unmodifiable copy of this metadata. Any attempt to modify a property of the
-     * returned object will throw an {@link UnmodifiableMetadataException}. The state of this
-     * object is not modified.
-     *
-     * <p>This method is useful for reusing the same metadata object as a template.
-     * For example:</p>
-     *
-     * {@preformat java
-     *     DefaultCitation myCitation = new DefaultCitation();
-     *     myCitation.setTitle(new SimpleInternationalString("The title of my book"));
-     *     myCitation.setEdition(new SimpleInternationalString("First edition"));
-     *     final Citation firstEdition = (Citation) myCitation.unmodifiable();
-     *
-     *     myCitation.setEdition(new SimpleInternationalString("Second edition"));
-     *     final Citation secondEdition = (Citation) myCitation.unmodifiable();
-     *     // The title of the second edition is unchanged compared to the first edition.
-     * }
-     *
-     * The default implementation makes the following choice:
-     *
-     * <ul>
-     *   <li>If this metadata is itself unmodifiable, then this method returns {@code this} unchanged.</li>
-     *   <li>Otherwise this method {@linkplain #clone() clone} this metadata and
-     *       {@linkplain #freeze() freeze} the clone before to return it.</li>
-     * </ul>
-     *
-     * @return an unmodifiable copy of this metadata.
-     *
-     * @see MetadataCopier
-     *
-     * @deprecated Replaced by {@code MetadataCopier.forModifiable(getStandard()).copy(this).transition(State.FINAL)}.
-     */
-    @Deprecated
-    public AbstractMetadata unmodifiable() {
-        if (!isModifiable()) {
-            unmodifiable = this;
-        }
-        /*
-         * The 'unmodifiable' field is reset to null by checkWritePermission().
-         * However this is not sufficient since the setter method of some child
-         * could have been invoked without invoking any setter method on 'this'.
-         * So we also need to perform an equality check.
-         */
-        if (unmodifiable == null || !equals(unmodifiable)) {
-            final ModifiableMetadata candidate = (ModifiableMetadata) MetadataCopier.forModifiable(getStandard()).copy(this);
-            candidate.freeze();
-            /*
-             * Set the field only after success. The 'unmodifiable' field must
-             * stay null if an exception occurred during clone() or freeze().
-             */
-            unmodifiable = candidate;
-        }
-        assert !unmodifiable.isModifiable();
-        return unmodifiable;
-    }
-
-    /**
-     * Declares this metadata and all its properties as unmodifiable. Any attempt to modify a
-     * property after this method call will throw an {@link UnmodifiableMetadataException}.
-     * If this metadata is already unmodifiable, then this method does nothing.
-     *
-     * <p>Subclasses usually do not need to override this method since the default implementation
-     * performs its work using Java reflection.</p>
-     *
-     * @see #state()
-     * @see #checkWritePermission()
-     *
-     * @deprecated Replaced by {@code transition(State.FINAL)}.
-     */
-    @Deprecated
-    public void freeze() {
-        transition(State.FINAL);
-    }
-
-    /**
-     * @deprecated Replaced by {@link #checkWritePermission(Object)}.
-     *
-     * @throws UnmodifiableMetadataException if this metadata is unmodifiable.
-     */
-    @Deprecated
-    protected void checkWritePermission() throws UnmodifiableMetadataException {
-        if (state == FINAL) {
-            throw new UnmodifiableMetadataException(Resources.format(Resources.Keys.UnmodifiableMetadata));
-        } else {
-            unmodifiable = null;                    // Discard since this metadata is going to change.
-        }
-    }
-
-    /**
      * Checks if changes in the metadata are allowed. All {@code setFoo(…)} methods in subclasses
      * shall invoke this method (directly or indirectly) before to apply any change.
      * The current property value should be specified in argument.
@@ -416,7 +300,9 @@
      */
     protected void checkWritePermission(Object current) throws UnmodifiableMetadataException {
         if (state != COMPLETABLE) {
-            checkWritePermission();
+            if (state == FINAL) {
+                throw new UnmodifiableMetadataException(Resources.format(Resources.Keys.UnmodifiableMetadata));
+            }
         } else if (current != null) {
             final MetadataStandard standard;
             if (current instanceof AbstractMetadata) {
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java
index 55e5be1..c7d7e8a 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java
@@ -196,7 +196,7 @@
      * @param authority  the the person or party responsible for maintenance of the namespace, or {@code null} if none.
      * @param code       the alphanumeric value identifying an instance in the namespace, or {@code null} if none.
      *
-     * @see org.apache.sis.metadata.iso.citation.Citations#getUnicodeIdentifier(Citation)
+     * @see org.apache.sis.metadata.iso.citation.Citations#toCodeSpace(Citation)
      */
     public DefaultIdentifier(final Citation authority, final String code) {
         this.authority = authority;
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadata.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadata.java
index adb42eb..4246ac1 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadata.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultMetadata.java
@@ -1421,7 +1421,7 @@
      * @param  newValue  the new distribution info.
      */
     public void setDistributionInfo(final Distribution newValue) {
-        checkWritePermission();
+        checkWritePermission(distributionInfo);
         distributionInfo = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/Citations.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/Citations.java
index 339120f..6a83995 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/Citations.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/Citations.java
@@ -25,7 +25,6 @@
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
-import org.opengis.referencing.IdentifiedObject;                // For javadoc
 import org.apache.sis.util.Static;
 import org.apache.sis.util.Characters;
 import org.apache.sis.util.CharSequences;
@@ -78,7 +77,7 @@
  * </ul>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 1.0
+ * @version 1.1
  * @since   0.3
  * @module
  */
@@ -810,27 +809,6 @@
     }
 
     /**
-     * Infers a valid Unicode identifier from the given citation, or returns {@code null} if none.
-     *
-     * @param  citation  the citation for which to get the Unicode identifier, or {@code null}.
-     * @return a non-empty Unicode identifier for the given citation without leading or trailing whitespaces,
-     *         or {@code null} if the given citation is null or does not have any Unicode identifier or title.
-     *
-     * @see org.apache.sis.referencing.ImmutableIdentifier
-     * @see org.apache.sis.referencing.IdentifiedObjects#getSimpleNameOrIdentifier(IdentifiedObject)
-     * @see org.apache.sis.util.CharSequences#isUnicodeIdentifier(CharSequence)
-     *
-     * @since 0.6
-     *
-     * @deprecated Replaced by {@link #toCodeSpace(Citation)} in order to reduce the risk of inconsistent
-     *             behavior if those two methods are mixed.
-     */
-    @Deprecated
-    public static String getUnicodeIdentifier(final Citation citation) {
-        return removeIgnorableCharacters(Identifiers.getIdentifier(citation, true));
-    }
-
-    /**
      * Infers a code space from the given citation, or returns {@code null} if none.
      * This method is useful for extracting a short designation of an authority (e.g. {@code "EPSG"})
      * for processing purpose. This method performs the following actions:
@@ -880,17 +858,6 @@
     }
 
     /**
-     * @deprecated Renamed as {@link #toCodeSpace(Citation)}. The previous name was confusing because this
-     * method does not return the namespace of the given citation, but instead represents it as a namespace.
-     *
-     * @since 0.8
-     */
-    @Deprecated
-    public static String getCodeSpace(final Citation citation) {
-        return toCodeSpace(citation);
-    }
-
-    /**
      * Removes characters that are ignorable according Unicode specification.
      *
      * @param  identifier  the character sequence from which to remove ignorable characters, or {@code null}.
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitation.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitation.java
index efdb4ae..932a78b 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitation.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultCitation.java
@@ -497,7 +497,7 @@
      * @param newValue Other citations details, or {@code null} if none.
      */
     public void setOtherCitationDetails(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(otherCitationDetails);
         otherCitationDetails = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultContact.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultContact.java
index aaf1c89..412b7ef 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultContact.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultContact.java
@@ -424,7 +424,7 @@
      * @param  newValue  the new hours of service.
      */
     public void setHoursOfService(final InternationalString newValue) {
-        checkWritePermission();
+        checkWritePermission(hoursOfService);
         hoursOfService = newValue;
     }
 
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultTelephone.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultTelephone.java
index f1aef1f..f9d6f7c 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultTelephone.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultTelephone.java
@@ -216,8 +216,8 @@
      *
      * <p>This field references the same collection than {@link DefaultContact#phones} when possible.
      * Note that the link between this collection and {@code DefaultContact.phones} is broken when
-     * {@link DefaultContact#freeze()} is invoked, since the {@code Cloner.clone(Object)} method
-     * creates a new (unmodifiable) collection.</p>
+     * {@link DefaultContact} is copied by {@link org.apache.sis.metadata.MetadataCopier}, since the
+     * {@code Cloner.clone(Object)} method creates a new (unmodifiable) collection.</p>
      *
      * @deprecated This field will be removed after we removed the deprecated public methods.
      */
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/CachedStatement.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/CachedStatement.java
index 306dd04..6b35eb3 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/CachedStatement.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/CachedStatement.java
@@ -18,13 +18,15 @@
 
 import java.util.Locale;
 import java.util.logging.Level;
+import java.util.logging.Filter;
+import java.util.logging.Logger;
 import java.util.logging.LogRecord;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Types;
+import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.logging.WarningListeners;
 import org.apache.sis.internal.system.Loggers;
 
 
@@ -51,6 +53,11 @@
  */
 final class CachedStatement implements AutoCloseable {
     /**
+     * Where to log warnings.
+     */
+    static final Logger LOGGER = Logging.getLogger(Loggers.SQL);
+
+    /**
      * The interface for which the prepared statement has been created.
      */
     final Class<?> type;
@@ -81,23 +88,21 @@
     long expireTime;
 
     /**
-     * Where to report the warnings. This is not necessarily a logger, since users can register listeners.
+     * Where to report the warnings before to eventually log them.
      */
-    private final WarningListeners<MetadataSource> listeners;
+    private final Filter logFilter;
 
     /**
      * Constructs a metadata result from the specified connection.
      *
      * @param type       the GeoAPI interface to implement.
      * @param statement  the prepared statement.
-     * @param listeners  where to report the warnings.
+     * @param logFilter  where to report the warnings.
      */
-    CachedStatement(final Class<?> type, final PreparedStatement statement,
-            final WarningListeners<MetadataSource> listeners)
-    {
+    CachedStatement(final Class<?> type, final PreparedStatement statement, final Filter logFilter) {
         this.type      = type;
         this.statement = statement;
-        this.listeners = listeners;
+        this.logFilter = logFilter;
     }
 
     /**
@@ -183,6 +188,8 @@
         record.setSourceClassName(source.getCanonicalName());
         record.setSourceMethodName(method);
         record.setLoggerName(Loggers.SQL);
-        listeners.warning(record);
+        if (logFilter == null || logFilter.isLoggable(record)) {
+            LOGGER.log(record);
+        }
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java
index 797e3ae..75f6bf8 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataFallback.java
@@ -26,7 +26,6 @@
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.util.logging.WarningListener;
 import org.apache.sis.xml.NilReason;
 
 import static java.util.Collections.singleton;
@@ -225,20 +224,6 @@
      * Ignored.
      */
     @Override
-    public void addWarningListener(WarningListener<? super MetadataSource> listener) {
-    }
-
-    /**
-     * Ignored.
-     */
-    @Override
-    public void removeWarningListener(WarningListener<? super MetadataSource> listener) {
-    }
-
-    /**
-     * Ignored.
-     */
-    @Override
     public void close() {
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java
index 5e4a6c2..75f15b8 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java
@@ -28,8 +28,8 @@
 import java.util.EnumSet;
 import java.util.Iterator;
 import java.util.Locale;
-import java.util.NoSuchElementException;
 import java.util.logging.Level;
+import java.util.logging.Filter;
 import java.util.logging.LogRecord;
 import java.lang.reflect.Array;
 import java.lang.reflect.Method;
@@ -65,8 +65,6 @@
 import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.collection.CodeListSet;
 import org.apache.sis.util.collection.WeakValueHashMap;
-import org.apache.sis.util.logging.WarningListeners;
-import org.apache.sis.util.logging.WarningListener;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.ArgumentChecks;
@@ -110,7 +108,7 @@
  *
  * @author  Touraïvane (IRD)
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 1.0
+ * @version 1.1
  * @since   0.8
  * @module
  */
@@ -262,11 +260,11 @@
     private final ThreadLocal<LookupInfo> lastUsed;
 
     /**
-     * Where to report the warnings. This is not necessarily a logger, since users can register listeners.
+     * Where to report the warnings before to eventually log them.
      *
      * @see #readColumn(LookupInfo, Method, Dispatcher)
      */
-    private final WarningListeners<MetadataSource> listeners;
+    private volatile Filter logFilter;
 
     /**
      * Whether at least one {@link CloseTask} is scheduled for execution.
@@ -391,7 +389,6 @@
         this.statements   = new CachedStatement[maxStatements - 1];
         this.tableColumns = new HashMap<>();
         this.pool         = new WeakValueHashMap<>(CacheKey.class);
-        this.listeners    = new WarningListeners<>(this);
         this.lastUsed     = ThreadLocal.withInitial(LookupInfo::new);
     }
 
@@ -401,9 +398,8 @@
      * but will use their own {@link Connection}.
      * This constructor is useful when concurrency is desired.
      *
-     * <p>The new {@code MetadataSource} initially contains all {@linkplain #addWarningListener warning listeners}
-     * declared in the given {@code source}. But listeners added or removed in a {@code MetadataSource} after the
-     * construction will not impact the other {@code MetadataSource} instance.</p>
+     * <p>The new {@code MetadataSource} initially contains the {@linkplain #setWarningFilter warning filter}
+     * declared in the given {@code source}.</p>
      *
      * @param  source  the source from which to copy the configuration.
      */
@@ -419,7 +415,7 @@
         classloader  = source.classloader;
         pool         = source.pool;
         lastUsed     = source.lastUsed;
-        listeners    = new WarningListeners<>(this, source.listeners);
+        logFilter    = source.logFilter;
     }
 
     /**
@@ -434,7 +430,6 @@
         classloader  = getClass().getClassLoader();
         pool         = null;
         lastUsed     = null;
-        listeners    = null;
     }
 
     /**
@@ -940,7 +935,7 @@
                     final String query = helper.clear().append("SELECT * FROM ")
                             .appendIdentifier(schema, tableName).append(" WHERE ")
                             .appendIdentifier(ID_COLUMN).append("=?").toString();
-                    result = new CachedStatement(type, connection().prepareStatement(query), listeners);
+                    result = new CachedStatement(type, connection().prepareStatement(query), logFilter);
                 }
                 value = result.getValue(toSearch.identifier, columnName);
                 isArray = (value instanceof java.sql.Array);
@@ -1073,56 +1068,44 @@
         record.setSourceClassName(source.getCanonicalName());
         record.setSourceMethodName(method);
         record.setLoggerName(Loggers.SQL);
-        listeners.warning(record);
+        final Filter filter = logFilter;
+        if (filter == null || filter.isLoggable(record)) {
+            CachedStatement.LOGGER.log(record);
+        }
     }
 
     /**
-     * Adds a listener to be notified when a warning occurred while reading from or writing metadata.
+     * Sets a filter to be notified when a warning occurred while reading from or writing metadata.
      * When a warning occurs, there is a choice:
      *
      * <ul>
-     *   <li>If this metadata source has no warning listener, then the warning is logged at {@link Level#WARNING}.</li>
-     *   <li>If this metadata source has at least one warning listener, then all listeners are notified
-     *       and the warning is <strong>not</strong> logged by this metadata source instance.</li>
+     *   <li>If this metadata source has no warning filter, or if the filter returns {@code true},
+     *       then the warning is logged at {@link Level#WARNING}.</li>
+     *   <li>Otherwise the warning is not logged by this metadata source instance.
+     *       The filter implementation is free to keep a reference to the given record,
+     *       for example in order to display it in a graphical user interface.</li>
      * </ul>
      *
-     * Consider invoking this method in a {@code try} … {@code finally} block if the {@code MetadataSource}
-     * lifetime is longer than the listener lifetime, as below:
+     * @param  filter  the filter to set, or {@code null} for removing the filter.
+     * @return the previous filter, or {@code null} if none.
      *
-     * {@preformat java
-     *     source.addWarningListener(listener);
-     *     try {
-     *         // Do some work...
-     *     } finally {
-     *         source.removeWarningListener(listener);
-     *     }
-     * }
-     *
-     * @param  listener  the listener to add.
-     * @throws IllegalArgumentException if the given listener is already registered in this metadata source.
-     *
-     * @deprecated {@code WarningListener} to be replaced by {@link java.util.logging.Filter}.
+     * @since 1.1
      */
-    @Deprecated
-    public void addWarningListener(final WarningListener<? super MetadataSource> listener)
-            throws IllegalArgumentException
-    {
-        listeners.addWarningListener(listener);
+    public Filter setWarningFilter(final Filter filter) {
+        Filter p = logFilter;
+        logFilter = filter;
+        return p;
     }
 
     /**
-     * Removes a previously registered listener.
+     * Returns the current warning filter.
      *
-     * @param  listener  the listener to remove.
-     * @throws NoSuchElementException if the given listener is not registered in this metadata source.
+     * @return the current filter, or {@code null} if none.
      *
-     * @deprecated {@code WarningListener} to be replaced by {@link java.util.logging.Filter}.
+     * @since 1.1
      */
-    @Deprecated
-    public void removeWarningListener(final WarningListener<? super MetadataSource> listener)
-            throws NoSuchElementException
-    {
-        listeners.removeWarningListener(listener);
+    public Filter getWarningFilter() {
+        return logFilter;
     }
 
     /**
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/package-info.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/package-info.java
index 14c2a0f..14e4bc0 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/package-info.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/package-info.java
@@ -42,7 +42,7 @@
  *
  * @author  Touraïvane (IRD)
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 1.0
+ * @version 1.1
  *
  * @see org.apache.sis.referencing.factory.sql
  *
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/xml/MarshallerPool.java b/core/sis-metadata/src/main/java/org/apache/sis/xml/MarshallerPool.java
index b40c1c2..2c1528c 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/xml/MarshallerPool.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/xml/MarshallerPool.java
@@ -59,7 +59,7 @@
  * from multiple threads.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.1
  *
  * @see XML
  * @see <a href="http://jaxb.java.net/guide/Performance_and_thread_safety.html">JAXB Performance and thread-safety</a>
@@ -187,11 +187,7 @@
          * Prepares a copy of the property map (if any), then removes the
          * properties which are handled especially by this constructor.
          */
-        template = new PooledTemplate(properties, implementation);
-        final Object rootNamespace = template.remove(XML.DEFAULT_NAMESPACE, null);
-        if (rootNamespace != null) {
-            Logging.getLogger(Loggers.XML).warning(XML.DEFAULT_NAMESPACE + " property is no longer supported.");
-        }
+        template           = new PooledTemplate(properties, implementation);
         marshallers        = new ConcurrentLinkedDeque<>();
         unmarshallers      = new ConcurrentLinkedDeque<>();
         isRemovalScheduled = new AtomicBoolean();
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/xml/Namespaces.java b/core/sis-metadata/src/main/java/org/apache/sis/xml/Namespaces.java
index 6beccea..3b068c1 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/xml/Namespaces.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/xml/Namespaces.java
@@ -453,28 +453,6 @@
 
     /**
      * The <code>{@value}</code> URL.
-     * The usual prefix for this namespace is {@code "gmi"}.
-     *
-     * @category ISO
-     *
-     * @deprecated as of ISO 19115-4, splitted in many different namespaces.
-     */
-    @Deprecated
-    public static final String GMI = LegacyNamespaces.GMI;
-
-    /**
-     * The <code>{@value}</code> URL.
-     * The usual prefix for this namespace is {@code "gmx"}.
-     *
-     * @category ISO
-     *
-     * @deprecated as of ISO 19115-3, splitted in many different namespaces.
-     */
-    @Deprecated
-    public static final String GMX = LegacyNamespaces.GMX;
-
-    /**
-     * The <code>{@value}</code> URL.
      * The usual prefix for this namespace is {@code "gts"}.
      *
      * @category ISO
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/xml/Pooled.java b/core/sis-metadata/src/main/java/org/apache/sis/xml/Pooled.java
index 4d0bcef..c06fb65 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/xml/Pooled.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/xml/Pooled.java
@@ -36,7 +36,6 @@
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.logging.WarningListener;
 import org.apache.sis.internal.util.CollectionsExt;
 import org.apache.sis.internal.util.Strings;
 import org.apache.sis.internal.jaxb.Context;
@@ -53,7 +52,7 @@
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Cullen Rombach (Image Matters)
- * @version 1.0
+ * @version 1.1
  * @since   0.3
  * @module
  */
@@ -154,7 +153,7 @@
     /**
      * The object to inform about warnings, or {@code null} if none.
      */
-    private Filter warningListener;
+    private Filter logFilter;
 
     /**
      * The {@link System#nanoTime()} value of the last call to {@link #reset(Pooled)}.
@@ -223,7 +222,7 @@
         resolver         = template.resolver;
         converter        = template.converter;
         rootAdapters     = template.rootAdapters;
-        warningListener  = template.warningListener;
+        logFilter        = template.logFilter;
         resetTime        = System.nanoTime();
         if (this instanceof Marshaller) {
             bitMasks |= Context.MARSHALLING;
@@ -380,11 +379,7 @@
                     return;
                 }
                 case XML.WARNING_FILTER: {
-                    warningListener = (Filter) value;
-                    return;
-                }
-                case XML.WARNING_LISTENER: {
-                    warningListener = ((WarningListener<?>) value).asFilter();
+                    logFilter = (Filter) value;
                     return;
                 }
                 case TypeRegistration.ROOT_ADAPTERS: {
@@ -425,8 +420,7 @@
             case XML.METADATA_VERSION:  return versionMetadata;
             case XML.RESOLVER:          return resolver;
             case XML.CONVERTER:         return converter;
-            case XML.WARNING_FILTER:    return warningListener;
-            case XML.WARNING_LISTENER:  return null;
+            case XML.WARNING_FILTER:    return logFilter;
             case XML.LENIENT_UNMARSHAL: return (bitMasks & Context.LENIENT_UNMARSHAL) != 0;
             case XML.STRING_SUBSTITUTES: {
                 int n = 0;
@@ -563,6 +557,6 @@
      */
     final Context begin() {
         return new Context(bitMasks | specificBitMasks(), locale, timezone,
-                schemas, versionGML, versionMetadata, resolver, converter, warningListener);
+                schemas, versionGML, versionMetadata, resolver, converter, logFilter);
     }
 }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/xml/XML.java b/core/sis-metadata/src/main/java/org/apache/sis/xml/XML.java
index 25d5411..eeda0be 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/xml/XML.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/xml/XML.java
@@ -46,7 +46,6 @@
 import org.apache.sis.util.Version;
 import org.apache.sis.util.Workaround;
 import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.logging.WarningListener;
 import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.system.SystemListener;
 import org.apache.sis.internal.jaxb.TypeRegistration;
@@ -76,19 +75,18 @@
  *   <tr><td>{@link #LOCALE}</td>             <td>{@link Locale}</td>            <td>for specifying the locale to use for international strings and code lists.</td></tr>
  *   <tr><td>{@link #TIMEZONE}</td>           <td>{@link TimeZone}</td>          <td>for specifying the timezone to use for dates and times.</td></tr>
  *   <tr><td>{@link #SCHEMAS}</td>            <td>{@link Map}</td>               <td>for specifying the root URL of metadata schemas to use.</td></tr>
- *   <tr><td>{@link #DEFAULT_NAMESPACE}</td>  <td>{@link String}</td>            <td>for specifying the default namespace of the XML document to write.</td></tr>
  *   <tr><td>{@link #GML_VERSION}</td>        <td>{@link Version}</td>           <td>for specifying the GML version of the document to be (un)marshalled.</td></tr>
  *   <tr><td>{@link #METADATA_VERSION}</td>   <td>{@link Version}</td>           <td>for specifying the metadata version of the document to be (un)marshalled.</td></tr>
  *   <tr><td>{@link #RESOLVER}</td>           <td>{@link ReferenceResolver}</td> <td>for replacing {@code xlink} or {@code uuidref} attributes by the actual object to use.</td></tr>
  *   <tr><td>{@link #CONVERTER}</td>          <td>{@link ValueConverter}</td>    <td>for controlling the conversion of URL, UUID, Units or similar objects.</td></tr>
  *   <tr><td>{@link #STRING_SUBSTITUTES}</td> <td>{@code String[]}</td>          <td>for specifying which code lists to replace by simpler {@code <gco:CharacterString>} elements.</td></tr>
- *   <tr><td>{@link #WARNING_LISTENER}</td>   <td>{@link WarningListener}</td>   <td>for being notified about non-fatal warnings.</td></tr>
+ *   <tr><td>{@link #WARNING_FILTER}</td>     <td>{@link Filter}</td>            <td>for being notified about non-fatal warnings.</td></tr>
  * </table>
  *
  * @author  Cédric Briançon (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Cullen Rombach (Image Matters)
- * @version 1.0
+ * @version 1.1
  * @since   0.3
  * @module
  */
@@ -177,16 +175,6 @@
     // If more keys are documented, update the Pooled.SCHEMAS_KEY array.
 
     /**
-     * Specifies the default namespace of the XML document to write.
-     * An example of value for this key is {@code "http://www.isotc211.org/2005/gmd"}.
-     *
-     * @deprecated This property is no longer honored by Apache SIS 1.0.
-     *             Use {@link javax.xml.bind.annotation.XmlSchema} instead.
-     */
-    @Deprecated
-    public static final String DEFAULT_NAMESPACE = "org.apache.sis.xml.defaultNamespace";
-
-    /**
      * Specifies the GML version of the document to be marshalled or unmarshalled.
      * The GML version may affect the set of XML elements to be marshalled and their namespaces.
      * Note that GML 3.2 is identical to ISO 19136:2007.
@@ -373,21 +361,6 @@
     public static final String WARNING_FILTER = "org.apache.sis.xml.warningFilter";
 
     /**
-     * Specifies a listener to be notified when a non-fatal error occurred during the (un)marshalling.
-     * The value for this property shall be an instance of {@code WarningListener<Object>}.
-     *
-     * <p>By default, warnings that occur during the (un)marshalling process are logged. However if a
-     * property is set for this key, then the {@link WarningListener#warningOccured(Object, LogRecord)}
-     * method will be invoked and the warning will <em>not</em> be logged by the (un)marshaller.</p>
-     *
-     * @see WarningListener
-     *
-     * @deprecated Replaced by {@link #WARNING_FILTER}.
-     */
-    @Deprecated
-    public static final String WARNING_LISTENER = "org.apache.sis.xml.warningListener";
-
-    /**
      * The pool of marshallers and unmarshallers used by this class.
      * The field name uses the uppercase convention because this field is almost constant:
      * this field is initially null, then created by {@link #getPool()} when first needed.
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/xml/package-info.java b/core/sis-metadata/src/main/java/org/apache/sis/xml/package-info.java
index 64b3978..1fd8e46 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/xml/package-info.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/xml/package-info.java
@@ -59,7 +59,7 @@
  * @author  Guilhem Legal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Cullen Rombach (Image Matters)
- * @version 1.0
+ * @version 1.1
  * @since   0.3
  * @module
  */
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataCopierTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataCopierTest.java
index 7765a19..5c2634c 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataCopierTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataCopierTest.java
@@ -17,8 +17,10 @@
 package org.apache.sis.metadata;
 
 import org.opengis.metadata.citation.Citation;
+import org.opengis.metadata.extent.GeographicExtent;
 import org.apache.sis.metadata.iso.citation.DefaultCitation;
 import org.apache.sis.metadata.iso.citation.HardCodedCitations;
+import org.apache.sis.metadata.iso.extent.DefaultGeographicDescription;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
@@ -70,6 +72,19 @@
     }
 
     /**
+     * Tests {@link MetadataCopier#copy(Class, Object)} when the given type is a parent
+     * of the interface implemented by the given argument.
+     */
+    @Test
+    public void testCopyWithSuperType() {
+        final MetadataCopier copier = new MetadataCopier(MetadataStandard.ISO_19115);
+        final DefaultGeographicDescription original = new DefaultGeographicDescription("Some area.");
+        final GeographicExtent copy = copier.copy(GeographicExtent.class, original);
+        assertNotSame(original, copy);
+        assertEquals (original, copy);
+    }
+
+    /**
      * Tests {@link MetadataCopier#copy(Class, Object)} with an implementation class specified instead of an interface.
      */
     @Test
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java
index fa046f4..3990f1b 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java
@@ -22,6 +22,7 @@
 import java.util.HashSet;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.metadata.quality.Completeness;
+import org.opengis.metadata.extent.GeographicExtent;
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.coverage.grid.RectifiedGrid;
@@ -58,7 +59,7 @@
  * </ul>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.0
  * @since   0.3
  * @module
  */
@@ -133,6 +134,7 @@
         assertEquals("getInterface(Citation)",               Citation.class,         getInterface(Citation.class));
         assertEquals("getInterface(DefaultCitation)",        Citation.class,         getInterface(DefaultCitation.class));
         assertEquals("getInterface(AbstractCompleteness)",   Completeness.class,     getInterface(AbstractCompleteness.class));
+        assertEquals("getInterface(GeographicExtent)",       GeographicExtent.class, getInterface(GeographicExtent.class));
 
         standard = MetadataStandard.ISO_19111;
         assertEquals("getInterface(Citation)",               Citation.class,         getInterface(Citation.class));
diff --git a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultCitationTest.java b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultCitationTest.java
index 5450807..c861bdb 100644
--- a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultCitationTest.java
+++ b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/citation/DefaultCitationTest.java
@@ -164,23 +164,6 @@
     }
 
     /**
-     * Tests {@link DefaultCitation#unmodifiable()}.
-     *
-     * @deprecated To be removed after we removed {@link DefaultCitation#unmodifiable()}.
-     */
-    @Test
-    @Deprecated
-    public void testUnmodifiable() {
-        final DefaultCitation original = create();
-        final DefaultCitation clone = (DefaultCitation) original.unmodifiable();    // This will invoke 'freeze()'.
-        assertSame("original.unmodifiable", clone, original.unmodifiable());
-        assertSame("clone.unmodifiable",    clone, clone.unmodifiable());
-        assertEquals("original.state", DefaultCitation.State.EDITABLE, original.state());
-        assertEquals("clone.state",    DefaultCitation.State.FINAL,    clone.state());
-        assertCopy(original, clone);
-    }
-
-    /**
      * Verifies that {@code clone} is a copy of {@code original}, sharing same instance of values when possible.
      */
     private static void assertCopy(final DefaultCitation original, final DefaultCitation clone) {
diff --git a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/FinalLocationType.java b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/FinalLocationType.java
index 255a2bf..5ca0cd2 100644
--- a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/FinalLocationType.java
+++ b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/FinalLocationType.java
@@ -26,6 +26,7 @@
 import org.opengis.metadata.extent.GeographicExtent;
 import org.apache.sis.internal.util.UnmodifiableArrayList;
 import org.apache.sis.metadata.ModifiableMetadata;
+import org.apache.sis.metadata.MetadataCopier;
 import org.apache.sis.util.ArgumentChecks;
 
 // Branch-dependent imports
@@ -40,7 +41,7 @@
  * system than the original location type.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.1
  * @since   0.8
  * @module
  */
@@ -134,8 +135,8 @@
         theme           = source.getTheme();
         identifications = snapshot(source.getIdentifications());
         definition      = source.getDefinition();
-        territoryOfUse  = (GeographicExtent) unmodifiable(source.getTerritoryOfUse());
-        owner           = (Party) unmodifiable(source.getOwner());
+        territoryOfUse  = unmodifiable(GeographicExtent.class, source.getTerritoryOfUse());
+        owner           = unmodifiable(Party.class, source.getOwner());
         parents         = snapshot(source.getParents(),  rs, existing);
         children        = snapshot(source.getChildren(), rs, existing);
         referenceSystem = rs;
@@ -196,13 +197,18 @@
 
     /**
      * Returns an unmodifiable copy of the given metadata, if necessary and possible.
+     *
+     * @param  <T>       compile-time value of the {@code type} argument.
+     * @param  type      the interface of the metadata object to eventually copy.
+     * @param  metadata  the metadata object to eventually copy, or {@code null}.
+     * @return an unmodifiable copy of the given metadata object, or {@code null} if the given argument is {@code null}.
      */
-    private static Object unmodifiable(final Object metadata) {
+    private static <T> T unmodifiable(final Class<T> type, T metadata) {
         if (metadata instanceof ModifiableMetadata) {
-            return ((ModifiableMetadata) metadata).unmodifiable();
-        } else {
-            return metadata;
+            metadata = MetadataCopier.forModifiable(((ModifiableMetadata) metadata).getStandard()).copy(type, metadata);
+            ((ModifiableMetadata) metadata).transition(ModifiableMetadata.State.FINAL);
         }
+        return metadata;
     }
 
     /**
diff --git a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/package-info.java b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/package-info.java
index 2a273b7..f74a09b 100644
--- a/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/package-info.java
+++ b/core/sis-referencing-by-identifiers/src/main/java/org/apache/sis/referencing/gazetteer/package-info.java
@@ -31,7 +31,7 @@
  *
  * @author  Chris Mattmann (JPL)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.1
  * @since   0.8
  * @module
  */
diff --git a/core/sis-referencing-by-identifiers/src/test/java/org/apache/sis/referencing/gazetteer/LocationTypeTest.java b/core/sis-referencing-by-identifiers/src/test/java/org/apache/sis/referencing/gazetteer/LocationTypeTest.java
index 461ae41..34a3971 100644
--- a/core/sis-referencing-by-identifiers/src/test/java/org/apache/sis/referencing/gazetteer/LocationTypeTest.java
+++ b/core/sis-referencing-by-identifiers/src/test/java/org/apache/sis/referencing/gazetteer/LocationTypeTest.java
@@ -33,7 +33,7 @@
  * Tests {@link AbstractLocationType}, {@link FinalLocationType} and {@link ModifiableLocationType}.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.1
  * @since   0.8
  * @module
  */
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/distance/DistanceUtils.java b/core/sis-referencing/src/main/java/org/apache/sis/distance/DistanceUtils.java
deleted file mode 100644
index 4037eeb..0000000
--- a/core/sis-referencing/src/main/java/org/apache/sis/distance/DistanceUtils.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.distance;
-
-import org.apache.sis.geometry.DirectPosition2D;
-
-/**
- * Class to calculate distances on earth surface. Actual calculation code very
- * similar to Apache SIS but refractor to allow use of custom classes.
- *
- * @deprecated Replaced by {@link org.apache.sis.referencing.GeodeticCalculator}.
- * See <a href="https://issues.apache.org/jira/browse/SIS-385">SIS-385</a>.
- */
-@Deprecated
-public final class DistanceUtils {
-  private DistanceUtils() {
-  }
-
-  public static final int EARTH_RADIUS = 6371; // in km
-  public static final double HALF_EARTH_CIRCUMFERENCE = 20037.58; // in km
-
-  /**
-   * Returns a coordinate on the great circle at the specified bearing.
-   *
-   * @param latitude
-   *          the latitude of center of circle
-   * @param longitude
-   *          the longitude of center of circle
-   * @param d
-   *          the distance from the center
-   * @param bearing
-   *          the great circle bearing
-   * @return a coordinate at the specified bearing
-   *
-   * @deprecated Replaced by {@link org.apache.sis.referencing.GeodeticCalculator#getEndPoint()}.
-   */
-  @Deprecated
-  public static DirectPosition2D getPointOnGreatCircle(double latitude, double longitude,
-      double d, double bearing) {
-    double angularDistance = d / EARTH_RADIUS;
-
-    double lon1 = Math.toRadians(longitude);
-    double lat1 = Math.toRadians(latitude);
-
-    double cosLat = Math.cos(lat1);
-    double sinLat = Math.sin(lat1);
-
-    double sinD = Math.sin(angularDistance);
-    double cosD = Math.cos(angularDistance);
-    double brng = Math.toRadians(bearing);
-
-    double lat2 = Math.asin((sinLat * cosD) + (cosLat * sinD * Math.cos(brng)));
-    double lon2 = lon1
-        + Math.atan2(Math.sin(brng) * sinD * cosLat, cosD - sinLat
-            * Math.sin(lat2));
-
-    return new DirectPosition2D(Math.toDegrees(lat2), Math.toDegrees(lon2));
-  }
-
-  /**
-   * Calculates haversine (great circle) distance between two lat/lon
-   * coordinates.
-   *
-   * @param latitude1
-   *          latitude of first coordinate
-   * @param longitude1
-   *          longitude of first coordinate
-   * @param latitude2
-   *          latitude of second coordinate
-   * @param longitude2
-   *          longitude of second coordinate
-   * @return great circle distance between specified lat/lon coordinates
-   *
-   * @deprecated Replaced by {@link org.apache.sis.referencing.GeodeticCalculator#getGeodesicDistance()}.
-   */
-  @Deprecated
-  public static double getHaversineDistance(double latitude1,
-      double longitude1, double latitude2, double longitude2) {
-    double longRadian1 = Math.toRadians(longitude1);
-    double latRadian1 = Math.toRadians(latitude1);
-    double longRadian2 = Math.toRadians(longitude2);
-    double latRadian2 = Math.toRadians(latitude2);
-    double angularDistance = Math.acos(Math.sin(latRadian1)
-        * Math.sin(latRadian2) + Math.cos(latRadian1) * Math.cos(latRadian2)
-        * Math.cos(longRadian1 - longRadian2));
-    return EARTH_RADIUS * angularDistance;
-  }
-}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralDirectPosition.java b/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralDirectPosition.java
index 6a43ae4..852dd42 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralDirectPosition.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralDirectPosition.java
@@ -80,14 +80,6 @@
     public final double[] coordinates;
 
     /**
-     * @deprecated Renamed {@link #coordinates}.
-     *
-     * @see <a href="https://issues.apache.org/jira/browse/SIS-461">SIS-461</a>
-     */
-    @Deprecated
-    public transient double[] ordinates;
-
-    /**
      * The coordinate reference system for this position, or {@code null}.
      */
     private CoordinateReferenceSystem crs;
@@ -111,7 +103,6 @@
      */
     public GeneralDirectPosition(final int dimension) throws NegativeArraySizeException {
         coordinates = new double[dimension];
-        ordinates = coordinates;
     }
 
     /**
@@ -134,7 +125,6 @@
      */
     public GeneralDirectPosition(final double... coordinates) {
         this.coordinates = coordinates;
-        ordinates = coordinates;
     }
 
     /**
@@ -147,7 +137,6 @@
         coordinates = point.getCoordinate();                            // Should already be cloned.
         crs = point.getCoordinateReferenceSystem();
         ensureDimensionMatches("crs", coordinates.length, crs);
-        ordinates = coordinates;
     }
 
     /**
@@ -172,7 +161,6 @@
             throw new IllegalArgumentException(Errors.format(
                     Errors.Keys.UnparsableStringForClass_2, "POINT", wkt));
         }
-        ordinates = coordinates;
     }
 
     /**
@@ -325,7 +313,6 @@
             }
             GeneralDirectPosition e = (GeneralDirectPosition) super.clone();
             field.set(e, coordinates.clone());
-            e.ordinates = e.coordinates;
             return e;
         } catch (ReflectiveOperationException | CloneNotSupportedException exception) {
             /*
@@ -337,11 +324,6 @@
         }
     }
 
-    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
-        in.defaultReadObject();
-        ordinates = coordinates;
-    }
-
     /**
      * {@inheritDoc}
      */
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java b/core/sis-referencing/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java
deleted file mode 100644
index fcc74cd..0000000
--- a/core/sis-referencing/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.metadata.iso;
-
-import java.util.Map;
-import java.util.Locale;
-import org.opengis.metadata.Identifier;
-import org.opengis.metadata.citation.Citation;
-import org.opengis.util.InternationalString;
-
-
-/**
- * Immutable value uniquely identifying an object within a namespace, together with a version.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
- * @since 0.3
- * @module
- *
- * @deprecated Moved to {@link org.apache.sis.referencing} for anticipation with Jigsaw modules.
- */
-@Deprecated
-public class ImmutableIdentifier extends org.apache.sis.referencing.ImmutableIdentifier {
-
-    /**
-     * Creates a new identifier from the specified one. This is a copy constructor which
-     * get the code, codespace, authority and version from the given identifier.
-     *
-     * @param identifier  the identifier to copy.
-     *
-     * @see #castOrCopy(Identifier)
-     */
-    public ImmutableIdentifier(final Identifier identifier) {
-        super(identifier);
-    }
-
-    /**
-     * Creates a new identifier from the specified code and authority.
-     *
-     * @param authority  the person or party responsible for maintenance of the namespace, or {@code null} if not available.
-     * @param codeSpace  identifier or namespace in which the code is valid, or {@code null} if not available.
-     *                   This is often an abbreviation of the authority name.
-     * @param code       alphanumeric value identifying an instance in the namespace. The code can not be null.
-     */
-    public ImmutableIdentifier(final Citation authority, final String codeSpace, final String code) {
-        super(authority, codeSpace, code);
-    }
-
-    /**
-     * Creates a new identifier from the specified code and authority,
-     * with an optional version number and description.
-     *
-     * @param authority    the person or party responsible for maintenance of the namespace, or {@code null} if not available.
-     * @param codeSpace    identifier or namespace in which the code is valid, or {@code null} if not available.
-     *                     This is often an abbreviation of the authority name.
-     * @param code         alphanumeric value identifying an instance in the namespace. The code can not be null.
-     * @param version      the version identifier for the namespace as specified by the code authority, or {@code null} if none.
-     * @param description  natural language description of the meaning of the code value, or {@code null} if none.
-     */
-    public ImmutableIdentifier(final Citation authority, final String codeSpace,
-            final String code, final String version, final InternationalString description)
-    {
-        super(authority, codeSpace, code, version, description);
-    }
-
-    /**
-     * Constructs an identifier from the given properties. Keys are strings from the table below.
-     * The map given in argument shall contain an entry at least for the
-     * {@value org.opengis.metadata.Identifier#CODE_KEY} key.
-     * Other properties listed in the table below are optional.
-     *
-     * <table class="sis">
-     *   <caption>Recognized properties</caption>
-     *   <tr>
-     *     <th>Property name</th>
-     *     <th>Value type</th>
-     *     <th>Returned by</th>
-     *   </tr>
-     *   <tr>
-     *     <td>{@value org.opengis.metadata.Identifier#CODE_KEY}</td>
-     *     <td>{@link String}</td>
-     *     <td>{@link #getCode()}</td>
-     *   </tr>
-     *   <tr>
-     *     <td>{@value org.opengis.metadata.Identifier#CODESPACE_KEY}</td>
-     *     <td>{@link String}</td>
-     *     <td>{@link #getCodeSpace()}</td>
-     *   </tr>
-     *   <tr>
-     *     <td>{@value org.opengis.metadata.Identifier#AUTHORITY_KEY}</td>
-     *     <td>{@link String} or {@link Citation}</td>
-     *     <td>{@link #getAuthority()}</td>
-     *   </tr>
-     *   <tr>
-     *     <td>{@value org.opengis.metadata.Identifier#VERSION_KEY}</td>
-     *     <td>{@link String}</td>
-     *     <td>{@link #getVersion()}</td>
-     *   </tr>
-     *   <tr>
-     *     <td>{@value org.opengis.metadata.Identifier#DESCRIPTION_KEY}</td>
-     *     <td>{@link String} or {@link InternationalString}</td>
-     *     <td>{@link #getDescription()}</td>
-     *   </tr>
-     *   <tr>
-     *     <td>{@value org.apache.sis.referencing.AbstractIdentifiedObject#LOCALE_KEY}</td>
-     *     <td>{@link Locale}</td>
-     *     <td>(none)</td>
-     *   </tr>
-     * </table>
-     *
-     * <div class="section">Localization</div>
-     * {@code "description"} is a localizable attributes which may have a language and country
-     * code suffix. For example the {@code "description_fr"} property stands for description in
-     * {@linkplain Locale#FRENCH French} and the {@code "description_fr_CA"} property stands
-     * for description in {@linkplain Locale#CANADA_FRENCH French Canadian}.
-     *
-     * <p>The {@code "locale"} property applies only to exception messages, if any.
-     * After successful construction, {@code ImmutableIdentifier} instances do not keep the locale
-     * since localizations are deferred to the {@link InternationalString#toString(Locale)} method.</p>
-     *
-     * @param  properties  the properties to be given to this identifier.
-     * @throws IllegalArgumentException if a property has an illegal value.
-     */
-    public ImmutableIdentifier(final Map<String,?> properties) throws IllegalArgumentException {
-        super(properties);
-    }
-
-    /**
-     * Returns a SIS identifier implementation with the values of the given arbitrary implementation.
-     * This method performs the first applicable action in the following choices:
-     *
-     * <ul>
-     *   <li>If the given object is {@code null}, then this method returns {@code null}.</li>
-     *   <li>Otherwise if the given object is already an instance of
-     *       {@code ImmutableIdentifier}, then it is returned unchanged.</li>
-     *   <li>Otherwise a new {@code ImmutableIdentifier} instance is created using the
-     *       {@linkplain #ImmutableIdentifier(Identifier) copy constructor} and returned.
-     *       Note that this is a <cite>shallow</cite> copy operation, since the other
-     *       metadata contained in the given object are not recursively copied.</li>
-     * </ul>
-     *
-     * @param  object  the object to get as a SIS implementation, or {@code null} if none.
-     * @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.
-     */
-    public static ImmutableIdentifier castOrCopy(final Identifier object) {
-        if (object == null || object instanceof ImmutableIdentifier) {
-            return (ImmutableIdentifier) object;
-        }
-        return new ImmutableIdentifier(object);
-    }
-}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
index f38df3e..04238dc 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
@@ -86,7 +86,6 @@
 import org.apache.sis.metadata.iso.extent.Extents;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.logging.Logging;
-import org.apache.sis.util.logging.WarningListener;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.Utilities;
 import org.apache.sis.util.Static;
@@ -433,16 +432,6 @@
     }
 
     /**
-     * @deprecated {@code WarningListener} argument replaced by {@code java.util.logging.Filter}.
-     */
-    @Deprecated
-    public static CoordinateReferenceSystem fromAuthority(CoordinateReferenceSystem crs,
-            final CRSAuthorityFactory factory, final WarningListener<?> listener) throws FactoryException
-    {
-        return fromAuthority(crs, factory, (listener != null) ? listener.asFilter() : null);
-    }
-
-    /**
      * Suggests a coordinate reference system which could be a common target for coordinate operations having the
      * given sources. This method compares the {@linkplain #getGeographicBoundingBox(CoordinateReferenceSystem)
      * domain of validity} of all given CRSs. If a CRS has a domain of validity that contains the domain of all other
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
index 578e2c9..f266bdb 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
@@ -286,9 +286,7 @@
             (short) 0, (short) 0, (short) 0, (short) 0, (byte) 0, (byte) 0),                 // UPS and UTM info
 
     /**
-     * Unspecified datum based upon the GRS 1980 Authalic Sphere. Spheres use a simpler algorithm for
-     * {@linkplain org.apache.sis.referencing.datum.DefaultEllipsoid#orthodromicDistance
-     * orthodromic distance computation}, which may be faster and more robust.
+     * Unspecified datum based upon the GRS 1980 Authalic Sphere.
      *
      * <blockquote><table class="compact">
      * <caption>Sphere properties</caption>
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
index 353d086..fc91821 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
@@ -56,7 +56,7 @@
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Guilhem Legal (Geomatys)
- * @version 1.0
+ * @version 1.1
  *
  * @see CRS
  * @see org.apache.sis.geometry.Envelopes
@@ -345,7 +345,7 @@
      * @return the first name, alias or identifier which is a valid Unicode identifier, or {@code null} if none.
      *
      * @see ImmutableIdentifier
-     * @see Citations#getUnicodeIdentifier(Citation)
+     * @see Citations#toCodeSpace(Citation)
      * @see CharSequences#isUnicodeIdentifier(CharSequence)
      *
      * @since 1.0
@@ -384,14 +384,6 @@
     }
 
     /**
-     * @deprecated Renamed {@link #getSimpleNameOrIdentifier(IdentifiedObject)}.
-     */
-    @Deprecated
-    public static String getUnicodeIdentifier(final IdentifiedObject object) {
-        return getSimpleNameOrIdentifier(object);
-    }
-
-    /**
      * Looks up a URN, such as {@code "urn:ogc:def:crs:EPSG:9.1:4326"}, of the specified object.
      * This method searches in all {@linkplain org.apache.sis.referencing.factory.GeodeticAuthorityFactory geodetic
      * authority factories} known to SIS for an object {@linkplain org.apache.sis.util.ComparisonMode#APPROXIMATE
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java
index 7e97721..c1f6cd2 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java
@@ -282,13 +282,4 @@
      * @see org.opengis.referencing.cs.RangeMeaning#WRAPAROUND
      */
     POSITIVE_RANGE;
-
-    /**
-     * @deprecated Renamed {@link #DISPLAY_ORIENTED} since "conventional" is too vague.
-     *             For example the (latitude, longitude) axis order is also conventional.
-     *
-     * @since 0.5
-     */
-    @Deprecated
-    public static final AxesConvention CONVENTIONALLY_ORIENTED = DISPLAY_ORIENTED;
 }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
index 1aa2ec7..a004719 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/DefaultEllipsoid.java
@@ -29,14 +29,12 @@
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.Identifier;
 import org.opengis.referencing.datum.Ellipsoid;
-import org.apache.sis.geometry.DirectPosition2D;
 import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.internal.util.DoubleDouble;
 import org.apache.sis.internal.jaxb.gml.Measure;
 import org.apache.sis.internal.jaxb.referencing.SecondDefiningParameter;
 import org.apache.sis.internal.metadata.MetadataUtilities;
 import org.apache.sis.internal.referencing.Formulas;
-import org.apache.sis.internal.referencing.Resources;
 import org.apache.sis.internal.referencing.WKTKeywords;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.referencing.AbstractIdentifiedObject;
@@ -46,7 +44,6 @@
 import org.apache.sis.util.Utilities;
 import org.apache.sis.measure.Units;
 
-import static java.lang.Math.*;
 import static java.lang.Double.*;
 import static org.apache.sis.util.ArgumentChecks.ensureStrictlyPositive;
 import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
@@ -71,10 +68,6 @@
  *   <li>{@linkplain #getEccentricity() eccentricity}</li>
  * </ul>
  *
- * <div class="section">Distance calculations</div>
- * This class contains an {@link #orthodromicDistance(double, double, double, double)} convenience method
- * for calculating distances on great circles.
- *
  * <div class="section">Creating new ellipsoid instances</div>
  * New instances can be created either directly by specifying all information to a factory method (choices 3
  * and 4 below), or indirectly by specifying the identifier of an entry in a database (choices 1 and 2 below).
@@ -131,16 +124,6 @@
     private static final long serialVersionUID = -1149451543954764081L;
 
     /**
-     * Maximum number of iterations in the {@link #orthodromicDistance(double, double, double, double)} method.
-     */
-    private static final int MAX_ITERATIONS = 100;
-
-    /**
-     * Small tolerance value for {@link #orthodromicDistance(double, double, double, double)}.
-     */
-    private static final double EPS = 0.5E-13;
-
-    /**
      * Tolerance threshold for comparing floating point numbers.
      *
      * @see Numerics#COMPARISON_THRESHOLD
@@ -523,108 +506,6 @@
     }
 
     /**
-     * Returns the orthodromic distance between two geographic coordinates.
-     * The orthodromic distance is the shortest distance between two points on a ellipsoid's surface.
-     * The orthodromic path is always on a great circle.
-     *
-     * <div class="note"><b>Note:</b>
-     * Orthodromic distances are different than the <cite>loxodromic distance</cite>.
-     * The later is a longer distance on a path with a constant direction on the compass.</div>
-     *
-     * @param  λ1  longitude of first  point (in decimal degrees).
-     * @param  φ1  latitude  of first  point (in decimal degrees).
-     * @param  λ2  longitude of second point (in decimal degrees).
-     * @param  φ2  latitude  of second point (in decimal degrees).
-     * @return the orthodromic distance (in the units of this ellipsoid's axis).
-     *
-     * @deprecated Replaced by {@link org.apache.sis.referencing.GeodeticCalculator}.
-     *
-     * @see <a href="https://issues.apache.org/jira/browse/SIS-386">SIS-386</a>
-     */
-    @Deprecated
-    public double orthodromicDistance(double λ1, double φ1, double λ2, double φ2) {
-        λ1 = toRadians(λ1);
-        φ1 = toRadians(φ1);
-        λ2 = toRadians(λ2);
-        φ2 = toRadians(φ2);
-        /*
-         * Solution of the geodetic inverse problem after T.Vincenty.
-         * Modified Rainsford's method with Helmert's elliptical terms.
-         * Effective in any azimuth and at any distance short of antipodal.
-         *
-         * Latitudes and longitudes in radians positive North and East.
-         * Forward azimuths at both points returned in radians from North.
-         *
-         * Programmed for CDC-6600 by LCDR L.Pfeifer NGS ROCKVILLE MD 18FEB75
-         * Modified for IBM SYSTEM 360 by John G.Gergen NGS ROCKVILLE MD 7507
-         * Ported from Fortran to Java by Martin Desruisseaux.
-         *
-         * Source: ftp://ftp.ngs.noaa.gov/pub/pcsoft/for_inv.3d/source/inverse.for
-         *         subroutine INVER1
-         */
-        final double F = 1 / getInverseFlattening();
-        final double R = 1 - F;
-
-        double tu1 = R * tan(φ1);
-        double tu2 = R * tan(φ2);
-        double cu1 = 1 / sqrt(tu1*tu1 + 1);
-        double cu2 = 1 / sqrt(tu2*tu2 + 1);
-        double su1 = cu1 * tu1;
-        double s   = cu1 * cu2;
-        double baz =   s * tu2;
-        double faz = baz * tu1;
-        double x   =  λ2 - λ1;
-        for (int i=0; i<MAX_ITERATIONS; i++) {
-            final double sx = sin(x);
-            final double cx = cos(x);
-            tu1 = cu2 * sx;
-            tu2 = baz - su1*cu2*cx;
-            final double sy = hypot(tu1, tu2);
-            final double cy = s*cx + faz;
-            final double y = atan2(sy, cy);
-            final double SA = s * (sx/sy);
-            final double c2a = 1 - SA*SA;
-            double cz = 2*faz;
-            if (c2a > 0) {
-                cz = -cz/c2a + cy;
-            }
-            double e = cz*cz*2 - 1;
-            double c = ((-3*c2a+4)*F + 4) * c2a * F/16;
-            double d = x;
-            x = ((e*cy*c+cz)*sy*c + y) * SA;
-            x = (1-c)*x*F + λ2-λ1;
-
-            if (abs(d-x) <= EPS) {
-                x = sqrt((1/(R*R) - 1) * c2a + 1) + 1;
-                x = (x-2)/x;
-                c = 1-x;
-                c = (x*x/4 + 1)/c;
-                d = (0.375*x*x - 1)*x;
-                x = e*cy;
-                s = 1 - 2*e;
-                s = ((((sy*sy*4 - 3)*s*cz*d/6-x)*d/4+cz)*sy*d+y)*c*R * getSemiMajorAxis();
-                return s;
-            }
-        }
-        // No convergence. It may be because coordinate points
-        // are equals or because they are at antipodes.
-        if (abs(λ1-λ2) <= COMPARISON_THRESHOLD && abs(φ1-φ2) <= COMPARISON_THRESHOLD) {
-            return 0; // Coordinate points are equals
-        }
-        if (abs(φ1) <= COMPARISON_THRESHOLD && abs(φ2) <= COMPARISON_THRESHOLD) {
-            return abs(λ1-λ2) * getSemiMajorAxis(); // Points are on the equator.
-        }
-        // At least one input coordinate is NaN.
-        if (isNaN(λ1) || isNaN(φ1) || isNaN(λ2) || isNaN(φ2)) {
-            return NaN;
-        }
-        // Other cases: no solution for this algorithm.
-        throw new ArithmeticException(Resources.format(Resources.Keys.NoConvergenceForPoints_2,
-                  new DirectPosition2D(toDegrees(λ1), toDegrees(φ1)),
-                  new DirectPosition2D(toDegrees(λ2), toDegrees(φ2))));
-    }
-
-    /**
      * Returns the difference between the semi-major axis length of two ellipsoids.
      * If the two ellipsoid does not use the same unit of measurement, than the axis
      * length of the other ellipsoid is converted into the units of this ellipsoid axis.
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/Sphere.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/Sphere.java
index 436aa5c..4fbfb8b 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/Sphere.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/Sphere.java
@@ -26,8 +26,7 @@
 
 
 /**
- * A ellipsoid which is spherical. This ellipsoid implements a faster
- * {@link #orthodromicDistance(double, double, double, double)} method.
+ * A ellipsoid which is spherical.
  *
  * <div class="section">Immutability and thread safety</div>
  * This class is immutable and thus thread-safe if the property <em>values</em> (not necessarily the map itself)
@@ -35,7 +34,7 @@
  * all components were created using only SIS factories and static constants.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.7
+ * @version 1.1
  * @since   0.4
  * @module
  */
@@ -98,27 +97,4 @@
         return 1 / other.getInverseFlattening();
     }
 
-    /**
-     * Returns the orthodromic distance between two geographic coordinates.
-     * The orthodromic distance is the shortest distance between two points
-     * on a sphere's surface. The orthodromic path is always on a great circle.
-     *
-     * @param  λ1  longitude of first point (in decimal degrees).
-     * @param  φ1  latitude of first point (in decimal degrees).
-     * @param  λ2  longitude of second point (in decimal degrees).
-     * @param  φ2  latitude of second point (in decimal degrees).
-     * @return the orthodromic distance (in the units of this ellipsoid's axis).
-     */
-    @Override
-    @Deprecated
-    public double orthodromicDistance(double λ1, double φ1, double λ2, double φ2) {
-        φ1 = toRadians(φ1);
-        φ2 = toRadians(φ2);
-        final double dx = toRadians(abs(λ2-λ1) % 360);
-        double rho = sin(φ1)*sin(φ2) + cos(φ1)*cos(φ2)*cos(dx);
-        assert abs(rho) < 1.0000001 : rho;
-        if (rho > +1) rho = +1;                         // Catch rounding error.
-        if (rho < -1) rho = -1;                         // Catch rounding error.
-        return acos(rho) * getSemiMajorAxis();
-    }
 }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java
index 9c4be13..f67a13e 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/datum/package-info.java
@@ -32,7 +32,6 @@
  * <ul>
  *   <li>{@link org.apache.sis.referencing.datum.DefaultEllipsoid#getAuthalicRadius()}</li>
  *   <li>{@link org.apache.sis.referencing.datum.DefaultEllipsoid#getEccentricity()}</li>
- *   <li>{@link org.apache.sis.referencing.datum.DefaultEllipsoid#orthodromicDistance(double, double, double, double)}</li>
  *   <li>{@link org.apache.sis.referencing.datum.DefaultPrimeMeridian#getGreenwichLongitude(javax.measure.Unit)
  *       DefaultPrimeMeridian.getGreenwichLongitude(Unit)}</li>
  *   <li>{@link org.apache.sis.referencing.datum.DefaultGeodeticDatum#getBursaWolfParameters()}</li>
@@ -54,7 +53,7 @@
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Cédric Briançon (Geomatys)
- * @version 0.7
+ * @version 1.1
  * @since   0.4
  * @module
  */
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java
index 04895bf..7379d6c 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/MathTransforms.java
@@ -357,7 +357,7 @@
                 return IdentityTransform.create(firstAffectedCoordinate + dimension + numTrailingCoordinates);
             }
         }
-        return PassThroughTransform.create0(firstAffectedCoordinate, subTransform, numTrailingCoordinates);
+        return PassThroughTransform.create(firstAffectedCoordinate, subTransform, numTrailingCoordinates);
     }
 
     /**
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java
index 3a47636..1782e41 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java
@@ -149,19 +149,8 @@
      * @param  subTransform           the sub-transform to apply on modified coordinates.
      * @param  numTrailingCoordinates   number of trailing coordinates to pass through.
      * @return a pass-through transform, not necessarily a {@code PassThroughTransform} instance.
-     *
-     * @deprecated Moved to {@link MathTransforms#passThrough(int, MathTransform, int)}.
      */
-    @Deprecated
-    public static MathTransform create(final int firstAffectedCoordinate,
-                                       final MathTransform subTransform,
-                                       final int numTrailingCoordinates)
-    {
-        return MathTransforms.passThrough(firstAffectedCoordinate, subTransform, numTrailingCoordinates);
-    }
-
-    /** TODO: rename create(…) and recycle above javadoc. */
-    static MathTransform create0(final int firstAffectedCoordinate, final MathTransform subTransform, final int numTrailingCoordinates) {
+    static MathTransform create(final int firstAffectedCoordinate, final MathTransform subTransform, final int numTrailingCoordinates) {
         Matrix matrix = MathTransforms.getMatrix(subTransform);
         if (matrix != null) {
             return newInstance(firstAffectedCoordinate, matrix, numTrailingCoordinates);
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/package-info.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/package-info.java
index f4a7ba6..973fcd9 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/package-info.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/package-info.java
@@ -94,7 +94,7 @@
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @author  Guilhem Legal (Geomatys)
- * @version 1.0
+ * @version 1.1
  * @since   0.4
  * @module
  */
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/distance/LatLonPointRadiusTest.java b/core/sis-referencing/src/test/java/org/apache/sis/distance/LatLonPointRadiusTest.java
deleted file mode 100644
index 0958264..0000000
--- a/core/sis-referencing/src/test/java/org/apache/sis/distance/LatLonPointRadiusTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.sis.distance;
-
-
-// JDK imports
-import java.awt.geom.Rectangle2D;
-
-// SIS imports
-import org.apache.sis.test.TestCase;
-import org.apache.sis.geometry.DirectPosition2D;
-
-// JUnit imports
-import org.junit.Test;
-import static org.junit.Assert.*;
-
-/**
- * Tests methods from the {@link LatLonPointRadius} class.
- *
- * @author rlaidlaw
- */
-public strictfp class LatLonPointRadiusTest extends TestCase
-{
-  private static final double EPSILON = 0.000001;
-
-  /**
-   * Tests the LatLonPointRadius constructor.
-   */
-  @Test
-  public void testCreateLatLonPointRadius()
-  {
-    LatLonPointRadius region = new LatLonPointRadius(new DirectPosition2D(0.0, 0.0), 100.0);
-    assertNotNull(region);
-  }
-
-  /**
-   * Tests the getCircularRegionApproximation() method.
-   */
-  @Test
-  public void testGetCircularRegionApproximation()
-  {
-    LatLonPointRadius pr1 = new LatLonPointRadius(new DirectPosition2D(0.0, 0.0), 25000.0);
-    DirectPosition2D pts1[] = pr1.getCircularRegionApproximation(10);
-    assertEquals(5, pts1.length);
-    assertEquals(-90.0, pts1[0].y, EPSILON);
-    assertEquals(-180.0, pts1[0].x, EPSILON);
-    assertEquals(90.0, pts1[1].y, EPSILON);
-    assertEquals(-180.0, pts1[1].x, EPSILON);
-    assertEquals(90.0, pts1[2].y, EPSILON);
-    assertEquals(180.0, pts1[2].x, EPSILON);
-    assertEquals(-90.0, pts1[3].y, EPSILON);
-    assertEquals(180.0, pts1[3].x, EPSILON);
-    assertEquals(-90.0, pts1[4].y, EPSILON);
-    assertEquals(-180.0, pts1[4].x, EPSILON);
-
-    LatLonPointRadius pr2 = new LatLonPointRadius(new DirectPosition2D(0.0, 0.0), 1000.0);
-    DirectPosition2D pts2[] = pr2.getCircularRegionApproximation(6);
-    assertEquals(7, pts2.length);
-  }
-
-  /**
-   * Tests the getRectangularRegionApproximation() method.
-   */
-  @Test
-  public void testGetRectangularRegionApproximation()
-  {
-    LatLonPointRadius pr1 = new LatLonPointRadius(new DirectPosition2D(0.0, 0.0), 25000.0);
-    Rectangle2D r1 = pr1.getRectangularRegionApproximation(10);
-    assertEquals(0.0, r1.getX(), EPSILON);
-    assertEquals(0.0, r1.getY(), EPSILON);
-    assertEquals(360.0, r1.getWidth(), EPSILON);
-    assertEquals(180.0, r1.getHeight(), EPSILON);
-  }
-}
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java b/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java
index 893e79d..83a6f54 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/datum/DefaultEllipsoidTest.java
@@ -19,16 +19,11 @@
 import java.util.Random;
 import javax.xml.bind.JAXBException;
 import org.apache.sis.measure.Units;
-import org.apache.sis.measure.Latitude;
 import org.apache.sis.measure.Longitude;
-import org.apache.sis.referencing.IdentifiedObjects;
-import org.apache.sis.test.TestUtilities;
 import org.apache.sis.test.xml.TestCase;
 import org.apache.sis.test.DependsOn;
-import org.apache.sis.test.DependsOnMethod;
 import org.junit.Test;
 
-import static java.lang.StrictMath.*;
 import static org.apache.sis.test.ReferencingAssert.*;
 
 
@@ -114,82 +109,6 @@
     }
 
     /**
-     * Tests the orthodromic distances computed by {@link DefaultEllipsoid}. There is actually two algorithms:
-     * one for the ellipsoidal model, and a simpler one for spherical model. This method tests the ellipsoidal
-     * model using known values of nautical mile at different latitude.
-     *
-     * <p>This method performs the test on the Clark 1866 ellipsoid, which was the basis for the Imperial and
-     * U.S. definitions prior the First International Extraordinary Hydrographic Conference in Monaco (1929).</p>
-     */
-    @Test
-    public void testOrthodromicDistance() {
-        final DefaultEllipsoid e = new DefaultEllipsoid(GeodeticDatumMock.NAD27.getEllipsoid()); // Clark 1866
-        assertEquals("Nautical mile at equator",    1842.78, e.orthodromicDistance(0,    -HM,   0,    +HM), 0.01);
-        assertEquals("Nautical mile at North pole", 1861.67, e.orthodromicDistance(0,  90-HM*2, 0,  90   ), 0.02);
-        assertEquals("Nautical mile at South pole", 1861.67, e.orthodromicDistance(0, -90+HM*2, 0, -90   ), 0.02);
-        assertEquals("International nautical mile", 1852.00, e.orthodromicDistance(0,  45-HM,   0,  45+HM), 0.20);
-        /*
-         * Test parallel segments of increasing length at random positions on the equator.
-         */
-        final Random random = TestUtilities.createRandomNumberGenerator();
-        final double semiMajor = e.getSemiMajorAxis();
-        for (double length = 0; length <= Longitude.MAX_VALUE; length += 0.5) {
-            final double λ = nextLongitude(random);
-            assertEquals(semiMajor * toRadians(length), e.orthodromicDistance(λ, 0, λ+length, 0), 0.2);
-        }
-    }
-
-    /**
-     * Tests the orthodromic distances computed by {@link DefaultEllipsoid} on a sphere,
-     * and compares them with the distances computed by {@link Sphere}.
-     */
-    @Test
-    @DependsOnMethod("testOrthodromicDistance")
-    public void testOrthodromicDistanceOnSphere() {
-        /*
-         * Creates instance of DefaultEllipsoid and Sphere with the same properties.
-         * Those instances will use different formulas for orthodromic distances, which we will compare.
-         */
-        final DefaultEllipsoid e = new DefaultEllipsoid(GeodeticDatumMock.SPHERE.getEllipsoid());
-        final double radius = e.getSemiMajorAxis();
-        final Sphere s = new Sphere(IdentifiedObjects.getProperties(e), radius, false, e.getAxisUnit());
-        assertTrue(e.isSphere());
-        assertTrue(s.isSphere());
-        /*
-         * Test parallel segments of increasing length at random positions on the equator.
-         */
-        final Random random = TestUtilities.createRandomNumberGenerator();
-        for (double length = 0; length <= Longitude.MAX_VALUE; length += 0.5) {
-            final double λ = nextLongitude(random);
-            final double distance = radius * toRadians(length);
-            assertEquals(distance, s.orthodromicDistance(λ, 0, λ+length, 0), SPHERICAL_TOLERANCE);
-            assertEquals(distance, e.orthodromicDistance(λ, 0, λ+length, 0), SPHERICAL_TOLERANCE);
-        }
-        /*
-         * Test meridian segments from equator to increasing latitudes.
-         */
-        for (double φ = Latitude.MIN_VALUE; φ <= Latitude.MAX_VALUE; φ += 0.5) {
-            final double λ = nextLongitude(random);
-            final double distance = radius * toRadians(abs(φ));
-            assertEquals(distance, s.orthodromicDistance(λ, 0, λ, φ), SPHERICAL_TOLERANCE);
-            assertEquals(distance, e.orthodromicDistance(λ, 0, λ, φ), SPHERICAL_TOLERANCE);
-        }
-        /*
-         * Tests random segments.
-         */
-        final double circumference = (radius * (1 + 1E-8)) * (2*PI);
-        for (int i=0; i<100; i++) {
-            final double φ1 =  -90 + 180*random.nextDouble();
-            final double φ2 =  -90 + 180*random.nextDouble();
-            final double λ1 = -180 + 360*random.nextDouble();
-            final double λ2 = -180 + 360*random.nextDouble();
-            final double distance = s.orthodromicDistance(λ1, φ1, λ2, φ2);
-            assertTrue(distance >= 0 && distance <= circumference);
-            assertEquals(distance, e.orthodromicDistance(λ1, φ1, λ2, φ2), SPHERICAL_TOLERANCE);
-        }
-    }
-
-    /**
      * Tests the {@link DefaultEllipsoid#getAuthalicRadius()} method on the GRS 1980 ellipsoid (EPSG:7019).
      * The expected result is the radius of the sphere defined by EPSG:7048.
      */
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateOperationTest.java b/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateOperationTest.java
index aab1218..f7223d7 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateOperationTest.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateOperationTest.java
@@ -17,7 +17,6 @@
 package org.apache.sis.test.integration;
 
 import java.util.Random;
-import java.util.Collections;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.datum.Ellipsoid;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
@@ -28,14 +27,12 @@
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.crs.AbstractCRS;
 import org.apache.sis.referencing.cs.AxesConvention;
-import org.apache.sis.referencing.datum.DefaultEllipsoid;
 import org.apache.sis.referencing.operation.transform.MathTransformTestCase;
 import org.apache.sis.internal.referencing.CoordinateOperations;
 import org.apache.sis.test.DependsOn;
 import org.junit.Test;
 
 import static org.junit.Assert.*;
-import static java.lang.StrictMath.*;
 
 
 /**
@@ -43,7 +40,7 @@
  * orthodromic distances, <i>etc</i>.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.1
  * @since   0.8
  * @module
  */
@@ -91,40 +88,37 @@
         validate();
         /*
          * Constructs an array of random points. The first 8 points
-         * are initialized to know values. Other points are left random.
+         * are initialized to know values. Other points are random.
          */
-        final double   cartesianDistance[] = new double[4];
-        final double orthodromicDistance[] = new double[4];
-        final double[] array0 = new double[900];                    // Must be divisible by 3.
-        for (int i=0; i<array0.length; i++) {
+        final double distance[] = new double[4];
+        final double[] array0 = new double[900];                // Must be divisible by 3.
+
+        array0[0]=35.0; array0[1]=24.0; array0[2]=8000;         // 24°N 35°E 8km
+        array0[3]=34.8; array0[4]=24.7; array0[5]=5000;         // … about 80 km away
+        distance[0] = 80284.00;
+
+        // array0[6,7,8,10,11] = 0
+        array0[9]=180;                                          // Antipodes; distance should be 2*6378.137 km
+        distance[1] = ellipsoid.getSemiMajorAxis() * 2;
+
+                       array0[13]=-90;
+        array0[15]=180; array0[16]=+90;                         // Antipodes; distance should be 2*6356.752 km
+        distance[2] = ellipsoid.getSemiMinorAxis() * 2;
+
+        array0[18]= 95; array0[19]=-38;
+        array0[21]=-85; array0[22]=+38;                         // Antipodes
+        distance[3] = 12740147.19;
+
+        for (int i=24; i<array0.length; i++) {
             final int range;
             switch (i % 3) {
                 case 0:  range =   360; break;                      // Longitude
                 case 1:  range =   180; break;                      // Latitidue
                 case 2:  range = 10000; break;                      // Altitude
-                default: range =     0; break;                      // Should not happen
+                default: throw new AssertionError(i);
             }
             array0[i] = random.nextDouble() * range - (range/2);
         }
-        array0[0]=35.0; array0[1]=24.0; array0[2]=8000;             // 24°N 35°E 8km
-        array0[3]=34.8; array0[4]=24.7; array0[5]=5000;             // … about 80 km away
-        cartesianDistance  [0] = 80284.00;
-        orthodromicDistance[0] = 80302.99;                          // Not really exact.
-
-        array0[6]=  0; array0[ 7]=0.0; array0[ 8]=0;
-        array0[9]=180; array0[10]=0.0; array0[11]=0;                // Antipodes; distance should be 2*6378.137 km
-        cartesianDistance  [1] = ellipsoid.getSemiMajorAxis() * 2;
-        orthodromicDistance[1] = ellipsoid.getSemiMajorAxis() * PI;
-
-        array0[12]=  0; array0[13]=-90; array0[14]=0;
-        array0[15]=180; array0[16]=+90; array0[17]=0;               // Antipodes; distance should be 2*6356.752 km
-        cartesianDistance  [2] = ellipsoid.getSemiMinorAxis() * 2;
-        orthodromicDistance[2] = 20003931.46;
-
-        array0[18]= 95; array0[19]=-38; array0[20]=0;
-        array0[21]=-85; array0[22]=+38; array0[23]=0;               // Antipodes
-        cartesianDistance  [3] = 12740147.19;
-        orthodromicDistance[3] = 20003867.86;
         /*
          * Transforms all points, and then inverse transform them. The resulting
          * array2 should be equal to array0 except for rounding errors. We tolerate
@@ -141,7 +135,6 @@
         }
         /*
          * Compares the distances between "special" points with expected distances.
-         * This tests the ellipsoid orthodromic distance computation as well.
          * We require a precision of 10 centimetres.
          */
         for (int i=0; i < array0.length / 6; i++) {
@@ -150,30 +143,8 @@
                     array1[base+0] - array1[base+3],
                     array1[base+1] - array1[base+4],
                     array1[base+2] - array1[base+5]);
-            if (i < cartesianDistance.length) {
-                assertEquals("Cartesian distance", cartesianDistance[i], cartesian, 0.1);
-            }
-            /*
-             * Compares with orthodromic distance. Distance is computed using an ellipsoid
-             * at the maximal altitude (i.e. the length of semi-major axis is increased to
-             * fit the maximal altitude).
-             */
-            try {
-                final double altitude = max(array0[base+2], array0[base+5]);
-                final DefaultEllipsoid ellip = DefaultEllipsoid.createFlattenedSphere(
-                        Collections.singletonMap(Ellipsoid.NAME_KEY, "Temporary"),
-                        ellipsoid.getSemiMajorAxis() + altitude,
-                        ellipsoid.getInverseFlattening(),
-                        ellipsoid.getAxisUnit());
-                double orthodromic = ellip.orthodromicDistance(array0[base+0], array0[base+1],
-                                                               array0[base+3], array0[base+4]);
-                orthodromic = hypot(orthodromic, array0[base+2] - array0[base+5]);
-                if (i < orthodromicDistance.length) {
-                    assertEquals("Orthodromic distance", orthodromicDistance[i], orthodromic, 0.1);
-                }
-                assertTrue("Distance consistency", cartesian <= orthodromic);
-            } catch (ArithmeticException exception) {
-                // Orthodromic distance computation didn't converge. Ignore...
+            if (i < distance.length) {
+                assertEquals("Cartesian distance", distance[i], cartesian, 0.1);
             }
         }
     }
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java b/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
index 558a6fe..1a29823 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
@@ -276,9 +276,6 @@
     org.apache.sis.internal.referencing.ServicesForMetadataTest.class,
     org.apache.sis.internal.referencing.EllipsoidalHeightCombinerTest.class,
     org.apache.sis.geometry.CoordinateFormatTest.class,
-
-    org.apache.sis.distance.LatLonPointRadiusTest.class,        // Pending refactoring in a geometry package.
-
     org.apache.sis.test.integration.CoordinateReferenceSystemTest.class,
     org.apache.sis.test.integration.CoordinateOperationTest.class,
     org.apache.sis.test.integration.DatumShiftTest.class,
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java b/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
index 9ea0e55..1e2739f 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
@@ -1544,7 +1544,7 @@
      * @return {@code true} if the given character sequence is a legal Unicode identifier.
      *
      * @see org.apache.sis.referencing.ImmutableIdentifier
-     * @see org.apache.sis.metadata.iso.citation.Citations#getUnicodeIdentifier(Citation)
+     * @see org.apache.sis.metadata.iso.citation.Citations#toCodeSpace(Citation)
      * @see org.apache.sis.referencing.IdentifiedObjects#getSimpleNameOrIdentifier(IdentifiedObject)
      */
     public static boolean isUnicodeIdentifier(final CharSequence identifier) {
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java b/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java
index 8b12933..c409796 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/ComparisonMode.java
@@ -174,14 +174,6 @@
     DEBUG;
 
     /**
-     * @deprecated Renamed {@link #APPROXIMATE}.
-     *
-     * @see <a href="https://issues.apache.org/jira/browse/SIS-440">SIS-440</a>
-     */
-    @Deprecated
-    public static final ComparisonMode APPROXIMATIVE = APPROXIMATE;
-
-    /**
      * Returns {@code true} if this comparison ignores metadata.
      * This method currently returns {@code true} for {@code IGNORE_METADATA}, {@code APPROXIMATE}
      * or {@code DEBUG} only, but this list may be extended in future SIS versions.
@@ -208,16 +200,6 @@
     }
 
     /**
-     * @deprecated Renamed {@link #isApproximate()}.
-     *
-     * @see <a href="https://issues.apache.org/jira/browse/SIS-440">SIS-440</a>
-     */
-    @Deprecated
-    public boolean isApproximative() {
-        return isApproximate();
-    }
-
-    /**
      * If the two given objects are equal according one of the modes enumerated in this class,
      * then returns that mode. Otherwise returns {@code null}.
      *
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/Utilities.java b/core/sis-utility/src/main/java/org/apache/sis/util/Utilities.java
index d11a357..8adf5b4 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/Utilities.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/Utilities.java
@@ -113,16 +113,6 @@
     }
 
     /**
-     * @deprecated Renamed {@link #equalsApproximately(Object, Object)}.
-     *
-     * @see <a href="https://issues.apache.org/jira/browse/SIS-440">SIS-440</a>
-     */
-    @Deprecated
-    public static boolean equalsApproximatively(final Object object1, final Object object2) {
-        return equalsApproximately(object1, object2);
-    }
-
-    /**
      * Convenience method for testing two objects for equality using the given level of strictness.
      * If at least one of the given objects implement the {@link LenientComparable} interface, then
      * the comparison is performed using the {@link LenientComparable#equals(Object, ComparisonMode)}
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java b/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java
index df73cb4..2fc3afd 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/logging/Logging.java
@@ -48,7 +48,7 @@
  * </ul>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
  * @since   0.3
  * @module
  */
@@ -261,7 +261,7 @@
                 if (!classname.equals(classe)) {
                     continue;
                 }
-            } else if (!WarningListeners.isPublic(element)) {
+            } else if (!isPublic(element)) {
                 continue;
             }
             /*
@@ -304,6 +304,30 @@
     }
 
     /**
+     * Returns {@code true} if the given stack trace element describes a method considered part of public API.
+     * This method is invoked in order to infer the class and method names to declare in a {@link LogRecord}.
+     * We do not document this feature in public Javadoc because it is based on heuristic rules that may change.
+     *
+     * <p>The current implementation compares the class name against a hard-coded list of classes to hide.
+     * This implementation may change in any future SIS version.</p>
+     *
+     * @param  e  a stack trace element.
+     * @return {@code true} if the class and method specified by the given element can be considered public API.
+     */
+    private static boolean isPublic(final StackTraceElement e) {
+        final String classname = e.getClassName();
+        if (classname.startsWith("java") || classname.startsWith(Modules.INTERNAL_CLASSNAME_PREFIX) ||
+            classname.indexOf('$') >= 0 || e.getMethodName().indexOf('$') >= 0)
+        {
+            return false;
+        }
+        if (classname.startsWith(Modules.CLASSNAME_PREFIX + "util.logging.")) {
+            return classname.endsWith("Test");      // Consider JUnit tests as public.
+        }
+        return true;    // TODO: with StackWalker on JDK9, check if the class is public.
+    }
+
+    /**
      * Invoked when an unexpected error occurred. This method logs a message at {@link Level#WARNING}
      * to the specified logger. The originating class name and method name can optionally be specified.
      * If any of them is {@code null}, then it will be inferred from the error stack trace as described below.
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/logging/QuietLogRecord.java b/core/sis-utility/src/main/java/org/apache/sis/util/logging/QuietLogRecord.java
deleted file mode 100644
index d10ff94..0000000
--- a/core/sis-utility/src/main/java/org/apache/sis/util/logging/QuietLogRecord.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.util.logging;
-
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-
-
-/**
- * A log record to be logged without stack trace, unless the user specified it explicitly.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.8
- * @since   0.3
- * @module
- *
- * @deprecated Moved to {@link org.apache.sis.storage.event.QuietLogRecord}.
- */
-@Deprecated
-final class QuietLogRecord extends LogRecord {
-    /**
-     * For cross-version compatibility.
-     */
-    private static final long serialVersionUID = -8225936118310305206L;
-
-    /**
-     * {@code true} if the user invoked {@link #setThrown(Throwable)}.
-     * In such case, {@link #clearThrown()} will not reset the throwable to null.
-     */
-    private boolean explicitThrown;
-
-    /**
-     * Creates a new log record for the given message and exception.
-     */
-    QuietLogRecord(final Level level, final String message, final Exception exception) {
-        super(level, message);
-        super.setThrown(exception);
-    }
-
-    /**
-     * Sets the throwable to the given value. The given throwable will not be cleared
-     * when the record will be logged.
-     */
-    @Override
-    public void setThrown(final Throwable thrown) {
-        explicitThrown = true;
-        super.setThrown(thrown);
-    }
-
-    /**
-     * Clears the throwable if it has not been explicit set by the user.
-     * Otherwise do nothing.
-     */
-    void clearThrown() {
-        if (!explicitThrown) {
-            super.setThrown(null);
-        }
-    }
-}
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/logging/WarningListener.java b/core/sis-utility/src/main/java/org/apache/sis/util/logging/WarningListener.java
deleted file mode 100644
index a97777a..0000000
--- a/core/sis-utility/src/main/java/org/apache/sis/util/logging/WarningListener.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.util.logging;
-
-import java.util.EventListener;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-import java.util.logging.Filter;
-
-
-/**
- * Intercepts non-fatal error messages logged by {@link org.apache.sis.storage.DataStore} or other SIS objects.
- * Warnings are encapsulated in {@link LogRecord} objects and logged at {@link Level#WARNING} if the emitter does not
- * have registered any {@code WarningListener}. This listener allows applications to intercept warning records for
- * displaying them in a dialog (or any other action that the application may choose) instead than logging them.
- *
- * <div class="note"><b>Comparison with alternative approaches:</b>
- * it is also possible to listen to login events by registering a custom {@link java.util.logging.Handler} to the logger.
- * But {@code Handler} instances are registered on a per-logger basis and receive all messages sent to that logger
- * regardless their emitter. By contrast, {@code WarningListener} instances are registered on a per-{@code DataStore}
- * basis (or any other emitter) and receive all messages sent by that emitter regardless the destination logger.
- * The emitter is part of the information given to the {@link #warningOccured(Object, LogRecord)} method,
- * in addition to the log record.</div>
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
- *
- * @param <S>  the base type of objects that emit warnings (the <cite>source</cite>).
- *
- * @see WarningListeners
- * @see org.apache.sis.storage.DataStore#addWarningListener(WarningListener)
- * @see org.apache.sis.storage.event.StoreListener
- *
- * @since 0.3
- * @module
- *
- * @deprecated Replaced by {@link java.util.logging.Filter}.
- */
-@Deprecated
-public interface WarningListener<S> extends EventListener {
-    /**
-     * Returns the type of objects that emit warnings of interest for this listener.
-     * This is typically, but not necessarily, the class having the name returned by
-     * {@link LogRecord#getSourceClassName()}, or one of its parent classes.
-     *
-     * @return the base type of objects that emit warnings (the <cite>source</cite>).
-     */
-    Class<S> getSourceClass();
-
-    /**
-     * Reports the occurrence of a non-fatal error. The emitter process (often a
-     * {@link org.apache.sis.storage.DataStore} in the midst of a reading process)
-     * will continue following the call to this method.
-     *
-     * <p>The {@code LogRecord} provides the warning {@linkplain LogRecord#getMessage() message} together with
-     * programmatic information like the {@linkplain LogRecord#getSourceClassName() source class name} and
-     * {@linkplain LogRecord#getSourceMethodName() method name} where the warning occurred. The log record
-     * may optionally contains the exception which has been {@linkplain LogRecord#getThrown() thrown}.</p>
-     *
-     * <p>Applications may choose to ignore the warning, display a dialog or take any other action they choose.
-     * Applications do not need to log the warning, since logging will be done automatically if the emitter has
-     * no registered warning listeners.</p>
-     *
-     * @param source   the object that emitted a warning, or {@code null} if not available.
-     * @param warning  the warning message together with programmatic information.
-     */
-    void warningOccured(S source, LogRecord warning);
-
-    /**
-     * Wraps this listener in a {@code java.util.logging.Filter} for transitioning
-     * to the replacement of this interface.
-     */
-    default Filter asFilter() {
-        return (LogRecord warning) -> {
-            warningOccured(null, warning);
-            return false;
-        };
-    }
-}
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/logging/WarningListeners.java b/core/sis-utility/src/main/java/org/apache/sis/util/logging/WarningListeners.java
deleted file mode 100644
index cf51192..0000000
--- a/core/sis-utility/src/main/java/org/apache/sis/util/logging/WarningListeners.java
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.util.logging;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.logging.LogRecord;
-import java.util.NoSuchElementException;
-import org.apache.sis.util.Localized;
-import org.apache.sis.util.Exceptions;
-import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.util.resources.Errors;
-import org.apache.sis.internal.system.Modules;
-import org.apache.sis.internal.util.UnmodifiableArrayList;
-
-
-/**
- * Holds a list of {@link WarningListener} instances and provides convenience methods for emitting warnings.
- * This is a helper class for {@link org.apache.sis.storage.DataStore} implementations or for other services
- * susceptible to emit warnings.
- * Observers can {@linkplain #addWarningListener can add listeners} for being notified about warnings, and
- * processes can invoke one of the {@code warning(…)} methods for emitting warnings. All warnings are given
- * to the listeners as {@link LogRecord} instances (this allows localizable messages and additional information
- * like {@linkplain LogRecord#getMillis() timestamp} and {@linkplain LogRecord#getThrown() stack trace}).
- * This {@code WarningListeners} class provides convenience methods like {@link #warning(String, Exception)},
- * which builds {@code LogRecord} from an exception or from a string, but all those {@code warning(…)} methods
- * ultimately delegate to {@link #warning(LogRecord)}, thus providing a single point that subclasses can override.
- * When a warning is emitted, the default behavior is:
- *
- * <ul>
- *   <li>If at least one {@link WarningListener} is registered,
- *       then all listeners are notified and the warning is <strong>not</strong> logged.
- *   <li>Otherwise if the value returned by {@link LogRecord#getLoggerName()} is non-null,
- *       then the warning will be logged to that named logger.</li>
- *   <li>Otherwise the warning is logged to the logger returned by {@link #getLogger()}.</li>
- * </ul>
- *
- * <div class="section">Thread safety</div>
- * The same {@code WarningListeners} instance can be safely used by many threads without synchronization
- * on the part of the caller. Subclasses should make sure that any overridden methods remain safe to call
- * from multiple threads.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
- *
- * @param <S>  the type of the source of warnings.
- *
- * @see WarningListener
- * @see org.apache.sis.storage.DataStore#listeners
- *
- * @since 0.3
- * @module
- *
- * @deprecated Replaced by {@link org.apache.sis.storage.event.StoreListeners}.
- */
-@Deprecated
-public class WarningListeners<S> implements Localized {
-    /**
-     * The declared source of warnings. This is not necessarily the real source,
-     * but this is the source that the implementer wants to declare as public API.
-     */
-    private final S source;
-
-    /**
-     * The listeners, or {@code null} if none. This is a <cite>copy on write</cite> array:
-     * no elements are modified once the array have been created.
-     */
-    private WarningListener<? super S>[] listeners;
-
-    /**
-     * Creates a new instance with initially no listener.
-     * Warnings will be logger to the destination given by {@link #getLogger()},
-     * unless at least one listener is {@linkplain #addWarningListener registered}.
-     *
-     * @param source  the declared source of warnings. This is not necessarily the real source,
-     *                but this is the source that the implementer wants to declare as public API.
-     */
-    public WarningListeners(final S source) {
-        this.source = source;
-    }
-
-    /**
-     * Creates a new instance initialized with the same listeners than the given instance.
-     * This constructor is useful when a {@code DataStore} or other data producer needs to
-     * be duplicated for concurrency reasons.
-     *
-     * @param source  the declared source of warnings. This is not necessarily the real source,
-     *                but this is the source that the implementer wants to declare as public API.
-     * @param other   the existing instance from which to copy the listeners, or {@code null} if none.
-     *
-     * @since 0.8
-     */
-    public WarningListeners(final S source, final WarningListeners<? super S> other) {
-        this(source);
-        if (other != null) {
-            listeners = other.listeners;
-        }
-    }
-
-    /**
-     * Returns the source declared source of warnings.
-     * This value is specified at construction time.
-     *
-     * @return the declared source of warnings.
-     *
-     * @since 0.8
-     */
-    public S getSource() {
-        return source;
-    }
-
-    /**
-     * The locale to use for formatting warning messages, or {@code null} for the default locale.
-     * If the {@code source} object given to the constructor implements the {@link Localized} interface,
-     * then this method delegates to its {@code getLocale()} method. Otherwise this method returns {@code null}.
-     */
-    @Override
-    public Locale getLocale() {
-        return (source instanceof Localized) ? ((Localized) source).getLocale() : null;
-    }
-
-    /**
-     * Returns the logger where to send the warnings when no other destination is specified.
-     * This logger is used when:
-     *
-     * <ul>
-     *   <li>no listener has been {@linkplain #addWarningListener registered}, and</li>
-     *   <li>the {@code LogRecord} does not {@linkplain LogRecord#getLoggerName() specify a logger}.</li>
-     * </ul>
-     *
-     * The default implementation infers a logger name from the package name of the {@code source} object.
-     * Subclasses should override this method if they can provide a more determinist logger instance,
-     * typically from a static final constant.
-     *
-     * @return the logger where to send the warnings when there is no other destination.
-     */
-    public Logger getLogger() {
-        return Logging.getLogger(source.getClass());
-    }
-
-    /**
-     * Reports a warning represented by the given log record. The default implementation forwards
-     * the given record to <strong>one</strong> of the following destinations, in preference order:
-     *
-     * <ol>
-     *   <li><code>{@linkplain WarningListener#warningOccured WarningListener.warningOccured}(source, record)</code>
-     *       on all {@linkplain #addWarningListener registered listeners} it at least one such listener exists.</li>
-     *   <li><code>{@linkplain Logging#getLogger(String) Logging.getLogger}(record.{@linkplain LogRecord#getLoggerName
-     *       getLoggerName()}).{@linkplain Logger#log(LogRecord) log}(record)</code> if the logger name is non-null.</li>
-     *   <li><code>{@linkplain #getLogger()}.{@linkplain Logger#log(LogRecord) log}(record)</code> otherwise.</li>
-     * </ol>
-     *
-     * @param record  the warning as a log record.
-     */
-    public void warning(final LogRecord record) {
-        final WarningListener<? super S>[] current;
-        synchronized (this) {
-            current = listeners;
-        }
-        if (current != null) {
-            for (final WarningListener<? super S> listener : current) {
-                listener.warningOccured(source, record);
-            }
-        } else {
-            final String name = record.getLoggerName();
-            final Logger logger;
-            if (name != null) {
-                logger = Logging.getLogger(name);
-            } else {
-                logger = getLogger();
-                record.setLoggerName(logger.getName());
-            }
-            if (record instanceof QuietLogRecord) {
-                ((QuietLogRecord) record).clearThrown();
-            }
-            logger.log(record);
-        }
-    }
-
-    /**
-     * Reports a warning represented by the given message and exception.
-     * At least one of {@code message} and {@code exception} shall be non-null.
-     * If both are non-null, then the exception message will be concatenated after the given message.
-     * If the exception is non-null, its stack trace will be omitted at logging time for avoiding to
-     * pollute console output (keeping in mind that this method should be invoked only for non-fatal
-     * warnings). See {@linkplain #warning(Level, String, Exception) below} for more explanation.
-     *
-     * <p>This method is a shortcut for <code>{@linkplain #warning(Level, String, Exception)
-     * warning}({@linkplain Level#WARNING}, message, exception)</code>.
-     *
-     * @param message    the message to log, or {@code null} if none.
-     * @param exception  the exception to log, or {@code null} if none.
-     */
-    public void warning(String message, Exception exception) {
-        warning(Level.WARNING, message, exception);
-    }
-
-    /**
-     * Reports a warning at the given level represented by the given message and exception.
-     * At least one of {@code message} and {@code exception} shall be non-null.
-     * If both are non-null, then the exception message will be concatenated after the given message.
-     *
-     * <div class="section">Stack trace omission</div>
-     * If there is no registered listener, then the {@link #warning(LogRecord)} method will send the record to the
-     * {@linkplain #getLogger() logger}, but <em>without</em> the stack trace. This is done that way because stack
-     * traces consume lot of space in the logging files, while being considered implementation details in the context
-     * of {@code WarningListeners} (on the assumption that the logging message provides sufficient information).
-     * If the stack trace is desired, then users can either:
-     * <ul>
-     *   <li>invoke {@code warning(LogRecord)} directly, or</li>
-     *   <li>override {@code warning(LogRecord)} and invoke {@link LogRecord#setThrown(Throwable)} explicitly, or</li>
-     *   <li>register a listener which will log the record itself.</li>
-     * </ul>
-     *
-     * @param level      the warning level.
-     * @param message    the message to log, or {@code null} if none.
-     * @param exception  the exception to log, or {@code null} if none.
-     */
-    public void warning(final Level level, String message, final Exception exception) {
-        ArgumentChecks.ensureNonNull("level", level);
-        final LogRecord record;
-        final StackTraceElement[] trace;
-        if (exception != null) {
-            trace = exception.getStackTrace();
-            message = Exceptions.formatChainedMessages(getLocale(), message, exception);
-            if (message == null) {
-                message = exception.toString();
-            }
-            record = new QuietLogRecord(level, message, exception);
-        } else {
-            ArgumentChecks.ensureNonEmpty("message", message);
-            trace = Thread.currentThread().getStackTrace();
-            record = new LogRecord(level, message);
-        }
-        for (final StackTraceElement e : trace) {
-            if (isPublic(e)) {
-                record.setSourceClassName(e.getClassName());
-                record.setSourceMethodName(e.getMethodName());
-                break;
-            }
-        }
-        warning(record);
-    }
-
-    /**
-     * Returns {@code true} if the given stack trace element describes a method considered part of public API.
-     * This method is invoked in order to infer the class and method names to declare in a {@link LogRecord}.
-     * We do not document this feature in public Javadoc because it is based on heuristic rules that may change.
-     *
-     * <p>The current implementation compares the class name against a hard-coded list of classes to hide.
-     * This implementation may change in any future SIS version.</p>
-     *
-     * @param  e  a stack trace element.
-     * @return {@code true} if the class and method specified by the given element can be considered public API.
-     */
-    static boolean isPublic(final StackTraceElement e) {
-        final String classname = e.getClassName();
-        if (classname.startsWith("java") || classname.startsWith(Modules.INTERNAL_CLASSNAME_PREFIX) ||
-            classname.indexOf('$') >= 0 || e.getMethodName().indexOf('$') >= 0)
-        {
-            return false;
-        }
-        if (classname.startsWith(Modules.CLASSNAME_PREFIX + "util.logging.")) {
-            return classname.endsWith("Test");      // Consider JUnit tests as public.
-        }
-        return true;    // TODO: with StackWalker on JDK9, check if the class is public.
-    }
-
-    /**
-     * Adds a listener to be notified when a warning occurred.
-     * When a warning occurs, there is a choice:
-     *
-     * <ul>
-     *   <li>If this object has no warning listener, then the warning is logged at
-     *       {@link java.util.logging.Level#WARNING}.</li>
-     *   <li>If this object has at least one warning listener, then all listeners are notified
-     *       and the warning is <strong>not</strong> logged by this object.</li>
-     * </ul>
-     *
-     * @param  listener  the listener to add.
-     * @throws IllegalArgumentException if the given listener is already registered.
-     */
-    public synchronized void addWarningListener(final WarningListener<? super S> listener)
-            throws IllegalArgumentException
-    {
-        ArgumentChecks.ensureNonNull("listener", listener);
-        final WarningListener<? super S>[] current = listeners;
-        final int length = (current != null) ? current.length : 0;
-
-        @SuppressWarnings({"unchecked", "rawtypes"}) // Generic array creation.
-        final WarningListener<? super S>[] copy = new WarningListener[length + 1];
-        for (int i=0; i<length; i++) {
-            final WarningListener<? super S> c = current[i];
-            if (c == listener) {
-                throw new IllegalArgumentException(Errors.format(Errors.Keys.ElementAlreadyPresent_1, listener));
-            }
-            copy[i] = c;
-        }
-        copy[length] = listener;
-        listeners = copy;
-    }
-
-    /**
-     * Removes a previously registered listener.
-     *
-     * @param  listener  the listener to remove.
-     * @throws NoSuchElementException if the given listener is not registered.
-     */
-    public synchronized void removeWarningListener(final WarningListener<? super S> listener)
-            throws NoSuchElementException
-    {
-        ArgumentChecks.ensureNonNull("listener", listener);
-        final WarningListener<? super S>[] current = listeners;
-        if (current != null) {
-            for (int i=0; i<current.length; i++) {
-                if (current[i] == listener) {
-                    if (current.length == 1) {
-                        listeners = null;
-                    } else {
-                        @SuppressWarnings({"unchecked", "rawtypes"}) // Generic array creation.
-                        final WarningListener<? super S>[] copy = new WarningListener[current.length - 1];
-                        System.arraycopy(current, 0, copy, 0, i);
-                        System.arraycopy(current, i+1, copy, i, copy.length - i);
-                        listeners = copy;
-                    }
-                    return;
-                }
-            }
-        }
-        throw new NoSuchElementException(Errors.format(Errors.Keys.ElementNotFound_1, listener));
-    }
-
-    /**
-     * Returns all registered warning listeners, or an empty list if none.
-     * This method returns an unmodifiable snapshot of the listener list at the time this method is invoked.
-     *
-     * @return immutable list of all registered warning listeners.
-     *
-     * @since 0.8
-     */
-    public List<WarningListener<? super S>> getListeners() {
-        final WarningListener<? super S>[] current;
-        synchronized (this) {
-            current = listeners;
-        }
-        return (current != null) ? UnmodifiableArrayList.wrap(current) : Collections.emptyList();
-    }
-
-    /**
-     * Returns {@code true} if this object contains at least one listener.
-     *
-     * @return {@code true} if this object contains at least one listener, {@code false} otherwise.
-     *
-     * @since 0.4
-     */
-    public synchronized boolean hasListeners() {
-        return listeners != null;
-    }
-}
diff --git a/core/sis-utility/src/main/java/org/apache/sis/util/logging/package-info.java b/core/sis-utility/src/main/java/org/apache/sis/util/logging/package-info.java
index c5d651e..31d6ac6 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/util/logging/package-info.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/util/logging/package-info.java
@@ -50,7 +50,7 @@
  * order to give SIS a chance to redirect log events to an other logging framework.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
  *
  * @see <a href="http://download.oracle.com/javase/6/docs/technotes/guides/logging/overview.html">Java Logging Overview</a>
  *
diff --git a/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java b/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
index 7da3477..3702235 100644
--- a/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
+++ b/core/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
@@ -52,7 +52,6 @@
     org.apache.sis.util.resources.IndexedResourceBundleTest.class,
     org.apache.sis.util.ArgumentChecksTest.class,                       // Uses resources.
     org.apache.sis.util.logging.PerformanceLevelTest.class,
-    org.apache.sis.util.logging.WarningListenersTest.class,
     org.apache.sis.util.logging.MonolineFormatterTest.class,
     org.apache.sis.util.logging.LoggerAdapterTest.class,
     org.apache.sis.math.FractionTest.class,
diff --git a/core/sis-utility/src/test/java/org/apache/sis/util/logging/WarningListenersTest.java b/core/sis-utility/src/test/java/org/apache/sis/util/logging/WarningListenersTest.java
deleted file mode 100644
index 42b7318..0000000
--- a/core/sis-utility/src/test/java/org/apache/sis/util/logging/WarningListenersTest.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.util.logging;
-
-import java.util.logging.LogRecord;
-import java.util.NoSuchElementException;
-import org.apache.sis.test.DependsOnMethod;
-import org.apache.sis.test.TestCase;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-
-/**
- * Tests the {@link WarningListeners} class.
- *
- * @author  Martin Desruisseaux (Geomatys)
- * @version 0.3
- * @since   0.3
- * @module
- */
-@Deprecated
-public final strictfp class WarningListenersTest extends TestCase implements WarningListener<String> {
-    /**
-     * The object to be tested. Its source will be set to the string {@code "source"}.
-     */
-    private final WarningListeners<String> listeners;
-
-    /**
-     * The warning received by {@link #warningOccured(String, LogRecord)}.
-     * This is stored for allowing test methods to verify the properties.
-     */
-    private LogRecord warning;
-
-    /**
-     * Creates a new test case.
-     */
-    public WarningListenersTest() {
-        listeners = new WarningListeners<>("source");
-    }
-
-    /**
-     * Returns the type warning sources.
-     */
-    @Override
-    public Class<String> getSourceClass() {
-        return String.class;
-    }
-
-    /**
-     * Invoked when a warning occurred. The implementation in this test verifies that the {@code source} argument has
-     * the expected values, then stores the log record in the {@link #warning} field for inspection by the test method.
-     */
-    @Override
-    public void warningOccured(final String source, final LogRecord warning) {
-        assertEquals("source", source);
-        this.warning = warning;
-    }
-
-    /**
-     * Returns {@code "TestListener"}, for verification of error messages in exceptions.
-     */
-    @Override
-    public String toString() {
-        return "TestListener";
-    }
-
-    /**
-     * Tests {@link WarningListeners#addWarningListener(WarningListener)} followed by
-     * {@link WarningListeners#removeWarningListener(WarningListener)}
-     */
-    @Test
-    public void testAddAndRemoveWarningListener() {
-        listeners.addWarningListener(this);
-        try {
-            listeners.addWarningListener(this);
-        } catch (IllegalArgumentException e) {
-            // This is the expected exception.
-            assertTrue(e.getMessage().contains("TestListener"));
-        }
-        listeners.removeWarningListener(this);
-        try {
-            listeners.removeWarningListener(this);
-        } catch (NoSuchElementException e) {
-            // This is the expected exception.
-            assertTrue(e.getMessage().contains("TestListener"));
-        }
-    }
-
-    /**
-     * Tests {@link WarningListeners#warning(String, Exception)} with a registered listener.
-     */
-    @Test
-    @DependsOnMethod("testAddAndRemoveWarningListener")
-    public void testWarning() {
-        listeners.addWarningListener(this);
-        listeners.warning("The message", null);
-        listeners.removeWarningListener(this);
-        assertNotNull("Listener has not been notified.", warning);
-        assertEquals(getClass().getName(), warning.getSourceClassName());
-        assertEquals("testWarning", warning.getSourceMethodName());
-        assertEquals("The message", warning.getMessage());
-    }
-}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/distance/LatLonPointRadius.java b/storage/sis-storage/src/main/java/org/apache/sis/index/tree/LatLonPointRadius.java
similarity index 69%
rename from core/sis-referencing/src/main/java/org/apache/sis/distance/LatLonPointRadius.java
rename to storage/sis-storage/src/main/java/org/apache/sis/index/tree/LatLonPointRadius.java
index a58d767..82a0429 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/distance/LatLonPointRadius.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/index/tree/LatLonPointRadius.java
@@ -15,18 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.sis.distance;
+package org.apache.sis.index.tree;
 
-//JDK imports
 import java.awt.geom.Area;
 import java.awt.geom.Path2D;
 import java.awt.geom.Rectangle2D;
-
-// GeoAPI import
 import org.opengis.geometry.DirectPosition;
-
-//SIS imports
-import org.apache.sis.geometry.DirectPosition2D;
 import org.apache.sis.measure.Longitude;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.GeodeticCalculator;
@@ -34,11 +28,9 @@
 /**
  * Represents a 2D point associated with a radius to enable great circle
  * estimation on earth surface.
- *
- * @deprecated Replaced by {@link org.apache.sis.referencing.GeodeticCalculator#createGeodesicCircle2D(double)}.
  */
-@Deprecated
-public class LatLonPointRadius {
+final class LatLonPointRadius {
+  private static final double HALF_EARTH_CIRCUMFERENCE = 20037.58; // in km
 
   private final DirectPosition center;
   private final double radius;
@@ -51,61 +43,20 @@
    * @param radius
    *          the radius of the search region
    */
-  public LatLonPointRadius(DirectPosition center, double radius) {
+  LatLonPointRadius(DirectPosition center, double radius) {
     this.center = center;
     this.radius = radius;
   }
 
   /**
-   * Gets the circular region approximation on the earth surface using haversine
-   * formula.
-   *
-   * @param numberOfPoints
-   *          the number of points used to estimate the circular region
-   * @return an array of DirectPosition2D representing the points that estimate the
-   *         circular region
-   */
-  public DirectPosition2D[] getCircularRegionApproximation(int numberOfPoints) {
-    if (radius >= DistanceUtils.HALF_EARTH_CIRCUMFERENCE) {
-      DirectPosition2D[] points = new DirectPosition2D[5];
-      points[0] = new DirectPosition2D(-180.0, -90.0);
-      points[1] = new DirectPosition2D(-180.0, 90.0);
-      points[2] = new DirectPosition2D(180.0, 90.0);
-      points[3] = new DirectPosition2D(180.0, -90.0);
-      points[4] = points[0];
-      return points;
-    }
-    // plus one to add closing point
-    DirectPosition2D[] points = new DirectPosition2D[numberOfPoints + 1];
-
-    double bearingIncrement = 0;
-    if (numberOfPoints > 0) { bearingIncrement = 360/numberOfPoints; }
-
-    final GeodeticCalculator calculator = GeodeticCalculator.create(CommonCRS.SPHERE.geographic());
-    calculator.setStartGeographicPoint(center.getOrdinate(1), center.getOrdinate(0));
-    calculator.setGeodesicDistance(radius);
-
-    for (int i = 0; i < numberOfPoints; i++)
-    {
-      calculator.setStartingAzimuth(i * bearingIncrement);
-      DirectPosition p = calculator.getEndPoint();
-      points[i] = new DirectPosition2D(p.getOrdinate(1), p.getOrdinate(0));
-    }
-
-    points[numberOfPoints] = points[0];
-
-    return points;
-  }
-
-  /**
    * Calculates the rectangular region enclosing the circular search region.
    *
    * @param numberOfPoints
    *          the number of points used to estimate the circular search region
    * @return Java Rectangle2D object that bounds the circlar search region
    */
-  public Rectangle2D getRectangularRegionApproximation(int numberOfPoints) {
-    if (radius >= DistanceUtils.HALF_EARTH_CIRCUMFERENCE) {
+  Rectangle2D getRectangularRegionApproximation(int numberOfPoints) {
+    if (radius >= HALF_EARTH_CIRCUMFERENCE) {
       return new Rectangle2D.Double(0.0, 0.0, 360.0, 180.0);
     }
     int numberOfCrossOvers = 0;
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/index/tree/QuadTree.java b/storage/sis-storage/src/main/java/org/apache/sis/index/tree/QuadTree.java
index cfb8e4d..bda627c 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/index/tree/QuadTree.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/index/tree/QuadTree.java
@@ -22,7 +22,6 @@
 
 import org.apache.sis.geometry.DirectPosition2D;
 import org.apache.sis.geometry.Envelope2D;
-import org.apache.sis.distance.LatLonPointRadius;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.GeodeticCalculator;
 
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java
index 0f4dc55..a7aedfb 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java
@@ -291,7 +291,7 @@
      * it is caller's responsibility to wrap the stream in a {@link java.io.BufferedInputStream} if desired.
      *
      * @param  filename  data store name to report in case of failure.
-     * @param  listeners set of registered {@code WarningListener}s for the data store, or {@code null} if none.
+     * @param  listeners set of registered {@code StoreListener}s for the data store, or {@code null} if none.
      * @return the input stream.
      * @throws DataStoreException if the channel is read-once.
      * @throws IOException if the input stream or its underlying byte channel can not be created.
@@ -307,7 +307,7 @@
      * it is caller's responsibility to wrap the stream in a {@link java.io.BufferedOutputStream} if desired.
      *
      * @param  filename  data store name to report in case of failure.
-     * @param  listeners set of registered {@code WarningListener}s for the data store, or {@code null} if none.
+     * @param  listeners set of registered {@code StoreListener}s for the data store, or {@code null} if none.
      * @return the output stream.
      * @throws DataStoreException if the channel is write-once.
      * @throws IOException if the output stream or its underlying byte channel can not be created.
@@ -324,7 +324,7 @@
      * this method throws an exception.
      *
      * @param  filename  data store name to report in case of failure.
-     * @param  listeners set of registered {@code WarningListener}s for the data store, or {@code null} if none.
+     * @param  listeners set of registered {@code StoreListener}s for the data store, or {@code null} if none.
      * @return the channel for the given input.
      * @throws DataStoreException if the channel is read-once.
      * @throws IOException if an error occurred while opening the channel.
@@ -338,7 +338,7 @@
      * this method throws an exception.
      *
      * @param  filename  data store name to report in case of failure.
-     * @param  listeners set of registered {@code WarningListener}s for the data store, or {@code null} if none.
+     * @param  listeners set of registered {@code StoreListener}s for the data store, or {@code null} if none.
      * @return the channel for the given output.
      * @throws DataStoreException if the channel is write-once.
      * @throws IOException if an error occurred while opening the channel.
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java
index 194a435..d8bdffd 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java
@@ -19,7 +19,6 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.IdentityHashMap;
-import java.util.NoSuchElementException;
 import java.util.Optional;
 import org.opengis.util.ScopedName;
 import org.opengis.util.GenericName;
@@ -30,7 +29,6 @@
 import org.opengis.parameter.ParameterValueGroup;
 import org.apache.sis.util.Localized;
 import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.util.logging.WarningListener;
 import org.apache.sis.internal.storage.StoreUtilities;
 import org.apache.sis.internal.storage.Resources;
 import org.apache.sis.internal.util.Strings;
@@ -486,56 +484,6 @@
     }
 
     /**
-     * Adds a listener to be notified when a warning occurred while reading from or writing to the storage.
-     * When a warning occurs, there is a choice:
-     *
-     * <ul>
-     *   <li>If this data store has no warning listener, then the warning is logged at
-     *       {@link java.util.logging.Level#WARNING}.</li>
-     *   <li>If this data store has at least one warning listener, then all listeners are notified
-     *       and the warning is <strong>not</strong> logged by this data store instance.</li>
-     * </ul>
-     *
-     * Consider invoking this method in a {@code try} … {@code finally} block if the {@code DataStore}
-     * lifetime is longer than the listener lifetime, as below:
-     *
-     * {@preformat java
-     *     datastore.addWarningListener(listener);
-     *     try {
-     *         // Do some work...
-     *     } finally {
-     *         datastore.removeWarningListener(listener);
-     *     }
-     * }
-     *
-     * @param  listener  the listener to add.
-     * @throws IllegalArgumentException if the given listener is already registered in this data store.
-     *
-     * @deprecated Replaced by {@code addListener(listener, WarningEvent.class)}.
-     */
-    @Deprecated
-    public void addWarningListener(final WarningListener<? super DataStore> listener)
-            throws IllegalArgumentException
-    {
-        listeners.addWarningListener(listener);
-    }
-
-    /**
-     * Removes a previously registered listener.
-     *
-     * @param  listener  the listener to remove.
-     * @throws NoSuchElementException if the given listener is not registered in this data store.
-     *
-     * @deprecated Replaced by {@code removeListener(listener, WarningEvent.class)}.
-     */
-    @Deprecated
-    public void removeWarningListener(final WarningListener<? super DataStore> listener)
-            throws NoSuchElementException
-    {
-        listeners.removeWarningListener(listener);
-    }
-
-    /**
      * Closes this data store and releases any underlying resources.
      *
      * @throws DataStoreException if an error occurred while closing this data store.
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/event/StoreListeners.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/event/StoreListeners.java
index 01521cb..2e18ac1 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/storage/event/StoreListeners.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/event/StoreListeners.java
@@ -29,7 +29,6 @@
 import org.apache.sis.util.Exceptions;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.logging.Logging;
-import org.apache.sis.util.logging.WarningListener;
 import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.storage.StoreResource;
 import org.apache.sis.storage.DataStoreProvider;
@@ -72,11 +71,11 @@
  * from multiple threads.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
  * @since   1.0
  * @module
  */
-public class StoreListeners extends org.apache.sis.util.logging.WarningListeners implements Localized {
+public class StoreListeners implements Localized {
     /**
      * Parent manager to notify in addition to this manager.
      */
@@ -210,7 +209,6 @@
      * @param source  the source of events. Can not be null.
      */
     public StoreListeners(final StoreListeners parent, Resource source) {
-        super(source);
         /*
          * Undocumented feature for allowing subclass to specify `this` as the source resource.
          * This is used as a convenience by AbstractResource internal class. We need this hack
@@ -230,7 +228,6 @@
      *
      * @return the source of events.
      */
-    @Override
     public Resource getSource() {
         return source;
     }
@@ -319,7 +316,7 @@
      *
      * @return the logger where to send the warnings when there is no other destination.
      */
-    private Logger logger() {
+    private Logger getLogger() {
         Resource src = source;
         final DataStore ds = getDataStore(this);
         if (ds != null) {
@@ -378,7 +375,6 @@
      * @param  message    the warning message to report, or {@code null} if none.
      * @param  exception  the exception to report, or {@code null} if none.
      */
-    @Override
     public void warning(String message, Exception exception) {
         warning(Level.WARNING, message, exception);
     }
@@ -404,7 +400,6 @@
      * @param  message    the message to log, or {@code null} if none.
      * @param  exception  the exception to log, or {@code null} if none.
      */
-    @Override
     public void warning(final Level level, String message, final Exception exception) {
         ArgumentChecks.ensureNonNull("level", level);
         final LogRecord record;
@@ -476,7 +471,6 @@
      *
      * @param  description  warning details provided as a log record.
      */
-    @Override
     @SuppressWarnings("unchecked")
     public void warning(final LogRecord description) {
         if (!fire(new WarningEvent(source, description), WarningEvent.class)) {
@@ -485,7 +479,7 @@
             if (name != null) {
                 logger = Logging.getLogger(name);
             } else {
-                logger = logger();
+                logger = getLogger();
                 description.setLoggerName(logger.getName());
             }
             if (description instanceof QuietLogRecord) {
@@ -616,58 +610,4 @@
         } while (m != null);
         return false;
     }
-
-    /**
-     * Returns {@code true} if this object contains at least one listener.
-     *
-     * @return {@code true} if this object contains at least one listener, {@code false} otherwise.
-     */
-    @Override
-    @Deprecated
-    public boolean hasListeners() {
-        return hasListeners(StoreEvent.class);
-    }
-
-    /**
-     * @deprecated Replaced by {@code addListener(listener, WarningEvent.class)}.
-     */
-    @Override
-    @Deprecated
-    public void addWarningListener(final WarningListener listener) {
-        addListener(new Legacy(listener), WarningEvent.class);
-    }
-
-    /**
-     * @deprecated Replaced by {@code removeListener(listener, WarningEvent.class)}.
-     */
-    @Override
-    @Deprecated
-    public void removeWarningListener(final WarningListener listener) {
-        for (ForType<?> e = listeners; e != null; e = e.next) {
-            if (e.type.equals(WarningEvent.class)) {
-                StoreListener<?>[] list = e.listeners;
-                if (list != null) {
-                    for (final StoreListener<?> c : list) {
-                        if (c instanceof Legacy && ((Legacy) c).delegate == listener) {
-                            removeListener((StoreListener<WarningEvent>) c, WarningEvent.class);
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    @Deprecated
-    private static final class Legacy implements StoreListener<WarningEvent> {
-        final WarningListener<? super Resource> delegate;
-
-        Legacy(final WarningListener<? super Resource> delegate) {
-            this.delegate = delegate;
-        }
-
-        @Override public void eventOccured(WarningEvent event) {
-            delegate.warningOccured(event.getSource(), event.getDescription());
-        }
-    }
 }
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/event/package-info.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/event/package-info.java
index 5745fca..c9a46b7 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/storage/event/package-info.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/event/package-info.java
@@ -34,7 +34,7 @@
  * to a specific kind of event}.
  *
  * @author  Johann Sorel (Geomatys)
- * @since   1.0
+ * @since   1.1
  * @version 1.0
  * @module
  */
diff --git a/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java b/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java
index 9dc4462..8ba40a4 100644
--- a/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java
+++ b/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java
@@ -298,7 +298,7 @@
         /**
          * Returns configuration associated to the given key, or {@code null} if none.
          *
-         * @param  key  one of {@link XML#LOCALE}, {@link XML#TIMEZONE} or {@link XML#WARNING_LISTENER}.
+         * @param  key  one of {@link XML#LOCALE}, {@link XML#TIMEZONE} or {@link XML#WARNING_FILTER}.
          * @return the configuration for the given key, or {@code null} if none or if the given key is invalid.
          */
         @Override