/*******************************************************************************
 * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
 * This program and the accompanying materials are made available under the 
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
 * which accompanies this distribution. 
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at 
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     Oracle - initial API and implementation from Oracle TopLink
 ******************************************************************************/  
package org.eclipse.persistence.indirection;

import java.beans.PropertyChangeListener;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.persistence.descriptors.changetracking.CollectionChangeEvent;
import org.eclipse.persistence.descriptors.changetracking.CollectionChangeTracker;
import org.eclipse.persistence.descriptors.changetracking.MapChangeEvent;

/**
 * IndirectMap allows a domain class to take advantage of TopLink indirection
 * without having to declare its instance variable as a ValueHolderInterface.
 * <p>To use an IndirectMap:<ul>
 * <li> Declare the appropriate instance variable with type Map or Hashtable
 * <li> Send the message #useTransparentMap(String) to the appropriate
 * CollectionMapping.
 * </ul>
 * EclipseLink will place an
 * IndirectMap in the instance variable when the containing domain object is read from
 * the datatabase. With the first message sent to the IndirectMap, the contents
 * are fetched from the database and normal Hashtable/Map behavior is resumed.
 *
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 * @see org.eclipse.persistence.mappings.CollectionMapping
 * @see org.eclipse.persistence.indirection.IndirectList
 * @author Big Country
 * @since TOPLink/Java 2.5
 */
public class IndirectMap<K, V> extends Hashtable<K, V> implements CollectionChangeTracker, IndirectCollection {

    /** Reduce type casting */
    protected volatile Hashtable<K, V> delegate;

    /** Delegate indirection behavior to a value holder */
    protected ValueHolderInterface valueHolder;

    /** Change tracking listener. */
    private transient PropertyChangeListener changeListener;
    
    /** The mapping attribute name, used to raise change events. */
    private transient String attributeName;

    /** Store initial size for lazy init. */
    protected int initialCapacity = 11;

    /** Store load factor for lazy init. */
    protected float loadFactor = 0.75f;

    /**
     * PUBLIC:
     * Construct a new, empty IndirectMap with a default
     * capacity and load factor.
     */
    public IndirectMap() {
        this(11);
    }

    /**
     * PUBLIC:
     * Construct a new, empty IndirectMap with the specified initial capacity
     * and default load factor.
     *
     * @param   initialCapacity   the initial capacity of the hashtable
     */
    public IndirectMap(int initialCapacity) {
        this(initialCapacity, 0.75f);
    }

    /**
     * PUBLIC:
     * Construct a new, empty IndirectMap with the specified initial
     * capacity and load factor.
     *
     * @param      initialCapacity   the initial capacity of the hashtable
     * @param      loadFactor        a number between 0.0 and 1.0
     * @exception  IllegalArgumentException  if the initial capacity is less
     *               than or equal to zero, or if the load factor is less than
     *               or equal to zero
     */
    public IndirectMap(int initialCapacity, float loadFactor) {
        super(0);
        this.initialize(initialCapacity, loadFactor);
    }

    /**
     * PUBLIC:
     * Construct a new IndirectMap with the same mappings as the given Map.
     * The IndirectMap is created with a capacity of twice the number of entries
     * in the given Map or 11 (whichever is greater), and a default load factor, which is 0.75.
     * @param m a map containing the mappings to use
     */
    public IndirectMap(Map<? extends K, ? extends V> m) {
        super(0);
        this.initialize(m);
    }

    /**
     * Return the freshly-built delegate.
     */
    protected Hashtable<K, V> buildDelegate() {
        Hashtable<K, V> value = (Hashtable<K, V>)getValueHolder().getValue();
        if (value == null) {
            value = new Hashtable<>(this.initialCapacity, this.loadFactor);
        }
        return value;
    }

    /**
     * @see java.util.Hashtable#clear()
     */
    @Override
    public synchronized void clear() {
        if (hasTrackedPropertyChangeListener()) {
            Iterator<K> objects = this.keySet().iterator();
            while (objects.hasNext()) {
                K o = objects.next();
                objects.remove();
                this.raiseRemoveChangeEvent(o, this.get(o));
            }
        } else {
            this.getDelegate().clear();
        }
    }

    
    /**
     * INTERNAL:
     * clear any changes that have been deferred to instantiation.
     * Indirect collections with change tracking avoid instantiation on add/remove.
     */
    @Override
    public void clearDeferredChanges(){
    }
    
    /**
     * @see java.util.Hashtable#clone()
     * This will result in a database query if necessary.
     */

