/*
 * 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.List;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.lang.reflect.Type;
import java.lang.reflect.ParameterizedType;
import org.opengis.util.NameSpace;
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.IdentifiedObject;
import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.metadata.iso.citation.Citations;
import org.apache.sis.internal.referencing.DeprecatedCode;
import org.apache.sis.internal.referencing.DeprecatedName;
import org.apache.sis.util.iso.Types;
import org.apache.sis.util.Deprecable;
import org.apache.sis.util.resources.Errors;

import static org.apache.sis.util.ArgumentChecks.*;

// Branch-dependent imports
import org.opengis.referencing.ReferenceIdentifier;


/**
 * Base class of builders for various kind of {@link IdentifiedObject}. This class provides convenience methods
 * for filling the {@link #properties} map to be given to an {@link org.opengis.referencing.ObjectFactory}.
 * The main properties are:
 *
 * <ul class="verbose">
 *   <li><b>{@linkplain AbstractIdentifiedObject#getName() Name}:</b><br>
 *       each {@code IdentifiedObject} shall have a name, which can be specified by a call to any of the
 *       {@link #addName(CharSequence) addName(…)} methods defined in this class.</li>
 *
 *   <li><b>{@linkplain AbstractIdentifiedObject#getAlias() Aliases}:</b><br>
 *       {@code IdentifiedObject}s can optionally have an arbitrary amount of aliases, which are also specified
 *       by the {@code addName(…)} methods. Each call after the first one adds an alias.</li>
 *
 *   <li><b>{@linkplain AbstractIdentifiedObject#getIdentifiers() Identifiers}:</b><br>
 *       {@code IdentifiedObject}s can also have an arbitrary amount of identifiers, which are specified by any
 *       of the {@link #addIdentifier(String) addIdentifier(…)} methods. Like names, more than one identifier
 *       can be added by invoking the method many time.</li>
 *
 *   <li><b>{@linkplain ImmutableIdentifier#getCodeSpace() Code space}:</b><br>
 *       {@code IdentifiedObject} names and identifiers can be local to a code space defined by an authority.
 *       Both the authority and code space can be specified by the {@link #setCodeSpace(Citation, String)} method,
 *       and usually (but not necessarily) apply to all {@code Identifier} instances.</li>
 *
 *   <li><b>{@linkplain ImmutableIdentifier#getVersion() Version}:</b><br>
 *       {@code Identifier}s can optionally have a version specified by the {@link #setVersion(String)} method.
 *       The version usually (but not necessarily) applies to all {@code Identifier} instances.</li>
 *
 *   <li><b>{@linkplain ImmutableIdentifier#getDescription() Description}:</b><br>
 *       {@code Identifier}s can optionally have a description specified by the {@link #setDescription(CharSequence)} method.
 *       The description applies only to the next identifier to create.</li>
 *
 *   <li><b>{@linkplain AbstractIdentifiedObject#getRemarks() Remarks}:</b><br>
 *       {@code IdentifiedObject}s can have at most one remark, which is specified by the
 *       {@link #setRemarks(CharSequence) code setRemarks(…)} method.</li>
 * </ul>
 *
 * <div class="section">Namespaces and scopes</div>
 * The {@code addName(…)} and {@code addIdentifier(…)} methods come in three flavors:
 *
 * <ul class="verbose">
 *   <li>The {@link #addIdentifier(String)} and {@link #addName(CharSequence)} methods combine the given argument
 *       with the above-cited authority, code space, version and description information.
 *       The result is a {@linkplain org.apache.sis.util.iso.DefaultLocalName local name} or identifier,
 *       in which the code space information is stored but not shown by the {@code toString()} method.</li>
 *
 *   <li>The {@link #addIdentifier(Citation, String)} and {@link #addName(Citation, CharSequence)} methods use the given
 *       {@link Citation} argument, ignoring any authority or code space information given to this {@code Builder}.
 *       The result is a {@linkplain org.apache.sis.util.iso.DefaultScopedName scoped name} or identifier,
 *       in which the code space information is shown by the {@code toString()} method.</li>
 *
 *   <li>The {@code addIdentifier(Identifier)}, {@code addName(Identifier)} and {@link #addName(GenericName)}
 *       methods take the given object <cite>as-is</cite>. Any authority, code space, version or description
 *       information given to the {@code Builder} are ignored.</li>
 * </ul>
 *
 * <div class="note"><b>Example:</b>
 * The EPSG database defines a projection named <cite>"Mercator (variant A)"</cite> (EPSG:9804).
 * This projection was named <cite>"Mercator (1SP)"</cite> in older EPSG database versions.
 * The same projection was also named "{@code Mercator_1SP}" by OGC some specifications.
 * If we choose EPSG as our primary naming authority, then those three names can be declared as below:
 *
 * {@preformat java
 *   builder.setCodespace (Citations.EPSG, "EPSG")
 *          .addName("Mercator (variant A)")
 *          .addName("Mercator (1SP)")
 *          .addName(Citations.OGC, "Mercator_1SP")
 * }
 *
 * The {@code toString()} representation of those three names are {@code "Mercator (variant A)"},
 * {@code "Mercator (1SP)"} (note the absence of {@code "EPSG:"} prefix, which is stored as the
 * name {@linkplain org.apache.sis.util.iso.DefaultLocalName#scope() scope} but not shown) and
 * <code>"<b>OGC:</b>Mercator_1SP"</code> respectively.</div>
 *
 *
 * <div class="section">Builder property lifetimes</div>
 * Some complex objects require the creation of many components. For example constructing a
 * {@linkplain org.apache.sis.referencing.crs.AbstractCRS Coordinate Reference System} (CRS) may require constructing a
 * {@linkplain org.apache.sis.referencing.cs.AbstractCS coordinate system}, a
 * {@linkplain org.apache.sis.referencing.datum.AbstractDatum datum} and an
 * {@linkplain org.apache.sis.referencing.datum.DefaultEllipsoid ellipsoid} among other components.
 * However all those components often (but not necessarily) share the same authority, code space and version information.
 * In order to simplify that common usage, two groups of properties have different lifetimes in the {@code Builder} class:
 *
 * <ul>
 *   <li>
 *     {@linkplain NamedIdentifier#getAuthority() Authority},
 *     {@linkplain NamedIdentifier#getCodeSpace() code space} and
 *     {@linkplain NamedIdentifier#getVersion()   version}:<br>
 *     Kept until they are specified again, because those properties are typically shared by all components.
 *   </li><li>
 *     {@linkplain AbstractIdentifiedObject#getName()        Name},
 *     {@linkplain AbstractIdentifiedObject#getAlias()       aliases},
 *     {@linkplain AbstractIdentifiedObject#getIdentifiers() identifiers},
 *     {@linkplain ImmutableIdentifier#getDescription()      description} and
 *     {@linkplain AbstractIdentifiedObject#getRemarks()     remarks}:<br>
 *     Cleared after each call to a {@code createXXX(…)} method, because those properties are usually specific
 *     to a particular {@code IdentifiedObject} or {@code Identifier} instance.
 *   </li>
 * </ul>
 *
 * <div class="section">Usage examples</div>
 * See {@link org.apache.sis.parameter.ParameterBuilder} class javadoc for more examples with the
 * <cite>Mercator</cite> projection parameters.
 *
 * <div class="section">Note for subclass implementers</div>
 * <ul>
 *   <li>The type {@code <B>} shall be exactly the subclass type.
 *       For performance reasons, this is verified only if Java assertions are enabled.</li>
 *   <li>All {@code createXXX(…)} methods shall invoke {@link #onCreate(boolean)} before and after
 *       usage of {@link #properties} map by the factory.</li>
 * </ul>
 *
 * <div class="note"><b>Example:</b>
 * {@preformat java
 *     public class MyBuilder extends Builder<MyBuilder> {
 *         public Foo createFoo() {
 *             onCreate(false);
 *             Foo foo = factory.createFoo(properties);
 *             onCreate(true);
 *             return foo;
 *         }
 *     }
 * }
 * </div>
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 0.8
 *
 * @param <B>  the builder subclass.
 *
 * @since 0.4
 * @module
 */
