/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sis.metadata;

import java.util.Map;
import java.util.Set;
import java.util.List;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Currency;
import java.util.NoSuchElementException;
import java.lang.reflect.Modifier;
import java.nio.charset.Charset;
import javax.xml.bind.annotation.XmlTransient;
import org.opengis.util.CodeList;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.collection.Containers;
import org.apache.sis.util.collection.CodeListSet;
import org.apache.sis.internal.util.CollectionsExt;
import org.apache.sis.internal.util.CheckedHashSet;
import org.apache.sis.internal.util.CheckedArrayList;
import org.apache.sis.internal.metadata.Resources;
import org.apache.sis.internal.system.Semaphores;

import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
import static org.apache.sis.internal.metadata.MetadataUtilities.valueIfDefined;


/**
 * Base class of metadata having an editable content.
 * Newly created {@code ModifiableMetadata} are initially in {@linkplain State#EDITABLE editable} state.
 * The metadata can be populated using the setter methods provided by subclasses, then transition to the
 * {@linkplain State#FINAL final} state for making it safe to share by many consumers.
 *
 * <h2>Tip for subclass implementations</h2>
 * Subclasses can follow the pattern below for every {@code get} and {@code set} methods,
 * with a different processing for singleton value or for {@linkplain Collection collections}.
 *
 * {@preformat java
 *     public class MyMetadata {
 *
 *         // ==== Example for a singleton value =============================
 *
 *         private Foo property;
 *
 *         public Foo getProperty() {
 *             return property;
 *         }
 *
 *         public void setProperty(Foo newValue) {
 *             checkWritePermission();
 *             property = newValue;
 *         }
 *
 *         // ==== Example for a collection ==================================
 *
 *         private Collection<Foo> properties;
 *
 *         public Collection<Foo> getProperties() {
 *             return properties = nonNullCollection(properties, Foo.class);
 *         }
 *
 *         public void setProperties(Collection<Foo> newValues) {
 *             // the call to checkWritePermission() is implicit
 *             properties = writeCollection(newValues, properties, Foo.class);
 *         }
 *     }
 * }
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.0
 * @since   0.3
 * @module
 */
@XmlTransient
public abstract class ModifiableMetadata extends AbstractMetadata {
    /**
     * The {@link #state} value meaning that the metadata is modifiable.
     * This is the default state when new {@link ModifiableMetadata} instances are created.
     */
    private static final byte EDITABLE = 0;

    /**
     * See https://issues.apache.org/jira/browse/SIS-81 - not yet committed.
     */
    private static final byte STAGED = 1;

    /**
     * A value for {@link #state} meaning that execution of {@code transitionTo(…)} is in progress.
     * Must be greater than all other values except {@link #COMPLETABLE} and {@link #FINAL}.
     */
    private static final byte FREEZING = 2;

    /**
     * The {@link #state} value meaning that missing properties can be set,
     * but no existing properties can be modified (including collections).
     * This is a kind of semi-final state.
     */
    private static final byte COMPLETABLE = 3;

    /**
     * A value for {@link #state} meaning that {@code transitionTo(State.FINAL)} has been invoked.
     * Must be greater than all other values.
     */
    private static final byte FINAL = 4;

    /**
     * Whether this metadata has been made unmodifiable, as one of {@link #EDITABLE}, {@link #FREEZING}
     * {@link #COMPLETABLE} or {@link #FINAL} values.
     *
     * <p>This field is not yet serialized because we are not sure to keep this information as a byte in
     * the future. We could for example use an {@code int} and use remaining bits for caching hash-code
     * value of final metadata.</p>
     */
    private transient byte state;

    /**
     * Constructs an initially empty metadata.
     * The initial state is {@link State#EDITABLE}.
     */
    protected ModifiableMetadata() {
    }

