/*
 * 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.referencing;

import java.util.Map;
import java.util.Set;
import java.util.Collection;
import java.util.Collections;
import java.util.AbstractCollection;
import java.util.Iterator;
import java.util.Locale;
import java.util.Objects;
import java.util.Formattable;
import java.util.FormattableFlags;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
import org.opengis.util.GenericName;
import org.opengis.util.NameFactory;
import org.opengis.util.InternationalString;
import org.opengis.metadata.Identifier;
import org.opengis.metadata.citation.Citation;
import org.opengis.referencing.ObjectFactory;
import org.opengis.referencing.AuthorityFactory;
import org.opengis.referencing.IdentifiedObject;
import org.apache.sis.internal.jaxb.Context;
import org.apache.sis.internal.jaxb.UseLegacyMetadata;
import org.apache.sis.internal.jaxb.referencing.Code;
import org.apache.sis.internal.util.Strings;
import org.apache.sis.internal.util.UnmodifiableArrayList;
import org.apache.sis.internal.metadata.NameToIdentifier;
import org.apache.sis.internal.referencing.WKTUtilities;
import org.apache.sis.internal.metadata.MetadataUtilities;
import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.io.wkt.FormattableObject;
import org.apache.sis.io.wkt.Formatter;
import org.apache.sis.io.wkt.ElementKind;
import org.apache.sis.xml.Namespaces;
import org.apache.sis.util.Deprecable;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.LenientComparable;
import org.apache.sis.util.Classes;
import org.apache.sis.util.iso.Types;
import org.apache.sis.util.iso.DefaultNameFactory;
import org.apache.sis.util.resources.Errors;

import static org.apache.sis.util.ArgumentChecks.*;
import static org.apache.sis.util.Utilities.deepEquals;
import static org.apache.sis.internal.util.CollectionsExt.nonNull;
import static org.apache.sis.internal.util.CollectionsExt.nonEmpty;
import static org.apache.sis.internal.util.CollectionsExt.immutableSet;


/**
 * Base class for objects identified by a name or a code. Those objects are typically
 * {@linkplain org.apache.sis.referencing.datum.DefaultGeodeticDatum geodetic datum}   (e.g. <cite>"World Geodetic System 1984"</cite>),
 * {@linkplain org.apache.sis.referencing.crs.AbstractCRS Coordinate Reference System} (e.g. <cite>"WGS 84 / World Mercator"</cite>) or
 * {@linkplain org.apache.sis.referencing.operation.DefaultConversion map projection}  (e.g. <cite>"Mercator (variant A)"</cite>).
 * Those names, or a code (e.g. {@code "EPSG:3395"}), can be used for fetching an object from a database.
 * However it is not sufficient to know the object name. We also need to know who define that name
 * (the {@linkplain NamedIdentifier#getAuthority() authority}) since the same objects are often named differently
 * depending on the providers, or conversely the same name is used for different objects depending on the provider.
 *
 * <p>The main information stored in an {@code IdentifiedObject} are:</p>
 * <ul>
 *   <li>a primary {@linkplain #getName() name}, considered by the object creator as the preferred name,</li>
 *   <li>an arbitrary amount of {@linkplain #getAlias() aliases}, for example a list of names used by other providers,</li>
 *   <li>an arbitrary amount of {@linkplain #getIdentifiers() identifiers}, typically primary keys in the provider database,</li>
 *   <li>optional {@linkplain #getRemarks() remarks}.</li>
 * </ul>
 *
 * <h2>Instantiation</h2>
 * This class is conceptually <cite>abstract</cite>, even if it is technically possible to instantiate it.
 * Applications should instead instantiate the most specific subclass having a name starting by {@code Default}.
 * However exceptions to this rule may occur when it is not possible to identify the exact type.
 *
 * <div class="note"><b>Example:</b>
 * It is sometime not possible to infer the exact coordinate system type from
 * <a href="http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/doc-files/WKT.html">version 1
 * of <cite>Well Known Text format</cite></a>, for example when parsing a {@code LOCAL_CS} element.
 * In such exceptional situation, a plain {@code AbstractCS} object may be instantiated.</div>
 *
 * {@code IdentifiedObject} instances are created in two main ways:
 *
 * <ul>
 *   <li>Using an {@link ObjectFactory}, in which case all properties can be explicitly specified.</li>
 *   <li>Using an {@link AuthorityFactory}, in which case only a code (typically a primary key) is specified.
 *       The {@linkplain NamedIdentifier#getAuthority() authority}
 *       and {@linkplain NamedIdentifier#getCode() authority code} values are set to the authority name
 *       of the factory object, and the authority code supplied by the client, respectively.
 *       All other information are fetched from the database.</li>
 * </ul>
 *
 * <h2>Immutability and thread safety</h2>
 * This base class is immutable if the {@link Citation}, {@link Identifier}, {@link GenericName} and
 * {@link InternationalString} instances given to the constructor are also immutable. Most SIS subclasses and
 * related classes are immutable under similar conditions. This means that unless otherwise noted in the javadoc,
 * {@code IdentifiedObject} instances created using only SIS factories and static constants can be shared by many
 * objects and passed between threads without synchronization.
 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @version 1.1
 * @since   0.4
 * @module
 */