public abstract class Builder<B extends Builder<B>> {
    /**
     * The properties to be given to {@link org.opengis.referencing.ObjectFactory} methods.
     * This map may contain values for the
     * {@value org.opengis.referencing.IdentifiedObject#NAME_KEY},
     * {@value org.opengis.referencing.IdentifiedObject#ALIAS_KEY},
     * {@value org.opengis.referencing.IdentifiedObject#IDENTIFIERS_KEY} and
     * {@value org.opengis.referencing.IdentifiedObject#REMARKS_KEY} keys.
     * Subclasses may add other entries like
     * {@value org.opengis.referencing.ReferenceSystem#DOMAIN_OF_VALIDITY_KEY} and
     * {@value org.opengis.referencing.ReferenceSystem#SCOPE_KEY} keys.
     *
     * <p>See <cite>Notes for subclass implementers</cite> in class javadoc for usage conditions.</p>
     *
     * @see #onCreate(boolean)
     */
    protected final Map<String,Object> properties;

    /**
     * A temporary list for aliases, before to assign them to the {@link #properties}.
     */
    private final List<GenericName> aliases;

    /**
     * A temporary list for identifiers, before to assign them to the {@link #properties}.
     */
    private final List<ReferenceIdentifier> identifiers;

    /**
     * The codespace as a {@code NameSpace} object, or {@code null} if not yet created.
     * This object is built from the "codespace" value when first needed.
     */
    private transient NameSpace namespace;

    /**
     * The name factory, fetched when first needed.
     *
     * @see #factory()
     */
    private transient NameFactory nameFactory;

    /**
     * Creates a new builder.
     */
    protected Builder() {
        assert verifyParameterizedType(getClass());
        properties  = new HashMap<>(8);
        aliases     = new ArrayList<>();  // Will often stay empty (default constructor handles those cases well).
        identifiers = new ArrayList<>();
    }

    /**
     * Verifies that {@code B} in {@code <B extends Builder<B>} is the expected class.
     * This method is for assertion purposes only.
     */
    private static boolean verifyParameterizedType(final Class<?> expected) {
        for (Class<?> c = expected; c != null; c = c.getSuperclass()) {
            Type type = c.getGenericSuperclass();
            if (type instanceof ParameterizedType) {
                final ParameterizedType p = (ParameterizedType) type;
                if (p.getRawType() == Builder.class) {
                    type = p.getActualTypeArguments()[0];
                    if (type == expected) return true;
                    throw new AssertionError(type);
                }
            }
        }
        return false;
    }