    /*
        There are 3 situations when clone() is called:
        1.    The developer actually wants to clone the collection (typically to modify one
            of the 2 resulting collections). In which case the contents must be read from
            the database.
        2.    A UnitOfWork needs a clone (or backup clone) of the collection. But the
            UnitOfWork checks "instantiation" before cloning collections ("un-instantiated"
            collections are not cloned).
        3.    A MergeManager needs an extra copy of the collection (because the "backup"
            and "target" are the same object?). But the MergeManager checks "instantiation"
            before merging collections (again, "un-instantiated" collections are not merged).
    */
    @Override
    public synchronized Object clone() {
        IndirectMap<K, V> result = (IndirectMap<K, V>)super.clone();
        result.delegate = (Hashtable<K, V>)this.getDelegate().clone();
        result.valueHolder = new ValueHolder(result.delegate);
        result.attributeName = null;
        result.changeListener = null;
        return result;
    }

    /**
     * @see java.util.Hashtable#contains(java.lang.Object)
     */
    @Override
    public synchronized boolean contains(Object value) {
        return this.getDelegate().contains(value);
    }

    /**
     * @see java.util.Hashtable#containsKey(java.lang.Object)
     */
    @Override
    public synchronized boolean containsKey(Object key) {
        return this.getDelegate().containsKey(key);
    }

    /**
     * @see java.util.Hashtable#containsValue(java.lang.Object)
     */
    @Override
    public boolean containsValue(Object value) {
        return this.getDelegate().containsValue(value);
    }

    /**
     * @see java.util.Hashtable#elements()
     */
    @Override
    public synchronized Enumeration<V> elements() {
        return this.getDelegate().elements();
    }

    /**
     * @see java.util.Hashtable#entrySet()
     */
    @Override
    public Set<Map.Entry<K,V>> entrySet() {
        return new Set<Map.Entry<K,V>> (){
            Set<Map.Entry<K,V>> delegateSet = IndirectMap.this.getDelegate().entrySet();
            
            @Override
            public int size(){
                return this.delegateSet.size();
            }
        
            @Override
            public boolean isEmpty(){
                return this.delegateSet.isEmpty();
            }
        
            @Override
            public boolean contains(Object o){
                return this.delegateSet.contains(o);
            }
        
            @Override
            public Iterator<Map.Entry<K,V>> iterator(){
                return new Iterator<Map.Entry<K,V>>() {
                    Iterator<Map.Entry<K, V>> delegateIterator = delegateSet.iterator();
                    Map.Entry<K, V> currentObject;
                    
                    @Override
                    public boolean hasNext() {
                        return this.delegateIterator.hasNext();
                    }
                    
                    @Override
                    public Map.Entry<K, V> next() {
                        this.currentObject = this.delegateIterator.next();
                        return this.currentObject;
                    }
                    
                    @Override
                    public void remove() {
                        raiseRemoveChangeEvent(currentObject.getKey(), currentObject.getValue());
                        this.delegateIterator.remove();
                    }
                };
            }
        
            @Override
            public Object[] toArray(){
                return this.delegateSet.toArray();
            }
    
            @Override
            public <T> T[] toArray(T a[]){
                return this.delegateSet.toArray(a);
            }
    
            @Override
            public boolean add(Map.Entry<K, V> o){
                return this.delegateSet.add(o);
            }
        
            @Override
            public boolean remove(Object o){
                if (!(o instanceof Map.Entry)) {
                    return false;
                }
                return (IndirectMap.this.remove(((Map.Entry)o).getKey()) != null);
            }
        
            @Override
            public boolean containsAll(Collection<?> c){
                return this.delegateSet.containsAll(c);
            }
        
            @Override
            public boolean addAll(Collection<? extends Map.Entry<K, V>> c){
                return this.delegateSet.addAll(c);
            }
        
            @Override
            public boolean retainAll(Collection<?> c){
                boolean result = false;
                Iterator objects = delegateSet.iterator();
                while (objects.hasNext()) {
                    Map.Entry object = (Map.Entry)objects.next();
                    if (!c.contains(object)) {
                        objects.remove();
                        raiseRemoveChangeEvent(object.getKey(), object.getValue());
                        result = true;
                    }
                }
                return result;
            }
            
            @Override
            public boolean removeAll(Collection<?> c){
                boolean result = false;
                for (Iterator cs = c.iterator(); cs.hasNext(); ){
                    Object object = cs.next();
                    if ( ! (object instanceof Map.Entry)){
                        continue;
                    }
                    Object removed = IndirectMap.this.remove(((Map.Entry)object).getKey());
                    if (removed != null){
                        result = true;
                    }
                }
                return result;
            }
        
            @Override
            public void clear(){
                IndirectMap.this.clear();
            }
        
            @Override
            public boolean equals(Object o){
                return this.delegateSet.equals(o);
            }
            
            @Override
            public int hashCode(){
                return this.delegateSet.hashCode();
            }
        };
    }

