/*
 *  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.directory.shared.ldap.util;


import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

import org.apache.commons.collections.KeyValue;
import org.apache.directory.shared.i18n.I18n;


/**
 * A map of objects whose mapping entries are sequenced based on the order in
 * which they were added. This data structure has fast <i>O(1)</i> search time,
 * deletion time, and insertion time.
 * <p>
 * Although this map is sequenced, it cannot implement {@link java.util.List}
 * because of incompatible interface definitions. The remove methods in List and
 * Map have different return values (see: {@link java.util.List#remove(Object)}
 * and {@link java.util.Map#remove(Object)}).
 * <p>
 * This class is not thread safe. When a thread safe implementation is required,
 * use {@link java.util.Collections#synchronizedMap(Map)} as it is documented,
 * or use explicit synchronization controls.
 * 
 * @since Commons Collections 2.0
 * @version $Revision$ $Date$
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class SequencedHashMap implements Map, Cloneable, Externalizable
{

    /**
     * {@link java.util.Map.Entry} that doubles as a node in the linked list of
     * sequenced mappings.
     */
    private static class Entry implements Map.Entry, KeyValue
    {
        // Note: This class cannot easily be made clonable. While the actual
        // implementation of a clone would be simple, defining the semantics is
        // difficult. If a shallow clone is implemented, then entry.next.prev !=
        // entry, which is unintuitive and probably breaks all sorts of
        // assumptions
        // in code that uses this implementation. If a deep clone is
        // implemented, then what happens when the linked list is cyclical (as
        // is
        // the case with SequencedHashMap)? It's impossible to know in the clone
        // when to stop cloning, and thus you end up in a recursive loop,
        // continuously cloning the "next" in the list.

        private final Object key;

        private Object value;

        // package private to allow the SequencedHashMap to access and
        // manipulate
        // them.
        Entry next = null;

        Entry prev = null;


        public Entry(Object key, Object value)
        {
            this.key = key;
            this.value = value;
        }


        // per Map.Entry.getKey()
        public Object getKey()
        {
            return this.key;
        }


        // per Map.Entry.getValue()
        public Object getValue()
        {
            return this.value;
        }


        // per Map.Entry.setValue()
        public Object setValue( Object value )
        {
            Object oldValue = this.value;
            this.value = value;
            return oldValue;
        }


        /**
         * Compute the instance's hash code
         * @return the instance's hash code 
         */
        public int hashCode()
        {
            // implemented per api docs for Map.Entry.hashCode()
            return ( ( getKey() == null ? 0 : getKey().hashCode() ) ^ ( getValue() == null ? 0 : getValue().hashCode() ) );
        }


        public boolean equals( Object obj )
        {
            if ( obj == null )
                return false;
            if ( obj == this )
                return true;
            if ( !( obj instanceof Map.Entry ) )
                return false;

            Map.Entry other = ( Map.Entry ) obj;

            // implemented per api docs for Map.Entry.equals(Object)
            return ( ( getKey() == null ? other.getKey() == null : getKey().equals( other.getKey() ) ) && ( getValue() == null ? other
                .getValue() == null
                : getValue().equals( other.getValue() ) ) );
        }


        public String toString()
        {
            return "[" + getKey() + "=" + getValue() + "]";
        }
    }


    /**
     * Construct an empty sentinel used to hold the head (sentinel.next) and the
     * tail (sentinel.prev) of the list. The sentinel has a <code>null</code>
     * key and value.
     */
    private static final Entry createSentinel()
    {
        Entry s = new Entry( null, null );
        s.prev = s;
        s.next = s;
        return s;
    }

    /**
     * Sentinel used to hold the head and tail of the list of entries.
     */
    private Entry sentinel;

    /**
     * Map of keys to entries
     */
    private HashMap entries;

    /**
     * Holds the number of modifications that have occurred to the map,
     * excluding modifications made through a collection view's iterator (e.g.
     * entrySet().iterator().remove()). This is used to create a fail-fast
     * behavior with the iterators.
     */
    private transient long modCount = 0;


    /**
     * Construct a new sequenced hash map with default initial size and load
     * factor.
     */
    public SequencedHashMap()
    {
        sentinel = createSentinel();
        entries = new HashMap();
    }


    /**
     * Construct a new sequenced hash map with the specified initial size and
     * default load factor.
     * 
     * @param initialSize
     *            the initial size for the hash table
     * @see HashMap#HashMap(int)
     */
    public SequencedHashMap(int initialSize)
    {
        sentinel = createSentinel();
        entries = new HashMap( initialSize );
    }


    /**
     * Construct a new sequenced hash map with the specified initial size and
     * load factor.
     * 
     * @param initialSize
     *            the initial size for the hash table
     * @param loadFactor
     *            the load factor for the hash table.
     * @see HashMap#HashMap(int,float)
     */
    public SequencedHashMap(int initialSize, float loadFactor)
    {
        sentinel = createSentinel();
        entries = new HashMap( initialSize, loadFactor );
    }


    /**
     * Construct a new sequenced hash map and add all the elements in the
     * specified map. The order in which the mappings in the specified map are
     * added is defined by {@link #putAll(Map)}.
     */
    public SequencedHashMap(Map m)
    {
        this();
        putAll( m );
    }


    /**
     * Removes an internal entry from the linked list. This does not remove it
     * from the underlying map.
     */
    private void removeEntry( Entry entry )
    {
        entry.next.prev = entry.prev;
        entry.prev.next = entry.next;
    }


    /**
     * Inserts a new internal entry to the tail of the linked list. This does
     * not add the entry to the underlying map.
     */
    private void insertEntry( Entry entry )
    {
        entry.next = sentinel;
        entry.prev = sentinel.prev;
        sentinel.prev.next = entry;
        sentinel.prev = entry;
    }


    // per Map.size()

    /**
     * Implements {@link Map#size()}.
     */
    public int size()
    {
        // use the underlying Map's size since size is not maintained here.
        return entries.size();
    }


    /**
     * Implements {@link Map#isEmpty()}.
     */
    public boolean isEmpty()
    {
        // for quick check whether the map is entry, we can check the linked
        // list
        // and see if there's anything in it.
        return sentinel.next == sentinel;
    }


    /**
     * Implements {@link Map#containsKey(Object)}.
     */
    public boolean containsKey( Object key )
    {
        // pass on to underlying map implementation
        return entries.containsKey( key );
    }


    /**
     * Implements {@link Map#containsValue(Object)}.
     */
    public boolean containsValue( Object value )
    {
        // unfortunately, we cannot just pass this call to the underlying map
        // because we are mapping keys to entries, not keys to values. The
        // underlying map doesn't have an efficient implementation anyway, so
        // this
        // isn't a big deal.

        // do null comparison outside loop so we only need to do it once. This
        // provides a tighter, more efficient loop at the expense of slight
        // code duplication.
        if ( value == null )
        {
            for ( Entry pos = sentinel.next; pos != sentinel; pos = pos.next )
            {
                if ( pos.getValue() == null )
                    return true;
            }
        }
        else
        {
            for ( Entry pos = sentinel.next; pos != sentinel; pos = pos.next )
            {
                if ( value.equals( pos.getValue() ) )
                    return true;
            }
        }
        return false;
    }


    /**
     * Implements {@link Map#get(Object)}.
     */
    public Object get( Object o )
    {
        // find entry for the specified key object
        Entry entry = ( Entry ) entries.get( o );
        if ( entry == null )
            return null;

        return entry.getValue();
    }


    /**
     * Return the entry for the "oldest" mapping. That is, return the Map.Entry
     * for the key-value pair that was first put into the map when compared to
     * all the other pairings in the map. This behavior is equivalent to using
     * <code>entrySet().iterator().next()</code>, but this method provides an
     * optimized implementation.
     * 
     * @return The first entry in the sequence, or <code>null</code> if the
     *         map is empty.
     */
    public Map.Entry getFirst()
    {
        // sentinel.next points to the "first" element of the sequence -- the
        // head
        // of the list, which is exactly the entry we need to return. We must
        // test
        // for an empty list though because we don't want to return the
        // sentinel!
        return ( isEmpty() ) ? null : sentinel.next;
    }


    /**
     * Return the key for the "oldest" mapping. That is, return the key for the
     * mapping that was first put into the map when compared to all the other
     * objects in the map. This behavior is equivalent to using
     * <code>getFirst().getKey()</code>, but this method provides a slightly
     * optimized implementation.
     * 
     * @return The first key in the sequence, or <code>null</code> if the map
     *         is empty.
     */
    public Object getFirstKey()
    {
        // sentinel.next points to the "first" element of the sequence -- the
        // head
        // of the list -- and the requisite key is returned from it. An empty
        // list
        // does not need to be tested. In cases where the list is empty,
        // sentinel.next will point to the sentinel itself which has a null key,
        // which is exactly what we would want to return if the list is empty (a
        // nice convenient way to avoid test for an empty list)
        return sentinel.next.getKey();
    }


    /**
     * Return the value for the "oldest" mapping. That is, return the value for
     * the mapping that was first put into the map when compared to all the
     * other objects in the map. This behavior is equivalent to using
     * <code>getFirst().getValue()</code>, but this method provides a
     * slightly optimized implementation.
     * 
     * @return The first value in the sequence, or <code>null</code> if the
     *         map is empty.
     */
    public Object getFirstValue()
    {
        // sentinel.next points to the "first" element of the sequence -- the
        // head
        // of the list -- and the requisite value is returned from it. An empty
        // list does not need to be tested. In cases where the list is empty,
        // sentinel.next will point to the sentinel itself which has a null
        // value,
        // which is exactly what we would want to return if the list is empty (a
        // nice convenient way to avoid test for an empty list)
        return sentinel.next.getValue();
    }


    /**
     * Return the entry for the "newest" mapping. That is, return the Map.Entry
     * for the key-value pair that was first put into the map when compared to
     * all the other pairings in the map. The behavior is equivalent to:
     * 
     * <pre>
     * Object obj = null;
     * Iterator iter = entrySet().iterator();
     * while ( iter.hasNext() )
     * {
     *     obj = iter.next();
     * }
     * return ( Map.Entry ) obj;
     * </pre>
     * 
     * However, the implementation of this method ensures an O(1) lookup of the
     * last key rather than O(n).
     * 
     * @return The last entry in the sequence, or <code>null</code> if the map
     *         is empty.
     */
    public Map.Entry getLast()
    {
        // sentinel.prev points to the "last" element of the sequence -- the
        // tail
        // of the list, which is exactly the entry we need to return. We must
        // test
        // for an empty list though because we don't want to return the
        // sentinel!
        return ( isEmpty() ) ? null : sentinel.prev;
    }


    /**
     * Return the key for the "newest" mapping. That is, return the key for the
     * mapping that was last put into the map when compared to all the other
     * objects in the map. This behavior is equivalent to using
     * <code>getLast().getKey()</code>, but this method provides a slightly
     * optimized implementation.
     * 
     * @return The last key in the sequence, or <code>null</code> if the map
     *         is empty.
     */
    public Object getLastKey()
    {
        // sentinel.prev points to the "last" element of the sequence -- the
        // tail
        // of the list -- and the requisite key is returned from it. An empty
        // list
        // does not need to be tested. In cases where the list is empty,
        // sentinel.prev will point to the sentinel itself which has a null key,
        // which is exactly what we would want to return if the list is empty (a
        // nice convenient way to avoid test for an empty list)
        return sentinel.prev.getKey();
    }


    /**
     * Return the value for the "newest" mapping. That is, return the value for
     * the mapping that was last put into the map when compared to all the other
     * objects in the map. This behavior is equivalent to using
     * <code>getLast().getValue()</code>, but this method provides a slightly
     * optimized implementation.
     * 
     * @return The last value in the sequence, or <code>null</code> if the map
     *         is empty.
     */
    public Object getLastValue()
    {
        // sentinel.prev points to the "last" element of the sequence -- the
        // tail
        // of the list -- and the requisite value is returned from it. An empty
        // list does not need to be tested. In cases where the list is empty,
        // sentinel.prev will point to the sentinel itself which has a null
        // value,
        // which is exactly what we would want to return if the list is empty (a
        // nice convenient way to avoid test for an empty list)
        return sentinel.prev.getValue();
    }


    /**
     * Implements {@link Map#put(Object, Object)}.
     */
    public Object put( Object key, Object value )
    {
        modCount++;

        Object oldValue = null;

        // lookup the entry for the specified key
        Entry e = ( Entry ) entries.get( key );

        // check to see if it already exists
        if ( e != null )
        {
            // remove from list so the entry gets "moved" to the end of list
            removeEntry( e );

            // update value in map
            oldValue = e.setValue( value );

            // Note: We do not update the key here because its unnecessary. We
            // only
            // do comparisons using equals(Object) and we know the specified key
            // and
            // that in the map are equal in that sense. This may cause a problem
            // if
            // someone does not implement their hashCode() and/or equals(Object)
            // method properly and then use it as a key in this map.
        }
        else
        {
            // add new entry
            e = new Entry( key, value );
            entries.put( key, e );
        }
        // assert(entry in map, but not list)

        // add to list
        insertEntry( e );

        return oldValue;
    }


    /**
     * Implements {@link Map#remove(Object)}.
     */
    public Object remove( Object key )
    {
        Entry e = removeImpl( key );
        return ( e == null ) ? null : e.getValue();
    }


    /**
     * Fully remove an entry from the map, returning the old entry or null if
     * there was no such entry with the specified key.
     */
    private Entry removeImpl( Object key )
    {
        Entry e = ( Entry ) entries.remove( key );
        if ( e == null )
            return null;
        modCount++;
        removeEntry( e );
        return e;
    }


    /**
     * Adds all the mappings in the specified map to this map, replacing any
     * mappings that already exist (as per {@link Map#putAll(Map)}). The order
     * in which the entries are added is determined by the iterator returned
     * from {@link Map#entrySet()} for the specified map.
     * 
     * @param t
     *            the mappings that should be added to this map.
     * @throws NullPointerException
     *             if <code>t</code> is <code>null</code>
     */
    public void putAll( Map t )
    {
        Iterator iter = t.entrySet().iterator();
        while ( iter.hasNext() )
        {
            Map.Entry entry = ( Map.Entry ) iter.next();
            put( entry.getKey(), entry.getValue() );
        }
    }


    /**
     * Implements {@link Map#clear()}.
     */
    public void clear()
    {
        modCount++;

        // remove all from the underlying map
        entries.clear();

        // and the list
        sentinel.next = sentinel;
        sentinel.prev = sentinel;
    }


    /**
     * Implements {@link Map#equals(Object)}.
     */
    public boolean equals( Object obj )
    {
        if ( obj == null )
            return false;
        if ( obj == this )
            return true;

        if ( !( obj instanceof Map ) )
            return false;

        return entrySet().equals( ( ( Map ) obj ).entrySet() );
    }


    /**
     * Implements {@link Map#hashCode()}.
     * @return the instance's hash code 
     */
    public int hashCode()
    {
        return entrySet().hashCode();
    }


    /**
     * Provides a string representation of the entries within the map. The
     * format of the returned string may change with different releases, so this
     * method is suitable for debugging purposes only. If a specific format is
     * required, use {@link #entrySet()}.{@link Set#iterator() iterator()} and
     * iterate over the entries in the map formatting them as appropriate.
     */
    public String toString()
    {
        StringBuffer buf = new StringBuffer();
        buf.append( '[' );
        for ( Entry pos = sentinel.next; pos != sentinel; pos = pos.next )
        {
            buf.append( pos.getKey() );
            buf.append( '=' );
            buf.append( pos.getValue() );
            if ( pos.next != sentinel )
            {
                buf.append( ',' );
            }
        }
        buf.append( ']' );

        return buf.toString();
    }


    /**
     * Implements {@link Map#keySet()}.
     */
    public Set keySet()
    {
        return new AbstractSet()
        {

            // required impls
            public Iterator iterator()
            {
                return new OrderedIterator( KEY );
            }


            public boolean remove( Object o )
            {
                Entry e = SequencedHashMap.this.removeImpl( o );
                return ( e != null );
            }


            // more efficient impls than abstract set
            public void clear()
            {
                SequencedHashMap.this.clear();
            }


            public int size()
            {
                return SequencedHashMap.this.size();
            }


            public boolean isEmpty()
            {
                return SequencedHashMap.this.isEmpty();
            }


            public boolean contains( Object o )
            {
                return SequencedHashMap.this.containsKey( o );
            }

        };
    }


    /**
     * Implements {@link Map#values()}.
     */
    public Collection values()
    {
        return new AbstractCollection()
        {
            // required impl
            public Iterator iterator()
            {
                return new OrderedIterator( VALUE );
            }


            public boolean remove( Object value )
            {
                // do null comparison outside loop so we only need to do it
                // once. This
                // provides a tighter, more efficient loop at the expense of
                // slight
                // code duplication.
                if ( value == null )
                {
                    for ( Entry pos = sentinel.next; pos != sentinel; pos = pos.next )
                    {
                        if ( pos.getValue() == null )
                        {
                            SequencedHashMap.this.removeImpl( pos.getKey() );
                            return true;
                        }
                    }
                }
                else
                {
                    for ( Entry pos = sentinel.next; pos != sentinel; pos = pos.next )
                    {
                        if ( value.equals( pos.getValue() ) )
                        {
                            SequencedHashMap.this.removeImpl( pos.getKey() );
                            return true;
                        }
                    }
                }

                return false;
            }


            // more efficient impls than abstract collection
            public void clear()
            {
                SequencedHashMap.this.clear();
            }


            public int size()
            {
                return SequencedHashMap.this.size();
            }


            public boolean isEmpty()
            {
                return SequencedHashMap.this.isEmpty();
            }


            public boolean contains( Object o )
            {
                return SequencedHashMap.this.containsValue( o );
            }
        };
    }


    /**
     * Implements {@link Map#entrySet()}.
     */
    public Set entrySet()
    {
        return new AbstractSet()
        {
            // helper
            private Entry findEntry( Object o )
            {
                if ( o == null )
                    return null;
                if ( !( o instanceof Map.Entry ) )
                    return null;

                Map.Entry e = ( Map.Entry ) o;
                Entry entry = ( Entry ) entries.get( e.getKey() );
                if ( entry != null && entry.equals( e ) )
                    return entry;
                else
                    return null;
            }


            // required impl
            public Iterator iterator()
            {
                return new OrderedIterator( ENTRY );
            }


            public boolean remove( Object o )
            {
                Entry e = findEntry( o );
                if ( e == null )
                    return false;

                return SequencedHashMap.this.removeImpl( e.getKey() ) != null;
            }


            // more efficient impls than abstract collection
            public void clear()
            {
                SequencedHashMap.this.clear();
            }


            public int size()
            {
                return SequencedHashMap.this.size();
            }


            public boolean isEmpty()
            {
                return SequencedHashMap.this.isEmpty();
            }


            public boolean contains( Object o )
            {
                return findEntry( o ) != null;
            }
        };
    }

    // constants to define what the iterator should return on "next"
    private static final int KEY = 0;

    private static final int VALUE = 1;

    private static final int ENTRY = 2;

    private static final int REMOVED_MASK = 0x80000000;

    private class OrderedIterator implements Iterator
    {
        /**
         * Holds the type that should be returned from the iterator. The value
         * should be either KEY, VALUE, or ENTRY. To save a tiny bit of memory,
         * this field is also used as a marker for when remove has been called
         * on the current object to prevent a second remove on the same element.
         * Essentially, if this value is negative (i.e. the bit specified by
         * REMOVED_MASK is set), the current position has been removed. If
         * positive, remove can still be called.
         */
        private int returnType;

        /**
         * Holds the "current" position in the iterator. When pos.next is the
         * sentinel, we've reached the end of the list.
         */
        private Entry pos = sentinel;

        /**
         * Holds the expected modification count. If the actual modification
         * count of the map differs from this value, then a concurrent
         * modification has occurred.
         */
        private transient long expectedModCount = modCount;


        /**
         * Construct an iterator over the sequenced elements in the order in
         * which they were added. The {@link #next()} method returns the type
         * specified by <code>returnType</code> which must be either KEY,
         * VALUE, or ENTRY.
         */
        public OrderedIterator(int returnType)
        {
            // // Since this is a private inner class, nothing else should have
            // // access to the constructor. Since we know the rest of the outer
            // // class uses the iterator correctly, we can leave of the
            // following
            // // check:
            // if(returnType >= 0 && returnType <= 2) {
            // throw new IllegalArgumentException("Invalid iterator type");
            // }

            // Set the "removed" bit so that the iterator starts in a state
            // where
            // "next" must be called before "remove" will succeed.
            this.returnType = returnType | REMOVED_MASK;
        }


        /**
         * Returns whether there is any additional elements in the iterator to
         * be returned.
         * 
         * @return <code>true</code> if there are more elements left to be
         *         returned from the iterator; <code>false</code> otherwise.
         */
        public boolean hasNext()
        {
            return pos.next != sentinel;
        }


        /**
         * Returns the next element from the iterator.
         * 
         * @return the next element from the iterator.
         * @throws NoSuchElementException
         *             if there are no more elements in the iterator.
         * @throws ConcurrentModificationException
         *             if a modification occurs in the underlying map.
         */
        public Object next()
        {
            if ( modCount != expectedModCount )
            {
                throw new ConcurrentModificationException();
            }
            if ( pos.next == sentinel )
            {
                throw new NoSuchElementException();
            }

            // clear the "removed" flag
            returnType = returnType & ~REMOVED_MASK;

            pos = pos.next;
            switch ( returnType )
            {
                case KEY:
                    return pos.getKey();
                case VALUE:
                    return pos.getValue();
                case ENTRY:
                    return pos;
                default:
                    // should never happen
                    throw new Error( I18n.err( I18n.ERR_04425, returnType ) );
            }

        }


        /**
         * Removes the last element returned from the {@link #next()} method
         * from the sequenced map.
         * 
         * @throws IllegalStateException
         *             if there isn't a "last element" to be removed. That is,
         *             if {@link #next()} has never been called, or if
         *             {@link #remove()} was already called on the element.
         * @throws ConcurrentModificationException
         *             if a modification occurs in the underlying map.
         */
        public void remove()
        {
            if ( ( returnType & REMOVED_MASK ) != 0 )
            {
                throw new IllegalStateException( I18n.err( I18n.ERR_04426 ) );
            }
            if ( modCount != expectedModCount )
            {
                throw new ConcurrentModificationException();
            }

            SequencedHashMap.this.removeImpl( pos.getKey() );

            // update the expected mod count for the remove operation
            expectedModCount++;

            // set the removed flag
            returnType = returnType | REMOVED_MASK;
        }
    }


    // APIs maintained from previous version of SequencedHashMap for backwards
    // compatibility

    /**
     * Creates a shallow copy of this object, preserving the internal structure
     * by copying only references. The keys and values themselves are not
     * <code>clone()</code>'d. The cloned object maintains the same sequence.
     * 
     * @return A clone of this instance.
     * @throws CloneNotSupportedException
     *             if clone is not supported by a subclass.
     */
    public Object clone() throws CloneNotSupportedException
    {
        // yes, calling super.clone() silly since we're just blowing away all
        // the stuff that super might be doing anyway, but for motivations on
        // this, see:
        // http://www.javaworld.com/javaworld/jw-01-1999/jw-01-object.html
        SequencedHashMap map = ( SequencedHashMap ) super.clone();

        // create new, empty sentinel
        map.sentinel = createSentinel();

        // create a new, empty entry map
        // note: this does not preserve the initial capacity and load factor.
        map.entries = new HashMap();

        // add all the mappings
        map.putAll( this );

        // Note: We cannot just clone the hashmap and sentinel because we must
        // duplicate our internal structures. Cloning those two will not clone
        // all
        // the other entries they reference, and so the cloned hash map will not
        // be
        // able to maintain internal consistency because there are two objects
        // with
        // the same entries. See discussion in the Entry implementation on why
        // we
        // cannot implement a clone of the Entry (and thus why we need to
        // recreate
        // everything).

        return map;
    }


    /**
     * Returns the Map.Entry at the specified index
     * 
     * @throws ArrayIndexOutOfBoundsException
     *             if the specified index is <code>&lt; 0</code> or
     *             <code>&gt;</code> the size of the map.
     */
    private Map.Entry getEntry( int index )
    {
        Entry pos = sentinel;

        if ( index < 0 )
        {
            throw new ArrayIndexOutOfBoundsException( I18n.err( I18n.ERR_04427, index ) );
        }

        // loop to one before the position
        int i = -1;
        while ( i < ( index - 1 ) && pos.next != sentinel )
        {
            i++;
            pos = pos.next;
        }
        // pos.next is the requested position

        // if sentinel is next, past end of list
        if ( pos.next == sentinel )
        {
            throw new ArrayIndexOutOfBoundsException( I18n.err( I18n.ERR_04428, index, ( i + 1 ) ) );
        }

        return pos.next;
    }


    /**
     * Gets the key at the specified index.
     * 
     * @param index
     *            the index to retrieve
     * @return the key at the specified index, or null
     * @throws ArrayIndexOutOfBoundsException
     *             if the <code>index</code> is <code>&lt; 0</code> or
     *             <code>&gt;</code> the size of the map.
     */
    public Object get( int index )
    {
        return getEntry( index ).getKey();
    }


    /**
     * Gets the value at the specified index.
     * 
     * @param index
     *            the index to retrieve
     * @return the value at the specified index, or null
     * @throws ArrayIndexOutOfBoundsException
     *             if the <code>index</code> is <code>&lt; 0</code> or
     *             <code>&gt;</code> the size of the map.
     */
    public Object getValue( int index )
    {
        return getEntry( index ).getValue();
    }


    /**
     * Gets the index of the specified key.
     * 
     * @param key
     *            the key to find the index of
     * @return the index, or -1 if not found
     */
    public int indexOf( Object key )
    {
        Entry e = ( Entry ) entries.get( key );
        if ( e == null )
        {
            return -1;
        }
        int pos = 0;
        while ( e.prev != sentinel )
        {
            pos++;
            e = e.prev;
        }
        return pos;
    }


    /**
     * Gets an iterator over the keys.
     * 
     * @return an iterator over the keys
     */
    public Iterator iterator()
    {
        return keySet().iterator();
    }


    /**
     * Gets the last index of the specified key.
     * 
     * @param key
     *            the key to find the index of
     * @return the index, or -1 if not found
     */
    public int lastIndexOf( Object key )
    {
        // keys in a map are guaranteed to be unique
        return indexOf( key );
    }


    /**
     * Returns a List view of the keys rather than a set view. The returned list
     * is unmodifiable. This is required because changes to the values of the
     * list (using {@link java.util.ListIterator#set(Object)}) will effectively
     * remove the value from the list and reinsert that value at the end of the
     * list, which is an unexpected side effect of changing the value of a list.
     * This occurs because changing the key, changes when the mapping is added
     * to the map and thus where it appears in the list.
     * <p>
     * An alternative to this method is to use {@link #keySet()}
     * 
     * @see #keySet()
     * @return The ordered list of keys.
     */
    public List sequence()
    {
        List l = new ArrayList( size() );
        Iterator iter = keySet().iterator();
        while ( iter.hasNext() )
        {
            l.add( iter.next() );
        }

        return Collections.unmodifiableList( l );
    }


    /**
     * Removes the element at the specified index.
     * 
     * @param index
     *            The index of the object to remove.
     * @return The previous value corresponding the <code>key</code>, or
     *         <code>null</code> if none existed.
     * @throws ArrayIndexOutOfBoundsException
     *             if the <code>index</code> is <code>&lt; 0</code> or
     *             <code>&gt;</code> the size of the map.
     */
    public Object remove( int index )
    {
        return remove( get( index ) );
    }


    // per Externalizable.readExternal(ObjectInput)

    /**
     * Deserializes this map from the given stream.
     * 
     * @param in
     *            the stream to deserialize from
     * @throws IOException
     *             if the stream raises it
     * @throws ClassNotFoundException
     *             if the stream raises it
     */
    public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
    {
        int size = in.readInt();
        for ( int i = 0; i < size; i++ )
        {
            Object key = in.readObject();
            Object value = in.readObject();
            put( key, value );
        }
    }


    /**
     * Serializes this map to the given stream.
     * 
     * @param out
     *            the stream to serialize to
     * @throws IOException
     *             if the stream raises it
     */
    public void writeExternal( ObjectOutput out ) throws IOException
    {
        out.writeInt( size() );
        for ( Entry pos = sentinel.next; pos != sentinel; pos = pos.next )
        {
            out.writeObject( pos.getKey() );
            out.writeObject( pos.getValue() );
        }
    }

    // add a serial version uid, so that if we change things in the future
    // without changing the format, we can still deserialize properly.
    private static final long serialVersionUID = 3380552487888102930L;

}