    /**
     * Returns {@code this} casted to {@code <B>}. The cast is valid if the assertion performed
     * at construction time passes. Since the {@code <B>} type is hard-coded in the source code,
     * if the JUnit test passes then the cast should always be valid for all instances of the
     * same builder class.
     */
    @SuppressWarnings("unchecked")
    private B self() {
        return (B) this;
    }

    /**
     * Creates a new builder initialized to properties of the given object.
     * The properties recognized by this constructor are documented
     * {@linkplain IdentifiedObjects#getProperties(IdentifiedObject, String...) here}.
     *
     * @param object  the identified object from which to inherit properties, or {@code null}.
     *
     * @since 0.6
     */
    protected Builder(final IdentifiedObject object) {
        this();
        if (object != null) {
            properties.putAll(IdentifiedObjects.getProperties(object));
            final GenericName[] valueAlias = (GenericName[]) properties.remove(IdentifiedObject.ALIAS_KEY);
            final ReferenceIdentifier[] valueIds = (ReferenceIdentifier[])  properties.remove(IdentifiedObject.IDENTIFIERS_KEY);
            if (valueAlias != null) aliases.addAll(Arrays.asList(valueAlias));
            if (valueIds != null) identifiers.addAll(Arrays.asList(valueIds));
        }
    }

    /**
     * Returns the name factory to use for creating namespaces and local names.
     * The factory will be fetched when first needed, and while not change anymore
     * for the rest of this {@code Builder} lifetime.
     */
    private NameFactory factory() {
        if (nameFactory == null) {
            nameFactory = DefaultFactories.forBuildin(NameFactory.class);
        }
        return nameFactory;
    }

    /**
     * Creates or returns an existing name for the given string in the current namespace.
     * The namespace may be cleared at anytime by a call to {@link #setCodeSpace(Citation, String)}.
     */
    private GenericName createName(final CharSequence name) {
        final NameFactory factory = factory();
        if (namespace == null) {
            final String codespace = getCodeSpace();
            if (codespace != null) {
                namespace = factory.createNameSpace(factory.createLocalName(null, codespace), null);
            }
        }
        return factory.createLocalName(namespace, name);
    }

    /**
     * Creates or returns an existing name for the given string in the given namespace.
     */
    private GenericName createName(final Citation authority, final CharSequence name) {
        if (authority == getAuthority()) {
            return createName(name);
        } else {
            return new NamedIdentifier(authority, name);
        }
    }

    /**
     * Creates an identifier for the given authority. If and only if the given authority is the default one,
     * then the new identifier will also contain the user-supplied code space and version (if any).
     * The new identifier will be marked as deprecated if {@link #isDeprecated()} returns {@code true}.
     */
    private ReferenceIdentifier createIdentifier(final Citation authority, final String identifier) {
        final String codeSpace;
        final String version;
        if (authority == getAuthority()) {
            codeSpace  = getCodeSpace();
            version    = getVersion();
        } else {
            // Do not use the version information since it applies to the default authority rather than the given one.
            codeSpace = Citations.toCodeSpace(authority);
            version   = null;
        }
        return createIdentifier(authority, codeSpace, identifier, version);
    }

    /**
     * Creates an identifier for the given authority, code space and version.
     * The new identifier will be marked as deprecated if {@link #isDeprecated()} returns {@code true}.
     */
    private ReferenceIdentifier createIdentifier(final Citation authority,
            final String codeSpace, final String identifier, final String version)
    {
        if (isDeprecated()) {
            return new DeprecatedCode(authority, codeSpace, identifier, version, null, getRemarks());
        } else {
            return new ImmutableIdentifier(authority, codeSpace, identifier, version, getDescription());
        }
    }

    /**
     * Converts the given name into an identifier. Note that {@link NamedIdentifier}
     * implements both {@link GenericName} and {@link Identifier} interfaces.
     */
    private static ReferenceIdentifier toIdentifier(final GenericName name) {
        return (name instanceof ReferenceIdentifier) ? (ReferenceIdentifier) name : new NamedIdentifier(name);
    }

    /**
     * Sets the property value for the given key, if a change is still possible. The check for change permission
     * is needed for all keys defined in the {@link Identifier} interface. This check is not needed for other keys,
     * so callers do not need to invoke this method for other keys.
     *
     * @param  key    the key of the property to set.
     * @param  value  the value to set.
     * @return {@code true} if the property changed as a result of this method call.
     * @throws IllegalStateException if a new value is specified in a phase where the value can not be changed.
     */
    private boolean setProperty(final String key, final Object value) throws IllegalStateException {
        final Object previous = properties.putIfAbsent(key, value);
        if (previous != null) {
            if (previous.equals(value)) {
                return false;
            }
            if (properties.get(IdentifiedObject.NAME_KEY) != null) {
                throw new IllegalStateException(Errors.getResources(properties)
                        .getString(Errors.Keys.ValueAlreadyDefined_1, key));
            }
            properties.put(key, value);
        }
        return true;
    }

    /**
     * Returns the value of the first argument given by the last call to {@link #setCodeSpace(Citation, String)},
     * or {@code null} if none. The default value is {@code null}.
     *
     * @return the citation specified by the last call to {@code setCodeSpace(…)}, or {@code null} if none.
     *
     * @since 0.6
     */
    private Citation getAuthority() {
        return (Citation) properties.get(Identifier.AUTHORITY_KEY);
    }