    /**
     * @see java.util.Hashtable#equals(java.lang.Object)
     */
    @Override
    public synchronized boolean equals(Object o) {
        return this.getDelegate().equals(o);
    }

    /**
     * @see java.util.Hashtable#get(java.lang.Object)
     */
    @Override
    public synchronized V get(Object key) {
        return this.getDelegate().get(key);
    }

    /**
     * INTERNAL:
     * Check whether the contents have been read from the database.
     * If they have not, read them and set the delegate.
     * This method used to be synchronized, which caused deadlock.
     */
    protected Hashtable<K, V> getDelegate() {
        if (delegate == null) {
            synchronized(this){
                if (delegate == null) {
                    delegate = this.buildDelegate();
                }
            }
        }
        return delegate;
    }
    
    /**
     * INTERNAL:
     * Return the real collection object.
     * This will force instantiation.
     */
    @Override
    public Object getDelegateObject() {
        return getDelegate();
    }

    /**
     * INTERNAL:
     * Return the mapping attribute name, used to raise change events.
     */
    @Override
     public String getTrackedAttributeName() {
         return attributeName;
     }
     
    /**
     * Return the property change listener for change tracking.
     */
    @Override
     public PropertyChangeListener _persistence_getPropertyChangeListener() {
         return changeListener;
     }
    
     /**
      * PUBLIC:
      * Return the valueHolder.
      * This method used to be synchronized, which caused deadlock.
      */
    @Override
     public ValueHolderInterface getValueHolder() {
         // PERF: lazy initialize value holder and vector as are normally set after creation.
         if (valueHolder == null) {
             synchronized(this){
                 if (valueHolder == null) {
                     valueHolder = new ValueHolder(new Hashtable<>(initialCapacity, loadFactor));
                 }
             }
         }
         return valueHolder;
     }

    /**
     * @see java.util.Hashtable#hashCode()
     */
    @Override
    public synchronized int hashCode() {
        return this.getDelegate().hashCode();
    }

    /**
     * INTERNAL:
     * Return if the collection has a property change listener for change tracking.
     */
     public boolean hasTrackedPropertyChangeListener() {
         return this.changeListener != null;
     }
     
    /**
     * Initialize the instance.
     */
    protected void initialize(int initialCapacity, float loadFactor) {
        this.delegate = null;
        this.loadFactor = loadFactor;
        this.initialCapacity = initialCapacity;
        this.valueHolder = null;
    }

    /**
     * Initialize the instance.
     */
    protected void initialize(Map<? extends K, ? extends V> m) {
        this.delegate = null;
        Hashtable<K, V> temp = new Hashtable<>(m);

        this.valueHolder = new ValueHolder(temp);
    }

    /**
     * @see java.util.Hashtable#isEmpty()
     */
    @Override
    public boolean isEmpty() {
        return this.getDelegate().isEmpty();
    }

    /**
     * PUBLIC:
     * Return whether the contents have been read from the database.
     */
    @Override
    public boolean isInstantiated() {
        return this.getValueHolder().isInstantiated();
    }

    /**
     * @see java.util.Hashtable#keys()
     */
    @Override
    public synchronized Enumeration<K> keys() {
        return this.getDelegate().keys();
    }

