/*
 * 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.Set;
import java.util.Map;
import java.util.LinkedHashSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
import java.io.IOException;
import java.io.Serializable;
import java.io.ObjectInputStream;
import java.io.InvalidClassException;
import java.security.AccessController;
import org.opengis.metadata.Identifier;
import org.opengis.metadata.citation.Citation;
import org.opengis.metadata.ExtendedElementInformation;
import org.apache.sis.util.Classes;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.collection.TreeTable;
import org.apache.sis.util.collection.CheckedContainer;
import org.apache.sis.internal.system.Modules;
import org.apache.sis.internal.system.Semaphores;
import org.apache.sis.internal.system.SystemListener;
import org.apache.sis.internal.simple.SimpleCitation;
import org.apache.sis.internal.util.FinalFieldSetter;
import org.apache.sis.internal.util.Strings;

import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
import static org.apache.sis.util.ArgumentChecks.ensureNonNullElement;


/**
 * Enumeration of some metadata standards. A standard is defined by a set of Java interfaces
 * in a specific package or sub-packages. For example the {@linkplain #ISO_19115 ISO 19115}
 * standard is defined by <a href="http://www.geoapi.org">GeoAPI</a> interfaces in the
 * {@link org.opengis.metadata} package and sub-packages.
 *
 * <p>This class provides some methods operating on metadata instances through
 * {@linkplain java.lang.reflect Java reflection}. The following rules are assumed:</p>
 *
 * <ul>
 *   <li>Metadata properties are defined by the collection of following getter methods found
 *       <strong>in the interface</strong>, ignoring implementation methods:
 *       <ul>
 *         <li>{@code get*()} methods with arbitrary return type;</li>
 *         <li>or {@code is*()} methods with boolean return type.</li>
 *       </ul></li>
 *   <li>All properties are <cite>readable</cite>.</li>
 *   <li>A property is also <cite>writable</cite> if a {@code set*(…)} method is defined
 *       <strong>in the implementation class</strong> for the corresponding getter method.
 *       The setter method doesn't need to be defined in the interface.</li>
 * </ul>
 *
 * An instance of {@code MetadataStandard} is associated to every {@link AbstractMetadata} objects.
 * The {@code AbstractMetadata} base class usually form the basis of ISO 19115 implementations but
 * can also be used for other standards.
 *
 * <h2>Defining new {@code MetadataStandard} instances</h2>
 * Users should use the pre-defined constants when applicable.
 * However if new instances need to be defined, then there is a choice:
 *
 * <ul>
 *   <li>For <em>read-only</em> metadata, {@code MetadataStandard} can be instantiated directly.
 *       Only getter methods will be used and all operations that modify the metadata properties
 *       will throw an {@link UnmodifiableMetadataException}.</li>
 *   <li>For <em>read/write</em> metadata, the {@link #getImplementation(Class)}
 *       method must be overridden in a {@code MetadataStandard} subclass.</li>
 * </ul>
 *
 * <h2>Thread safety</h2>
 * The same {@code MetadataStandard} instance can be safely used by many threads without synchronization
 * on the part of the caller. Subclasses shall make sure that any overridden methods remain safe to call
 * from multiple threads, because the same {@code MetadataStandard} instances are typically referenced
 * by a large amount of {@link ModifiableMetadata}.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.0
 *
 * @see AbstractMetadata
 *
 * @since 0.3
 * @module
 */
public class MetadataStandard implements Serializable {
    /**
     * For cross-version compatibility.
     */
    private static final long serialVersionUID = 7549790450195184843L;

    /**
     * {@code true} if implementations can alter the API defined in the interfaces by
     * adding or removing properties. If {@code true}, then {@link PropertyAccessor}
     * will check for {@link Deprecated} and {@link org.opengis.annotation.UML}
     * annotations in the implementation classes in addition to the interfaces.
     *
     * <p>A value of {@code true} is useful when Apache SIS implements a newer standard
     * than GeoAPI, but have a slight performance cost at construction time. Performance
     * after construction should be the same.</p>
     */
    static final boolean IMPLEMENTATION_CAN_ALTER_API = false;

    /**
     * Metadata instances defined in this class. The current implementation does not yet
     * contains the user-defined instances. However this may be something we will need to
     * do in the future.
     */
    private static final MetadataStandard[] INSTANCES;

    /**
     * An instance working on ISO 19111 standard as defined by GeoAPI interfaces
     * in the {@link org.opengis.referencing} package and sub-packages.
     */
    public static final MetadataStandard ISO_19111;

    /**
     * An instance working on ISO 19115 standard as defined by GeoAPI interfaces
     * in the {@link org.opengis.metadata} package and sub-packages.
     */
    public static final MetadataStandard ISO_19115;

    /**
     * An instance working on ISO 19123 standard as defined by GeoAPI interfaces
     * in the {@link org.opengis.coverage} package and sub-packages.
     */
    public static final MetadataStandard ISO_19123;
    static {
        final String[] acronyms = {"CoordinateSystem", "CS", "CoordinateReferenceSystem", "CRS"};

        // If new StandardImplementation instances are added below, please update StandardImplementation.readResolve().
        ISO_19115 = new StandardImplementation("ISO 19115", "org.opengis.metadata.", "org.apache.sis.metadata.iso.", null, null);
        ISO_19111 = new StandardImplementation("ISO 19111", "org.opengis.referencing.", "org.apache.sis.referencing.", acronyms, new MetadataStandard[] {ISO_19115});
        ISO_19123 = new MetadataStandard      ("ISO 19123", "org.opengis.coverage.", new MetadataStandard[] {ISO_19111});
        INSTANCES = new MetadataStandard[] {
            ISO_19111,
            ISO_19115,
            ISO_19123
        };
        SystemListener.add(new SystemListener(Modules.METADATA) {
            @Override protected void classpathChanged() {
                clearCache();
            }
        });
    }