    /**
     * Returns the value of the last argument given by the last call to {@link #setCodeSpace(Citation, String)},
     * or {@code null} if none. The default value is {@code null}.
     *
     * @return the string specified by the last call to {@code setCodeSpace(…)}, or {@code null} if none.
     *
     * @since 0.6
     */
    private String getCodeSpace() {
        return (String) properties.get(ReferenceIdentifier.CODESPACE_KEY);
    }

    /**
     * Sets the {@code Identifier} authority and code space.
     * The code space is often the authority's abbreviation, but not necessarily.
     *
     * <div class="note"><b>Example:</b> Coordinate Reference System (CRS) objects identified by codes from the
     * EPSG database are maintained by the <cite>International Association of Oil &amp; Gas producers</cite> (IOGP)
     * authority, but the code space is {@code "EPSG"} for historical reasons.</div>
     *
     * This method is typically invoked only once, since a compound object often uses the same code space
     * for all individual components.
     *
     * <p><b>Condition:</b>
     * this method can not be invoked after one or more names or identifiers have been added (by calls to the
     * {@code addName(…)} or {@code addIdentifier(…)} methods) for the next object to create. This method can be
     * invoked again after the name, aliases and identifiers have been cleared by a call to {@code createXXX(…)}.</p>
     *
     * <p><b>Lifetime:</b>
     * this property is kept unchanged until this {@code setCodeSpace(…)} method is invoked again.</p>
     *
     * @param  authority  bibliographic reference to the authority defining the codes, or {@code null} if none.
     * @param  codespace  the {@code IdentifiedObject} codespace, or {@code null} for inferring it from the authority.
     * @return {@code this}, for method call chaining.
     * @throws IllegalStateException if {@code addName(…)} or {@code addIdentifier(…)} has been invoked at least
     *         once since builder construction or since the last call to a {@code createXXX(…)} method.
     *
     * @see ImmutableIdentifier#getAuthority()
     * @see ImmutableIdentifier#getCodeSpace()
     */
    public B setCodeSpace(final Citation authority, final String codespace) {
        if (!setProperty(ReferenceIdentifier.CODESPACE_KEY, codespace)) {
            namespace = null;
        }
        setProperty(Identifier.AUTHORITY_KEY, authority);
        return self();
    }

    /**
     * Returns the value given by the last call to {@link #setVersion(String)}, or {@code null} if none.
     * The default value is {@code null}.
     *
     * @return the value specified by the last call to {@code setVersion(…)}, or {@code null} if none.
     *
     * @since 0.6
     */
    private String getVersion() {
        return (String) properties.get(ReferenceIdentifier.VERSION_KEY);
    }

    /**
     * Sets the {@code Identifier} version of object definitions. This method is typically invoked only once,
     * since a compound object often uses the same version for all individual components.
     *
     * <p><b>Condition:</b>
     * this method can not be invoked after one or more names or identifiers have been added (by calls to the
     * {@code addName(…)} or {@code addIdentifier(…)} methods) for the next object to create. This method can be
     * invoked again after the name, aliases and identifiers have been cleared by a call to {@code createXXX(…)}.</p>
     *
     * <p><b>Lifetime:</b>
     * this property is kept unchanged until this {@code setVersion(…)} method is invoked again.</p>
     *
     * @param  version  the version of code definitions, or {@code null} if none.
     * @return {@code this}, for method call chaining.
     * @throws IllegalStateException if {@code addName(…)} or {@code addIdentifier(…)} has been invoked at least
     *         once since builder construction or since the last call to a {@code createXXX(…)} method.
     */
    public B setVersion(final String version) {
        setProperty(ReferenceIdentifier.VERSION_KEY, version);
        return self();
    }

    /**
     * Adds an {@code IdentifiedObject} name given by a {@code String} or {@code InternationalString}.
     * The given string will be combined with the authority, {@linkplain #setCodeSpace(Citation, String)
     * code space} and {@linkplain #setVersion(String) version} information for creating the
     * {@link Identifier} or {@link GenericName} object.
     *
     * <div class="section">Name and aliases</div>
     * This method can be invoked many times. The first invocation sets the
     * {@linkplain AbstractIdentifiedObject#getName() primary name}, and
     * all subsequent invocations add an {@linkplain AbstractIdentifiedObject#getAlias() alias}.
     *
     * <div class="section">Deprecated names</div>
     * Some names may exist for historical reasons but have their use discouraged.
     * If <code>{@linkplain #setDeprecated(boolean) setDeprecated}(true)</code> has been invoked, then this
     * method creates a deprecated alias with the current {@linkplain #setRemarks(CharSequence) remarks}.
     * The remark should suggest a replacement, for example with a sentence like
     * <cite>"Superseded by {@literal <new-name>}"</cite>.
     *
     * <p>Note that deprecated names are always added as aliases, never as the primary name of an identified object.</p>
     *
     * <p><b>Lifetime:</b>
     * the name and all aliases are cleared after a {@code createXXX(…)} method has been invoked.</p>
     *
     * @param  name  the {@code IdentifiedObject} name as a {@link String} or {@link InternationalString} instance.
     * @return {@code this}, for method call chaining.
     */
    public B addName(final CharSequence name) {
        ensureNonNull("name", name);
        if (isDeprecated()) {
            aliases.add(new DeprecatedName(getAuthority(), getCodeSpace(), name, getVersion(), getRemarks()));
        } else if (properties.putIfAbsent(IdentifiedObject.NAME_KEY, name.toString()) != null) {
            // A primary name is already present. Add the given name as an alias instead.
            aliases.add(createName(name));
        }
        return self();
    }

