/*
 * 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 javax.xml.bind.annotation.XmlTransient;
import org.apache.sis.util.Emptiable;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.LenientComparable;
import org.apache.sis.util.collection.TreeTable;


/**
 * Provides basic operations using Java reflection for metadata implementations.
 * All {@code AbstractMetadata} instances shall be associated to a {@link MetadataStandard}.
 * The metadata standard is given by the {@link #getStandard()} method and is typically a
 * constant fixed by the subclass.
 *
 * <p>There is a large number of {@code AbstractMetadata} subclasses (not necessarily as direct children)
 * for the same standard, where each subclass implement one Java interface defined by the metadata standard.
 * This base class reduces the effort required to implement those metadata interfaces by providing
 * {@link #equals(Object)}, {@link #hashCode()} and {@link #toString()} implementations.
 * Those methods are implemented using Java reflection for invoking the getter methods
 * defined by the {@code MetadataStandard}.</p>
 *
 * {@code AbstractMetadata} subclasses may be read-only or read/write, at implementation choice.
 * The methods that modify the metadata may throw {@link UnmodifiableMetadataException} if the
 * metadata does not support the operation. Those methods are:
 *
 * <table class="sis">
 * <caption>Metadata operations</caption>
 * <tr>
 *   <th>Read-only operations</th>
 *   <th class="sep">Read/write operations</th>
 * </tr>
 * <tr>
 *   <td><ul>
 *     <li>{@link #isEmpty()}</li>
 *     <li>{@link #asMap()} with {@code get} operations</li>
 *     <li>{@link #asTreeTable()} with {@code getValue} operations</li>
 *     <li>{@link #equals(Object, ComparisonMode)}</li>
 *   </ul></td>
 *   <td class="sep"><ul>
 *     <li>{@link #prune()}</li>
 *     <li>{@link #asMap()} with {@code put} operations</li>
 *     <li>{@link #asTreeTable()} with {@code setValue} operations</li>
 *   </ul></td>
 * </tr>
 * </table>
 *
 * <h2>Thread safety</h2>
 * Instances of this class are <strong>not</strong> synchronized for multi-threading.
 * Synchronization, if needed, is caller's responsibility. Note that synchronization locks
 * are not necessarily the metadata instances. For example an other common approach is to
 * use a single lock for the whole metadata tree (including children).
 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.0
 *
 * @see MetadataStandard
 *
 * @since 0.3
 * @module
 */
@XmlTransient
public abstract class AbstractMetadata implements LenientComparable, Emptiable {
    /**
     * Creates an initially empty metadata.
     */
    protected AbstractMetadata() {
    }

    /**
     * Returns the metadata standard implemented by subclasses.
     * Subclasses will typically return a hard-coded constant such as
     * {@link MetadataStandard#ISO_19115}.
     *
     * <h4>Note for implementers</h4>
     * Implementation of this method shall not depend on the object state,
     * since this method may be indirectly invoked by copy constructors.
     *
     * @return the metadata standard implemented.
     */
    public abstract MetadataStandard getStandard();

    /**
     * Returns the metadata interface implemented by this class. It should be one of the interfaces
     * defined in the {@linkplain #getStandard() metadata standard} implemented by this class.
     *
     * @return the standard interface implemented by this implementation class.
     *
     * @see MetadataStandard#getInterface(Class)
     */
    public Class<?> getInterface() {
        return getStandard().getInterface(getClass());
    }

    /**
     * Returns {@code true} if this metadata contains only {@code null},
     * {@linkplain org.apache.sis.xml.NilObject nil} or empty properties.
     * A non-null and non-nil property is considered empty in any of the following cases:
     *
     * <ul>
     *   <li>An empty {@linkplain CharSequence character sequences}.</li>
     *   <li>An {@linkplain java.util.Collection#isEmpty() empty collection} or an empty array.</li>
     *   <li>A collection or array containing only {@code null}, nil or empty elements.</li>
     *   <li>An other metadata object containing only {@code null}, nil or empty properties.</li>
     * </ul>
     *
     * Note that empty properties can be removed by calling the {@link ModifiableMetadata#prune()} method.
     *
     * <h4>Note for implementers</h4>
     * The default implementation uses Java reflection indirectly, by iterating over all entries
     * returned by {@link MetadataStandard#asValueMap(Object, Class, KeyNamePolicy, ValueExistencePolicy)}.
     * Subclasses that override this method should usually not invoke {@code super.isEmpty()},
     * because the Java reflection will discover and process the properties defined in the
     * subclasses - which is usually not the intent when overriding a method.
     *
     * @return {@code true} if this metadata is empty.
     *
     * @see org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox#isEmpty()
     */
    @Override
    public boolean isEmpty() {
        return Pruner.isEmpty(this, false);
    }

