package org.apache.commons.collections;

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

public class FastHashMap extends HashMap {
  protected HashMap map = null;
  
  protected boolean fast = false;
  
  public FastHashMap() {
    this.map = new HashMap();
  }
  
  public FastHashMap(int paramInt) {
    this.map = new HashMap(paramInt);
  }
  
  public FastHashMap(int paramInt, float paramFloat) {
    this.map = new HashMap(paramInt, paramFloat);
  }
  
  public FastHashMap(Map paramMap) {
    this.map = new HashMap(paramMap);
  }
  
  public void clear() {
    if (this.fast) {
      synchronized (this) {
        HashMap hashMap = (HashMap)this.map.clone();
        hashMap.clear();
        this.map = hashMap;
      } 
    } else {
      synchronized (this.map) {
        this.map.clear();
      } 
    } 
  }
  
  public Object clone() {
    FastHashMap fastHashMap = null;
    if (this.fast) {
      fastHashMap = new FastHashMap(this.map);
    } else {
      synchronized (this.map) {
        fastHashMap = new FastHashMap(this.map);
      } 
    } 
    fastHashMap.setFast(getFast());
    return fastHashMap;
  }
  
  public boolean containsKey(Object paramObject) {
    if (this.fast)
      return this.map.containsKey(paramObject); 
    synchronized (this.map) {
      return this.map.containsKey(paramObject);
    } 
  }
  
  public boolean containsValue(Object paramObject) {
    if (this.fast)
      return this.map.containsValue(paramObject); 
    synchronized (this.map) {
      return this.map.containsValue(paramObject);
    } 
  }
  
  public Set entrySet() {
    return new EntrySet(this);
  }
  
  public boolean equals(Object paramObject) {
    if (paramObject == this)
      return true; 
    if (!(paramObject instanceof Map))
      return false; 
    Map map = (Map)paramObject;
    if (this.fast) {
      if (map.size() != this.map.size())
        return false; 
      for (Map.Entry entry : this.map.entrySet()) {
        Object object1 = entry.getKey();
        Object object2 = entry.getValue();
        if (object2 == null) {
          if (map.get(object1) != null || !map.containsKey(object1))
            return false; 
          continue;
        } 
        if (!object2.equals(map.get(object1)))
          return false; 
      } 
      return true;
    } 
    synchronized (this.map) {
      if (map.size() != this.map.size())
        return false; 
      for (Map.Entry entry : this.map.entrySet()) {
        Object object1 = entry.getKey();
        Object object2 = entry.getValue();
        if (object2 == null) {
          if (map.get(object1) != null || !map.containsKey(object1))
            return false; 
          continue;
        } 
        if (!object2.equals(map.get(object1)))
          return false; 
      } 
      return true;
    } 
  }
  
  public Object get(Object paramObject) {
    if (this.fast)
      return this.map.get(paramObject); 
    synchronized (this.map) {
      return this.map.get(paramObject);
    } 
  }
  
  public boolean getFast() {
    return this.fast;
  }
  
  public int hashCode() {
    if (this.fast) {
      int i = 0;
      Iterator iterator = this.map.entrySet().iterator();
      while (iterator.hasNext())
        i += iterator.next().hashCode(); 
      return i;
    } 
    synchronized (this.map) {
      int i = 0;
      Iterator iterator = this.map.entrySet().iterator();
      while (iterator.hasNext())
        i += iterator.next().hashCode(); 
      return i;
    } 
  }
  
  public boolean isEmpty() {
    if (this.fast)
      return this.map.isEmpty(); 
    synchronized (this.map) {
      return this.map.isEmpty();
    } 
  }
  
  public Set keySet() {
    return new KeySet(this);
  }
  
  public Object put(Object paramObject1, Object paramObject2) {
    if (this.fast)
      synchronized (this) {
        HashMap hashMap = (HashMap)this.map.clone();
        Object object = hashMap.put(paramObject1, paramObject2);
        this.map = hashMap;
        return object;
      }  
    synchronized (this.map) {
      return this.map.put(paramObject1, paramObject2);
    } 
  }
  