    /**
     * Bibliographical reference to the international standard.
     *
     * @see #getCitation()
     */
    final Citation citation;

    /**
     * The root package for metadata interfaces. Must have a trailing {@code '.'}.
     */
    final String interfacePackage;

    /**
     * The dependencies, or {@code null} if none.
     *
     * Note: the {@code null} value is for serialization compatibility.
     */
    private final MetadataStandard[] dependencies;

    /**
     * Accessors for the specified implementation classes.
     * The only legal value types are:
     *
     * <ul>
     *   <li>{@link MetadataStandard} if type is handled by {@linkplain #dependencies} rather than this standard.</li>
     *   <li>{@link Class} if we found the interface for the type but did not yet created the {@link PropertyAccessor}.</li>
     *   <li>{@link PropertyAccessor} otherwise.</li>
     * </ul>
     */
    private final transient ConcurrentMap<CacheKey,Object> accessors;      // written by reflection on deserialization.

    /**
     * Creates a new instance working on implementation of interfaces defined in the specified package.
     *
     * <div class="note"><b>Example:</b>: For the ISO 19115 standard reflected by GeoAPI interfaces,
     * {@code interfacePackage} shall be the {@link org.opengis.metadata} package.</div>
     *
     * @param  citation          bibliographical reference to the international standard.
     * @param  interfacePackage  the root package for metadata interfaces.
     * @param  dependencies      the dependencies to other metadata standards.
     */
    public MetadataStandard(final Citation citation, final Package interfacePackage, MetadataStandard... dependencies) {
        ensureNonNull("citation",         citation);
        ensureNonNull("interfacePackage", interfacePackage);
        ensureNonNull("dependencies",     dependencies);
        this.citation         = citation;
        this.interfacePackage = interfacePackage.getName() + '.';
        this.accessors        = new ConcurrentHashMap<>();                          // Also defined in readObject(…)
        if (dependencies.length == 0) {
            this.dependencies = null;
        } else {
            this.dependencies = dependencies = dependencies.clone();
            for (int i=0; i<dependencies.length; i++) {
                ensureNonNullElement("dependencies", i, dependencies[i]);
            }
        }
    }

    /**
     * Creates a new instance working on implementation of interfaces defined in the
     * specified package. This constructor is used only for the pre-defined constants.
     *
     * @param  citation          bibliographical reference to the international standard.
     * @param  interfacePackage  the root package for metadata interfaces.
     * @param  dependencies      the dependencies to other metadata standards, or {@code null} if none.
     */
    MetadataStandard(final String citation, final String interfacePackage, final MetadataStandard[] dependencies) {
        this.citation         = new SimpleCitation(citation);
        this.interfacePackage = interfacePackage;
        this.accessors        = new ConcurrentHashMap<>();
        this.dependencies     = dependencies;               // No clone, since this constructor is for internal use only.
    }

    /**
     * Returns {@code true} if class or interface of the given name is supported by this standard.
     * This method verifies if the class is a member of the package given at construction time or
     * a sub-package. This method does not verify if the type is supported by a dependency.
     *
     * @param  classname  the name of the type to verify.
     * @return {@code true} if the given type is supported by this standard.
     */
    final boolean isSupported(final String classname) {
        return classname.startsWith(interfacePackage);
    }

    /**
     * Returns the metadata standard for the given class. The argument given to this method can be
     * either an interface defined by the standard, or a class implementing such interface. If the
     * class implements more than one interface, then the first interface recognized by this method,
     * in declaration order, will be retained.
     *
     * <p>The current implementation recognizes only the standards defined by the public static
     * constants defined in this class. A future SIS version may recognize user-defined constants.</p>
     *
     * @param  type  the metadata standard interface, or an implementation class.
     * @return the metadata standard for the given type, or {@code null} if not found.
     */
    public static MetadataStandard forClass(final Class<?> type) {
        String classname = type.getName();
        for (final MetadataStandard candidate : INSTANCES) {
            if (candidate.isSupported(classname)) {
                return candidate;
            }
        }
        for (final Class<?> interf : Classes.getAllInterfaces(type)) {
            classname = interf.getName();
            for (final MetadataStandard candidate : INSTANCES) {
                if (candidate.isSupported(classname)) {
                    return candidate;
                }
            }
        }
        return null;
    }

    /**
     * Clears the cache of accessors. This method is invoked when the classpath changed,
     * in order to discard the references to classes that may need to be unloaded.
     */
    static void clearCache() {
        for (final MetadataStandard standard : INSTANCES) {
            standard.accessors.clear();
        }
    }

    /**
     * Returns a bibliographical reference to the international standard.
     * The default implementation return the citation given at construction time.
     *
     * @return bibliographical reference to the international standard.
     */
    public Citation getCitation() {
        return citation;
    }

    /**
     * Returns a key for use in {@link #getAccessor(CacheKey, boolean)} for the given type.
     * The type may be an interface (typically a GeoAPI interface) or an implementation class.
     */
    private CacheKey createCacheKey(Class<?> type) {
        final Class<?> implementation = getImplementation(type);
        if (implementation != null) {
            type = implementation;
        }
        return new CacheKey(type);
    }