    /**
     * Whether the metadata is still editable or has been made final.
     * New {@link ModifiableMetadata} instances are initially {@link #EDITABLE}
     * and can be made {@link #FINAL} after construction by a call to {@link ModifiableMetadata#transitionTo(State)}.
     *
     * <div class="note"><b>Note:</b>
     * more states may be added in future Apache SIS versions. On possible candidate is {@code STAGED}.
     * See <a href="https://issues.apache.org/jira/browse/SIS-81">SIS-81</a>.</div>
     *
     * @author  Martin Desruisseaux (Geomatys)
     * @version 1.0
     * @since   1.0
     * @module
     */
    public enum State {
        /**
         * The metadata is modifiable.
         * This is the default state when new {@link ModifiableMetadata} instances are created.
         * Note that a modifiable metadata instance does <strong>not</strong> imply that all
         * properties contained in that instance are also editable.
         */
        EDITABLE(ModifiableMetadata.EDITABLE),

        /**
         * The metadata allows missing values to be set, but does not allow existing values to be modified.
         * This state is not appendable, i.e. it does not allow adding elements in a collection.
         */
        COMPLETABLE(ModifiableMetadata.COMPLETABLE),

        /**
         * The metadata is unmodifiable.
         * When a metadata is final, it can not be moved back to an editable state
         * (but it is still possible to create a modifiable copy with {@link MetadataCopier}).
         * Invoking any setter method on an unmodifiable metadata cause an
         * {@link UnmodifiableMetadataException} to be thrown.
         */
        FINAL(ModifiableMetadata.FINAL);

        /**
         * Mapping from {@link ModifiableMetadata} private flags to {@code State} enumeration.
         * A mapping exists because {@code ModifiableMetadata} does not use the same set of enumeration values
         * (e.g. it has an internal {@link #FREEZING} value), and because future versions may use a bitmask.
         */
        private static final State[] VALUES = new State[ModifiableMetadata.FINAL + 1];
        static {
            VALUES[ModifiableMetadata.EDITABLE]    = EDITABLE;
            VALUES[ModifiableMetadata.STAGED]      = EDITABLE;
            VALUES[ModifiableMetadata.FREEZING]    = FINAL;
            VALUES[ModifiableMetadata.COMPLETABLE] = COMPLETABLE;
            VALUES[ModifiableMetadata.FINAL]       = FINAL;
        }

        /**
         * The numerical code associated to this enumeration value. It serves similar purpose to the
         * {@link #ordinal()} value, but is nevertheless provided for the reasons given in {@link #VALUES}.
         */
        final byte code;

        /**
         * Creates a new state associated to the given code numerical code.
         */
        private State(final byte code) {
            this.code = code;
        }
    }

    /**
     * Tells whether this instance of metadata is editable.
     * This is initially {@link State#EDITABLE} for new {@code ModifiableMetadata} instances,
     * but can be changed by a call to {@link #transitionTo(State)}.
     *
     * <p>{@link State#FINAL} implies that all properties are also final.
     * This recursivity does not necessarily apply to other states. For example {@link State#EDITABLE}
     * does <strong>not</strong> imply that all {@code ModifiableMetadata} children are also editable.</p>
     *
     * <div class="note"><b>API note:</b>
     * the {@code ModifiableMetadata} state is not a metadata per se, but rather an information about
     * this particular instance of a metadata class. Two metadata instances may be in different states
     * but still have the same metadata content. For this reason, this method does not have {@code get}
     * prefix for avoiding confusion with getter and setter methods of metadata properties.</div>
     *
     * @return the state (editable, completable or final) of this {@code ModifiableMetadata} instance.
     *
     * @since 1.0
     */
    public State state() {
        return State.VALUES[state];
    }

