/*
 * 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.Arrays;
import java.util.List;
import java.util.Map;
import java.util.IdentityHashMap;
import java.util.ConcurrentModificationException;
import org.apache.sis.internal.system.Semaphores;
import org.apache.sis.internal.util.UnmodifiableArrayList;
import org.apache.sis.util.Exceptions;


/**
 * A visitor of metadata properties with a safety against infinite recursivity.
 * The visitor may compute a result, for example a hash code value or a boolean
 * testing whether the metadata is empty. Each {@code MetadataVisitor} instance
 * is used by one thread; this class does not need to be thread-safe.
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.0
 *
 * @param  <R>  the type of result of walking in the metadata.
 *
 * @since 1.0
 * @module
 */
abstract class MetadataVisitor<R> {
    /**
     * Sentinel value that may be returned by {@link #visit(Class, Object)} for notifying the walker to stop.
     * This value causes {@link #walk walk(…)} to stop its iteration, but does not stop iteration by the parent
     * if {@code walk(…)} has been invoked recursively. The {@link #result()} method shall return a valid result
     * even if the iteration has been terminated.
     */
    static final Object SKIP_SIBLINGS = InterruptedException.class;     // The choice of this type is arbitrary.

    /**
     * A guard against infinite recursivity in {@link #walk(MetadataStandard, Class, Object, boolean)}.
     * Keys are visited metadata instances and values are computed value. The value may be null if
     * the computation is in progress.
     *
     * <h4>The problem</h4>
     * Cyclic associations can exist in ISO 19115 metadata. For example {@code Instrument} has a reference
     * to the platform it is mounted on, and the {@code Platform} has a list of instruments mounted on it.
     * Consequently walking down the metadata tree can cause infinite recursivity, unless we keep trace of
     * previously visited metadata objects in order to avoid visiting them again.
     *
     * We use an {@link IdentityHashMap} for that purpose, since the recursivity problem exists only when revisiting
     * the exact same instance. Furthermore, {@code HashMap} would not suit since it invokes {@code equals(Object)}
     * and {@code hashCode()}, which are among the methods that we want to avoid invoking twice.
     */
    private final Map<Object,R> visited;

    /**
     * The name of the property being visited as the last element of the queue. If {@code visit} method
     * is invoked recursively, then the properties before the last one are the parent properties.
     * The number of valid elements is {@link #nestedCount}.
     */
    private String[] propertyPath;

    /**
     * Count of nested calls to {@link #walk(MetadataStandard, Class, Object, boolean)} method.
     * When this count reach zero, the visitor should be removed from the thread local variable.
     */
    private int nestedCount;

    /**
     * Value of the {@link Semaphores#NULL_COLLECTION} flag when we started the walk.
     * The {@code NULL_COLLECTION} flag 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.
     */
    private boolean allowNull;

    /**
     * Creates a new visitor.
     */
    MetadataVisitor() {
        visited = new IdentityHashMap<>();
        propertyPath = new String[6];
    }

    /**
     * The thread-local variable that created this {@code MetadataVisitor} instance.
     * This is usually a static final {@code VISITORS} constant defined in the subclass.
     * May be {@code null} if this visitor does not use thread-local instances.
     */
    ThreadLocal<? extends MetadataVisitor<?>> creator() {
        return null;
    }

    /**
     * Sets the name of the method being visited. This is invoked by {@code PropertyAccessor.walk} methods only.
     */
    final void setCurrentProperty(final String name) {
        propertyPath[nestedCount - 1] = name;
    }

    /**
     * Returns the path to the currently visited property.
     * Each element in the list is the UML identifier of a property.
     * Element at index 0 is the name of the property of the root metadata object being visited.
     * Element at index 1 is the name of a property which is a children of above property, <i>etc.</i>
     *
     * <p>The returned list is valid only during {@link #visit(Class, Object)} method execution.
     * The content of this list become undetermined after the {@code visit} method returned.</p>
     *
     * @return the path to the currently visited property.
     */
    List<String> getCurrentPropertyPath() {
        return UnmodifiableArrayList.wrap(propertyPath, 0, nestedCount);
    }