    /**
     * Returns the accessor for the specified implementation class, or {@code null} if none.
     * The given class shall not be the standard interface, unless the metadata is read-only.
     * More specifically, the given {@code type} shall be one of the following:
     *
     * <ul>
     *   <li>The value of {@code metadata.getClass()};</li>
     *   <li>The value of {@link #getImplementation(Class)} after check for non-null value.</li>
     * </ul>
     *
     * @param  key        the implementation class together with the type declared by the property.
     * @param  mandatory  whether this method shall throw an exception or return {@code null}
     *         if no accessor is found for the given implementation class.
     * @return the accessor for the given implementation, or {@code null} if the given class does not
     *         implement a metadata interface of the expected package and {@code mandatory} is {@code false}.
     * @throws ClassCastException if the specified class does not implement a metadata interface
     *         of the expected package and {@code mandatory} is {@code true}.
     */
    final PropertyAccessor getAccessor(final CacheKey key, final boolean mandatory) {
        /*
         * Check for accessors created by previous calls to this method.
         * Values are added to this cache but never cleared.
         */
        final Object value = accessors.get(key);
        if (value instanceof PropertyAccessor) {
            return (PropertyAccessor) value;
        }
        /*
         * Check if we started some computation that we can finish. A partial computation exists
         * when we already found the Class<?> for the interface, but didn't created the accessor.
         */
        final Class<?> type;
        if (value instanceof Class<?>) {
            type = (Class<?>) value;                        // Stored result of previous call to findInterface(…).
            assert type == findInterface(key) : key;
        } else if (key.isValid()) {
            /*
             * Nothing was computed, we need to start from scratch. The first step is to find
             * the interface implemented by the given class. If we can not find an interface,
             * we will delegate to the dependencies and store the result for avoiding redoing
             * this search next time.
             */
            type = findInterface(key);
            if (type == null) {
                if (dependencies != null) {
                    for (final MetadataStandard dependency : dependencies) {
                        final PropertyAccessor accessor = dependency.getAccessor(key, false);
                        if (accessor != null) {
                            accessors.put(key, accessor);               // Ok to overwrite existing instance here.
                            return accessor;
                        }
                    }
                }
                if (mandatory) {
                    throw new ClassCastException(key.unrecognized());
                }
                return null;
            }
        } else {
            throw new ClassCastException(key.invalid());
        }
        /*
         * Found the interface for which to create an accessor. Creates the accessor now, unless an accessor
         * has been created concurrently in another thread in which case the later will be returned.
         */
        return (PropertyAccessor) accessors.compute(key, (k, v) -> {
            if (v instanceof PropertyAccessor) {
                return v;
            }
            final Class<?> standardImpl = getImplementation(type);
            final PropertyAccessor accessor;
            if (SpecialCases.isSpecialCase(type)) {
                accessor = new SpecialCases(type, k.type, standardImpl);
            } else {
                accessor = new PropertyAccessor(type, k.type, standardImpl);
            }
            return accessor;
        });
    }

    /**
     * Returns {@code true} if the given type is assignable to a type from this standard or one of its dependencies.
     * If this method returns {@code true}, then invoking {@link #getInterface(Class)} is guaranteed to succeed
     * without throwing an exception.
     *
     * @param  type  the implementation class (can be {@code null}).
     * @return {@code true} if the given class is an interface of this standard,
     *         or implements an interface of this standard.
     */
    public boolean isMetadata(final Class<?> type) {
        return (type != null) && !type.isPrimitive() && isMetadata(new CacheKey(type));
    }

    /**
     * Implementation of {@link #isMetadata(Class)} with the possibility to specify the property type.
     * We do not provide the additional functionality of this method in public API on the assumption
     * that if the user know the base metadata type implemented by the value, then (s)he already know
     * that the value is a metadata instance.
     *
     * @see #getInterface(CacheKey)
     */
    private boolean isMetadata(final CacheKey key) {
        assert key.isValid() : key;
        if (accessors.containsKey(key)) {
            return true;
        }
        if (dependencies != null) {
            for (final MetadataStandard dependency : dependencies) {
                if (dependency.isMetadata(key)) {
                    accessors.putIfAbsent(key, dependency);
                    return true;
                }
            }
        }
        /*
         * At this point, all cached values (including those in dependencies) have been checked.
         * Performs the 'findInterface' computation only in last resort. Current implementation
         * does not store negative results in order to avoid filling the cache with unrelated classes.
         */
        final Class<?> standardType = findInterface(key);
        if (standardType != null) {
            accessors.putIfAbsent(key, standardType);
            return true;
        }
        return false;
    }

    /**
     * Returns {@code true} if the given implementation class, normally rejected by {@link #findInterface(CacheKey)},
     * should be accepted as a pseudo-interface. We use this undocumented feature when Apache SIS experiments a new
     * API which is not yet published in GeoAPI. This happen for example when upgrading Apache SIS public API from
     * the ISO 19115:2003 standard to the ISO 19115:2014 version, but GeoAPI interfaces are still the old version.
     * In such case, API that would normally be present in GeoAPI interfaces are temporarily available only in
     * Apache SIS implementation classes.
     */
    boolean isPendingAPI(final Class<?> type) {
        return false;
    }

