/*
 * 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.beanutils2;

import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

/**
 * <p>A customized implementation of {@code java.util.HashMap} designed
 * to operate in a multi-threaded environment where the large majority of
 * method calls are read-only, instead of structural changes.  When operating
 * in "fast" mode, read calls are non-synchronized and write calls perform the
 * following steps:</p>
 * <ul>
 * <li>Clone the existing collection
 * <li>Perform the modification on the clone
 * <li>Replace the existing collection with the (modified) clone
 * </ul>
 * <p>When first created, objects of this class default to "slow" mode, where
 * all accesses of any type are synchronized but no cloning takes place.  This
 * is appropriate for initially populating the collection, followed by a switch
 * to "fast" mode (by calling {@code setFast(true)}) after initialization
 * is complete.</p>
 *
 * <p><strong>NOTE</strong>: If you are creating and accessing a
 * {@code HashMap} only within a single thread, you should use
 * {@code java.util.HashMap} directly (with no synchronization), for
 * maximum performance.</p>
 *
 * <p><strong>NOTE</strong>: <i>This class is not cross-platform.
 * Using it may cause unexpected failures on some architectures.</i>
 * It suffers from the same problems as the double-checked locking idiom.
 * In particular, the instruction that clones the internal collection and the
 * instruction that sets the internal reference to the clone can be executed
 * or perceived out-of-order.  This means that any read operation might fail
 * unexpectedly, as it may be reading the state of the internal collection
 * before the internal collection is fully formed.
 * For more information on the double-checked locking idiom, see the
 * <a href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">
 * Double-Checked Locking Idiom Is Broken Declaration</a>.</p>
 *
 * @since Commons Collections 1.0
 */
public class WeakFastHashMap<K, V> extends HashMap<K, V> {

    private static final long serialVersionUID = 1L;

    /**
     * The underlying map we are managing.
     */
    private volatile Map<K, V> map = null;

    /**
     * Are we currently operating in "fast" mode?
     */
    private boolean fast = false;

    // Constructors


    /**
     * Construct an empty map.
     */
    public WeakFastHashMap() {
        super();
        this.map = createMap();
    }

    /**
     * Construct an empty map with the specified capacity.
     *
     * @param capacity  the initial capacity of the empty map
     */
    public WeakFastHashMap(final int capacity) {
        super();
        this.map = createMap(capacity);
    }

    /**
     * Construct an empty map with the specified capacity and load factor.
     *
     * @param capacity  the initial capacity of the empty map
     * @param factor  the load factor of the new map
     */
    public WeakFastHashMap(final int capacity, final float factor) {
        super();
        this.map = createMap(capacity, factor);
    }

    /**
     * Construct a new map with the same mappings as the specified map.
     *
     * @param map  the map whose mappings are to be copied
     */
    public WeakFastHashMap(final Map<? extends K, ? extends V> map) {
        super();
        this.map = createMap(map);
    }

    // Property access


    /**
     *  Returns true if this map is operating in fast mode.
     *
     *  @return true if this map is operating in fast mode
     */
    public boolean getFast() {
        return this.fast;
    }

    /**
     *  Sets whether this map is operating in fast mode.
     *
     *  @param fast true if this map should operate in fast mode
     */
    public void setFast(final boolean fast) {
        this.fast = fast;
    }

    // Map access

    // These methods can forward straight to the wrapped Map in 'fast' mode.
    // (because they are query methods)

    /**
     * Return the value to which this map maps the specified key.  Returns
     * {@code null} if the map contains no mapping for this key, or if
     * there is a mapping with a value of {@code null}.  Use the
     * {@code containsKey()} method to disambiguate these cases.
     *
     * @param key  the key whose value is to be returned
     * @return the value mapped to that key, or null
     */
    @Override
    public V get(final Object key) {
        if (fast) {
            return map.get(key);
        }
        synchronized (map) {
            return map.get(key);
        }
    }

    /**
     * Return the number of key-value mappings in this map.
     *
     * @return the current size of the map
     */
    @Override
    public int size() {
        if (fast) {
            return map.size();
        }
        synchronized (map) {
            return map.size();
        }
    }