@XmlType(name = "IdentifiedObjectType", propOrder = {
    "description",
    "identifier",
    "names",
    "remarks"
})
@XmlSeeAlso({
    org.apache.sis.referencing.crs.AbstractCRS.class,
    org.apache.sis.referencing.datum.AbstractDatum.class,
    org.apache.sis.referencing.datum.DefaultEllipsoid.class,
    org.apache.sis.referencing.datum.DefaultPrimeMeridian.class,
    org.apache.sis.referencing.cs.AbstractCS.class
})
@UseLegacyMetadata
public class AbstractIdentifiedObject extends FormattableObject implements IdentifiedObject,
        Formattable, LenientComparable, Deprecable, Serializable
{
    /**
     * Serial number for inter-operability with different versions.
     */
    private static final long serialVersionUID = -5173281694258483264L;

    /**
     * Optional key which can be given to the {@linkplain #AbstractIdentifiedObject(Map) constructor} for specifying
     * the locale to use for producing error messages. Notes:
     *
     * <ul>
     *   <li>The locale is not stored in any {@code AbstractIdentifiedObject} property;
     *       its value is ignored if no error occurred at construction time.</li>
     *   <li>The locale is used on a <cite>best effort</cite> basis;
     *       not all error messages may be localized.</li>
     * </ul>
     */
    public static final String LOCALE_KEY = Errors.LOCALE_KEY;

    /**
     * Optional key which can be given to the {@linkplain #AbstractIdentifiedObject(Map) constructor}
     * for specifying the object is deprecated. If deprecated, then the replacement should be specified
     * in the {@linkplain #getRemarks() remarks}.
     *
     * <div class="note"><b>Example:</b> "superseded by code XYZ".</div>
     *
     * @since 0.6
     */
    public static final String DEPRECATED_KEY = "deprecated";

    /**
     * The name for this object or code. Shall never be {@code null}.
     *
     * <p><b>Consider this field as final!</b>
     * This field is modified only at unmarshalling time by {@link Names#add(Identifier)}.</p>
     *
     * @see #getName()
     * @see #getNames()
     */
    private Identifier name;

    /**
     * An alternative name by which this object is identified, or {@code null} if none.
     * We must be prepared to handle either null or an empty set for "no alias" because
     * we may get both on unmarshalling.
     *
     * <p><b>Consider this field as final!</b>
     * This field is modified only at unmarshalling time by {@link Names#add(Identifier)}.</p>
     */
    private Collection<GenericName> alias;

    /**
     * An identifier which references elsewhere the object's defining information.
     * Alternatively an identifier by which this object can be referenced.
     *
     * <p><b>Consider this field as final!</b>
     * This field is modified only at unmarshalling time by {@link #setIdentifier(Code)}</p>
     *
     * @see #getIdentifiers()
     * @see #getIdentifier()
     */
    private Set<Identifier> identifiers;

    /**
     * Comments on or information about this object, or {@code null} if none.
     *
     * <p><b>Consider this field as final!</b>
     * This field is modified only at unmarshalling time by {@link #setRemarks(InternationalString)}</p>
     *
     * @see #getRemarks()
     */
    private InternationalString remarks;

    /**
     * {@code true} if this object is deprecated.
     *
     * @since 0.6
     */
    private final boolean deprecated;

    /**
     * The cached hash code value, or 0 if not yet computed. This field is calculated only when
     * first needed. We do not declare it {@code volatile} because it is not a big deal if this
     * field is calculated many time, and the same value should be produced by all computations.
     * The only possible outdated value is 0, which is okay.
     */
    private transient int hashCode;

    /**
     * Constructs an object 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.referencing.IdentifiedObject#NAME_KEY} or
     * {@value org.opengis.metadata.Identifier#CODE_KEY} key.
     * Other properties listed in the table below are optional.
     * In particular, {@code "authority"}, {@code "code"}, {@code "codespace"} and {@code "version"}
     * are convenience properties for building a name, and are ignored if the {@code "name"} property
     * is already a {@link Identifier} object instead of a {@link String}.
     *
     * <table class="sis">
     *   <caption>Recognized properties (non exhaustive list)</caption>
     *   <tr>
     *     <th>Property name</th>
     *     <th>Value type</th>
     *     <th>Returned by</th>
     *   </tr>
     *   <tr>
     *     <td>{@value org.opengis.referencing.IdentifiedObject#NAME_KEY}</td>
     *     <td>{@link Identifier} or {@link String}</td>
     *     <td>{@link #getName()}</td>
     *   </tr>
     *   <tr>
     *     <td>{@value org.opengis.metadata.Identifier#AUTHORITY_KEY}</td>
     *     <td>{@link String} or {@link Citation}</td>
     *     <td>{@link NamedIdentifier#getAuthority()} on the {@linkplain #getName() name}</td>
     *   </tr>
     *   <tr>
     *     <td>{@value org.opengis.metadata.Identifier#CODE_KEY}</td>
     *     <td>{@link String}</td>
     *     <td>{@link NamedIdentifier#getCode()} on the {@linkplain #getName() name}</td>
     *   </tr>
     *   <tr>
     *     <td>{@value org.opengis.metadata.Identifier#CODESPACE_KEY}</td>
     *     <td>{@link String}</td>
     *     <td>{@link NamedIdentifier#getCodeSpace()} on the {@linkplain #getName() name}</td>
     *   </tr>
     *   <tr>
     *     <td>{@value org.opengis.metadata.Identifier#VERSION_KEY}</td>
     *     <td>{@link String}</td>
     *     <td>{@link NamedIdentifier#getVersion()} on the {@linkplain #getName() name}</td>
     *   </tr>
     *   <tr>
     *     <td>{@value org.opengis.metadata.Identifier#DESCRIPTION_KEY}</td>
     *     <td>{@link String}</td>
     *     <td>{@link NamedIdentifier#getDescription()} on the {@linkplain #getName() name}</td>
     *   </tr>
     *   <tr>
     *     <td>{@value org.opengis.referencing.IdentifiedObject#ALIAS_KEY}</td>
     *     <td>{@link GenericName} or {@link CharSequence} (optionally as array)</td>
     *     <td>{@link #getAlias()}</td>
     *   </tr>
     *   <tr>
     *     <td>{@value org.opengis.referencing.IdentifiedObject#IDENTIFIERS_KEY}</td>
     *     <td>{@link Identifier} (optionally as array)</td>
     *     <td>{@link #getIdentifiers()}</td>
     *   </tr>
     *   <tr>
     *     <td>{@value org.opengis.referencing.IdentifiedObject#REMARKS_KEY}</td>
     *     <td>{@link InternationalString} or {@link String}</td>
     *     <td>{@link #getRemarks()}</td>
     *   </tr>
     *   <tr>
     *     <td>{@value #DEPRECATED_KEY}</td>
     *     <td>{@link Boolean}</td>
     *     <td>{@link #isDeprecated()}</td>
     *   </tr>
     *   <tr>
     *     <td>{@value #LOCALE_KEY}</td>
     *     <td>{@link Locale}</td>
     *     <td>(none)</td>
     *   </tr>
     * </table>
     *
     * <h4>Localization</h4>
     * All localizable attributes like {@code "remarks"} may have a language and country code suffix.
     * For example the {@code "remarks_fr"} property stands for remarks in {@linkplain Locale#FRENCH French} and
     * the {@code "remarks_fr_CA"} property stands for remarks in {@linkplain Locale#CANADA_FRENCH French Canadian}.
     * They are convenience properties for building the {@code InternationalString} value.
     *
     * <p>The {@code "locale"} property applies only in case of exception for formatting the error message, and
     * is used only on a <cite>best effort</cite> basis. The locale is discarded after successful construction
     * since localizations are applied by the {@link InternationalString#toString(Locale)} method.</p>
     *
     * <h4>Properties map versus explicit arguments</h4>
     * Generally speaking, information provided in the {@code properties} map are considered ignorable metadata
     * while information provided in explicit arguments to the sub-class constructors have an impact on coordinate
     * transformation results. See {@link #equals(Object, ComparisonMode)} for more information.
     *
     * @param  properties  the properties to be given to this identified object.
     * @throws IllegalArgumentException if a property has an invalid value.
     */
    public AbstractIdentifiedObject(final Map<String,?> properties) throws IllegalArgumentException {
        ensureNonNull("properties", properties);

        // ----------------------------
        // "name": String or Identifier
        // ----------------------------
        Object value = properties.get(NAME_KEY);
        if (value == null || value instanceof String) {
            if (value == null && properties.get(Identifier.CODE_KEY) == null) {
                throw new IllegalArgumentException(Errors.getResources(properties)
                        .getString(Errors.Keys.MissingValueForProperty_1, NAME_KEY));
            }
            name = new NamedIdentifier(PropertiesConverter.convert(properties));
        } else if (value instanceof Identifier) {
            name = (Identifier) value;
        } else {
            throw illegalPropertyType(properties, NAME_KEY, value);
        }

        // -------------------------------------------------------------------
        // "alias": CharSequence, CharSequence[], GenericName or GenericName[]
        // -------------------------------------------------------------------
        value = properties.get(ALIAS_KEY);
        final GenericName[] names;
        try {
            /*
             * Note: DefaultFactories.forBuildin(Class) filters the implementations in order to guarantee an
             * Apache SIS implementation. We need to revisit this mechanism for a real "dependency injection"
             * mechanism in the future.
             */
            final DefaultNameFactory factory = DefaultFactories.forBuildin(NameFactory.class, DefaultNameFactory.class);
            names = factory.toGenericNames(value);
        } catch (ClassCastException e) {
            throw (IllegalArgumentException) illegalPropertyType(properties, ALIAS_KEY, value).initCause(e);
        }
        alias = immutableSet(true, names);

        // -----------------------------------------
        // "identifiers": Identifier or Identifier[]
        // -----------------------------------------
        value = properties.get(IDENTIFIERS_KEY);
        if (value == null) {
            identifiers = null;
        } else if (value instanceof Identifier) {
            identifiers = Collections.singleton((Identifier) value);
        } else if (value instanceof Identifier[]) {
            identifiers = immutableSet(true, (Identifier[]) value);
        } else {
            throw illegalPropertyType(properties, IDENTIFIERS_KEY, value);
        }

        // ----------------------------------------
        // "remarks": String or InternationalString
        // ----------------------------------------
        remarks = Types.toInternationalString(properties, REMARKS_KEY);

        // ---------------------
        // "deprecated": Boolean
        // ---------------------
        value = properties.get(DEPRECATED_KEY);
        if (value == null) {
            deprecated = false;
        } else if (value instanceof Boolean) {
            deprecated = (Boolean) value;
        } else {
            throw illegalPropertyType(properties, DEPRECATED_KEY, value);
        }
    }

    /**
     * Returns the exception to be thrown when a property is of illegal type.
     */
    private static IllegalArgumentException illegalPropertyType(
            final Map<String,?> properties, final String key, final Object value)
    {
        return new IllegalArgumentException(Errors.getResources(properties)
                .getString(Errors.Keys.IllegalPropertyValueClass_2, key, value.getClass()));
    }

    /**
     * Constructs a new identified object with the same values than the specified one.
     * This copy constructor provides a way to convert an arbitrary implementation into a SIS one or a
     * user-defined one (as a subclass), usually in order to leverage some implementation-specific API.
     *
     * <p>This constructor performs a shallow copy, i.e. the properties are not cloned.</p>
     *
     * @param object  the object to shallow copy.
     */
    protected AbstractIdentifiedObject(final IdentifiedObject object) {
        ensureNonNull("object", object);
        name        =          object.getName();
        alias       = nonEmpty(object.getAlias()); // Favor null for empty set in case it is not Collections.EMPTY_SET
        identifiers = nonEmpty(object.getIdentifiers());
        remarks     =          object.getRemarks();
        deprecated  = (object instanceof Deprecable) ? ((Deprecable) object).isDeprecated() : false;
    }

    /**
     * Returns a SIS identified object 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 an instance of
     *       {@link org.opengis.referencing.crs.CoordinateReferenceSystem},
     *       {@link org.opengis.referencing.cs.CoordinateSystem},
     *       {@link org.opengis.referencing.cs.CoordinateSystemAxis},
     *       {@link org.opengis.referencing.datum.Datum},
     *       {@link org.opengis.referencing.datum.Ellipsoid},
     *       {@link org.opengis.referencing.datum.PrimeMeridian},
     *       {@link org.opengis.referencing.operation.OperationMethod},
     *       {@link org.opengis.referencing.operation.CoordinateOperation},
     *       {@link org.opengis.parameter.ParameterDescriptor} or
     *       {@link org.opengis.parameter.ParameterDescriptorGroup},
     *       then this method delegates to the {@code castOrCopy(…)} method of the corresponding SIS subclass.
     *       Note that if the given object implements more than one of the above-cited interfaces,
     *       then the {@code castOrCopy(…)} method to be used is unspecified.</li>
     *   <li>Otherwise if the given object is already an instance of
     *       {@code AbstractIdentifiedObject}, then it is returned unchanged.</li>
     *   <li>Otherwise a new {@code AbstractIdentifiedObject} instance is created using the
     *       {@linkplain #AbstractIdentifiedObject(IdentifiedObject) copy constructor}
     *       and returned. Note that this is a <cite>shallow</cite> copy operation, since the other
     *       properties 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 AbstractIdentifiedObject castOrCopy(final IdentifiedObject object) {
        return SubTypes.castOrCopy(object);
    }

    /**
     * Returns the GeoAPI interface implemented by this class.
     * This information is part of the data compared by {@link #equals(Object, ComparisonMode)}.
     *
     * <p>The default implementation returns {@code IdentifiedObject.class}.
     * Subclasses implementing a more specific GeoAPI interface shall override this method.</p>
     *
     * <h4>Invariants</h4>
     * The following invariants must hold for all {@code AbstractIdentifiedObject} instances:
     * <ul>
     *   <li><code>getInterface().{@linkplain Class#isInstance(Object) isInstance}(this)</code>
     *       shall return {@code true}.</li>
     *   <li>If {@code A.getClass() == B.getClass()} is {@code true}, then
     *       {@code A.getInterface() == B.getInterface()} shall be {@code true}.
     *       Note that the converse does not need to hold.</li>
     * </ul>
     *
     * @return the GeoAPI interface implemented by this class.
     */
    public Class<? extends IdentifiedObject> getInterface() {
        return IdentifiedObject.class;
    }

    /**
     * Returns the primary name by which this object is identified.
     *
     * @return the primary name.
     *
     * @see IdentifiedObjects#getName(IdentifiedObject, Citation)
     */
    @Override
    public Identifier getName() {
        return name;
    }

    /**
     * Returns alternative names by which this object is identified.
     *
     * @return the aliases, or an empty collection if there is none.
     *
     * @see #getName()
     */
    @Override
    public Collection<GenericName> getAlias() {
        return nonNull(alias);          // Needs to be null-safe because we may have a null value on unmarshalling.
    }

    /**
     * Returns identifiers which references elsewhere the object's defining information.
     * Alternatively identifiers by which this object can be referenced.
     *
     * @return this object identifiers, or an empty set if there is none.
     *
     * @see IdentifiedObjects#getIdentifier(IdentifiedObject, Citation)
     */
    @Override
    public Set<Identifier> getIdentifiers() {
        return nonNull(identifiers);    // Needs to be null-safe because we may have a null value on unmarshalling.
    }

    /**
     * Returns a narrative explanation of the role of this object.
     *
     * <h4>Default value</h4>
     * The default implementation returns the {@linkplain ImmutableIdentifier#getDescription() description}
     * provided by this object's {@linkplain #getName() name}.
     *
     * @return a narrative explanation of the role of this object, or {@code null} if none.
     *
     * @see ImmutableIdentifier#getDescription()
     *
     * @since 0.6
     */
    @XmlElement(name = "description")
    public InternationalString getDescription() {
        return (name != null) ? name.getDescription() : null;
    }

    /**
     * Returns comments on or information about this object, including data source information.
     * If this object {@linkplain #isDeprecated() is deprecated}, then the remarks should give
     * indication about the replacement (e.g. <cite>"superceded by …"</cite>).
     *
     * @return the remarks, or {@code null} if none.
     */
    @Override
    @XmlElement(name = "remarks")
    public InternationalString getRemarks() {
        return remarks;
    }

    /**
     * Returns {@code true} if this object is deprecated. Deprecated objects exist in some
     * {@linkplain org.opengis.referencing.AuthorityFactory authority factories} like the EPSG database.
     * If this method returns {@code true}, then the {@linkplain #getRemarks() remarks} should give
     * indication about the replacement (e.g. <cite>"superceded by …"</cite>).
     *
     * @return {@code true} if this object is deprecated.
     */
    @Override
    public boolean isDeprecated() {
        return deprecated;
    }

    /**
     * Returns {@code true} if either the {@linkplain #getName() primary name} or at least
     * one {@linkplain #getAlias() alias} matches the given string according heuristic rules.
     * The default implementation returns {@code true} if the given {@code name} is equal,
     * ignoring aspects documented below, to one of the following names:
     *
     * <ul>
     *   <li>The {@linkplain #getName() primary name}'s {@linkplain NamedIdentifier#getCode() code}
     *       (without {@linkplain NamedIdentifier#getCodeSpace() codespace}).</li>
     *   <li>Any {@linkplain #getAlias() alias}'s {@linkplain NamedIdentifier#tip() tip}
     *       (without {@linkplain NamedIdentifier#scope() scope} and namespace).</li>
     * </ul>
     *
     * The comparison ignores the following aspects:
     * <ul>
     *   <li>Lower/upper cases.</li>
     *   <li>Some Latin diacritical signs (e.g. {@code "Réunion"} and {@code "Reunion"} are considered equal).</li>
     *   <li>All characters that are not {@linkplain Character#isLetterOrDigit(int) letters or digits}
     *       (e.g. {@code "Mercator (1SP)"} and {@code "Mercator_1SP"} are considered equal).</li>
     *   <li>Namespaces or scopes, because this method is typically invoked with either the value of an other
     *       <code>IdentifiedObject.getName().getCode()</code> or with the <cite>Well Known Text</cite> (WKT)
     *       projection or parameter name.</li>
     * </ul>
     *
     * <h4>Usage</h4>
     * This method is invoked by SIS when comparing in {@link ComparisonMode#IGNORE_METADATA IGNORE_METADATA} mode
     * two objects that can be differentiated only by some identifier (name or alias), like
     * {@linkplain org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis coordinate system axes},
     * {@linkplain org.apache.sis.referencing.datum.AbstractDatum datum},
     * {@linkplain org.apache.sis.parameter.DefaultParameterDescriptor parameters} and
     * {@linkplain org.apache.sis.referencing.operation.DefaultOperationMethod operation methods}.
     * See {@link #equals(Object, ComparisonMode)} for more information.
     *
     * <p>This method is also invoked when searching a parameter or operation method for a given name.
     * For example the same projection is known as {@code "Mercator (variant A)"} (the primary name according EPSG)
     * and {@code "Mercator (1SP)"} (the legacy name prior EPSG 7.6). Since the latter is still in frequent use, SIS
     * accepts it as an alias of the <cite>Mercator (variant A)</cite> projection.</p>
     *
     * <h4>Overriding by subclasses</h4>
     * Some subclasses add more flexibility to the comparisons:
     * <ul>
     *   <li>{@linkplain org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis#isHeuristicMatchForName(String)
     *       Comparisons of coordinate system axis names} consider {@code "Lat"}, {@code "Latitude"} and
     *       {@code "Geodetic latitude"} as synonymous, and likewise for longitude.</li>
     *   <li>{@linkplain org.apache.sis.referencing.datum.AbstractDatum#isHeuristicMatchForName(String)
     *       Comparisons of datum names} ignore the {@code "D_"} prefix, if any.
     *       This prefix appears in ESRI datum name (e.g. {@code "D_WGS_1984"}).</li>
     *   <li>{@linkplain org.apache.sis.referencing.datum.DefaultGeodeticDatum#isHeuristicMatchForName(String)
     *       Comparisons of geodetic datum names} may ignore the prime meridian name, if any.
     *       Example: <cite>"(Paris)"</cite> in <cite>"Nouvelle Triangulation Française (Paris)"</cite>.</li>
     * </ul>
     *
     * <h4>Future evolutions</h4>
     * This method implements recommendations from the
     * <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#139">WKT 2 specification §B.5.2</a>,
     * together with heuristic rules learned from experience while trying to provide inter-operability
     * with different data producers. Those rules may be adjusted in any future SIS version according experience
     * gained while working with more data producers.
     *
     * @param  name  the name to compare with the object name or aliases.
     * @return {@code true} if the primary name or at least one alias matches the specified {@code name}.
     *
     * @see IdentifiedObjects#isHeuristicMatchForName(IdentifiedObject, String)
     * @see org.apache.sis.util.Characters.Filter#LETTERS_AND_DIGITS
     */
    public boolean isHeuristicMatchForName(final String name) {
        return NameToIdentifier.isHeuristicMatchForName(this.name, alias, name, NameToIdentifier.Simplifier.DEFAULT);
    }

    /**
     * Compares this object with the given object for equality.
     * The strictness level is controlled by the second argument,
     * from stricter to more permissive values:
     *
     * <table class="sis">
     *   <caption>Description of comparison modes</caption>
     *   <tr><th>Mode</th><th>Description</th></tr>
     *   <tr><td>{@link ComparisonMode#STRICT STRICT}:</td>
     *        <td>Verifies if the two objects are of the same {@linkplain #getClass() class}
     *            and compares all public properties, including SIS-specific (non standard) properties.</td></tr>
     *   <tr><td>{@link ComparisonMode#BY_CONTRACT BY_CONTRACT}:</td>
     *       <td>Verifies if the two objects implement the same {@linkplain #getInterface() GeoAPI interface}
     *           and compares all properties defined by that interface ({@linkplain #getName() name},
     *           {@linkplain #getIdentifiers() identifiers}, {@linkplain #getRemarks() remarks}, <i>etc</i>).
     *           The two objects do not need to be instances of the same implementation class
     *           and SIS-specific properties are ignored.</td></tr>
     *   <tr><td>{@link ComparisonMode#IGNORE_METADATA IGNORE_METADATA}:</td>
     *       <td>Compares only the properties relevant to coordinate transformations. Generally speaking, the content
     *           of the {@code properties} map given at {@linkplain #AbstractIdentifiedObject(Map) construction time}
     *           is considered ignorable metadata while the explicit arguments given to the constructor (if any) are
     *           considered non-ignorable. Note that there is some exceptions to this rule of thumb — see
     *           <cite>When object name matter</cite> below.</td></tr>
     *   <tr><td>{@link ComparisonMode#APPROXIMATE APPROXIMATE}:</td>
     *       <td>Same as {@code IGNORE_METADATA}, with some tolerance threshold on numerical values.</td></tr>
     *   <tr><td>{@link ComparisonMode#ALLOW_VARIANT ALLOW_VARIANT}:</td>
     *       <td>Same as {@code APPROXIMATE}, but ignores coordinate system axes.</td></tr>
     *   <tr><td>{@link ComparisonMode#DEBUG DEBUG}:</td>
     *        <td>Special mode for figuring out why two objects expected to be equal are not.</td></tr>
     * </table>
     *
     * The main guideline is that if {@code sourceCRS.equals(targetCRS, IGNORE_METADATA)} returns {@code true},
     * then the transformation from {@code sourceCRS} to {@code targetCRS} should be the identity transform
     * even if the two CRS do not have the same name.
     *
     * <h4>When object name matter</h4>
     * Some subclasses (especially
     * {@link org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis},
     * {@link org.apache.sis.referencing.datum.AbstractDatum} and
     * {@link org.apache.sis.parameter.DefaultParameterDescriptor}) will compare the
     * {@linkplain #getName() name} even in {@code IGNORE_METADATA} mode,
     * because objects of those types with different names have completely different meaning.
     * For example nothing differentiate the {@code "semi_major"} and {@code "semi_minor"} parameters except the name.
     * The name comparison may be lenient however, i.e. the rules may accept a name matching an alias.
     * See {@link #isHeuristicMatchForName(String)} for more information.
     *
     * <h4>Conformance to the <code>equals(Object)</code> method contract</h4>
     * {@link ComparisonMode#STRICT} is the only mode compliant with the {@link Object#equals(Object)} contract.
     * For all other modes, the comparison is not guaranteed to be <cite>symmetric</cite> neither
     * <cite>transitive</cite>. See {@link LenientComparable#equals(Object, ComparisonMode) LenientComparable}
     * for more information.
     *
     * @param  object  the object to compare to {@code this}.
     * @param  mode    the strictness level of the comparison.
     * @return {@code true} if both objects are equal according the given comparison mode.
     *
     * @see #computeHashCode()
     * @see org.apache.sis.util.Utilities#deepEquals(Object, Object, ComparisonMode)
     */
    @Override
    public boolean equals(final Object object, final ComparisonMode mode) {
        if (object == null) {
            return false;
        }
        switch (mode) {
            case STRICT: {
                if (getClass() != object.getClass()) {
                    return false;
                }
                final AbstractIdentifiedObject that = (AbstractIdentifiedObject) object;
                /*
                 * If the hash codes were cached for both objects, opportunistically compare them.
                 * This is an efficient way to quickly check if the two objects are different
                 * before the more extensive check below.
                 */
                if (mode == ComparisonMode.STRICT) {
                    final int tc = hashCode;
                    if (tc != 0) {
                        final int oc = that.hashCode;
                        if (oc != 0 && tc != oc) {
                            return false;
                        }
                    }
                }
                return Objects.equals(name, that.name) &&
                       nonNull(alias).equals(nonNull(that.alias)) &&
                       nonNull(identifiers).equals(nonNull(that.identifiers)) &&
                       Objects.equals(remarks, that.remarks);
            }
            case BY_CONTRACT: {
                if (!implementsSameInterface(object)) {
                    return false;
                }
                final IdentifiedObject that = (IdentifiedObject) object;
                return deepEquals(getName(),        that.getName(),        mode) &&
                       deepEquals(getAlias(),       that.getAlias(),       mode) &&
                       deepEquals(getIdentifiers(), that.getIdentifiers(), mode) &&
                       deepEquals(getRemarks(),     that.getRemarks(),     mode);
            }
            case IGNORE_METADATA:
            case APPROXIMATE:
            case ALLOW_VARIANT:
            case DEBUG: {
                return implementsSameInterface(object);
            }
            default: {
                throw new IllegalArgumentException(Errors.format(
                        Errors.Keys.UnknownEnumValue_2, ComparisonMode.class, mode));
            }
        }
    }

    /**
     * Returns {@code true} if the given object implements the same GeoAPI interface than this object.
     */
    private boolean implementsSameInterface(final Object object) {
        final Class<? extends IdentifiedObject> type = getInterface();
        if (object instanceof AbstractIdentifiedObject) {
            return ((AbstractIdentifiedObject) object).getInterface() == type;
        }
        /*
         * Fallback for non-SIS implementations.
         */
        if (type.isInstance(object)) {
            final Class<? extends IdentifiedObject>[] t = Classes.getLeafInterfaces(object.getClass(), type);
            if (t.length == 1 && t[0] == type) {
                return true;
            }
        }
        return false;
    }

    /**
     * Compares the specified object with this object for equality.
     * This method is implemented as below (omitting assertions):
     *
     * {@preformat java
     *     return equals(other, ComparisonMode.STRICT);
     * }
     *
     * Subclasses shall override {@link #equals(Object, ComparisonMode)} instead of this method.
     *
     * @param  object  the other object (may be {@code null}).
     * @return {@code true} if both objects are equal.
     */
    @Override
    public final boolean equals(final Object object) {
        final boolean eq = equals(object, ComparisonMode.STRICT);
        // If objects are equal, then they must have the same hash code value.
        assert !eq || hashCode() == object.hashCode() : this;
        return eq;
    }

    /**
     * Returns a hash value for this identified object. Two {@code AbstractIdentifiedObject} instances
     * for which {@link #equals(Object)} returns {@code true} shall have the same hash code value, if
     * the hash codes are computed on the same JVM instance for both objects. The hash code value is
     * <em>not</em> guaranteed to be stable between different versions of the Apache SIS library, or
     * between libraries running on different JVM.
     *
     * <h4>Implementation note</h4>
     * This method invokes {@link #computeHashCode()} when first needed, then caches the result.
     * Subclasses shall override {@link #computeHashCode()} instead of this method.
     *
     * @return the hash code value. This value may change in any future Apache SIS version.
     */
    @Override
    public final int hashCode() {                       // No need to synchronize; ok if invoked twice.
        int hash = hashCode;
        if (hash == 0) {
            hash = Long.hashCode(computeHashCode());
            if (hash == 0) {
                hash = -1;
            }
            hashCode = hash;
        }
        assert hash == -1 || hash == Long.hashCode(computeHashCode()) : hash;
        return hash;
    }

    /**
     * Invoked by {@link #hashCode()} for computing the hash code when first needed.
     * This method is invoked at most once in normal execution, or an arbitrary amount of times if Java
     * assertions are enabled. The hash code value shall never change during the whole lifetime of this
     * object in a JVM. The hash code value does not need to be the same in two different executions of
     * the JVM.
     *
     * <h4>Overriding</h4>
     * Subclasses can override this method for using more properties in hash code calculation.
     * All {@code computeHashCode()} methods shall invoke {@code super.computeHashCode()},
     * <strong>not</strong> {@code hashCode()}. Example:
     *
     * {@preformat java
     *     &#64;Override
     *     protected long computeHashCode() {
     *         return super.computeHashCode() + 31 * Objects.hash(myProperties);
     *     }
     * }
     *
     * @return the hash code value. This value may change in any future Apache SIS version.
     */
    protected long computeHashCode() {
        return Objects.hash(name, nonNull(alias), nonNull(identifiers), remarks) ^ getInterface().hashCode();
    }

    /**
     * Formats the inner part of the <cite>Well Known Text</cite> (WKT) representation for this object.
     * The default implementation writes the following elements:
     *
     * <ul>
     *   <li>The object {@linkplain #getName() name}.</li>
     * </ul>
     *
     * Keywords and metadata (scope, extent, identifier and remarks) shall not be formatted here.
     * For example if this formattable element is for a {@code GeodeticCRS[…]} element,
     * then subclasses shall write the content starting at the insertion point shown below:
     *
     * <div class="horizontal-flow">
     * <div><p><b>WKT example</b></p>
     * {@preformat text
     *   GeodeticCRS["WGS 84", ID["EPSG", 4326]]
     *                       ↑
     *               (insertion point)
     * }
     * </div><div>
     * <p><b>Java code example</b></p>
     * {@preformat java
     *     super.formatTo(formatter);
     *     // ... write the elements at the insertion point ...
     *     return "GeodeticCRS";
     * }
     * </div></div>
     *
     * <h4>Formatting non-standard WKT</h4>
     * If the implementation can not represent this object without violating some WKT constraints,
     * it can uses its own (non-standard) keywords but shall declare that it did so by invoking one
     * of the {@link Formatter#setInvalidWKT(IdentifiedObject, Exception) Formatter.setInvalidWKT(…)}
     * methods.
     *
     * <p>Alternatively, the implementation may also have no WKT keyword for this object.
     * In such case, this method shall return {@code null}.</p>
     *
     * @param  formatter  the formatter where to format the inner content of this WKT element.
     * @return the {@linkplain org.apache.sis.io.wkt.KeywordCase#CAMEL_CASE CamelCase} keyword
     *         for the WKT element, or {@code null} if unknown.
     *
     * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#21">WKT 2 specification §7</a>
     */
    @Override
    protected String formatTo(final Formatter formatter) {
        WKTUtilities.appendName(this, formatter, ElementKind.forType(getClass()));
        return null;
    }

    /**
     * Formats the name or identifier of this object using the provider formatter.
     * This method is invoked when an {@code IdentifiedObject} object is formatted
     * using the {@code "%s"} conversion specifier of {@link java.util.Formatter}.
     * Users don't need to invoke this method explicitly.
     *
     * <p>If the alternate flags is present (as in {@code "%#s"}), then this method
     * will format the identifier (if present) instead of the object name.</p>
     *
     * @param  formatter  the formatter in which to format this identified object.
     * @param  flags      whether to apply left alignment, use upper-case letters and/or use alternate form.
     * @param  width      minimal number of characters to write, padding with {@code ' '} if necessary.
     * @param  precision  maximal number of characters to write, or -1 if no limit.
     *
     * @see IdentifiedObjects#getName(IdentifiedObject, Citation)
     * @see IdentifiedObjects#getIdentifierOrName(IdentifiedObject)
     *
     * @since 1.1
     */
    @Override
    public void formatTo(final java.util.Formatter formatter, final int flags, final int width, final int precision) {
        final String value;
        if ((flags & FormattableFlags.ALTERNATE) != 0) {
            value = IdentifiedObjects.getIdentifierOrName(this);
        } else {
            value = IdentifiedObjects.getDisplayName(this, formatter.locale());
        }
        Strings.formatTo(formatter, flags, width, precision, value);
    }




    //////////////////////////////////////////////////////////////////////////////////////////////////
    ////////                                                                                  ////////
    ////////                               XML support with JAXB                              ////////
    ////////                                                                                  ////////
    ////////        The following methods are invoked by JAXB using reflection (even if       ////////
    ////////        they are private) or are helpers for other methods invoked by JAXB.       ////////
    ////////        Those methods can be safely removed if Geographic Markup Language         ////////
    ////////        (GML) support is not needed.                                              ////////
    ////////                                                                                  ////////
    //////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Constructs a new object in which every attributes are set to a null value.
     * <strong>This is not a valid object.</strong> This constructor is strictly
     * reserved to JAXB, which will assign values to the fields using reflexion.
     */
    AbstractIdentifiedObject() {
        deprecated = false;
    }

    /**
     * The {@code gml:id}, which is mandatory. The current implementation searches for the first identifier,
     * regardless its authority. If no identifier is found, then the name or aliases are used. If none of the
     * above is found (which should not occur for valid objects), then this method returns {@code null}.
     *
     * <p>If an identifier or a name has been found, this method returns the concatenation of the following
     * elements separated by hyphens:</p>
     * <ul>
     *   <li>The code space in lower case, retaining only characters that are valid for Unicode identifiers.</li>
     *   <li>The object type as defined in OGC's URN (see {@link org.apache.sis.internal.util.DefinitionURI})</li>
     *   <li>The object code, retaining only characters that are valid for Unicode identifiers.</li>
     * </ul>
     *
     * Example: {@code "epsg-crs-4326"}.
     *
     * <p>The returned ID needs to be unique only in the XML document being marshalled.
     * Consecutive invocations of this method do not need to return the same value,
     * since it may depends on the marshalling context.</p>
     */
    @XmlID
    @XmlSchemaType(name = "ID")
    @XmlAttribute(name = "id", namespace = Namespaces.GML, required = true)
    @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
    final String getID() {
        // Implementation is provided in the NameIterator class for reducing the size of
        // AbstractIdentifiedObject.class file in the common case where XML is not needed.
        return NameIterator.getID(Context.current(), this, name, alias, identifiers);
    }

    /**
     * Invoked by JAXB at unmarhalling time for specifying the value of the {@code gml:id} attribute.
     * That GML identifier is not actually stored in this {@code AbstractIdentifiedObject}
     * since we rather generate it dynamically from the ISO 19111 identifiers. But we still
     * need to declare that identifier to our unmarshaller context, in case it is referenced
     * from elsewhere in the XML document.
     */
    private void setID(final String id) {
        final Context context = Context.current();
        if (!Context.setObjectForID(context, this, id)) {
            Context.warningOccured(context, getClass(), "setID", Errors.class, Errors.Keys.DuplicatedIdentifier_1, id);
        }
    }

    /**
     * Returns a single element from the {@code Set<Identifier>} collection, or {@code null} if none.
     * We have to define this method because ISO 19111 defines the {@code identifiers} property as a collection
     * while GML 3.2 defines it as a singleton.
     *
     * <p>This method searches for the following identifiers, in preference order:</p>
     * <ul>
     *   <li>The first identifier having a code that begin with {@code "urn:"}.</li>
     *   <li>The first identifier having a code that begin with {@code "http:"}.</li>
     *   <li>The first identifier, converted to the {@code "urn:} syntax if possible.</li>
     * </ul>
     */
    @XmlElement(required = true)
    final Code getIdentifier() {
        return Code.forIdentifiedObject(getClass(), identifiers);
    }

    /**
     * Invoked by JAXB at unmarshalling time for setting the identifier.
     */
    private void setIdentifier(final Code identifier) {
        if (identifiers == null) {
            if (identifier != null) {
                final Identifier id = identifier.getIdentifier();
                if (id != null) {
                    identifiers = Collections.singleton(id);
                }
            }
        } else {
            MetadataUtilities.propertyAlreadySet(AbstractIdentifiedObject.class, "setIdentifier", "identifier");
        }
    }

    /**
     * Returns the {@link #name} and all aliases which are also instance of {@link Identifier}.
     * The latter happen often in SIS implementation since many aliases are instance of {@link NamedIdentifier}.
     *
     * <p>The returned collection is <cite>live</cite>: adding elements in that collection will modify this
     * {@code AbstractIdentifiedObject} instance. This is needed for unmarshalling with JAXB and should not
     * be used in other context.</p>
     *
     * <h4>Why there is no <code>setNames(…)</code> method</h4>
     * Some JAXB implementations never invoke setter method for collections. Instead they invoke the getter and
     * add directly the identifiers in the returned collection. Whether JAXB will perform or not a final call to
     * {@code setNames(…)} is JAXB-implementation dependent (JDK7 does but JDK6 and JDK8 early access do not).
     * It seems a more portable approach (at least for JAXB reference implementations) to design our class
     * without setter method, in order to have the same behavior on all supported JDK versions.
     *
     * @see <a href="https://java.net/jira/browse/JAXB-488">JAXB-488</a>
     */
    @XmlElement(name = "name", required = true)
    final Collection<Identifier> getNames() {
        return new Names();
    }

    /**
     * A writable view over the {@linkplain AbstractIdentifiedObject#getName() name} of the enclosing object followed
     * by all {@linkplain AbstractIdentifiedObject#getAlias() aliases} which are instance of {@link Identifier}.
     * Used by JAXB only at (un)marshalling time because GML merges the name and aliases in a single {@code <gml:name>}
     * property.
     *
     * <h4>Why we do not use {@code Identifier[]} array instead</h4>
     * It would be easier to define a {@code getNames()} method returning all identifiers in an array, and let JAXB
     * invoke {@code setNames(Identifier[])} at unmarshalling time.  But methods expecting an array in argument are
     * invoked by JAXB only after the full element has been unmarshalled. For some {@code AbstractIdentifiedObject}
     * subclasses, this is too late. For example {@code DefaultOperationMethod} may need to know the operation name
     * before to parse the parameters.
     */
    private final class Names extends AbstractCollection<Identifier> {
        /**
         * Invoked by JAXB before to write in the collection at unmarshalling time.
         * Do nothing since our object is already empty.
         */
        @Override
        public void clear() {
        }

        /**
         * Returns the number of name and aliases that are instance of {@link Identifier}.
         */
        @Override
        public int size() {
            return NameIterator.count(AbstractIdentifiedObject.this);
        }

        /**
         * Returns an iterator over the name and aliases that are instance of {@link Identifier}.
         */
        @Override
        public Iterator<Identifier> iterator() {
            return new NameIterator(AbstractIdentifiedObject.this);
        }

        /**
         * Invoked by JAXB at unmarshalling time for each identifier. The first identifier will be taken
         * as the name and all other identifiers (if any) as aliases.
         *
         * <p>Some (but not all) JAXB implementations never invoke setter method for collections.
         * Instead they invoke {@link AbstractIdentifiedObject#getNames()} and add directly the identifiers
         * in the returned collection. Consequently this method must writes directly in the enclosing object.
         * See <a href="https://java.net/jira/browse/JAXB-488">JAXB-488</a> for more information.</p>
         */
        @Override
        public boolean add(final Identifier id) {
            if (NameIterator.isUnnamed(name)) {
                name = id;
            } else {
                /*
                 * Our Code and RS_Identifier implementations should always create NamedIdentifier instance,
                 * so the `instanceof` check should not be necessary. But we do a paranoiac check anyway.
                 */
                final GenericName n = id instanceof GenericName ? (GenericName) id : new NamedIdentifier(id);
                if (alias == null) {
                    alias = Collections.singleton(n);
                } else {
                    /*
                     * This implementation is inefficient since each addition copies the array, but we rarely
                     * have more than two aliases.  This implementation is okay for a small number of aliases
                     * and ensures that the enclosing AbstractIdentifiedObject is unmodifiable except by this
                     * add(…) method.
                     *
                     * Note about alternative approaches
                     * ---------------------------------
                     * An alternative approach could be to use an ArrayList and replace it by an unmodifiable
                     * list only after unmarshalling (using an afterUnmarshal(Unmarshaller, Object) method),
                     * but we want to avoid Unmarshaller dependency (for reducing classes loading for users
                     * who are not interrested in XML) and it may actually be less efficient for the vast
                     * majority of cases where there is less than 3 aliases.
                     */
                    final int size = alias.size();
                    final GenericName[] names = alias.toArray(new GenericName[size + 1]);
                    names[size] = n;
                    alias = UnmodifiableArrayList.wrap(names);
                }
            }
            return true;
        }
    }

    /**
     * Invoked by JAXB for setting the remarks.
     *
     * @see #getRemarks()
     */
    private void setRemarks(final InternationalString value) {
        if (remarks == null) {
            remarks = value;
        } else {
            MetadataUtilities.propertyAlreadySet(AbstractIdentifiedObject.class, "setRemarks", "remarks");
        }
    }
}