    /**
     * Requests this metadata instance and (potentially) all its children to transition to a new state.
     * The action performed by this method depends on the {@linkplain #state() source state} and the
     * given target state, as listed in the following table:
     *
     * <table class="sis">
     *   <caption>State transitions</caption>
     *   <tr>
     *     <th>Current state</th>
     *     <th>Target state</th>
     *     <th>Action</th>
     *   </tr><tr>
     *     <td><var>Any</var></td>
     *     <td><var>Same</var></td>
     *     <td>Does nothing and returns {@code false}.</td>
     *   </tr><tr>
     *     <td>{@link State#EDITABLE}</td>
     *     <td>{@link State#COMPLETABLE}</td>
     *     <td>Marks this metadata and all children as completable.</td>
     *   </tr><tr>
     *     <td>Any</td>
     *     <td>{@link State#FINAL}</td>
     *     <td>Marks this metadata and all children as unmodifiable.</td>
     *   </tr><tr>
     *     <td>{@link State#FINAL}</td>
     *     <td>Any other</td>
     *     <td>Throws {@link UnmodifiableMetadataException}.</td>
     *   </tr>
     * </table>
     *
     * The effect of invoking this method may be recursive. For example transitioning to {@link State#FINAL}
     * implies transitioning all children {@code ModifiableMetadata} instances to the final state too.
     *
     * @param  target  the desired new state.
     * @return {@code true} if the state of this {@code ModifiableMetadata} changed as a result of this method call.
     * @throws UnmodifiableMetadataException if a transition to a less restrictive state
     *         (e.g. from {@link State#FINAL} to {@link State#EDITABLE}) was attempted.
     *
     * @since 1.0
     */
    public boolean transitionTo(final State target) {
        if (target.code < state) {
            throw new UnmodifiableMetadataException(Resources.format(Resources.Keys.UnmodifiableMetadata));
        }
        if (target.code == state || state == FREEZING) {
            return false;
        }
        byte result = state;
        try {
            state = FREEZING;
            StateChanger.applyTo(target, this);
            result = target.code;
        } finally {
            state = result;
        }
        return true;
    }

    /**
     * Checks if changes in the metadata are allowed. All {@code setFoo(…)} methods in subclasses
     * shall invoke this method (directly or indirectly) before to apply any change.
     * The current property value should be specified in argument.
     *
     * @param  current  the current value, or {@code null} if none.
     * @throws UnmodifiableMetadataException if this metadata is unmodifiable.
     *
     * @see #state()
     *
     * @since 1.0
     */
    protected void checkWritePermission(Object current) throws UnmodifiableMetadataException {
        if (state != COMPLETABLE) {
            if (state == FINAL) {
                throw new UnmodifiableMetadataException(Resources.format(Resources.Keys.UnmodifiableMetadata));
            }
        } else if (current != null) {
            final MetadataStandard standard;
            if (current instanceof AbstractMetadata) {
                standard = ((AbstractMetadata) current).getStandard();
            } else {
                standard = getStandard();
            }
            final Object c = standard.getTitle(current);
            if (c != null) current = c;
            throw new UnmodifiableMetadataException(Resources.format(Resources.Keys.ElementAlreadyInitialized_1, current));
        }
    }

    /**
     * Writes the content of the {@code source} collection into the {@code target} list,
     * creating it if needed. This method performs the following steps:
     *
     * <ul>
     *   <li>Invokes {@link #checkWritePermission(Object)} in order to ensure that this metadata is modifiable.</li>
     *   <li>If {@code source} is null or empty, returns {@code null}
     *       (meaning that the metadata property is not provided).</li>
     *   <li>If {@code target} is null, creates a new {@link List}.</li>
     *   <li>Copies the content of the given {@code source} into the target.</li>
     * </ul>
     *
     * @param  <E>          the type represented by the {@code Class} argument.
     * @param  source       the source list, or {@code null}.
     * @param  target       the target list, or {@code null} if not yet created.
     * @param  elementType  the base type of elements to put in the list.
     * @return a list (possibly the {@code target} instance) containing the {@code source}
     *         elements, or {@code null} if the source was null.
     * @throws UnmodifiableMetadataException if this metadata is unmodifiable.
     *
     * @see #nonNullList(List, Class)
     */
    @SuppressWarnings("unchecked")
    protected final <E> List<E> writeList(Collection<? extends E> source, List<E> target,
            Class<E> elementType) throws UnmodifiableMetadataException
    {
        return (List<E>) write(source, target, elementType, Boolean.FALSE);
    }