    /**
     * Removes all references to empty properties. The default implementation iterates over all
     * {@linkplain ValueExistencePolicy#NON_NULL non null} properties, and sets to {@code null}
     * the properties for which {@link #isEmpty()} returned {@code true}.
     *
     * @throws UnmodifiableMetadataException if this metadata is not modifiable.
     */
    public void prune() {
        Pruner.isEmpty(this, true);
    }

    /**
     * Returns a view of the property values in a {@link Map}. The map is backed by this metadata
     * object, so changes in the underlying metadata object are immediately reflected in the map
     * and conversely.
     *
     * <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)}.
     *
     * <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>Default implementation</h4>
     * The default implementation is equivalent to the following method call:
     *
     * {@preformat java
     *   return getStandard().asValueMap(this, null, KeyNamePolicy.JAVABEANS_PROPERTY, ValueExistencePolicy.NON_EMPTY);
     * }
     *
     * @return a view of this metadata object as a map.
     *
     * @see MetadataStandard#asValueMap(Object, Class, KeyNamePolicy, ValueExistencePolicy)
     */
    public Map<String,Object> asMap() {
        return getStandard().asValueMap(this, null, KeyNamePolicy.JAVABEANS_PROPERTY, ValueExistencePolicy.NON_EMPTY);
    }

    /**
     * Returns the property types and values 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.
     *
     * <h4>Default implementation</h4>
     * The default implementation is equivalent to the following method call:
     *
     * {@preformat java
     *   return getStandard().asTreeTable(this, null, ValueExistencePolicy.COMPACT);
     * }
     *
     * @return a tree table representation of the specified metadata.
     *
     * @see MetadataStandard#asTreeTable(Object, Class, ValueExistencePolicy)
     */
    public TreeTable asTreeTable() {
        return getStandard().asTreeTable(this, null, ValueExistencePolicy.COMPACT);
    }

    /**
     * Compares this metadata with the specified object for equality. The default
     * implementation uses Java reflection. Subclasses may override this method
     * for better performances, or for comparing "hidden" properties not specified
     * by the GeoAPI (or other standard) interface.
     *
     * @param  object  the object to compare with this metadata.
     * @param  mode    the strictness level of the comparison.
     * @return {@code true} if the given object is equal to this metadata.
     */
    @Override
    public boolean equals(final Object object, final ComparisonMode mode) {
        return getStandard().equals(this, object, mode);
    }

    /**
     * Performs a {@linkplain ComparisonMode#STRICT strict} comparison of this metadata with
     * the given object. This method is implemented as below:
     *
     * {@preformat java
     *     public final boolean equals(final Object object) {
     *         return equals(object, ComparisonMode.STRICT);
     *     }
     * }
     *
     * If a subclass needs to override the behavior of this method, then
     * override {@link #equals(Object, ComparisonMode)} instead.
     *
     * @param  object  the object to compare with this metadata for equality.
     * @return {@code true} if the given object is strictly equals to this metadata.
     */
    @Override
    public final boolean equals(final Object object) {
        return equals(object, ComparisonMode.STRICT);
    }

    /**
     * Computes a hash code value for this metadata using Java reflection. The hash code
     * is defined as the sum of hash code values of all non-empty properties, excluding
     * cyclic dependencies. For acyclic metadata, this method contract is compatible with
     * the {@link java.util.Set#hashCode()} one and ensures that the hash code value is
     * insensitive to the ordering of properties.
     *
     * <div class="note"><b>Implementation note:</b>
     * This method does not cache the value because current implementation has no notification mechanism
     * for tracking changes in children properties. If this metadata is known to be immutable,
     * then subclasses may consider caching the hash code value if performance is important.</div>
     *
     * @see MetadataStandard#hashCode(Object)
     */
    @Override
    public int hashCode() {
        return getStandard().hashCode(this);
    }

    /**
     * Returns a string representation of this metadata.
     * The default implementation is as below:
     *
     * {@preformat java
     *     return asTreeTable().toString();
     * }
     *
     * Note that this make extensive use of Unicode characters
     * and is better rendered with a monospaced font.
     */
    @Override
    public String toString() {
        return asTreeTable().toString();
    }
}