    /**
     * Return {@code true} if this map contains no mappings.
     *
     * @return is the map currently empty
     */
    @Override
    public boolean isEmpty() {
        if (fast) {
            return map.isEmpty();
        }
        synchronized (map) {
            return map.isEmpty();
        }
    }

    /**
     * Return {@code true} if this map contains a mapping for the
     * specified key.
     *
     * @param key  the key to be searched for
     * @return true if the map contains the key
     */
    @Override
    public boolean containsKey(final Object key) {
        if (fast) {
            return map.containsKey(key);
        }
        synchronized (map) {
            return map.containsKey(key);
        }
    }

    /**
     * Return {@code true} if this map contains one or more keys mapping
     * to the specified value.
     *
     * @param value  the value to be searched for
     * @return true if the map contains the value
     */
    @Override
    public boolean containsValue(final Object value) {
        if (fast) {
            return map.containsValue(value);
        }
        synchronized (map) {
            return map.containsValue(value);
        }
    }

    // Map modification

    // These methods perform special behavior in 'fast' mode.
    // The map is cloned, updated and then assigned back.
    // See the comments at the top as to why this won't always work.

    /**
     * Associate the specified value with the specified key in this map.
     * If the map previously contained a mapping for this key, the old
     * value is replaced and returned.
     *
     * @param key  the key with which the value is to be associated
     * @param value  the value to be associated with this key
     * @return the value previously mapped to the key, or null
     */
    @Override
    public V put(final K key, final V value) {
        if (fast) {
            synchronized (this) {
                final Map<K, V> temp = cloneMap(map);
                final V result = temp.put(key, value);
                map = temp;
                return result;
            }
        }
        synchronized (map) {
            return map.put(key, value);
        }
    }

    /**
     * Copy all of the mappings from the specified map to this one, replacing
     * any mappings with the same keys.
     *
     * @param in  the map whose mappings are to be copied
     */
    @Override
    public void putAll(final Map<? extends K, ? extends V> in) {
        if (fast) {
            synchronized (this) {
                final Map<K, V> temp =  cloneMap(map);
                temp.putAll(in);
                map = temp;
            }
        } else {
            synchronized (map) {
                map.putAll(in);
            }
        }
    }

    /**
     * Remove any mapping for this key, and return any previously
     * mapped value.
     *
     * @param key  the key whose mapping is to be removed
     * @return the value removed, or null
     */
    @Override
    public V remove(final Object key) {
        if (fast) {
            synchronized (this) {
                final Map<K, V> temp = cloneMap(map);
                final V result = temp.remove(key);
                map = temp;
                return result;
            }
        }
        synchronized (map) {
            return map.remove(key);
        }
    }

    /**
     * Remove all mappings from this map.
     */
    @Override
    public void clear() {
        if (fast) {
            synchronized (this) {
                map = createMap();
            }
        } else {
            synchronized (map) {
                map.clear();
            }
        }
    }

    // Basic object methods


    /**
     * Compare the specified object with this list for equality.  This
     * implementation uses exactly the code that is used to define the
     * list equals function in the documentation for the
     * {@code Map.equals} method.
     *
     * @param o  the object to be compared to this list
     * @return true if the two maps are equal
     */
    @Override
    public boolean equals(final Object o) {
        // Simple tests that require no synchronization
        if (o == this) {
            return true;
        } else if (!(o instanceof Map)) {
            return false;
        }
        final Map<?, ?> mo = (Map<?, ?>) o;

        // Compare the two maps for equality
        if (fast) {
            if (mo.size() != map.size()) {
                return false;
            }
            for (final Map.Entry<K, V> e : map.entrySet()) {
                final K key = e.getKey();
                final V value = e.getValue();
                if (value == null) {
                    if (!(mo.get(key) == null && mo.containsKey(key))) {
                        return false;
                    }
                } else {
                    if (!value.equals(mo.get(key))) {
                        return false;
                    }
                }
            }
            return true;

        }
        synchronized (map) {
            if (mo.size() != map.size()) {
                return false;
            }
            for (final Map.Entry<K, V> e : map.entrySet()) {
                final K key = e.getKey();
                final V value = e.getValue();
                if (value == null) {
                    if (!(mo.get(key) == null && mo.containsKey(key))) {
                        return false;
                    }
                } else {
                    if (!value.equals(mo.get(key))) {
                        return false;
                    }
                }
            }
            return true;
        }
    }

