/* EnumMap.java - Map where keys are enum constants
   Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.util;

import java.io.Serializable;

/**
 * @author Tom Tromey (tromey@redhat.com)
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 * @since 1.5
 */

public class EnumMap<K extends Enum<K>, V>
  extends AbstractMap<K, V>
  implements Cloneable, Serializable
{
  private static final long serialVersionUID = 458661240069192865L;

  V[] store;
  int cardinality;
  Class<K> enumClass;

  /**
   * The cache for {@link #entrySet()}.
   */
  transient Set<Map.Entry<K, V>> entries;

  static final Object emptySlot = new Object();

  public EnumMap(Class<K> keyType)
  {
    store = (V[]) new Object[keyType.getEnumConstants().length];
    Arrays.fill(store, emptySlot);
    cardinality = 0;
    enumClass = keyType;
  }

  public EnumMap(EnumMap<K, ? extends V> map)
  {
    store = (V[]) map.store.clone();
    cardinality = map.cardinality;
    enumClass = map.enumClass;
  }

  public EnumMap(Map<K, ? extends V> map)
  {
    if (map instanceof EnumMap)
      {
        EnumMap<K, ? extends V> other = (EnumMap<K, ? extends V>) map;
        store = (V[]) other.store.clone();
        cardinality = other.cardinality;
        enumClass = other.enumClass;
      }
    else
      {
        for (K key : map.keySet())
          {
            V value = map.get(key);
            if (store == null)
              {
                enumClass = key.getDeclaringClass();
                store = (V[]) new Object[enumClass.getEnumConstants().length];
              }
            int o = key.ordinal();
            if (store[o] == emptySlot)
              ++cardinality;
            store[o] = value;
          }
        // There must be a single element.
        if (store == null)
          throw new IllegalArgumentException("no elements in map");
      }
  }

  public int size()
  {
    return cardinality;
  }

  public boolean containsValue(Object value)
  {
    for (V i : store)
      {
        if (i != emptySlot && AbstractCollection.equals(i , value))
          return true;
      }
    return false;
  }

  public boolean containsKey(Object key)
  {
    if (! (key instanceof Enum))
      return false;
    Enum<K> e = (Enum<K>) key;
    if (e.getDeclaringClass() != enumClass)
      return false;
    return store[e.ordinal()] != emptySlot;
  }

  public V get(Object key)
  {
    if (! (key instanceof Enum))
      return null;
    Enum<K> e = (Enum<K>) key;
    if (e.getDeclaringClass() != enumClass)
      return null;
    V o = store[e.ordinal()];
    return o == emptySlot ? null : o;
  }

  public V put(K key, V value)
  {
    int o = key.ordinal();
    V result;
    if (store[o] == emptySlot)
      {
        result = null;
        ++cardinality;
      }
    else
      result = store[o];
    store[o] = value;
    return result;
  }

  public V remove(Object key)
  {
    if (! (key instanceof Enum))
      return null;
    Enum<K> e = (Enum<K>) key;
    if (e.getDeclaringClass() != enumClass)
      return null;
    V result = store[e.ordinal()];
    if (result == emptySlot)
      result = null;
    else
      --cardinality;
    store[e.ordinal()] = (V) emptySlot;
    return result;
  }

  public void putAll(Map<? extends K, ? extends V> map)
  {
    for (K key : map.keySet())
      {
        V value = map.get(key);

        int o = key.ordinal();
        if (store[o] == emptySlot)
          ++cardinality;
        store[o] = value;
      }
  }

  public void clear()
  {
    Arrays.fill(store, emptySlot);
    cardinality = 0;
  }

  public Set<K> keySet()
  {
    if (keys == null)
      {
        keys = new AbstractSet<K>()
        {
          public int size()
          {
            return cardinality;
          }

          public Iterator<K> iterator()
          {
            return new Iterator<K>()
            {
              int count = 0;
              int index = -1;

              public boolean hasNext()
              {
                return count < cardinality;
              }

              public K next()
              {
                ++count;
                for (++index; store[index] == emptySlot; ++index)
                  ;
                return enumClass.getEnumConstants()[index];
              }

              public void remove()
              {
                --cardinality;
                store[index] = (V) emptySlot;
              }
            };
          }

          public void clear()
          {
            EnumMap.this.clear();
          }

          public boolean contains(Object o)
          {
            return contains(o);
          }

          public boolean remove(Object o)
          {
            return EnumMap.this.remove(o) != null;
          }
        };
      }
    return keys;
  }

  public Collection<V> values()
  {
    if (values == null)
      {
        values = new AbstractCollection<V>()
        {
          public int size()
          {
            return cardinality;
          }

          public Iterator<V> iterator()
          {
            return new Iterator<V>()
            {
              int count = 0;
              int index = -1;

              public boolean hasNext()
              {
                return count < cardinality;
              }

              public V next()
              {
                ++count;
                for (++index; store[index] == emptySlot; ++index)
                  ;
                return store[index];
              }

              public void remove()
              {
                --cardinality;
                store[index] = (V) emptySlot;
              }
            };
          }

          public void clear()
          {
            EnumMap.this.clear();
          }
        };
      }
    return values;
  }

  public Set<Map.Entry<K, V>> entrySet()
  {
    if (entries == null)
      {
        entries = new AbstractSet<Map.Entry<K, V>>()
        {
          public int size()
          {
            return cardinality;
          }

          public Iterator<Map.Entry<K, V>> iterator()
          {
            return new Iterator<Map.Entry<K, V>>()
            {
              int count = 0;
              int index = -1;

              public boolean hasNext()
              {
                return count < cardinality;
              }

              public Map.Entry<K,V> next()
              {
                ++count;
                for (++index; store[index] == emptySlot; ++index)
                  ;
                // FIXME: we could just return something that
                // only knows the index.  That would be cleaner.
                return new AbstractMap.SimpleEntry<K, V>(enumClass.getEnumConstants()[index],
                                                           store[index])
                {
                  public V setValue(V newVal)
                  {
                    value = newVal;
                    return put(key, newVal);
                  }
                };
              }

              public void remove()
              {
                --cardinality;
                store[index] = (V) emptySlot;
              }
            };
          }

          public void clear()
          {
            EnumMap.this.clear();
          }

          public boolean contains(Object o)
          {
            if (! (o instanceof Map.Entry))
              return false;
            Map.Entry<K, V> other = (Map.Entry<K, V>) o;
            return (containsKey(other.getKey())
                    && AbstractCollection.equals(get(other.getKey()),
                                                 other.getValue()));
          }

          public boolean remove(Object o)
          {
            if (! (o instanceof Map.Entry))
              return false;
            Map.Entry<K, V> other = (Map.Entry<K, V>) o;
            return EnumMap.this.remove(other.getKey()) != null;
          }
        };
      }
    return entries;
  }

  public boolean equals(Object o)
  {
    if (! (o instanceof EnumMap))
      return false;
    EnumMap<K, V> other = (EnumMap<K, V>) o;
    if (other.enumClass != enumClass || other.cardinality != cardinality)
      return false;
    return Arrays.equals(store, other.store);
  }

  public EnumMap<K, V> clone()
  {
    EnumMap<K, V> result;
    try
      {
        result = (EnumMap<K, V>) super.clone();
      }
    catch (CloneNotSupportedException ignore)
      {
        // Can't happen.
        result = null;
      }
    result.store = (V[]) store.clone();
    return result;
  }

}