    /**
     * Returns the metadata interface implemented by the specified implementation.
     * Only one metadata interface can be implemented. If the given type is already
     * an interface from the standard, then it is returned directly.
     *
     * <p>If the given class is the return value of a property, then the type of that property should be specified
     * in the {@code key.propertyType} argument. This information allows this method to take in account only types
     * that are assignable to {@code propertyType}, so we can handle classes that implement many metadata interfaces.
     * For example the {@link org.apache.sis.internal.simple} package have various examples of implementing more than
     * one interface for convenience.</p>
     *
     * <p>This method ignores dependencies. Fallback on metadata standard dependencies shall be done by the caller.</p>
     *
     * @param  key  the standard interface or the implementation class.
     * @return the single interface, or {@code null} if none where found.
     */
    private Class<?> findInterface(final CacheKey key) {
        assert key.isValid() : key;
        if (key.type.isInterface()) {
            if (isSupported(key.type.getName())) {
                return key.type;
            }
        } else {
            /*
             * Gets every interfaces from the supplied package in declaration order,
             * including the ones declared in the super-class.
             */
            final Set<Class<?>> interfaces = new LinkedHashSet<>();
            for (Class<?> t=key.type; t!=null; t=t.getSuperclass()) {
                getInterfaces(t, key.propertyType, interfaces);
            }
            /*
             * If we found more than one interface, removes the
             * ones that are sub-interfaces of the other.
             */
            for (final Iterator<Class<?>> it=interfaces.iterator(); it.hasNext();) {
                final Class<?> candidate = it.next();
                for (final Class<?> child : interfaces) {
                    if (candidate != child && candidate.isAssignableFrom(child)) {
                        it.remove();
                        break;
                    }
                }
            }
            final Iterator<Class<?>> it = interfaces.iterator();
            if (it.hasNext()) {
                final Class<?> candidate = it.next();
                if (!it.hasNext()) {
                    return candidate;
                }
                /*
                 * Found more than one interface; we don't know which one to pick.
                 * Returns 'null' for now; the caller will thrown an exception.
                 */
            } else if (IMPLEMENTATION_CAN_ALTER_API) {
                /*
                 * Found no interface. According to our method contract we should return null.
                 * However we make an exception if the implementation class has a UML annotation.
                 * The reason is that when upgrading  API  from ISO 19115:2003 to ISO 19115:2014,
                 * implementations are provided in Apache SIS before the corresponding interfaces
                 * are published on GeoAPI. The reason why GeoAPI is slower to upgrade is that we
                 * have to go through a voting process inside the Open Geospatial Consortium (OGC).
                 * So we use those implementation classes as a temporary substitute for the interfaces.
                 */
                if (isPendingAPI(key.type)) {
                    return key.type;
                }
            }
        }
        return null;
    }

    /**
     * Puts every interfaces for the given type in the specified collection.
     * This method invokes itself recursively for scanning parent interfaces.
     *
     * <p>If the given class is the return value of a property, then the type of that property should be specified
     * in the {@code propertyType} argument. This information allows this method to take in account only the types
     * that are assignable to {@code propertyType}, so we can handle classes that implement many metadata interfaces.
     * For example the {@link org.apache.sis.internal.simple} package have various examples of implementing more than
     * one interface for convenience.</p>
     *
     * @see Classes#getAllInterfaces(Class)
     */
    private void getInterfaces(final Class<?> type, final Class<?> propertyType, final Collection<Class<?>> interfaces) {
        for (final Class<?> candidate : type.getInterfaces()) {
            if (propertyType.isAssignableFrom(candidate)) {
                if (isSupported(candidate.getName())) {
                    interfaces.add(candidate);
                }
                getInterfaces(candidate, propertyType, interfaces);
            } else if (IMPLEMENTATION_CAN_ALTER_API) {
                /*
                 * If a GeoAPI interface is not assignable to the property type, maybe it is because the property type
                 * did not existed at the time current GeoAPI version was published. In such case, the implementation
                 * class may be a placeholder (pending API) for the not-yet-published GeoAPI interfaces. In that case
                 * we skip the `isAssignableFrom` check, but without recursive addition of parent interfaces since we
                 * would not know when to stop.
                 */
                if (isPendingAPI(propertyType)) {
                    if (isSupported(candidate.getName())) {
                        interfaces.add(candidate);
                    }
                    // No recursive call here.
                }
            }
        }
    }

    /**
     * Returns the metadata interface implemented by the specified implementation class.
     * If the given type is already an interface from this standard, then it is returned
     * unchanged.
     *
     * <div class="note"><b>Note:</b>
     * The word "interface" may be taken in a looser sense than the usual Java sense because
     * if the given type is defined in this standard package, then it is returned unchanged.
     * The standard package is usually made of interfaces and code lists only, but this is
     * not verified by this method.</div>
     *
     * @param  <T>   the compile-time {@code type}.
     * @param  type  the implementation class.
     * @return the interface implemented by the given implementation class.
     * @throws ClassCastException if the specified implementation class does not implement an interface of this standard.
     *
     * @see AbstractMetadata#getInterface()
     */
    public <T> Class<? super T> getInterface(final Class<T> type) throws ClassCastException {
        ensureNonNull("type", type);
        return getInterface(new CacheKey(type));
    }

    /**
     * Implementation of {@link #getInterface(Class)} with the possibility to specify the property type.
     * We do not provide the additional functionality of this method in public API on the assumption that
     * users who want to invoke a {@code getInterface(…)} method does not know what that interface is.
     * In Apache SIS case, we invoke this method when we almost know what the interface is but want to
     * check if the actual value is a subtype.
     *
     * @see #isMetadata(CacheKey)
     */
    @SuppressWarnings("unchecked")
    final <T> Class<? super T> getInterface(final CacheKey key) throws ClassCastException {
        final Class<?> interf;
        final Object value = accessors.get(key);
        if (value instanceof PropertyAccessor) {
            interf = ((PropertyAccessor) value).type;
        } else if (value instanceof Class<?>) {
            interf = (Class<?>) value;
        } else if (value instanceof MetadataStandard) {
            interf = ((MetadataStandard) value).getInterface(key);
        } else if (key.isValid()) {
            interf = findInterface(key);
            if (interf != null) {
                accessors.putIfAbsent(key, interf);
            } else {
                if (dependencies != null) {
                    for (final MetadataStandard dependency : dependencies) {
                        if (dependency.isMetadata(key)) {
                            accessors.putIfAbsent(key, dependency);
                            return dependency.getInterface(key);
                        }
                    }
                }
                throw new ClassCastException(key.unrecognized());
            }
        } else {
            throw new ClassCastException(key.invalid());
        }
        assert interf.isAssignableFrom(key.type) : key;
        return (Class<? super T>) interf;
    }