    /**
     * Return the hash code value for this map.  This implementation uses
     * exactly the code that is used to define the list hash function in the
     * documentation for the {@code Map.hashCode} method.
     *
     * @return suitable integer hash code
     */
    @Override
    public int hashCode() {
        if (fast) {
            int h = 0;
            for (final Map.Entry<K, V> e : map.entrySet()) {
                h += e.hashCode();
            }
            return h;
        }
        synchronized (map) {
            int h = 0;
            for (final Map.Entry<K, V> e : map.entrySet()) {
                h += e.hashCode();
            }
            return h;
        }
    }

    /**
     * Return a shallow copy of this {@code FastHashMap} instance.
     * The keys and values themselves are not copied.
     *
     * @return a clone of this map
     */
    @Override
    public Object clone() {
        WeakFastHashMap<K, V> results = null;
        if (fast) {
            results = new WeakFastHashMap<>(map);
        } else {
            synchronized (map) {
                results = new WeakFastHashMap<>(map);
            }
        }
        results.setFast(getFast());
        return results;
    }

    // Map views


    /**
     * Return a collection view of the mappings contained in this map.  Each
     * element in the returned collection is a {@code Map.Entry}.
     * @return the set of map Map entries
     */
    @Override
    public Set<Map.Entry<K, V>> entrySet() {
        return new EntrySet();
    }

    /**
     * Return a set view of the keys contained in this map.
     * @return the set of the Map's keys
     */
    @Override
    public Set<K> keySet() {
        return new KeySet();
    }

    /**
     * Return a collection view of the values contained in this map.
     * @return the set of the Map's values
     */
    @Override
    public Collection<V> values() {
        return new Values();
    }

    // Abstractions on Map creations (for subclasses such as WeakFastHashMap)


    protected Map<K, V> createMap() {
        return new WeakHashMap<>();
    }

    protected Map<K, V> createMap(final int capacity) {
        return new WeakHashMap<>(capacity);
    }

    protected Map<K, V> createMap(final int capacity, final float factor) {
        return new WeakHashMap<>(capacity, factor);
    }

    protected Map<K, V> createMap(final Map<? extends K, ? extends V> map) {
        return new WeakHashMap<>(map);
    }

    protected Map<K, V> cloneMap(final Map<? extends K, ? extends V> map) {
        return createMap(map);
    }

    // Map view inner classes


    /**
     * Abstract collection implementation shared by keySet(), values() and entrySet().
     *
     * @param <E> the element type
     */
    private abstract class CollectionView<E> implements Collection<E> {

        public CollectionView() {
        }

        protected abstract Collection<E> get(Map<K, V> map);
        protected abstract E iteratorNext(Map.Entry<K, V> entry);

        @Override
        public void clear() {
            if (fast) {
                synchronized (WeakFastHashMap.this) {
                    map = createMap();
                }
            } else {
                synchronized (map) {
                    get(map).clear();
                }
            }
        }

        @Override
        public boolean remove(final Object o) {
            if (fast) {
                synchronized (WeakFastHashMap.this) {
                    final Map<K, V> temp = cloneMap(map);
                    final boolean r = get(temp).remove(o);
                    map = temp;
                    return r;
                }
            }
            synchronized (map) {
                return get(map).remove(o);
            }
        }

        @Override
        public boolean removeAll(final Collection<?> o) {
            if (fast) {
                synchronized (WeakFastHashMap.this) {
                    final Map<K, V> temp = cloneMap(map);
                    final boolean r = get(temp).removeAll(o);
                    map = temp;
                    return r;
                }
            }
            synchronized (map) {
                return get(map).removeAll(o);
            }
        }