    /**
     * Writes the content of the {@code source} collection into the {@code target} set,
     * creating it if needed. This method performs the following steps:
     *
     * <ul>
     *   <li>Invokes {@link #checkWritePermission(Object)} in order to ensure that this metadata is modifiable.</li>
     *   <li>If {@code source} is null or empty, returns {@code null}
     *       (meaning that the metadata property is not provided).</li>
     *   <li>If {@code target} is null, creates a new {@link Set}.</li>
     *   <li>Copies the content of the given {@code source} into the target.</li>
     * </ul>
     *
     * @param  <E>          the type represented by the {@code Class} argument.
     * @param  source       the source set, or {@code null}.
     * @param  target       the target set, or {@code null} if not yet created.
     * @param  elementType  the base type of elements to put in the set.
     * @return a set (possibly the {@code target} instance) containing the {@code source} elements,
     *         or {@code null} if the source was null.
     * @throws UnmodifiableMetadataException if this metadata is unmodifiable.
     *
     * @see #nonNullSet(Set, Class)
     */
    protected final <E> Set<E> writeSet(Collection<? extends E> source, Set<E> target,
            Class<E> elementType) throws UnmodifiableMetadataException
    {
        return (Set<E>) write(source, target, elementType, Boolean.TRUE);
    }

    /**
     * Writes the content of the {@code source} collection into the {@code target} list or set,
     * creating it if needed. This method performs the following steps:
     *
     * <ul>
     *   <li>Invokes {@link #checkWritePermission(Object)} in order to ensure that this metadata is modifiable.</li>
     *   <li>If {@code source} is null or empty, returns {@code null}
     *       (meaning that the metadata property is not provided).</li>
     *   <li>If {@code target} is null, creates a new {@link Set} or a new {@link List}
     *       depending on the value returned by {@link #collectionType(Class)}.</li>
     *   <li>Copies the content of the given {@code source} into the target.</li>
     * </ul>
     *
     * <h4>Choosing a collection type</h4>
     * Implementations shall invoke {@link #writeList writeList} or {@link #writeSet writeSet} methods
     * instead than this method when the collection type is enforced by ISO specification.
     * When the type is not enforced by the specification, some freedom are allowed at
     * implementer choice. The default implementation invokes {@link #collectionType(Class)}
     * in order to get a hint about whether a {@link List} or a {@link Set} should be used.
     *
     * @param  <E>          the type represented by the {@code Class} argument.
     * @param  source       the source collection, or {@code null}.
     * @param  target       the target collection, or {@code null} if not yet created.
     * @param  elementType  the base type of elements to put in the collection.
     * @return a collection (possibly the {@code target} instance) containing the {@code source} elements,
     *         or {@code null} if the source was null.
     * @throws UnmodifiableMetadataException if this metadata is unmodifiable.
     */
    protected final <E> Collection<E> writeCollection(Collection<? extends E> source, Collection<E> target,
            Class<E> elementType) throws UnmodifiableMetadataException
    {
        return write(source, target, elementType, null);
    }

    /**
     * Writes the content of the {@code source} collection into the {@code target} list or set,
     * creating it if needed.
     *
     * @param  useSet  {@link Boolean#TRUE} for creating a set, {@link Boolean#FALSE} for creating a list,
     *                 or null for automatic choice.
     */
    @SuppressWarnings("unchecked")
    private <E> Collection<E> write(final Collection<? extends E> source, Collection<E> target,
            final Class<E> elementType, Boolean useSet) throws UnmodifiableMetadataException
    {
        /*
         * It is not worth to copy the content if the current and the new instance are the
         * same. This is safe only using the != operator, not the !equals(Object) method.
         * This optimization is required for efficient working of PropertyAccessor.set(…)
         * and JAXB unmarshalling.
         */
        if (source != target) {
            if (state == FREEZING) {
                /*
                 * transitionTo(State.FINAL) is under progress. The source collection is already
                 * an unmodifiable instance created by StateChanger.
                 */
                assert (useSet != null) || collectionType(elementType).isInstance(source) : elementType;
                return (Collection<E>) source;
            }
            checkWritePermission(valueIfDefined(target));
            if (isNullOrEmpty(source)) {
                target = null;
            } else {
                /*
                 * Reuse the existing collection if available, except in State.COMPLETABLE case
                 * since that collection may the Collection.EMPTY_SET or EMPTY_LIST.
                 */
                if (target != null && state != COMPLETABLE) {
                    target.clear();
                } else {
                    if (useSet == null) {
                        useSet = useSet(elementType);
                    }
                    if (useSet) {
                        target = createSet(elementType, source);
                    } else {
                        target = createList(elementType, source);
                    }
                }
                target.addAll(source);
                if (state == COMPLETABLE) {
                    if (useSet) {
                        target = CollectionsExt.unmodifiableOrCopy((Set<E>) target);
                    } else {
                        target = CollectionsExt.unmodifiableOrCopy((List<E>) target);
                    }
                }
            }
        }
        return target;
    }