    /**
     * Adds an {@code IdentifiedObject} name in an alternative namespace. This method is typically invoked for
     * {@linkplain AbstractIdentifiedObject#getAlias() aliases} defined after the primary name.
     *
     * <div class="note"><b>Example:</b>
     * The <cite>"Longitude of natural origin"</cite> parameter defined by EPSG is named differently
     * by OGC and GeoTIFF. Those alternative names can be defined as below:
     *
     * {@preformat java
     *   builder.setCodespace(Citations.EPSG, "EPSG")          // Sets the default namespace to "EPSG".
     *          .addName("Longitude of natural origin")        // Primary name in builder default namespace.
     *          .addName(Citations.OGC, "central_meridian")    // First alias in "OGC" namespace.
     *          .addName(Citations.GEOTIFF, "NatOriginLong");  // Second alias in "GeoTIFF" namespace.
     * }
     *
     * In this example, {@code "central_meridian"} will be the
     * {@linkplain org.apache.sis.util.iso.DefaultScopedName#tip() tip} and {@code "OGC"} will be the
     * {@linkplain org.apache.sis.util.iso.DefaultScopedName#head() head} of the first alias.</div>
     *
     * <p><b>Lifetime:</b>
     * the name and all aliases are cleared after a {@code createXXX(…)} method has been invoked.</p>
     *
     * @param  authority  bibliographic reference to the authority defining the codes, or {@code null} if none.
     * @param  name       the {@code IdentifiedObject} alias as a name in the namespace of the given authority.
     * @return {@code this}, for method call chaining.
     *
     * @see #addIdentifier(Citation, String)
     */
    public B addName(final Citation authority, final CharSequence name) {
        ensureNonNull("name", name);
        final boolean isDeprecated = isDeprecated();
        if (!isDeprecated && properties.get(IdentifiedObject.NAME_KEY) != null) {
            // A primary name is already present. Add the given name as an alias instead.
            aliases.add(createName(authority, name));
        } else {
            final String codeSpace;
            final String version;
            if (authority == getAuthority()) {
                codeSpace  = getCodeSpace();
                version    = getVersion();
            } else {
                // Do not use the version information since it applies to the default authority rather than the given one.
                codeSpace = Citations.toCodeSpace(authority);
                version   = null;
            }
            if (isDeprecated) {
                aliases.add(new DeprecatedName(authority, codeSpace, name, version, getRemarks()));
            } else {
                properties.put(IdentifiedObject.NAME_KEY,
                        new NamedIdentifier(authority, codeSpace, name, version, getDescription()));
            }
        }
        return self();
    }

    /**
     * Adds an {@code IdentifiedObject} name fully specified by the given identifier.
     * This method ignores the authority, {@linkplain #setCodeSpace(Citation, String) code space},
     * {@linkplain #setVersion(String) version} and {@linkplain #setDescription(CharSequence) description}
     * specified to this builder (if any), since the given identifier may already contain those information.
     *
     * <div class="section">Name and aliases</div>
     * This method can be invoked many times. The first invocation sets the
     * {@linkplain AbstractIdentifiedObject#getName() primary name} to the given value, and
     * all subsequent invocations add an {@linkplain AbstractIdentifiedObject#getAlias() alias}.
     *
     * <p><b>Lifetime:</b>
     * the name and all aliases are cleared after a {@code createXXX(…)} method has been invoked.</p>
     *
     * @param  name  the {@code IdentifiedObject} name as an identifier.
     * @return {@code this}, for method call chaining.
     */
    public B addName(final ReferenceIdentifier name) {
        ensureNonNull("name", name);
        if (properties.putIfAbsent(IdentifiedObject.NAME_KEY, name) != null) {
            // A primary name is already present. Add the given name as an alias instead.
            aliases.add(name instanceof GenericName ? (GenericName) name : new NamedIdentifier(name));
        }
        return self();
    }

    /**
     * Adds an {@code IdentifiedObject} name fully specified by the given generic name.
     * This method ignores the authority, {@linkplain #setCodeSpace(Citation, String) code space},
     * {@linkplain #setVersion(String) version} and {@linkplain #setDescription(CharSequence) description}
     * specified to this builder (if any), since the given generic name may already contain those information.
     *
     * <div class="section">Name and aliases</div>
     * This method can be invoked many times. The first invocation sets the
     * {@linkplain AbstractIdentifiedObject#getName() primary name} to the given value, and
     * all subsequent invocations add an {@linkplain AbstractIdentifiedObject#getAlias() alias}.
     *
     * <p><b>Lifetime:</b>
     * the name and all aliases are cleared after a {@code createXXX(…)} method has been invoked.</p>
     *
     * @param  name  the {@code IdentifiedObject} name as an identifier.
     * @return {@code this}, for method call chaining.
     */
    public B addName(final GenericName name) {
        ensureNonNull("name", name);
        if (properties.get(IdentifiedObject.NAME_KEY) == null) {
            properties.put(IdentifiedObject.NAME_KEY, toIdentifier(name));
        } else {
            aliases.add(name);
        }
        return self();
    }