    /**
     * Returns the implementation class for the given interface, or {@code null} if none.
     * If non-null, the returned class must have a public no-argument constructor and the
     * metadata instance created by that constructor must be initially empty (no default value).
     * That no-argument constructor should never throw any checked exception.
     *
     * <p>The default implementation returns {@code null} in every cases. Subclasses shall
     * override this method in order to map GeoAPI interfaces to their implementation.</p>
     *
     * @param  <T>   the compile-time {@code type}.
     * @param  type  the interface, typically from the {@code org.opengis.metadata} package.
     * @return the implementation class, or {@code null} if none.
     */
    public <T> Class<? extends T> getImplementation(final Class<T> type) {
        return null;
    }

    /**
     * Returns a value of the "title" property of the given metadata object.
     * The title property is defined by {@link TitleProperty} annotation on the implementation class.
     *
     * @param  metadata  the metadata for which to get the title property, or {@code null}.
     * @return the title property value of the given metadata, or {@code null} if none.
     *
     * @see TitleProperty
     * @see ValueExistencePolicy#COMPACT
     */
    final Object getTitle(final Object metadata) {
        if (metadata != null) {
            final Class<?> type = metadata.getClass();
            final PropertyAccessor accessor = getAccessor(createCacheKey(type), false);
            if (accessor != null) {
                TitleProperty an = type.getAnnotation(TitleProperty.class);
                if (an != null || (an = accessor.implementation.getAnnotation(TitleProperty.class)) != null) {
                    return accessor.get(accessor.indexOf(an.name(), false), metadata);
                }
            }
        }
        return null;
    }

    /**
     * Returns the names of all properties defined in the given metadata type.
     * The property names appears both as keys and as values, but may be written differently.
     * The names may be {@linkplain KeyNamePolicy#UML_IDENTIFIER standard identifiers} (e.g.
     * as defined by ISO 19115), {@linkplain KeyNamePolicy#JAVABEANS_PROPERTY JavaBeans names},
     * {@linkplain KeyNamePolicy#METHOD_NAME method names} or {@linkplain KeyNamePolicy#SENTENCE
     * sentences} (usually in English).
     *
     * <div class="note"><b>Example:</b>
     * The following code prints <code>"alternateTitle<u>s</u>"</code> (note the plural):
     *
     * {@preformat java
     *   MetadataStandard standard = MetadataStandard.ISO_19115;
     *   Map<String, String> names = standard.asNameMap(Citation.class, UML_IDENTIFIER, JAVABEANS_PROPERTY);
     *   String value = names.get("alternateTitle");
     *   System.out.println(value);                   // alternateTitles
     * }
     * </div>
     *
     * The {@code keyPolicy} argument specify only the string representation of keys returned by the iterators.
     * No matter the key name policy, the {@code key} argument given to any {@link Map} method can be any of the
     * above-cited forms of property names.
     *
     * @param  type         the interface or implementation class of a metadata.
     * @param  keyPolicy    determines the string representation of map keys.
     * @param  valuePolicy  determines the string representation of map values.
     * @return the names of all properties defined by the given metadata type.
     * @throws ClassCastException if the specified interface or implementation class does
     *         not extend or implement a metadata interface of the expected package.
     */
    public Map<String,String> asNameMap(final Class<?> type, final KeyNamePolicy keyPolicy,
            final KeyNamePolicy valuePolicy) throws ClassCastException
    {
        ensureNonNull("type",        type);
        ensureNonNull("keyPolicy",   keyPolicy);
        ensureNonNull("valuePolicy", valuePolicy);
        return new NameMap(getAccessor(createCacheKey(type), true), keyPolicy, valuePolicy);
    }

    /**
     * Returns the type of all properties, or their declaring type, defined in the given metadata type.
     * The keys in the returned map are the same than the keys in the above {@linkplain #asNameMap name map}.
     * The values are determined by the {@code valuePolicy} argument, which can be
     * {@linkplain TypeValuePolicy#ELEMENT_TYPE element type} or the
     * {@linkplain TypeValuePolicy#DECLARING_INTERFACE declaring interface} among others.
     *
     * <div class="note"><b>Example:</b>
     * the following code prints the {@link org.opengis.util.InternationalString} class name:
     *
     * {@preformat java
     *   MetadataStandard  standard = MetadataStandard.ISO_19115;
     *   Map<String,Class<?>> types = standard.asTypeMap(Citation.class, UML_IDENTIFIER, ELEMENT_TYPE);
     *   Class<?> value = types.get("alternateTitle");
     *   System.out.println(value);                       // class org.opengis.util.InternationalString
     * }
     * </div>
     *
     * @param  type         the interface or implementation class of a metadata.
     * @param  keyPolicy    determines the string representation of map keys.
     * @param  valuePolicy  whether the values shall be property types, the element types
     *         (same as property types except for collections) or the declaring interface or class.
     * @return the types or declaring type of all properties defined in the given metadata type.
     * @throws ClassCastException if the specified interface or implementation class does
     *         not extend or implement a metadata interface of the expected package.
     */
    public Map<String,Class<?>> asTypeMap(final Class<?> type, final KeyNamePolicy keyPolicy,
            final TypeValuePolicy valuePolicy) throws ClassCastException
    {
        ensureNonNull("type",        type);
        ensureNonNull("keyPolicy",   keyPolicy);
        ensureNonNull("valuePolicy", valuePolicy);
        return new TypeMap(getAccessor(createCacheKey(type), true), keyPolicy, valuePolicy);
    }