    /**
     * @see java.util.Hashtable#keySet()
     */
    @Override
    public Set<K> keySet() {
        
        return new Set<K> (){
            Set<K> delegateSet = IndirectMap.this.getDelegate().keySet();
            
            @Override
            public int size(){
                return this.delegateSet.size();
            }
        
            @Override
            public boolean isEmpty(){
                return this.delegateSet.isEmpty();
            }
        
            @Override
            public boolean contains(Object o){
                return this.delegateSet.contains(o);
            }
        
            @Override
            public Iterator<K> iterator(){
                return new Iterator<K>() {
                    Iterator<K> delegateIterator = delegateSet.iterator();
                    K currentObject;
                    
                    @Override
                    public boolean hasNext() {
                        return this.delegateIterator.hasNext();
                    }
                    
                    @Override
                    public K next() {
                        this.currentObject = this.delegateIterator.next();
                        return this.currentObject;
                    }
                    
                    @Override
                    public void remove() {
                        IndirectMap.this.raiseRemoveChangeEvent(currentObject, IndirectMap.this.getDelegate().get(currentObject));
                        this.delegateIterator.remove();
                    }
                };
            }
        
            @Override
            public Object[] toArray(){
                return this.delegateSet.toArray();
            }
    
            @Override
            public Object[] toArray(Object a[]){
                return this.delegateSet.toArray(a);
            }
    
            @Override
            public boolean add(K o){
                return this.delegateSet.add(o);
            }
        
            @Override
            public boolean remove(Object o){
                return (IndirectMap.this.remove(o) != null);
            }
        
            @Override
            public boolean containsAll(Collection<?> c){
                return this.delegateSet.containsAll(c);
            }
        
            @Override
            public boolean addAll(Collection<? extends K> c){
                return this.delegateSet.addAll(c);
            }
        
            @Override
            public boolean retainAll(Collection<?> c){
                boolean result = false;
                Iterator objects = delegateSet.iterator();
                while (objects.hasNext()) {
                    Object object = objects.next();
                    if (!c.contains(object)) {
                        objects.remove();
                        IndirectMap.this.raiseRemoveChangeEvent(object, IndirectMap.this.getDelegate().get(object));
                        result = true;
                    }
                }
                return result;
            }
            
            @Override
            public boolean removeAll(Collection<?> c){
                boolean result = false;
                for (Iterator<?> cs = c.iterator(); cs.hasNext(); ){
                    if (IndirectMap.this.remove(cs.next()) != null ) {
                        result = true;
                    }
                }
                return result;
            }
        
            @Override
            public void clear(){
                IndirectMap.this.clear();
            }
        
            @Override
            public boolean equals(Object o){
                return this.delegateSet.equals(o);
            }
            
            @Override
            public int hashCode(){
                return this.delegateSet.hashCode();
            }
        };
            
            
    }

    /**
     * @see java.util.Hashtable#put(java.lang.Object, java.lang.Object)
     */
    @Override
    public synchronized V put(K key, V value) {
        V oldValue = this.getDelegate().put(key, value);
        if (oldValue != null){
            raiseRemoveChangeEvent(key, oldValue);
        }
        raiseAddChangeEvent(key, value);
        return oldValue;
    }
    

    /**
     * @see java.util.Hashtable#putAll(java.util.Map)
     */
    @Override
    public synchronized void putAll(Map<? extends K,? extends V> t) {
        // Must trigger add events if tracked or uow.
        if (hasTrackedPropertyChangeListener()) {
            Iterator<? extends K> objects = t.keySet().iterator();
            while (objects.hasNext()) {
                K key = objects.next();
                this.put(key, t.get(key));
            }
        }else{
            this.getDelegate().putAll(t);
        }
    }

    /**
     * @see java.util.Hashtable#rehash()
     */
    @Override
    protected void rehash() {
        throw new InternalError("unsupported");
    }

    /**
     * Raise the add change event and relationship maintainence.
     */
    protected void raiseAddChangeEvent(Object key, Object value) {
        if (hasTrackedPropertyChangeListener()) {
            _persistence_getPropertyChangeListener().propertyChange(new MapChangeEvent(this, getTrackedAttributeName(), this, key, value, CollectionChangeEvent.ADD, true));
        }
        // this is where relationship maintenance would go
    }

    /**
     * Raise the remove change event.
     */
    protected void raiseRemoveChangeEvent(Object key, Object value) {
        if (hasTrackedPropertyChangeListener()) {
            _persistence_getPropertyChangeListener().propertyChange(new MapChangeEvent(this, getTrackedAttributeName(), this, key, value, CollectionChangeEvent.REMOVE, true));
        }
        // this is where relationship maintenance would go
    }

    /**
     * @see java.util.Hashtable#remove(java.lang.Object)
     */
    @Override
    public synchronized V remove(Object key) {
        V value = this.getDelegate().remove(key);
        if (value != null){
            raiseRemoveChangeEvent(key, value);
        }
        return value;
    }

    /**
     * INTERNAL:
     * Set the mapping attribute name, used to raise change events.
     * This is required if the change listener is set.
     */
    @Override
     public void setTrackedAttributeName(String attributeName) {
         this.attributeName = attributeName;
     }

    /**
     * INTERNAL:
     * Set the property change listener for change tracking.
     */
    @Override
     public void _persistence_setPropertyChangeListener(PropertyChangeListener changeListener) {
         this.changeListener = changeListener;
     }
     
    /**
     * INTERNAL:
     * Set the value holder.
     */
    @Override
    public void setValueHolder(ValueHolderInterface valueHolder) {
        this.delegate = null;
        this.valueHolder = valueHolder;
    }

    /**
     * @see java.util.Hashtable#size()
     */
    @Override
    public int size() {
        return this.getDelegate().size();
    }
    
