/*
 * 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.commons.chain2.impl;

import org.apache.commons.chain2.Context;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * <p>Convenience base class for {@link Context} implementations.</p>
 *
 * <p>In addition to the minimal functionality required by the {@link Context}
 * interface, this class implements the recommended support for
 * <em>Attribute-Property Transparency</em>. This is implemented by
 * analyzing the available JavaBeans properties of this class (or its
 * subclass), exposes them as key-value pairs in the <code>Map</code>,
 * with the key being the name of the property itself.</p>
 *
 * <p><strong>IMPLEMENTATION NOTE</strong> - Because <code>empty</code> is a
 * read-only property defined by the <code>Map</code> interface, it may not
 * be utilized as an attribute key or property name.</p>
 *
 * @version $Id$
 */
public class ContextBase extends ContextMap<String, Object> {

    // ------------------------------------------------------------ Constructors

    /**
     *
     */
    private static final long serialVersionUID = 20120724L;

    /**
     * Default, no argument constructor.
     */
    public ContextBase() {
        super();
        initialize();
    }

    /**
     * <p>Initialize the contents of this {@link Context} by copying the
     * values from the specified <code>Map</code>.  Any keys in <code>map</code>
     * that correspond to local properties will cause the setter method for
     * that property to be called.</p>
     *
     * @param map Map whose key-value pairs are added
     *
     * @throws IllegalArgumentException if an exception is thrown
     *  writing a local property value
     * @throws UnsupportedOperationException if a local property does not
     *  have a write method.
     */
    public ContextBase(Map<? extends String, ? extends Object> map) {
        super(map);
        initialize();
        putAll(map);
    }

    // ------------------------------------------------------ Instance Variables

    // NOTE - PropertyDescriptor instances are not Serializable, so the
    // following variables must be declared as transient.  When a ContextBase
    // instance is deserialized, the no-arguments constructor is called,
    // and the initialize() method called there will repoopulate them.
    // Therefore, no special restoration activity is required.

    /**
     * <p>The <code>PropertyDescriptor</code>s for all JavaBeans properties
     * of this {@link Context} implementation class, keyed by property name.
     * This collection is allocated only if there are any JavaBeans
     * properties.</p>
     */
    private transient Map<String, PropertyDescriptor> descriptors = null;

    /**
     * <p>The same <code>PropertyDescriptor</code>s as an array.</p>
     */
    private transient PropertyDescriptor[] pd = null;

    /**
     * <p>Distinguished singleton value that is stored in the map for each
     * key that is actually a property.  This value is used to ensure that
     * <code>equals()</code> comparisons will always fail.</p>
     */
    private static final Object singleton;

    static {
        singleton = new Serializable() {
                private static final long serialVersionUID = 20120724L;

                @Override
                public boolean equals(Object object) {
                    return false;
                }

                @Override
                public int hashCode() {
                    return super.hashCode();
                }
            };
    }

    /**
     * <p>Zero-length array of parameter values for calling property getters.
     * </p>
     */
    private static Object[] zeroParams = new Object[0];

    // ------------------------------------------------------------- Map Methods

    /**
     * <p>Override the default <code>Map</code> behavior to clear all keys and
     * values except those corresponding to JavaBeans properties.</p>
     */
    @Override
    public void clear() {
        if (descriptors == null) {
            super.clear();
        } else {
            Iterator<String> keys = keySet().iterator();
            while (keys.hasNext()) {
                String key = keys.next();
                if (!descriptors.containsKey(key)) {
                    keys.remove();
                }
            }
        }
    }