    /**
     * Returns information about all properties defined in the given metadata type.
     * The keys in the returned map are the same than the keys in the above
     * {@linkplain #asNameMap name map}. The values contain information inferred from
     * the ISO names, the {@link org.opengis.annotation.Obligation} enumeration and the
     * {@link org.apache.sis.measure.ValueRange} annotations.
     *
     * <p>In the particular case of Apache SIS implementation, all values in the information map
     * additionally implement the following interfaces:</p>
     * <ul>
     *   <li>{@link Identifier} with the following properties:
     *     <ul>
     *       <li>The {@linkplain Identifier#getAuthority() authority} is this metadata standard {@linkplain #getCitation() citation}.</li>
     *       <li>The {@linkplain Identifier#getCodeSpace() codespace} is the standard name of the interface that contain the property.</li>
     *       <li>The {@linkplain Identifier#getCode() code} is the standard name of the property.</li>
     *     </ul>
     *   </li>
     *   <li>{@link CheckedContainer} with the following properties:
     *     <ul>
     *       <li>The {@linkplain CheckedContainer#getElementType() element type} is the type of property values
     *           as defined by {@link TypeValuePolicy#ELEMENT_TYPE}.</li>
     *     </ul>
     *   </li>
     * </ul>
     *
     * <div class="note"><b>Note:</b>
     * the rational for implementing {@code CheckedContainer} is to consider each {@code ExtendedElementInformation}
     * instance as the set of all possible values for the property. If the information had a {@code contains(E)} method,
     * it would return {@code true} if the given value is valid for that property.</div>
     *
     * In addition, for each map entry the value returned by {@link ExtendedElementInformation#getDomainValue()}
     * may optionally be an instance of any of the following classes:
     *
     * <ul>
     *   <li>{@link org.apache.sis.measure.NumberRange} if the valid values are constrained to some specific range.</li>
     * </ul>
     *
     * @param  type       the metadata interface or implementation class.
     * @param  keyPolicy  determines the string representation of map keys.
     * @return information about all properties defined in the given metadata type.
     * @throws ClassCastException if the given type does not implement a metadata interface of the expected package.
     *
     * @see org.apache.sis.metadata.iso.DefaultExtendedElementInformation
     */
    public Map<String,ExtendedElementInformation> asInformationMap(final Class<?> type, final KeyNamePolicy keyPolicy)
            throws ClassCastException
    {
        ensureNonNull("type",     type);
        ensureNonNull("keyNames", keyPolicy);
        return new InformationMap(citation, getAccessor(createCacheKey(type), true), keyPolicy);
    }

    /**
     * Returns indices for all properties defined in the given metadata type.
     * The keys in the returned map are the same than the keys in the above {@linkplain #asNameMap name map}.
     * The values are arbitrary indices numbered from 0 inclusive to <var>n</var> exclusive, where <var>n</var>
     * is the number of properties declared in the given metadata type.
     *
     * <p>Property indices may be used as an alternative to property names by some applications doing their own storage.
     * Such index usages are fine for temporary storage during the Java Virtual Machine lifetime, but indices should not
     * be used in permanent storage. The indices are stable as long as the metadata implementation does not change,
     * but may change when the implementation is upgraded to a newer version.</p>
     *
     * @param  type       the interface or implementation class of a metadata.
     * @param  keyPolicy  determines the string representation of map keys.
     * @return indices of all properties defined by the given metadata type.
     * @throws ClassCastException if the specified interface or implementation class does
     *         not extend or implement a metadata interface of the expected package.
     */
    public Map<String,Integer> asIndexMap(final Class<?> type, final KeyNamePolicy keyPolicy)
            throws ClassCastException
    {
        ensureNonNull("type",      type);
        ensureNonNull("keyPolicy", keyPolicy);
        return new IndexMap(getAccessor(createCacheKey(type), true), keyPolicy);
    }

    /**
     * Returns a view of the specified metadata object as a {@link Map}.
     * The map is backed by the metadata object using Java reflection, so changes in the
     * underlying metadata object are immediately reflected in the map and conversely.
     *
     * <p>The map content is determined by the arguments: {@code metadata} determines the set of
     * keys, {@code keyPolicy} determines their {@code String} representations of those keys and
     * {@code valuePolicy} determines whether entries having a null value or an empty collection
     * shall be included in the map.</p>
     *
     * <h4>Supported operations</h4>
     * The map supports the {@link Map#put(Object, Object) put(…)} and {@link Map#remove(Object)
     * remove(…)} operations if the underlying metadata object contains setter methods.
     * The {@code remove(…)} method is implemented by a call to {@code put(…, null)}.
     * Note that whether the entry appears as effectively removed from the map or just cleared
     * (i.e. associated to a null value) depends on the {@code valuePolicy} argument.
     *
     * <h4>Keys and values</h4>
     * The keys are case-insensitive and can be either the JavaBeans property name, the getter method name
     * or the {@linkplain org.opengis.annotation.UML#identifier() UML identifier}. The value given to a call
     * to the {@code put(…)} method shall be an instance of the type expected by the corresponding setter method,
     * or an instance of a type {@linkplain org.apache.sis.util.ObjectConverters#find(Class, Class) convertible}
     * to the expected type.
     *
     * <h4>Multi-values entries</h4>
     * Calls to {@code put(…)} replace the previous value, with one noticeable exception: if the metadata
     * property associated to the given key is a {@link java.util.Collection} but the given value is a single
     * element (not a collection), then the given value is {@linkplain java.util.Collection#add(Object) added}
     * to the existing collection. In other words, the returned map behaves as a <cite>multi-values map</cite>
     * for the properties that allow multiple values. If the intent is to unconditionally discard all previous
     * values, then make sure that the given value is a collection when the associated metadata property expects
     * such collection.
     *
     * <h4>Disambiguating instances that implement more than one metadata interface</h4>
     * It is some time convenient to implement more than one interface by the same class.
     * For example an implementation interested only in extents defined by geographic bounding boxes could implement
     * {@link org.opengis.metadata.extent.Extent} and {@link org.opengis.metadata.extent.GeographicBoundingBox}
     * by the same class. In such case, it is necessary to tell to this method which one of those two interfaces
     * shall be reflected in the returned map. This information can be provided by the {@code baseType} argument.
     * That argument needs to be non-null only in situations where an ambiguity can arise; {@code baseType} can be null
     * if the given metadata implements only one interface recognized by this {@code MetadataStandard} instance.
     *
     * @param  metadata     the metadata object to view as a map.
     * @param  baseType     base type of the metadata of interest, or {@code null} if unspecified.
     * @param  keyPolicy    determines the string representation of map keys.
     * @param  valuePolicy  whether the entries having null value or empty collection shall be included in the map.
     * @return a map view over the metadata object.
     * @throws ClassCastException if the metadata object does not implement a metadata interface of the expected package.
     *
     * @see AbstractMetadata#asMap()
     *
     * @since 0.8
     */
    public Map<String,Object> asValueMap(final Object metadata, final Class<?> baseType,
            final KeyNamePolicy keyPolicy, final ValueExistencePolicy valuePolicy) throws ClassCastException
    {
        ensureNonNull("metadata",    metadata);
        ensureNonNull("keyPolicy",   keyPolicy);
        ensureNonNull("valuePolicy", valuePolicy);
        return new ValueMap(metadata, getAccessor(new CacheKey(metadata.getClass(), baseType), true), keyPolicy, valuePolicy);
    }