    /**
     * Writes the content of the {@code source} map into the {@code target} map,
     * creating it if needed. This method performs the following steps:
     *
     * <ul>
     *   <li>Invokes {@link #checkWritePermission(Object)} in order to ensure that this metadata is modifiable.</li>
     *   <li>If {@code source} is null or empty, returns {@code null}
     *       (meaning that the metadata property is not provided).</li>
     *   <li>If {@code target} is null, creates a new {@link Map}.</li>
     *   <li>Copies the content of the given {@code source} into the target.</li>
     * </ul>
     *
     * @param  <K>      the type of keys represented by the {@code Class} argument.
     * @param  <V>      the type of values in the map.
     * @param  source   the source map, or {@code null}.
     * @param  target   the target map, or {@code null} if not yet created.
     * @param  keyType  the base type of keys to put in the map.
     * @return a map (possibly the {@code target} instance) containing the {@code source} entries,
     *         or {@code null} if the source was null.
     * @throws UnmodifiableMetadataException if this metadata is unmodifiable.
     *
     * @see #nonNullMap(Map, Class)
     *
     * @since 1.0
     */
    @SuppressWarnings("unchecked")
    protected final <K,V> Map<K,V> writeMap(final Map<? extends K, ? extends V> source, Map<K,V> target,
            Class<K> keyType) throws UnmodifiableMetadataException
    {
        /*
         * Code in this method is a copy of write(Collection, Collection, Class) with some calls inlined.
         * See the comments inside that write(…) method body for more information on the logic.
         */
        if (source != target) {
            if (state == FREEZING) {
                return (Map<K,V>) source;
            }
            checkWritePermission((target == null) || target.isEmpty() ? null : target);
            if (isNullOrEmpty(source)) {
                target = null;
            } else {
                if (target != null && state != COMPLETABLE) {
                    target.clear();
                } else {
                    target = createMap(keyType, source);
                }
                target.putAll(source);
                if (state == COMPLETABLE) {
                    target = CollectionsExt.unmodifiableOrCopy(target);
                }
            }
        }
        return target;
    }

    /**
     * Creates a list with the content of the {@code source} collection,
     * or returns {@code null} if the source is {@code null} or empty.
     * This is a convenience method for copying fields in subclass copy constructors.
     *
     * @param  <E>          the type represented by the {@code Class} argument.
     * @param  source       the source collection, or {@code null}.
     * @param  elementType  the base type of elements to put in the list.
     * @return a list containing the {@code source} elements,
     *         or {@code null} if the source was null or empty.
     */
    protected final <E> List<E> copyList(final Collection<? extends E> source, final Class<E> elementType) {
        if (isNullOrEmpty(source)) {
            return null;
        }
        final List<E> target = createList(elementType, source);
        target.addAll(source);
        return target;
    }

    /**
     * Creates a set with the content of the {@code source} collection,
     * or returns {@code null} if the source is {@code null} or empty.
     * This is a convenience method for copying fields in subclass copy constructors.
     *
     * @param  <E>          the type represented by the {@code Class} argument.
     * @param  source       the source collection, or {@code null}.
     * @param  elementType  the base type of elements to put in the set.
     * @return a set containing the {@code source} elements,
     *         or {@code null} if the source was null or empty.
     */
    protected final <E> Set<E> copySet(final Collection<? extends E> source, final Class<E> elementType) {
        if (isNullOrEmpty(source)) {
            return null;
        }
        final Set<E> target = createSet(elementType, source);
        target.addAll(source);
        return target;
    }