    /**
     * <p>Override the default <code>Map</code> behavior to return
     * <code>true</code> if the specified value is present in either the
     * underlying <code>Map</code> or one of the local property values.</p>
     *
     * @param value the value look for in the context.
     * @return <code>true</code> if found in this context otherwise
     *  <code>false</code>.
     * @throws IllegalArgumentException if a property getter
     *  throws an exception
     */
    @Override
    public boolean containsValue(Object value) {
        // Case 1 -- no local properties
        if (descriptors == null) {
            return super.containsValue(value);

        // Case 2 -- value found in the underlying Map
        } else if (super.containsValue(value)) {
            return true;
        }

        // Case 3 -- check the values of our readable properties
        for (PropertyDescriptor aPd : pd) {
            if (aPd.getReadMethod() != null) {
                Object prop = readProperty(aPd);
                if (value == null) {
                    if (prop == null) {
                        return true;
                    }
                } else if (value.equals(prop)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * <p>Override the default <code>Map</code> behavior to return a
     * <code>Set</code> that meets the specified default behavior except
     * for attempts to remove the key for a property of the {@link Context}
     * implementation class, which will throw
     * <code>UnsupportedOperationException</code>.</p>
     *
     * @return Set of entries in the Context.
     */
    @Override
    public Set<Entry<String, Object>> entrySet() {
        return new EntrySetImpl();
    }

    /**
     * <p>Override the default <code>Map</code> behavior to return the value
     * of a local property if the specified key matches a local property name.
     * </p>
     *
     * <p><strong>IMPLEMENTATION NOTE</strong> - If the specified
     * <code>key</code> identifies a write-only property, <code>null</code>
     * will arbitrarily be returned, in order to avoid difficulties implementing
     * the contracts of the <code>Map</code> interface.</p>
     *
     * @param key Key of the value to be returned
     * @return The value for the specified key.
     *
     * @throws IllegalArgumentException if an exception is thrown
     *  reading this local property value
     * @throws UnsupportedOperationException if this local property does not
     *  have a read method.
     */
    @Override
    public Object get(Object key) {
        // Case 1 -- no local properties
        if (descriptors == null) {
            return super.get(key);
        }

        // Case 2 -- this is a local property
        if (key != null) {
            PropertyDescriptor descriptor = descriptors.get(key);
            if (descriptor != null) {
                if (descriptor.getReadMethod() != null) {
                    return readProperty(descriptor);
                } else {
                    return null;
                }
            }
        }

        // Case 3 -- retrieve value from our underlying Map
        return super.get(key);
    }

    /**
     * <p>Override the default <code>Map</code> behavior to return
     * <code>true</code> if the underlying <code>Map</code> only contains
     * key-value pairs for local properties (if any).</p>
     *
     * @return <code>true</code> if this Context is empty, otherwise
     *  <code>false</code>.
     */
    @Override
    public boolean isEmpty() {
        // Case 1 -- no local properties
        if (descriptors == null) {
            return super.isEmpty();
        }

        // Case 2 -- compare key count to property count
        return super.size() <= descriptors.size();
    }

    /**
     * <p>Override the default <code>Map</code> behavior to return a
     * <code>Set</code> that meets the specified default behavior except
     * for attempts to remove the key for a property of the {@link Context}
     * implementation class, which will throw
     * <code>UnsupportedOperationException</code>.</p>
     *
     * @return The set of keys for objects in this Context.
     */
    @Override
    public Set<String> keySet() {
        return super.keySet();
    }

    /**
     * <p>Override the default <code>Map</code> behavior to set the value
     * of a local property if the specified key matches a local property name.
     * </p>
     *
     * @param key Key of the value to be stored or replaced
     * @param value New value to be stored
     * @return The value added to the Context.
     *
     * @throws IllegalArgumentException if an exception is thrown
     *  reading or writing this local property value
     * @throws UnsupportedOperationException if this local property does not
     *  have both a read method and a write method
     */
    @Override
    public Object put(String key, Object value) {
        /*
         * ConcurrentHashMap doesn't accept null values, see
         * http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html#put(String, Object)
         */
        if (value == null) {
            if (containsKey(key)) {
                remove(key);
            }

            return null;
        }

        // Case 1 -- no local properties
        if (descriptors == null) {
            return super.put(key, value);
        }

        // Case 2 -- this is a local property
        if (key != null) {
            PropertyDescriptor descriptor = descriptors.get(key);
            if (descriptor != null) {
                Object previous = null;
                if (descriptor.getReadMethod() != null) {
                    previous = readProperty(descriptor);
                }
                writeProperty(descriptor, value);
                return previous;
            }
        }

        // Case 3 -- store or replace value in our underlying map
        return super.put(key, value);
    }

    /**
     * <p>Override the default <code>Map</code> behavior to call the
     * <code>put()</code> method individually for each key-value pair
     * in the specified <code>Map</code>.</p>
     *
     * @param map <code>Map</code> containing key-value pairs to store
     *  (or replace)
     *
     * @throws IllegalArgumentException if an exception is thrown
     *  reading or writing a local property value
     * @throws UnsupportedOperationException if a local property does not
     *  have both a read method and a write method
     */
    @Override
    public void putAll(Map<? extends String, ? extends Object> map) {
        for (Entry<? extends String, ? extends Object> pair : map.entrySet()) {
            put(pair.getKey(), pair.getValue());
        }
    }

    /**
     * <p>Override the default <code>Map</code> behavior to throw
     * <code>UnsupportedOperationException</code> on any attempt to
     * remove a key that is the name of a local property.</p>
     *
     * @param key Key to be removed
     * @return The value removed from the Context.
     *
     * @throws UnsupportedOperationException if the specified
     *  <code>key</code> matches the name of a local property
     */
    @Override
    public Object remove(Object key) {
        // Case 1 -- no local properties
        if (descriptors == null) {
            return super.remove(key);
        }

        // Case 2 -- this is a local property
        if (key != null) {
            PropertyDescriptor descriptor = descriptors.get(key);
            if (descriptor != null) {
                throw new UnsupportedOperationException
                    ("Local property '" + key + "' cannot be removed");
            }
        }

        // Case 3 -- remove from underlying Map
        return super.remove(key);
    }

    /**
     * <p>Override the default <code>Map</code> behavior to return a
     * <code>Collection</code> that meets the specified default behavior except
     * for attempts to remove the key for a property of the {@link Context}
     * implementation class, which will throw
     * <code>UnsupportedOperationException</code>.</p>
     *
     * @return The collection of values in this Context.
     */
    @Override
    public Collection<Object> values() {
        return new ValuesImpl();
    }

    // --------------------------------------------------------- Private Methods

    /**
     * <p>Return an <code>Iterator</code> over the set of <code>Map.Entry</code>
     * objects representing our key-value pairs.</p>
     */
    private Iterator<Entry<String, Object>> entriesIterator() {
        return new EntrySetIterator();
    }

    /**
     * <p>Return a <code>Map.Entry</code> for the specified key value, if it
     * is present; otherwise, return <code>null</code>.</p>
     *
     * @param key Attribute key or property name
     */
    private Map.Entry<String, Object> entry(String key) {
        if (containsKey(key)) {
            return new MapEntryImpl(key, get(key));
        }
        return null;
    }

    /**
     * <p>Customize the contents of our underlying <code>Map</code> so that
     * it contains keys corresponding to all of the JavaBeans properties of
     * the {@link Context} implementation class.</p>
     *
     *
     * @throws IllegalArgumentException if an exception is thrown
     *  writing this local property value
     * @throws UnsupportedOperationException if this local property does not
     *  have a write method.
     */
    private void initialize() {
        // Retrieve the set of property descriptors for this Context class
        try {
            pd = Introspector.getBeanInfo
                (getClass()).getPropertyDescriptors();
        } catch (IntrospectionException e) {
            pd = new PropertyDescriptor[0]; // Should never happen
        }

        // Initialize the underlying Map contents
        for (PropertyDescriptor propertyDescriptor : pd) {
            String name = propertyDescriptor.getName();

            // Add descriptor (ignoring getClass() and isEmpty())
            if (!("class".equals(name) || "empty".equals(name))) {
                if (descriptors == null) {
                    descriptors = new HashMap<String, PropertyDescriptor>(pd.length - 2);
                }
                descriptors.put(name, propertyDescriptor);
                super.put(name, singleton);
            }
        }
    }

    /**
     * <p>Get and return the value for the specified property.</p>
     *
     * @param descriptor <code>PropertyDescriptor</code> for the
     *  specified property
     *
     * @throws IllegalArgumentException if an exception is thrown
     *  reading this local property value
     * @throws UnsupportedOperationException if this local property does not
     *  have a read method.
     */
    private Object readProperty(PropertyDescriptor descriptor) {
        try {
            Method method = descriptor.getReadMethod();
            if (method == null) {
                throw new UnsupportedOperationException
                    ("Property '" + descriptor.getName()
                     + "' is not readable");
            }
            return method.invoke(this, zeroParams);
        } catch (Exception e) {
            throw new UnsupportedOperationException
                ("Exception reading property '" + descriptor.getName()
                 + "': " + e.getMessage());
        }
    }

    /**
     * <p>Remove the specified key-value pair, if it exists, and return
     * <code>true</code>.  If this pair does not exist, return
     * <code>false</code>.</p>
     *
     * @param entry Key-value pair to be removed
     *
     * @throws UnsupportedOperationException if the specified key
     *  identifies a property instead of an attribute
     */
    private boolean remove(Map.Entry<String, Object> entry) {
        Map.Entry<String, Object> actual = entry(entry.getKey());
        if (actual == null) {
            return false;
        } else if (!entry.equals(actual)) {
            return false;
        } else {
            remove(entry.getKey());
            return true;
        }
    }

    /**
     * <p>Return an <code>Iterator</code> over the set of values in this
     * <code>Map</code>.</p>
     */
    private Iterator<Object> valuesIterator() {
        return new ValuesIterator();
    }

    /**
     * <p>Set the value for the specified property.</p>
     *
     * @param descriptor <code>PropertyDescriptor</code> for the
     *  specified property
     * @param value The new value for this property (must be of the
     *  correct type)
     *
     * @throws IllegalArgumentException if an exception is thrown
     *  writing this local property value
     * @throws UnsupportedOperationException if this local property does not
     *  have a write method.
     */
    private void writeProperty(PropertyDescriptor descriptor, Object value) {
        try {
            Method method = descriptor.getWriteMethod();
            if (method == null) {
                throw new UnsupportedOperationException
                    ("Property '" + descriptor.getName()
                     + "' is not writeable");
            }
            method.invoke(this, new Object[] {value});
        } catch (Exception e) {
            throw new UnsupportedOperationException
                ("Exception writing property '" + descriptor.getName()
                 + "': " + e.getMessage());
        }
    }

    // --------------------------------------------------------- Private Classes

    /**
     * <p>Private implementation of <code>Set</code> that implements the
     * semantics required for the value returned by <code>entrySet()</code>.</p>
     */
    private class EntrySetImpl extends AbstractSet<Entry<String, Object>> {

        @Override
        public void clear() {
            ContextBase.this.clear();
        }

        @Override
        public boolean contains(Object obj) {
            if (!(obj instanceof Map.Entry)) {
                return false;
            }

            /* The contains method is expecting the search type to be of the
             * same type stored. This contract is enforced as a precondition.
             * So we can safely suppress type safety warnings below. */
            @SuppressWarnings("unchecked")
            Map.Entry<String, Object> entry = (Map.Entry<String, Object>) obj;
            Entry<String, Object> actual = ContextBase.this.entry(entry.getKey());
            if (actual != null) {
                return actual.equals(entry);
            }
            return false;
        }

        @Override
        public boolean isEmpty() {
            return ContextBase.this.isEmpty();
        }

        @Override
        public Iterator<Entry<String, Object>> iterator() {
            return ContextBase.this.entriesIterator();
        }

        @Override
        public boolean remove(Object obj) {
            if (obj instanceof Map.Entry) {

                /* The remove method is expecting an input of the the same
                 * type as the entry set. This precondition is checked above,
                 * so we can safely suppress the unchecked warnings. */
                @SuppressWarnings("unchecked")
                Map.Entry<String, Object> entry = (Map.Entry<String, Object>) obj;
                return ContextBase.this.remove(entry);
            }
            return false;
        }

        @Override
        public int size() {
            return ContextBase.this.size();
        }

    }

    /**
     * <p>Private implementation of <code>Iterator</code> for the
     * <code>Set</code> returned by <code>entrySet()</code>.</p>
     */
    private class EntrySetIterator implements Iterator<Entry<String, Object>> {

        private Map.Entry<String, Object> entry = null;

        private Iterator<String> keys = ContextBase.this.keySet().iterator();

        public boolean hasNext() {
            return keys.hasNext();
        }

        public Entry<String, Object> next() {
            entry = ContextBase.this.entry(keys.next());
            return entry;
        }

        public void remove() {
            ContextBase.this.remove(entry);
        }

    }

    /**
     * <p>Private implementation of <code>Map.Entry</code> for each item in
     * <code>EntrySetImpl</code>.</p>
     */
    private class MapEntryImpl implements Map.Entry<String, Object> {

        MapEntryImpl(String key, Object value) {
            this.key = key;
            this.value = value;
        }

        private String key;

        private Object value;

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            } else if (!(obj instanceof Map.Entry)) {
                return false;
            }
            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj;
            if (key == null) {
                return entry.getKey() == null;
            }
            if (key.equals(entry.getKey())) {
                if (value == null) {
                    return entry.getValue() == null;
                }
                return value.equals(entry.getValue());
            }
            return false;
        }

        public String getKey() {
            return this.key;
        }

        public Object getValue() {
            return this.value;
        }

        @Override
        public int hashCode() {
            return (key == null ? 0 : key.hashCode())
                   ^ (value == null ? 0 : value.hashCode());
        }

        public Object setValue(Object value) {
            Object previous = this.value;
            ContextBase.this.put(this.key, value);
            this.value = value;
            return previous;
        }

        @Override
        public String toString() {
            return getKey() + "=" + getValue();
        }
    }


    /**
     * <p>Private implementation of <code>Collection</code> that implements the
     * semantics required for the value returned by <code>values()</code>.</p>
     */
    private class ValuesImpl extends AbstractCollection<Object> {

        @Override
        public void clear() {
            ContextBase.this.clear();
        }

        @Override
        public boolean contains(Object obj) {
            if (!(obj instanceof Map.Entry)) {
                return false;
            }
            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj;
            return ContextBase.this.containsValue(entry.getValue());
        }

        @Override
        public boolean isEmpty() {
            return ContextBase.this.isEmpty();
        }

        @Override
        public Iterator<Object> iterator() {
            return ContextBase.this.valuesIterator();
        }

        @Override
        public boolean remove(Object obj) {
            if (obj instanceof Map.Entry) {

                /* We are expecting the passed entry to be of a type
                 * Entry<String, Object>. This is checked in the precondition
                 * above, so we can safely suppress unchecked warnings. */
                @SuppressWarnings("unchecked")
                Map.Entry<String, Object> entry = (Map.Entry<String, Object>) obj;
                return ContextBase.this.remove(entry);
            }
            return false;
        }

        @Override
        public int size() {
            return ContextBase.this.size();
        }

    }


    /**
     * <p>Private implementation of <code>Iterator</code> for the
     * <code>Collection</code> returned by <code>values()</code>.</p>
     */
    private class ValuesIterator implements Iterator<Object> {

        private Map.Entry<String, Object> entry = null;

        private Iterator<String> keys = ContextBase.this.keySet().iterator();

        public boolean hasNext() {
            return keys.hasNext();
        }

        public Object next() {
            entry = ContextBase.this.entry(keys.next());
            return entry.getValue();
        }

        public void remove() {
            ContextBase.this.remove(entry);
        }

    }

}