    /**
     * Returns the specified metadata object as a tree table.
     * The tree table is backed by the metadata object using Java reflection, so changes in the
     * underlying metadata object are immediately reflected in the tree table and conversely.
     *
     * <p>The returned {@code TreeTable} instance contains the following columns:</p>
     * <ul class="verbose">
     *   <li>{@link org.apache.sis.util.collection.TableColumn#IDENTIFIER}<br>
     *       The {@linkplain org.opengis.annotation.UML#identifier() UML identifier} if any,
     *       or the Java Beans property name otherwise, of a metadata property. For example
     *       in a tree table view of {@link org.apache.sis.metadata.iso.citation.DefaultCitation},
     *       there is a node having the {@code "title"} identifier.</li>
     *
     *   <li>{@link org.apache.sis.util.collection.TableColumn#INDEX}<br>
     *       If the metadata property is a collection, then the zero-based index of the element in that collection.
     *       Otherwise {@code null}. For example in a tree table view of {@code DefaultCitation}, if the
     *       {@code "alternateTitle"} collection contains two elements, then there is a node with index 0
     *       for the first element and an other node with index 1 for the second element.
     *
     *       <div class="note"><b>Note:</b>
     *       The {@code (IDENTIFIER, INDEX)} pair can be used as a primary key for uniquely identifying a node
     *       in a list of children. That uniqueness is guaranteed only for the children of a given node;
     *       the same keys may appear in the children of any other nodes.</div></li>
     *
     *   <li>{@link org.apache.sis.util.collection.TableColumn#NAME}<br>
     *       A human-readable name for the node, derived from the identifier and the index.
     *       This is the column shown in the default {@link #toString()} implementation and
     *       may be localizable.</li>
     *
     *   <li>{@link org.apache.sis.util.collection.TableColumn#TYPE}<br>
     *       The base type of the value (usually an interface).</li>
     *
     *   <li>{@link org.apache.sis.util.collection.TableColumn#VALUE}<br>
     *       The metadata value for the node. Values in this column are writable if the underlying
     *       metadata class have a setter method for the property represented by the node.</li>
     *
     *   <li>{@link org.apache.sis.util.collection.TableColumn#REMARKS}<br>
     *       Remarks or warning on the property value. This is rarely present.
     *       It is provided when the value may look surprising, for example the longitude values
     *       in a geographic bounding box spanning the anti-meridian.</li>
     * </ul>
     *
     * <h4>Write operations</h4>
     * Only the {@code VALUE} column may be writable, with one exception: newly created children need
     * to have their {@code IDENTIFIER} set before any other operation. For example the following code
     * adds a title to a citation:
     *
     * {@preformat java
     *     TreeTable.Node node = ...;                               // The node for a DefaultCitation.
     *     TreeTable.Node child = node.newChild();
     *     child.setValue(TableColumn.IDENTIFIER, "title");
     *     child.setValue(TableColumn.VALUE, "Le petit prince");
     *     // Nothing else to do - the child node has been added.
     * }
     *
     * Nodes can be removed by invoking the {@link java.util.Iterator#remove()} method on the
     * {@linkplain org.apache.sis.util.collection.TreeTable.Node#getChildren() children} iterator.
     * Note that whether the child appears as effectively removed from the node or just cleared
     * (i.e. associated to a null value) depends on the {@code valuePolicy} argument.
     *
     * <h4>Disambiguating instances that implement more than one metadata interface</h4>
     * If the given {@code metadata} instance implements more than one interface recognized by this
     * {@code MetadataStandard}, then the {@code baseType} argument need to be non-null in order to
     * specify which interface to reflect in the tree.
     *
     * @param  metadata     the metadata object to view as a tree table.
     * @param  baseType     base type of the metadata of interest, or {@code null} if unspecified.
     * @param  valuePolicy  whether the property having null value or empty collection shall be included in the tree.
     * @return a tree table representation of the specified metadata.
     * @throws ClassCastException if the metadata object does not implement a metadata interface of the expected package.
     *
     * @see AbstractMetadata#asTreeTable()
     *
     * @since 0.8
     */
    public TreeTable asTreeTable(final Object metadata, Class<?> baseType, final ValueExistencePolicy valuePolicy)
            throws ClassCastException
    {
        ensureNonNull("metadata",    metadata);
        ensureNonNull("valuePolicy", valuePolicy);
        if (baseType == null) {
            baseType = getInterface(metadata.getClass());
        }
        return new TreeTableView(this, metadata, baseType, valuePolicy);
    }