    /**
     * Creates a list or set with the content of the {@code source} collection,
     * or returns {@code null} if the source is {@code null} or empty.
     * This is a convenience method for copying fields in subclass copy constructors.
     *
     * <p>The collection type is selected as described in the
     * {@link #nonNullCollection(Collection, Class)}.</p>
     *
     * @param  <E>          the type represented by the {@code Class} argument.
     * @param  source       the source collection, or {@code null}.
     * @param  elementType  the base type of elements to put in the collection.
     * @return a collection containing the {@code source} elements,
     *         or {@code null} if the source was null or empty.
     */
    protected final <E> Collection<E> copyCollection(final Collection<? extends E> source, final Class<E> elementType) {
        if (isNullOrEmpty(source)) {
            return null;
        }
        final Collection<E> target;
        if (useSet(elementType)) {
            target = createSet(elementType, source);
        } else {
            target = createList(elementType, source);
        }
        target.addAll(source);
        return target;
    }

    /**
     * Creates a map with the content of the {@code source} map,
     * or returns {@code null} if the source is {@code null} or empty.
     * This is a convenience method for copying fields in subclass copy constructors.
     *
     * @param  <K>      the type of keys represented by the {@code Class} argument.
     * @param  <V>      the type of values in the map.
     * @param  source   the source map, or {@code null}.
     * @param  keyType  the base type of keys to put in the map.
     * @return a map containing the {@code source} entries,
     *         or {@code null} if the source was null or empty.
     *
     * @since 1.0
     */
    protected final <K,V> Map<K,V> copyMap(final Map<? extends K, ? extends V> source, final Class<K> keyType) {
        if (isNullOrEmpty(source)) {
            return null;
        }
        final Map<K,V> target = createMap(keyType, source);
        target.putAll(source);
        return target;
    }

    /**
     * Creates a singleton list or set containing only the given value, if non-null.
     * This is a convenience method for initializing fields in subclass constructors.
     *
     * <p>The collection type is selected as described in the
     * {@link #nonNullCollection(Collection, Class)}.</p>
     *
     * @param  <E>          the type represented by the {@code Class} argument.
     * @param  value        the singleton value to put in the returned collection, or {@code null}.
     * @param  elementType  the element type (used only if {@code value} is non-null).
     * @return a new modifiable collection containing the given value,
     *         or {@code null} if the given value was null.
     */
    protected final <E> Collection<E> singleton(final E value, final Class<E> elementType) {
        if (value == null) {
            return null;
        }
        final Collection<E> collection;
        if (useSet(elementType)) {
            collection = createSet(elementType, null);
        } else {
            collection = new CheckedArrayList<>(elementType, 1);
        }
        collection.add(value);
        return collection;
    }

    /**
     * Returns {@code true} if empty collection should be returned as {@code null} value.
     * This is usually not a behavior that we allow in public API. However this behavior
     * is sometime desired internally, for example when marshalling with JAXB or when
     * performing a {@code equals}, {@code isEmpty} or {@code prune} operation
     * (for avoiding creating unnecessary collections).
     */
    private static boolean emptyCollectionAsNull() {
        return Semaphores.query(Semaphores.NULL_COLLECTION);
    }

    /**
     * Returns the specified list, or a new one if {@code current} is null.
     * This is a convenience method for implementation of {@code getFoo()} methods.
     *
     * @param  <E>          the type represented by the {@code Class} argument.
     * @param  current      the existing list, or {@code null} if the list has not yet been created.
     * @param  elementType  the element type (used only if {@code current} is null).
     * @return {@code current}, or a new list if {@code current} is null.
     */
    protected final <E> List<E> nonNullList(final List<E> current, final Class<E> elementType) {
        if (current != null) {
            return current.isEmpty() && emptyCollectionAsNull() ? null : current;
        }
        if (emptyCollectionAsNull()) {
            return null;
        }
        if (state < FREEZING) {
            return createList(elementType, current);        // `current` given as a matter of principle even if null.
        }
        return Collections.emptyList();
    }