    /**
     * Adds an {@code IdentifiedObject} identifier given by a {@code String}.
     * The given string will be combined with the authority, {@linkplain #setCodeSpace(Citation, String) code space}
     * {@linkplain #setVersion(String) version} and {@linkplain #setDescription(CharSequence) description} information
     * for creating the {@link Identifier} object.
     *
     * <div class="section">Deprecated identifiers</div>
     * Some identifiers may exist for historical reasons but have their use discouraged.
     * If <code>{@linkplain #setDeprecated(boolean) setDeprecated}(true)</code> has been invoked, then this
     * method creates a deprecated identifier with the current {@linkplain #setRemarks(CharSequence) remarks}.
     * The remark should suggest a replacement, for example with a sentence like
     * <cite>"Superseded by {@literal <new-code>}"</cite>.
     *
     * <p><b>Lifetime:</b>
     * all identifiers are cleared after a {@code createXXX(…)} method has been invoked.</p>
     *
     * @param  identifier  the {@code IdentifiedObject} identifier.
     * @return {@code this}, for method call chaining.
     */
    public B addIdentifier(final String identifier) {
        ensureNonNull("identifier", identifier);
        identifiers.add(createIdentifier(getAuthority(), getCodeSpace(), identifier, getVersion()));
        return self();
    }

    /**
     * Adds an {@code IdentifiedObject} identifier in an alternative namespace.
     * This method is typically invoked in complement to {@link #addName(Citation, CharSequence)}.
     *
     * <p><b>Lifetime:</b>
     * all identifiers are cleared after a {@code createXXX(…)} method has been invoked.</p>
     *
     * @param  authority   bibliographic reference to the authority defining the codes, or {@code null} if none.
     * @param  identifier  the {@code IdentifiedObject} identifier as a code in the namespace of the given authority.
     * @return {@code this}, for method call chaining.
     *
     * @see #addName(Citation, CharSequence)
     */
    public B addIdentifier(final Citation authority, final String identifier) {
        ensureNonNull("identifier", identifier);
        identifiers.add(createIdentifier(authority, identifier));
        return self();
    }

    /**
     * Adds an {@code IdentifiedObject} identifier fully specified by the given identifier.
     * This method ignores the authority, {@linkplain #setCodeSpace(Citation, String) code space},
     * {@linkplain #setVersion(String) version} and {@linkplain #setDescription(CharSequence) description}
     * specified to this builder (if any), since the given identifier already contains those information.
     *
     * <p><b>Lifetime:</b>
     * all identifiers are cleared after a {@code createXXX(…)} method has been invoked.</p>
     *
     * @param  identifier  the {@code IdentifiedObject} identifier.
     * @return {@code this}, for method call chaining.
     */
    public B addIdentifier(final ReferenceIdentifier identifier) {
        ensureNonNull("identifier", identifier);
        identifiers.add(identifier);
        return self();
    }


    /**
     * Returns {@code true} if the given name or identifier is deprecated.
     *
     * @see #isDeprecated()
     */
    private static boolean isDeprecated(final Object object) {
        return (object instanceof Deprecable) && ((Deprecable) object).isDeprecated();
    }

    /**
     * Adds all non-deprecated names and identifiers from the given object.
     * Other properties like description and remarks are ignored.
     *
     * <p>This is a convenience method for using an existing object as a template, before to modify
     * some names by calls to {@link #rename(Citation, CharSequence[])}.</p>
     *
     * @param  object  the object from which to copy the references to names and identifiers.
     * @return {@code this}, for method call chaining.
     *
     * @since 0.6
     */
    public B addNamesAndIdentifiers(final IdentifiedObject object) {
        ensureNonNull("object", object);
        for (final ReferenceIdentifier id : object.getIdentifiers()) {
            if (!isDeprecated(id)) {
                addIdentifier(id);
            }
        }
        ReferenceIdentifier id = object.getName();
        if (!isDeprecated(id)) {
            addName(id);
        }
        for (final GenericName alias : object.getAlias()) {
            if (!isDeprecated(alias)) {
                addName(alias);
            }
        }
        return self();
    }