  public void putAll(Map paramMap) {
    if (this.fast) {
      synchronized (this) {
        HashMap hashMap = (HashMap)this.map.clone();
        hashMap.putAll(paramMap);
        this.map = hashMap;
      } 
    } else {
      synchronized (this.map) {
        this.map.putAll(paramMap);
      } 
    } 
  }
  
  public Object remove(Object paramObject) {
    if (this.fast)
      synchronized (this) {
        HashMap hashMap = (HashMap)this.map.clone();
        Object object = hashMap.remove(paramObject);
        this.map = hashMap;
        return object;
      }  
    synchronized (this.map) {
      return this.map.remove(paramObject);
    } 
  }
  
  public void setFast(boolean paramBoolean) {
    this.fast = paramBoolean;
  }
  
  public int size() {
    if (this.fast)
      return this.map.size(); 
    synchronized (this.map) {
      return this.map.size();
    } 
  }
  
  public Collection values() {
    return new Values(this);
  }
  
  private abstract class CollectionView implements Collection {
    private final FastHashMap this$0;
    
    public CollectionView(FastHashMap this$0) {
      this.this$0 = this$0;
    }
    
    public boolean add(Object param1Object) {
      throw new UnsupportedOperationException();
    }
    
    public boolean addAll(Collection param1Collection) {
      throw new UnsupportedOperationException();
    }
    
    public void clear() {
      if (this.this$0.fast) {
        synchronized (this.this$0) {
          HashMap hashMap = (HashMap)this.this$0.map.clone();
          get(hashMap).clear();
          this.this$0.map = hashMap;
        } 
      } else {
        synchronized (this.this$0.map) {
          get(this.this$0.map).clear();
        } 
      } 
    }
    
    public boolean contains(Object param1Object) {
      if (this.this$0.fast)
        return get(this.this$0.map).contains(param1Object); 
      synchronized (this.this$0.map) {
        return get(this.this$0.map).contains(param1Object);
      } 
    }
    
    public boolean containsAll(Collection param1Collection) {
      if (this.this$0.fast)
        return get(this.this$0.map).containsAll(param1Collection); 
      synchronized (this.this$0.map) {
        return get(this.this$0.map).containsAll(param1Collection);
      } 
    }
    
    public boolean equals(Object param1Object) {
      if (param1Object == this)
        return true; 
      if (this.this$0.fast)
        return get(this.this$0.map).equals(param1Object); 
      synchronized (this.this$0.map) {
        return get(this.this$0.map).equals(param1Object);
      } 
    }
    
    protected abstract Collection get(Map param1Map);
    
    public int hashCode() {
      if (this.this$0.fast)
        return get(this.this$0.map).hashCode(); 
      synchronized (this.this$0.map) {
        return get(this.this$0.map).hashCode();
      } 
    }
    
    public boolean isEmpty() {
      if (this.this$0.fast)
        return get(this.this$0.map).isEmpty(); 
      synchronized (this.this$0.map) {
        return get(this.this$0.map).isEmpty();
      } 
    }
    
    public Iterator iterator() {
      return new CollectionViewIterator(this);
    }
    
    protected abstract Object iteratorNext(Map.Entry param1Entry);
    
    public boolean remove(Object param1Object) {
      if (this.this$0.fast)
        synchronized (this.this$0) {
          HashMap hashMap = (HashMap)this.this$0.map.clone();
          boolean bool = get(hashMap).remove(param1Object);
          this.this$0.map = hashMap;
          return bool;
        }  
      synchronized (this.this$0.map) {
        return get(this.this$0.map).remove(param1Object);
      } 
    }
    
    public boolean removeAll(Collection param1Collection) {
      if (this.this$0.fast)
        synchronized (this.this$0) {
          HashMap hashMap = (HashMap)this.this$0.map.clone();
          boolean bool = get(hashMap).removeAll(param1Collection);
          this.this$0.map = hashMap;
          return bool;
        }  
      synchronized (this.this$0.map) {
        return get(this.this$0.map).removeAll(param1Collection);
      } 
    }
    