    /**
     * INTERNAL
     * Set whether this collection should attempt do deal with adds and removes without retrieving the 
     * collection from the dB
     */
    @Override
    public void setUseLazyInstantiation(boolean useLazyInstantiation){
    }
    
    /**
     * INTERNAL:
     * Return the elements that have been removed before instantiation.
     */
    @Override
    public Collection getRemovedElements() {
        return null;
    }

    /**
     * INTERNAL:
     * Return the elements that have been added before instantiation.
     */
    @Override
    public Collection getAddedElements() {
        return null;
    }
    
    /**
     * INTERNAL:
     * Return if any elements that have been added or removed before instantiation.
     */
    @Override
    public boolean hasDeferredChanges() {
        return false;
    }

    /**
     * PUBLIC:
     * Use the Hashtable.toString(); but wrap it with braces to indicate
     * there is a bit of indirection.
     * Don't allow this method to trigger a database read.
     * @see java.util.Hashtable#toString()
     */
    @Override
    public String toString() {
        if (ValueHolderInterface.shouldToStringInstantiate) {
            return this.getDelegate().toString();
        }
        if (this.isInstantiated()) {
            return "{" + this.getDelegate().toString() + "}";
        } else {
            return "{" + org.eclipse.persistence.internal.helper.Helper.getShortClassName(this.getClass()) + ": not instantiated}";
        }
    }

    /**
     * @see java.util.Hashtable#values()
     */
    @Override
    public Collection<V> values() {
        return new Collection<V>() {
            protected Collection<V> delegateCollection = IndirectMap.this.getDelegate().values();

            @Override
            public int size(){
                return delegateCollection.size();
            }
            
            @Override
            public boolean isEmpty(){
                return delegateCollection.isEmpty();
            }
            
            @Override
            public boolean contains(Object o){
                return delegateCollection.contains(o);
            }
            
            @Override
            public Iterator<V> iterator() {
                return new Iterator<V>() {
                    Iterator<V> delegateIterator = delegateCollection.iterator();
                    V currentObject;
                    
                    @Override
                    public boolean hasNext() {
                        return this.delegateIterator.hasNext();
                    }
                    
                    @Override
                    public V next() {
                        this.currentObject = this.delegateIterator.next();
                        return this.currentObject;
                    }
                    
                    @Override
                    public void remove() {
                        Iterator iterator = IndirectMap.this.getDelegate().entrySet().iterator();
                        while (iterator.hasNext()){
                            Map.Entry entry = (Map.Entry)iterator.next();
                            if (entry.getValue().equals(currentObject)){
                                IndirectMap.this.raiseRemoveChangeEvent(entry.getKey(), entry.getValue());
                            }
                            
                        }
                        this.delegateIterator.remove();
                    }
                };
            }
        
            @Override
            public Object[] toArray(){
                return this.delegateCollection.toArray();
            }
            
            @Override
            public <T> T[] toArray(T a[]){
                return this.delegateCollection.toArray(a);
            }
            
            @Override
            public boolean add(V o){
                return this.delegateCollection.add(o);
            }
            
            @Override
            public boolean remove(Object o){
                Iterator iterator = IndirectMap.this.getDelegate().entrySet().iterator();
                while (iterator.hasNext()){
                    Map.Entry entry = (Map.Entry)iterator.next();
                    if (entry.getValue().equals(o)){
                        IndirectMap.this.raiseRemoveChangeEvent(entry.getKey(), entry.getValue());
                    }
                    return true;    
                }
                return false;
            }
            
            @Override
            public boolean containsAll(Collection<?> c){
                return this.delegateCollection.containsAll(c);
            }
            
            @Override
            public boolean addAll(Collection<? extends V> c){
                return this.delegateCollection.addAll(c);
            }
            
            @Override
            public boolean removeAll(Collection<?> c){
                boolean result = false;
                for (Iterator<?> iterator = c.iterator(); iterator.hasNext();){
                    if (remove(iterator.next()) ){
                        result = true;
                    }
                }
                return result;
            }
            
            @Override
            public boolean retainAll(Collection<?> c){
                boolean result = false;
                for (Iterator iterator = IndirectMap.this.entrySet().iterator(); iterator.hasNext();){
                    Map.Entry entry = (Map.Entry)iterator.next();
                    if (! c.contains(entry.getValue()) ) {
                        iterator.remove();
                        result = true;
                    }
                }
                return result;
            }
            
            @Override
            public void clear(){
                IndirectMap.this.clear();
            }
            
            
            @Override
            public boolean equals(Object o){
                return this.delegateCollection.equals(o);
            }
            
            @Override
            public int hashCode(){
                return this.delegateCollection.hashCode();
            }
            
        };
    }
}