    /**
     * Replaces the names associated to the given authority by the given new names.
     * More specifically:
     *
     * <ul>
     *   <li>The first occurrence of a name associated to {@code authority} will be replaced by a new name
     *       with the same authority and the local part defined by {@code replacements[0]}.</li>
     *   <li>The second occurrence of a name associated to {@code authority} will be replaced by a new name
     *       with the same authority and the local part defined by {@code replacements[1]}.</li>
     *   <li><i>etc.</i> until one of the following conditions is met:
     *     <ul>
     *       <li>There is no more name associated to the given authority in this {@code Builder}, in which case
     *           new names are inserted for all remaining elements in the {@code replacements} array.</li>
     *       <li>There is no more elements in the {@code replacements} array, in which case all remaining
     *           names associated to the given authority in this {@code Builder} are removed.</li>
     *     </ul>
     *   </li>
     * </ul>
     *
     * This method could also be understood as a {@code setNames(Citation, ...)} method, except that it modifies
     * only the names associated to the given authority and preserves the same order than previous names.
     *
     * @param  authority     the authority of the names to replaces.
     * @param  replacements  the new local parts for the names to replace,
     *         or {@code null} or an empty array for removing all names associated to the given authority.
     * @return {@code this}, for method call chaining.
     *
     * @since 0.6
     */
    public B rename(final Citation authority, final CharSequence... replacements) {
        ensureNonNull("authority", authority);
        final int length = (replacements != null) ? replacements.length : 0;
        /*
         * IdentifiedObjects store the "primary name" separately from aliases. Consequently we will start
         * the iteration at index -1 where i=-1 is used as a sentinel value meaning "primary name" before
         * to iterate over the aliases. Note that the type is not the same:
         *
         *   - Primary:   Identifier or String
         *   - Aliases:   Identifier or GenericName
         */
        int next = 0;
        int insertAt = aliases.size();
        for (int i = -1; i < aliases.size(); i++) {
            final Object old = (i < 0) ? properties.get(IdentifiedObject.NAME_KEY) : aliases.get(i);
            if (old == null) {
                continue;       // Actually only the primary name can be null.
            }
            final boolean wasID = (old instanceof Identifier);   // Usually true even for aliases.
            if (!authority.equals(wasID ? ((Identifier) old).getAuthority() : getAuthority())) {
                continue;       // Current name is not for the authority we are looking for.
            }
            /*
             * Found a name associated to the given authority. Process to the replacement if we still
             * have some elements to take in the 'replacements' array, otherwise remove the name.
             */
            if (next < length) {
                final CharSequence name;
                ensureNonNullElement("replacements", next, name = replacements[next++]);
                /*
                 * If the current name matches the specified replacement, we can leave the name as-is.
                 * Only if the name (in its local part) is not the same, proceed to the replacement.
                 */
                final String code = name.toString();
                if (!code.equals(wasID ? ((Identifier) old).getCode() : old.toString())) {
                    if (i < 0) {
                        properties.put(IdentifiedObject.NAME_KEY,
                                (authority != getAuthority()) ? new NamedIdentifier(authority, name) : code);
                    } else {
                        aliases.set(i, createName(authority, name));
                    }
                    insertAt = i + 1;
                }
            } else {
                if (i < 0) {
                    properties.remove(IdentifiedObject.NAME_KEY);
                } else {
                    aliases.remove(i--);
                }
            }
        }
        /*
         * If there is any remaining elements in the 'replacements' array, insert them right after the last
         * element of the given authority that we found (so we keep together the names of the same authority).
         */
        while (next < length) {
            final CharSequence name;
            ensureNonNullElement("replacements", next, name = replacements[next++]);
            aliases.add(insertAt++, createName(authority, name));
        }
        /*
         * If the primary name has been removed as a result of this method execution,
         * take the first alias as the new primary name.
         */
        if (properties.get(IdentifiedObject.NAME_KEY) == null && !aliases.isEmpty()) {
            properties.put(IdentifiedObject.NAME_KEY, toIdentifier(aliases.remove(0)));
        }
        return self();
    }

    /**
     * Replaces the identifiers associated to the given authority by the given new identifiers.
     * More specifically:
     *
     * <ul>
     *   <li>The first occurrence of an identifier associated to {@code authority} will be replaced by
     *       a new identifier with the same authority and the code defined by {@code replacements[0]}.</li>
     *   <li>The second occurrence of an identifier associated to {@code authority} will be replaced by a
     *       new identifier with the same authority and the local part defined by {@code replacements[1]}.</li>
     *   <li><i>etc.</i> until one of the following conditions is met:
     *     <ul>
     *       <li>There is no more identifier associated to the given authority in this {@code Builder}, in which case
     *           new identifiers are inserted for all remaining elements in the {@code replacements} array.</li>
     *       <li>There is no more elements in the {@code replacements} array, in which case all remaining
     *           identifiers associated to the given authority in this {@code Builder} are removed.</li>
     *     </ul>
     *   </li>
     * </ul>
     *
     * This method could also be understood as a {@code setIdentifiers(Citation, ...)} method, except that it modifies
     * only the identifiers associated to the given authority and preserves the same order than previous identifiers.
     *
     * @param  authority     the authority of the names to replaces.
     * @param  replacements  the new local parts for the names to replace,
     *         or {@code null} or an empty array for removing all names associated to the given authority.
     * @return {@code this}, for method call chaining.
     *
     * @since 0.8
     */
    public B reidentify(final Citation authority, final String... replacements) {
        ensureNonNull("authority", authority);
        final int length = (replacements != null) ? replacements.length : 0;
        int next = 0;
        int insertAt = identifiers.size();
        for (int i = 0; i < identifiers.size(); i++) {
            final Identifier old = identifiers.get(i);
            if (authority.equals(old.getAuthority())) {
                if (next < length) {
                    final String code;
                    ensureNonNullElement("replacements", next, code = replacements[next++]);
                    if (!code.equals(old.getCode())) {
                        identifiers.set(i, createIdentifier(authority, code));
                        insertAt = i + 1;
                    }
                } else {
                    identifiers.remove(i--);
                }
            }
        }
        while (next < length) {
            final String code;
            ensureNonNullElement("replacements", next, code = replacements[next++]);
            identifiers.add(insertAt++, createIdentifier(authority, code));
        }
        return self();
    }

    /**
     * Returns the parameter description specified by the last call to {@link #setDescription(CharSequence)},
     * or {@code null} if none.
     */
    private InternationalString getDescription() {
        return (InternationalString) properties.get("description");
    }