    /**
     * Compares the two specified metadata objects.
     * The two metadata arguments shall be implementations of a metadata interface defined by
     * this {@code MetadataStandard}, otherwise an exception will be thrown. However the two
     * arguments do not need to be the same implementation class.
     *
     * <h4>Shallow or deep comparisons</h4>
     * This method implements a <cite>shallow</cite> comparison in that properties are compared by
     * invoking their {@code properties.equals(…)} method without <em>explicit</em> recursive call
     * to this {@code standard.equals(…)} method for children metadata. However the comparison will
     * do <em>implicit</em> recursive calls if the {@code properties.equals(…)} implementations
     * delegate their work to this {@code standard.equals(…)} method, as {@link AbstractMetadata} does.
     * In the later case, the final result is a deep comparison.
     *
     * @param  metadata1  the first metadata object to compare.
     * @param  metadata2  the second metadata object to compare.
     * @param  mode       the strictness level of the comparison.
     * @return {@code true} if the given metadata objects are equals.
     * @throws ClassCastException if at least one metadata object does not
     *         implement a metadata interface of the expected package.
     *
     * @see AbstractMetadata#equals(Object, ComparisonMode)
     */
    public boolean equals(final Object metadata1, final Object metadata2,
            final ComparisonMode mode) throws ClassCastException
    {
        if (metadata1 == metadata2) {
            return true;
        }
        if (metadata1 == null || metadata2 == null) {
            return false;
        }
        final Class<?> type1 = metadata1.getClass();
        final Class<?> type2 = metadata2.getClass();
        if (type1 != type2 && mode == ComparisonMode.STRICT) {
            return false;
        }
        final PropertyAccessor accessor = getAccessor(new CacheKey(type1), true);
        if (type1 != type2 && (!accessor.type.isAssignableFrom(type2)
                || accessor.type != getAccessor(new CacheKey(type2), false).type))
        {
            /*
             * Note: the check for (accessor.type != getAccessor(…).type) would have been enough, but checking
             * for isAssignableFrom(…) first can avoid the (relatively costly) creation of new PropertyAccessor.
             */
            return false;
        }
        /*
         * At this point, we have to perform the actual property-by-property comparison.
         * Cycle may exist in metadata tree, so we have to keep trace of pair in process
         * of being compared for avoiding infinite recursivity.
         */
        final ObjectPair pair = new ObjectPair(metadata1, metadata2);
        final Set<ObjectPair> inProgress = ObjectPair.CURRENT.get();
        if (inProgress.add(pair)) {
            /*
             * The NULL_COLLECTION semaphore prevents creation of new empty collections by getter methods
             * (a consequence of lazy instantiation). The intent is to avoid creation of unnecessary objects
             * for all unused properties. Users should not see behavioral difference, except if they override
             * some getters with an implementation invoking other getters. However in such cases, users would
             * have been exposed to null values at XML marshalling time anyway.
             */
            final boolean allowNull = Semaphores.queryAndSet(Semaphores.NULL_COLLECTION);
            try {
                return accessor.equals(metadata1, metadata2, mode);
            } finally {
                inProgress.remove(pair);
                if (!allowNull) {
                    Semaphores.clear(Semaphores.NULL_COLLECTION);
                }
            }
        } else {
            /*
             * If we get here, a cycle has been found. Returns 'true' in order to allow the caller to continue
             * comparing other properties. It is okay because someone else is comparing those two same objects,
             * and that later comparison will do the actual check for property values.
             */
            return true;
        }
    }

    /**
     * Computes a hash code for the specified metadata. The hash code is defined as the sum
     * of hash code values of all non-empty properties, plus the hash code of the interface.
     * This is a similar contract than {@link java.util.Set#hashCode()} (except for the interface)
     * and ensures that the hash code value is insensitive to the ordering of properties.
     *
     * @param  metadata  the metadata object to compute hash code.
     * @return a hash code value for the specified metadata, or 0 if the given metadata is null.
     * @throws ClassCastException if the metadata object does not implement a metadata interface of the expected package.
     *
     * @see AbstractMetadata#hashCode()
     */
    public int hashCode(final Object metadata) throws ClassCastException {
        if (metadata != null) {
            final Integer hash = HashCode.getOrCreate().walk(this, null, metadata, true);
            if (hash != null) return hash;
            /*
             * 'hash' may be null if a cycle has been found. Example: A depends on B which depends on A,
             * in which case the null value is returned for the second occurrence of A (not the first one).
             * We can not compute a hash code value here, but it should be okay since that metadata is part
             * of a bigger metadata object, and that enclosing object should have other properties for computing
             * its hash code.
             */
        }
        return 0;
    }

    /**
     * Returns a string representation of this metadata standard.
     * This is for debugging purpose only and may change in any future version.
     */
    @Override
    public String toString() {
        return Strings.bracket(getClass(), citation.getTitle());
    }

    /**
     * Assigns a {@link ConcurrentMap} instance to the given field.
     * Used on deserialization only.
     */
    static <T extends MetadataStandard> void setMapForField(final Class<T> classe, final T instance, final String name)
            throws InvalidClassException
    {
        try {
            AccessController.doPrivileged(new FinalFieldSetter<>(classe, name)).set(instance, new ConcurrentHashMap<>());
        } catch (ReflectiveOperationException e) {
            throw FinalFieldSetter.readFailure(e);
        }
    }

    /**
     * Invoked during deserialization for restoring the transient fields.
     *
     * @param  in  the input stream from which to deserialize a metadata standard.
     * @throws IOException if an I/O error occurred while reading or if the stream contains invalid data.
     * @throws ClassNotFoundException if the class serialized on the stream is not on the classpath.
     */
    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        setMapForField(MetadataStandard.class, this, "accessors");
    }
}