    public boolean retainAll(Collection param1Collection) {
      if (this.this$0.fast)
        synchronized (this.this$0) {
          HashMap hashMap = (HashMap)this.this$0.map.clone();
          boolean bool = get(hashMap).retainAll(param1Collection);
          this.this$0.map = hashMap;
          return bool;
        }  
      synchronized (this.this$0.map) {
        return get(this.this$0.map).retainAll(param1Collection);
      } 
    }
    
    public int size() {
      if (this.this$0.fast)
        return get(this.this$0.map).size(); 
      synchronized (this.this$0.map) {
        return get(this.this$0.map).size();
      } 
    }
    
    public Object[] toArray() {
      if (this.this$0.fast)
        return get(this.this$0.map).toArray(); 
      synchronized (this.this$0.map) {
        return get(this.this$0.map).toArray();
      } 
    }
    
    public Object[] toArray(Object[] param1ArrayOfObject) {
      if (this.this$0.fast)
        return get(this.this$0.map).toArray(param1ArrayOfObject); 
      synchronized (this.this$0.map) {
        return get(this.this$0.map).toArray(param1ArrayOfObject);
      } 
    }
    
    private class CollectionViewIterator implements Iterator {
      private final FastHashMap.CollectionView this$1;
      
      private Map expected;
      
      private Map.Entry lastReturned;
      
      private Iterator iterator;
      
      public CollectionViewIterator(FastHashMap.CollectionView this$0) {
        this.this$1 = this$0;
        this.lastReturned = null;
        this.expected = this$0.this$0.map;
        this.iterator = this.expected.entrySet().iterator();
      }
      
      public boolean hasNext() {
        if (this.expected != this.this$1.this$0.map)
          throw new ConcurrentModificationException(); 
        return this.iterator.hasNext();
      }
      
      public Object next() {
        if (this.expected != this.this$1.this$0.map)
          throw new ConcurrentModificationException(); 
        this.lastReturned = this.iterator.next();
        return this.this$1.iteratorNext(this.lastReturned);
      }
      
      public void remove() {
        if (this.lastReturned == null)
          throw new IllegalStateException(); 
        if (this.this$1.this$0.fast) {
          synchronized (this.this$1.this$0) {
            if (this.expected != this.this$1.this$0.map)
              throw new ConcurrentModificationException(); 
            this.this$1.this$0.remove(this.lastReturned.getKey());
            this.lastReturned = null;
            this.expected = this.this$1.this$0.map;
          } 
        } else {
          this.iterator.remove();
          this.lastReturned = null;
        } 
      }
    }
  }
  
  private class KeySet extends CollectionView implements Set {
    private final FastHashMap this$0;
    
    KeySet(FastHashMap this$0) {
      super(this$0);
      this.this$0 = this$0;
    }
    
    protected Collection get(Map param1Map) {
      return param1Map.keySet();
    }
    
    protected Object iteratorNext(Map.Entry param1Entry) {
      return param1Entry.getKey();
    }
  }
  
  private class Values extends CollectionView {
    private final FastHashMap this$0;
    
    Values(FastHashMap this$0) {
      super(this$0);
      this.this$0 = this$0;
    }
    
    protected Collection get(Map param1Map) {
      return param1Map.values();
    }
    
    protected Object iteratorNext(Map.Entry param1Entry) {
      return param1Entry.getValue();
    }
  }
  
  private class EntrySet extends CollectionView implements Set {
    private final FastHashMap this$0;
    
    EntrySet(FastHashMap this$0) {
      super(this$0);
      this.this$0 = this$0;
    }
    
    protected Collection get(Map param1Map) {
      return param1Map.entrySet();
    }
    
    protected Object iteratorNext(Map.Entry param1Entry) {
      return param1Entry;
    }
  }
}