    /**
     * Invokes {@link #visit(Class, Object)} for all elements of the given metadata if that metadata has not
     * already been visited. The computation result is returned (may be the result of a previous computation).
     *
     * <p>This method is typically invoked recursively while we iterate down the metadata tree.
     * It creates a map of visited nodes when the iteration begin, and deletes that map when the
     * iteration ends.</p>
     *
     * @param  standard   the metadata standard implemented by the object to visit.
     * @param  type       the standard interface implemented by the metadata object, or {@code null} if unknown.
     * @param  metadata   the metadata to visit.
     * @param  mandatory  {@code true} for throwing an exception for unsupported metadata type, or {@code false} for ignoring.
     * @return the value of {@link #result()} after all elements of the given metadata have been visited.
     *         If the given metadata instance has already been visited, then this is the previously computed value.
     *         If the computation is in progress (e.g. a cyclic graph), then this method returns {@code null}.
     */
    final R walk(final MetadataStandard standard, final Class<?> type, final Object metadata, final boolean mandatory) {
        if (!visited.containsKey(metadata)) {               // Reminder: the associated value may be null.
            final PropertyAccessor accessor = standard.getAccessor(new CacheKey(metadata.getClass(), type), mandatory);
            if (accessor != null) {
                final Filter filter = preVisit(accessor);
                final boolean preconstructed;
                final R sentinel;
                switch (filter) {
                    case NONE:            return null;
                    case WRITABLE_RESULT: preconstructed = true;  sentinel = result(); break;
                    default:              preconstructed = false; sentinel = null;     break;
                }
                if (visited.put(metadata, sentinel) != null) {
                    // Should never happen, unless this method is invoked concurrently in another thread.
                    throw new ConcurrentModificationException();
                }
                if (nestedCount >= propertyPath.length) {
                    propertyPath = Arrays.copyOf(propertyPath, nestedCount * 2);
                }
                if (nestedCount++ == 0) {
                    /*
                     * 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.
                     */
                    allowNull = Semaphores.queryAndSet(Semaphores.NULL_COLLECTION);
                }
                try {
                    switch (filter) {
                        case NON_EMPTY:       accessor.walkReadable(this, metadata); break;
                        case WRITABLE:        accessor.walkWritable(this, metadata, metadata); break;
                        case WRITABLE_RESULT: accessor.walkWritable(this, metadata, sentinel); break;
                    }
                } catch (MetadataVisitorException e) {
                    throw e;
                } catch (Exception e) {
                    e = Exceptions.unwrap(e);
                    throw new MetadataVisitorException(Arrays.copyOf(propertyPath, nestedCount), accessor.type, e);
                } finally {
                    if (--nestedCount == 0) {
                        if (!allowNull) {
                            Semaphores.clear(Semaphores.NULL_COLLECTION);
                        }
                        final ThreadLocal<? extends MetadataVisitor<?>> creator = creator();
                        if (creator != null) creator.remove();
                    }
                }
                final R result = preconstructed ? sentinel : result();
                if (visited.put(metadata, result) != sentinel) {
                    throw new ConcurrentModificationException();
                }
                return result;
            }
        }
        return visited.get(metadata);
    }

    /**
     * Filter the properties to visit. A value of this enumeration is returned by {@link #preVisit(PropertyAccessor)}
     * before the properties of a metadata instance are visited.
     */
    enum Filter {
        /**
         * Do not visit any property (skip completely the metadata).
         */
        NONE,

        /**
         * Visit all non-null and non-empty standard properties.
         */
        NON_EMPTY,

        /**
         * Visit all writable properties. May include some non-standard properties.
         */
        WRITABLE,

        /**
         * Same as {@link #WRITABLE}, but write properties in the object returned by {@link #result()}.
         * This mode implies that {@code result()} is invoked <strong>before</strong> metadata properties
         * are visited instead than after.
         */
        WRITABLE_RESULT
    }

    /**
     * Invoked when a new metadata is about to be visited. After this method has been invoked,
     * {@link #visit(Class, Object)} will be invoked for each property in the metadata object.
     *
     * @param  accessor  information about the standard interface and implementation of the metadata being visited.
     * @return most common values are {@code NON_EMPTY} for visiting all non-empty properties (the default),
     *         or {@code WRITABLE} for visiting only writable properties.
     */
    Filter preVisit(PropertyAccessor accessor) {
        return Filter.NON_EMPTY;
    }

    /**
     * Invoked when a new metadata property is being visited. The current property value is given in argument.
     * The return value is interpreted as below:
     *
     * <ul>
     *   <li>{@link #SKIP_SIBLINGS}: do not iterate over other properties of current metadata,
     *       but continue iteration over properties of the parent metadata.</li>
     *   <li>{@code value}: continue with next sibling property without setting any value.</li>
     *   <li>{@code null}: clear the property value, then continue with next sibling property.
     *       If the property type is a collection, then "null" value is interpreted as an instruction
     *       to {@linkplain java.util.Collection#clear() clear} the collection.</li>
     *   <li>Any other value: set the property value to the given value,
     *       then continue with next sibling property.</li>
     * </ul>
     *
     * @param  type   the type of elements. Note that this is not necessarily the type
     *                of given {@code value} argument if the later is a collection.
     * @param  value  value of the metadata property being visited.
     * @return the new property value to set, or {@link #SKIP_SIBLINGS}.
     * @throws Exception if the visit operation failed.
     */
    abstract Object visit(Class<?> type, Object value) throws Exception;

    /**
     * Returns the result of visiting all elements in a metadata instance.
     * This method is invoked zero or one time per metadata instance.
     * The invocation time depends on the value returned by {@link #preVisit(PropertyAccessor)}:
     *
     * <ul>
     *   <li>If {@link Filter#NONE}, then this method is never invoked for the current metadata instance.</li>
     *   <li>If {@link Filter#NON_EMPTY} or {@link Filter#WRITABLE}, then this method is invoked after all properties
     *       have been visited or after {@link #visit(Class, Object)} returned {@link #SKIP_SIBLINGS}.</li>
     *   <li>If {@link Filter#WRITABLE_RESULT}, then this method is invoked <strong>before</strong> metadata
     *       properties are visited. In such case, this method should return an initially empty instance.</li>
     * </ul>
     *
     * The value returned by this method will be cached in case the same metadata instance is revisited again.
     * This value can be {@code null}.
     */
    R result() {
        return null;
    }
}