    /**
     * Returns the specified set, or a new one if {@code current} is null.
     * This is a convenience method for implementation of {@code getFoo()} methods.
     *
     * @param  <E>          the type represented by the {@code Class} argument.
     * @param  current      the existing set, or {@code null} if the set has not yet been created.
     * @param  elementType  the element type (used only if {@code current} is null).
     * @return {@code current}, or a new set if {@code current} is null.
     */
    protected final <E> Set<E> nonNullSet(final Set<E> current, final Class<E> elementType) {
        if (current != null) {
            return current.isEmpty() && emptyCollectionAsNull() ? null : current;
        }
        if (emptyCollectionAsNull()) {
            return null;
        }
        if (state < FREEZING) {
            return createSet(elementType, current);     // `current` given as a matter of principle even if null.
        }
        return Collections.emptySet();
    }

    /**
     * Returns the specified collection, or a new one if {@code current} is null.
     * This is a convenience method for implementation of {@code getFoo()} methods.
     *
     * <h4>Choosing a collection type</h4>
     * Implementations shall invoke {@link #nonNullList nonNullList(…)} or {@link #nonNullSet nonNullSet(…)}
     * instead than this method when the collection type is enforced by ISO specification.
     * When the type is not enforced by the specification, some freedom are allowed at implementer choice.
     * The default implementation invokes {@link #collectionType(Class)} in order to get a hint about whether
     * a {@link List} or a {@link Set} should be used.
     *
     * @param  <E>          the type represented by the {@code Class} argument.
     * @param  current      the existing collection, or {@code null} if the collection has not yet been created.
     * @param  elementType  the element type (used only if {@code current} is null).
     * @return {@code current}, or a new collection if {@code current} is null.
     */
    protected final <E> Collection<E> nonNullCollection(final Collection<E> current, final Class<E> elementType) {
        if (current != null) {
            assert collectionType(elementType).isInstance(current);
            return current.isEmpty() && emptyCollectionAsNull() ? null : current;
        }
        if (emptyCollectionAsNull()) {
            return null;
        }
        final boolean isModifiable = (state < FREEZING);
        if (useSet(elementType)) {
            if (isModifiable) {
                return createSet(elementType, current);         // `current` given as a matter of principle even if null.
            } else {
                return Collections.emptySet();
            }
        } else {
            if (isModifiable) {
                return createList(elementType, current);        // `current` given as a matter of principle even if null.
            } else {
                return Collections.emptyList();
            }
        }
    }

    /**
     * Returns the specified map, or a new one if {@code current} is null.
     * This is a convenience method for implementation of {@code getFoo()} methods.
     *
     * @param  <K>      the type of keys represented by the {@code Class} argument.
     * @param  <V>      the type of values in the map.
     * @param  current  the existing map, or {@code null} if the map has not yet been created.
     * @param  keyType  the key type (used only if {@code current} is null).
     * @return {@code current}, or a new map if {@code current} is null.
     *
     * @since 1.0
     */
    protected final <K,V> Map<K,V> nonNullMap(final Map<K,V> current, final Class<K> keyType) {
        if (current != null) {
            return current.isEmpty() && emptyCollectionAsNull() ? null : current;
        }
        if (emptyCollectionAsNull()) {
            return null;
        }
        if (state < FREEZING) {
            return createMap(keyType, current);         // `current` given as a matter of principle even if null.
        }
        return Collections.emptyMap();
    }

    /**
     * Creates a modifiable list for elements of the given type. This method is defined mostly
     * for consistency with {@link #createSet(Class, Collection)}.
     *
     * @param  source  the collection to be copied in the new list. This method uses this information
     *                 only for computing initial capacity; it does not perform the actual copy.
     */
    private static <E> List<E> createList(final Class<E> elementType, final Collection<?> source) {
        if (source == null) {
            /*
             * Do not specify an initial capacity, because the list will stay empty in a majority of cases
             * (i.e. the users will want to iterate over the list elements more often than they will want
             * to add elements). JDK implementation of ArrayList has a lazy instantiation mechanism for
             * initially empty lists, but as of JDK 10 this lazy instantiation works only for list having
             * the default capacity.
             */
            return new CheckedArrayList<>(elementType);
        }
        return new CheckedArrayList<>(elementType, source.size());
    }