    /**
     * Sets an {@code Identifier} or {@code IdentifiedObject} description.
     * Descriptions can be used in various contexts:
     *
     * <ul>
     *   <li>Before calls to {@link #addIdentifier(String)} or {@link #addIdentifier(Citation, String)}
     *       for specifying a natural language description of the meaning of the code value.
     *
     *       <div class="note"><b>Example:</b>
     *       {@code setDescription("World Geodetic System 1984").addIdentifier("4326")}</div></li>
     *
     *   <li>Before calls to a {@code createXXX(…)} method for providing a narrative explanation
     *       of the role of the object. Not all {@code IdentifiedObject} supports description.</li>
     * </ul>
     *
     * Calls to this method overwrite any previous value.
     *
     * <p><b>Lifetime:</b>
     * previous descriptions are discarded by calls to {@code setDescription(…)}.
     * Descriptions are cleared after a {@code createXXX(…)} method has been invoked.</p>
     *
     * @param  description  the description as a {@link String} or {@link InternationalString} instance, or {@code null} if none.
     * @return {@code this}, for method call chaining.
     *
     * @see ImmutableIdentifier#getDescription()
     */
    public B setDescription(final CharSequence description) {
        /*
         * Convert to InternationalString now in order to share the same instance if
         * the same description is used both for an Identifier and an IdentifiedObject.
         */
        properties.put("description", Types.toInternationalString(description));
        return self();
    }

    /**
     * Returns the remarks specified by the last call to {@link #setRemarks(CharSequence)},
     * or {@code null} if none.
     */
    private InternationalString getRemarks() {
        return (InternationalString) properties.get(IdentifiedObject.REMARKS_KEY);
    }

    /**
     * Sets remarks as a {@code String} or {@code InternationalString} instance.
     * Calls to this method overwrite any previous value.
     *
     * <p><b>Lifetime:</b>
     * previous remarks are discarded by calls to {@code setRemarks(…)}.
     * Remarks are cleared after a {@code createXXX(…)} method has been invoked.</p>
     *
     * @param  remarks  the remarks as a {@link String} or {@link InternationalString} instance, or {@code null} if none.
     * @return {@code this}, for method call chaining.
     */
    public B setRemarks(final CharSequence remarks) {
        /*
         * Convert to InternationalString now in order to share the same instance if
         * the same remarks is used both for an Identifier and an IdentifiedObject.
         */
        properties.put(IdentifiedObject.REMARKS_KEY, Types.toInternationalString(remarks));
        return self();
    }

    /**
     * Returns {@code true} if the deprecated flag is set to {@code true}.
     */
    private boolean isDeprecated() {
        return Boolean.TRUE.equals(properties.get(AbstractIdentifiedObject.DEPRECATED_KEY));
    }

    /**
     * Sets whether the next {@code Identifier} or {@code IdentifiedObject}s to create shall be considered deprecated.
     * Deprecated objects exist in some {@linkplain org.opengis.referencing.AuthorityFactory authority factories} like
     * the EPSG database.
     *
     * <p>Note that this method does not apply to name and identifiers, which have their own
     * {@code addDeprecatedFoo(…)} methods.</p>
     *
     * <p><b>Lifetime:</b>
     * Deprecation status is cleared after a {@code createXXX(…)} method has been invoked.</p>
     *
     * @param  deprecated {@code true} if the next names, identifiers and identified objects should be
     *         considered deprecated, or {@code false} otherwise.
     * @return {@code this}, for method call chaining.
     *
     * @see AbstractIdentifiedObject#isDeprecated()
     *
     * @since 0.6
     */
    public B setDeprecated(final boolean deprecated) {
        properties.put(AbstractIdentifiedObject.DEPRECATED_KEY, deprecated);
        return self();
    }

    /**
     * Initializes/cleanups the {@link #properties} map before/after a {@code createXXX(…)} execution.
     * Subclasses shall invoke this method in their {@code createXXX(…)} methods as below:
     *
     * {@preformat java
     *     public Foo createFoo() {
     *         final Foo foo;
     *         onCreate(false);
     *         try {
     *             foo = factory.createFoo(properties);
     *         } finally {
     *             onCreate(true);
     *         }
     *         return foo;
     *     }
     * }
     *
     * If {@code cleanup} is {@code true}, then this method clears the identification information
     * (name, aliases, identifiers, description, remarks and deprecation status) for preparing the
     * builder to the construction of an other object.
     * The authority, codespace and version properties are not cleared by this method.
     *
     * @param cleanup {@code false} when this method is invoked before object creation, and
     *                {@code true} when this method is invoked after object creation.
     *
     * @see #properties
     */
    protected void onCreate(final boolean cleanup) {
        final GenericName[] valueAlias;
        final Identifier[]  valueIds;
        if (cleanup) {
            properties .put(IdentifiedObject.NAME_KEY, null);
            properties .remove(IdentifiedObject.REMARKS_KEY);
            properties .remove("description");
            properties .remove(AbstractIdentifiedObject.DEPRECATED_KEY);
            aliases    .clear();
            identifiers.clear();
            valueAlias = null;
            valueIds   = null;
        } else {
            valueAlias = aliases    .toArray(new GenericName[aliases    .size()]);
            valueIds   = identifiers.toArray(new ReferenceIdentifier[identifiers.size()]);
        }
        properties.put(IdentifiedObject.ALIAS_KEY,       valueAlias);
        properties.put(IdentifiedObject.IDENTIFIERS_KEY, valueIds);
    }
}