        @Override
        public boolean retainAll(final Collection<?> o) {
            if (fast) {
                synchronized (WeakFastHashMap.this) {
                    final Map<K, V> temp = cloneMap(map);
                    final boolean r = get(temp).retainAll(o);
                    map = temp;
                    return r;
                }
            }
            synchronized (map) {
                return get(map).retainAll(o);
            }
        }

        @Override
        public int size() {
            if (fast) {
                return get(map).size();
            }
            synchronized (map) {
                return get(map).size();
            }
        }

        @Override
        public boolean isEmpty() {
            if (fast) {
                return get(map).isEmpty();
            }
            synchronized (map) {
                return get(map).isEmpty();
            }
        }

        @Override
        public boolean contains(final Object o) {
            if (fast) {
                return get(map).contains(o);
            }
            synchronized (map) {
                return get(map).contains(o);
            }
        }

        @Override
        public boolean containsAll(final Collection<?> o) {
            if (fast) {
                return get(map).containsAll(o);
            }
            synchronized (map) {
                return get(map).containsAll(o);
            }
        }

        @Override
        public <T> T[] toArray(final T[] o) {
            if (fast) {
                return get(map).toArray(o);
            }
            synchronized (map) {
                return get(map).toArray(o);
            }
        }

        @Override
        public Object[] toArray() {
            if (fast) {
                return get(map).toArray();
            }
            synchronized (map) {
                return get(map).toArray();
            }
        }

        @Override
        public boolean equals(final Object o) {
            if (o == this) {
                return true;
            }
            if (fast) {
                return get(map).equals(o);
            }
            synchronized (map) {
                return get(map).equals(o);
            }
        }

        @Override
        public int hashCode() {
            if (fast) {
                return get(map).hashCode();
            }
            synchronized (map) {
                return get(map).hashCode();
            }
        }

        @Override
        public boolean add(final E o) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean addAll(final Collection<? extends E> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public Iterator<E> iterator() {
            return new CollectionViewIterator();
        }

        private class CollectionViewIterator implements Iterator<E> {

            private Map<K, V> expected;
            private Map.Entry<K, V> lastReturned = null;
            private final Iterator<Map.Entry<K, V>> iterator;

            public CollectionViewIterator() {
                this.expected = map;
                this.iterator = expected.entrySet().iterator();
            }

            @Override
            public boolean hasNext() {
                if (expected != map) {
                    throw new ConcurrentModificationException();
                }
                return iterator.hasNext();
            }

            @Override
            public E next() {
                if (expected != map) {
                    throw new ConcurrentModificationException();
                }
                lastReturned = iterator.next();
                return iteratorNext(lastReturned);
            }

            @Override
            public void remove() {
                if (lastReturned == null) {
                    throw new IllegalStateException();
                }
                if (fast) {
                    synchronized (WeakFastHashMap.this) {
                        if (expected != map) {
                            throw new ConcurrentModificationException();
                        }
                        WeakFastHashMap.this.remove(lastReturned.getKey());
                        lastReturned = null;
                        expected = map;
                    }
                } else {
                    iterator.remove();
                    lastReturned = null;
                }
            }
        }
    }

    /**
     * Set implementation over the keys of the FastHashMap
     */
    private class KeySet extends CollectionView<K> implements Set<K> {

        @Override
        protected Collection<K> get(final Map<K, V> map) {
            return map.keySet();
        }

        @Override
        protected K iteratorNext(final Map.Entry<K, V> entry) {
            return entry.getKey();
        }

    }

    /**
     * Collection implementation over the values of the FastHashMap
     */
    private class Values extends CollectionView<V> {

        @Override
        protected Collection<V> get(final Map<K, V> map) {
            return map.values();
        }

        @Override
        protected V iteratorNext(final Map.Entry<K, V> entry) {
            return entry.getValue();
        }
    }

    /**
     * Set implementation over the entries of the FastHashMap
     */
    private class EntrySet extends CollectionView<Map.Entry<K, V>> implements Set<Map.Entry<K, V>> {

        @Override
        protected Collection<Map.Entry<K, V>> get(final Map<K, V> map) {
            return map.entrySet();
        }

        @Override
        protected Map.Entry<K, V> iteratorNext(final Map.Entry<K, V> entry) {
            return entry;
        }

    }

}