    /**
     * Creates a modifiable set for elements of the given type. This method will create an {@link EnumSet},
     * {@link CodeListSet} or {@link java.util.LinkedHashSet} depending on the {@code elementType} argument.
     * The set must have a stable iteration order (this is needed by {@link TreeTableView}).
     *
     * @param  source  the collection to be copied in the new set, or {@code null} if unknown.
     *                 This method uses this information only for computing initial capacity;
     *                 it does not perform the actual copy.
     */
    @SuppressWarnings({"unchecked","rawtypes"})
    private static <E> Set<E> createSet(final Class<E> elementType, final Collection<?> source) {
        if (Enum.class.isAssignableFrom(elementType)) {
            return EnumSet.noneOf((Class) elementType);
        }
        if (CodeList.class.isAssignableFrom(elementType) && Modifier.isFinal(elementType.getModifiers())) {
            return new CodeListSet(elementType);
        }
        /*
         * If we can not compute an initial capacity from the size of an existing source, use an arbitrary
         * small value (currently 4). We use a small value because collections will typically contain few
         * elements (often just a singleton).
         */
        return new CheckedHashSet<>(elementType, (source != null) ? Containers.hashMapCapacity(source.size()) : 4);
    }

    /**
     * Creates a modifiable map for elements of the given type.
     * The map must have a stable iteration order (this is needed by {@link TreeTableView}).
     *
     * @param  source  the map to be copied in the new map. This method uses this information
     *                 only for computing initial capacity; it does not perform the actual copy.
     */
    @SuppressWarnings({"unchecked","rawtypes"})
    private static <K,V> Map<K,V> createMap(final Class<K> keyType, final Map<?,?> source) {
        if (Enum.class.isAssignableFrom(keyType)) {
            return new EnumMap(keyType);
        } else {
            // Must be LinkedHashMap, not HashMap, because TreeTableView needs stable iteration order.
            return new LinkedHashMap<>((source != null) ? Containers.hashMapCapacity(source.size()) : 4);
        }
    }

    /**
     * Returns {@code true} if we should use a {@link Set} instead than a {@link List}
     * for elements of the given type.
     */
    private <E> boolean useSet(final Class<E> elementType) {
        final Class<? extends Collection<E>> type = collectionType(elementType);
        if (Set .class == (Class) type) return true;
        if (List.class == (Class) type) return false;
        throw new NoSuchElementException(Errors.format(Errors.Keys.UnsupportedType_1, type));
    }

    /**
     * Returns the type of collection to use for the given type. The current implementation can
     * return only two values: <code>{@linkplain Set}.class</code> if the property should not
     * accept duplicated values, or <code>{@linkplain List}.class</code> otherwise. Future SIS
     * versions may accept other types.
     *
     * <p>The default implementation returns <code>{@linkplain Set}.class</code> if the element type
     * is assignable to {@link CodeList}, {@link Enum}, {@link String}, {@link Charset},
     * {@link Locale} or {@link Currency}, and <code>{@linkplain List}.class</code> otherwise.
     * Subclasses can override this method for choosing different kind of collections.
     * <em>Note however that {@link Set} should be used only with immutable element types</em>,
     * for {@linkplain Object#hashCode() hash code} stability.</p>
     *
     * @param  <E>          the type of elements in the collection to be created.
     * @param  elementType  the type of elements in the collection to be created.
     * @return {@code List.class} or {@code Set.class} depending on whether the
     *         property shall accept duplicated values or not.
     */
    @SuppressWarnings({"rawtypes","unchecked"})
    protected <E> Class<? extends Collection<E>> collectionType(final Class<E> elementType) {
        return (Class) (CodeList.class.isAssignableFrom(elementType)
                ||          Enum.class.isAssignableFrom(elementType)
                ||       Charset.class.isAssignableFrom(elementType)
                ||        String.class ==               elementType
                ||        Locale.class ==               elementType
                ||      Currency.class ==               elementType
                ? Set.class : List.class);
    }
}
