Collections Data Structure Java

/*
 * 
 * JAFFA - Java Application Framework For All
 *
 * Copyright (C) 2002 JAFFA Development Group
 *
 *     This library is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU Lesser General Public
 *     License as published by the Free Software Foundation; either
 *     version 2.1 of the License, or (at your option) any later version.
 *
 *     This library 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
 *     Lesser General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public
 *     License along with this library; if not, write to the Free Software
 *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Redistribution and use of this software and associated documentation ("Software"),
 * with or without modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain copyright statements and notices.
 *         Redistributions must also contain a copy of this document.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 * 3. The name "JAFFA" must not be used to endorse or promote products derived from
 *  this Software without prior written permission. For written permission,
 *  please contact mail to: jaffagroup@yahoo.com.
 * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
 *  appear in their names without prior written permission.
 * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 */
import java.io.Serializable;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
 * This class combines the utility of the HashMap & the ListSet. Features are:
 * 1) Ensure quick random access to an object using a 'key'
 * 2) Iterate through the Map in the order in which the entries were made
 */
public class ListMap implements Map, Cloneable, Serializable {
    private static final int TYPE_KEY_SET = 0;
    private static final int TYPE_ENTRY_SET = 1;
    private static final int TYPE_VALUES = 2;
    /** This Map will contain the key-value pairs */
    private HashMap m_map = null;
    /** This List will maintain the keys in the order of entry */
    private ListSet m_list = null;
    // fields to hold the return Collections.
    private transient Set m_keySet = null;
    private transient Set m_entrySet = null;
    private transient Collection m_values = null;
    /** Creates new ListMap */
    public ListMap() {
        m_map = new HashMap();
        m_list = new ListSet();
    }
    /** Creates new ListMap specifying the initial capacity.
     * @param initialCapacity The initial capacity.
     */
    public ListMap(int initialCapacity) {
        m_map = new HashMap(initialCapacity);
        m_list = new ListSet(initialCapacity);
    }
    /** Creates new ListMap specifying the initial capacity and load factor.
     * @param initialCapacity The initial capacity.
     * @param loadFactor The loadFactor.
     */
    public ListMap(int initialCapacity, float loadFactor) {
        m_map = new HashMap(initialCapacity, loadFactor);
        m_list = new ListSet(initialCapacity);
    }
    /** Creates new ListMap from an existing Map
     * @param t An existing Map.
     */
    public ListMap(Map t) {
        if (t == null) {
            m_map = new HashMap();
            m_list = new ListSet();
        } else {
            m_map = new HashMap(t);
            m_list = new ListSet( t.keySet() );
        }
    }
    // *** MAP INTERFACE METHODS ***
    /** Adds an object to the Map. If the map previously contained a mapping for this key, the old value is replaced by the specified value.
     * @param key The key used for adding the object.
     * @param value The object to be added.
     * @return previous value associated with specified key, or null if there was no mapping for key. A null return can also indicate that the map previously associated null with the specified key.
     */
    public Object put(Object key, Object value) {
        return put(-1, key, value);
    }
    /** Removes the mapping for this key from this map if it is present.
     * @param key key whose mapping is to be removed from the map.
     * @return previous value associated with specified key, or null if there was no mapping for key.
     */
    public Object remove(Object key) {
        m_list.remove(key);
        return m_map.remove(key);
    }
    /** Returns a set view of the keys contained in this map.
     * @return a set view of the keys contained in this map.
     */
    public Set keySet() {
        if (m_keySet == null)
            m_keySet = new ListMap.KeySet();
        return m_keySet;
    }
    /** Removes all mappings from this map .*/
    public void clear() {
        m_list.clear();
        m_map.clear();
    }
    /** Returns a collection view of the values contained in this map.
     * @return a collection view of the values contained in this map.
     */
    public Collection values() {
        if (m_values == null)
            m_values = new ListMap.Values();
        return m_values;
    }
    /** Returns the hash code value for this map.
     * @return the hash code value for this map.
     */
    public int hashCode() {
        return m_map.hashCode();
    }
    /** Returns true if this map contains a mapping for the specified key.
     * @param key key whose presence in this map is to be tested.
     * @return true if this map contains a mapping for the specified key.
     */
    public boolean containsKey(Object key) {
        return m_map.containsKey(key);
    }
    /** Returns the number of key-value mappings in this map.
     * @return the number of key-value mappings in this map.
     */
    public int size() {
        return m_map.size();
    }
    /** Returns a set view of the mappings contained in this map.
     * @return a set view of the mappings contained in this map.
     */
    public Set entrySet() {
        if (m_entrySet == null)
            m_entrySet = new ListMap.EntrySet();
        return m_entrySet;
    }
    /** Returns true if this map maps one or more keys to the specified value.
     * @param value value whose presence in this map is to be tested.
     * @return true if this map maps one or more keys to the specified value.
     */
    public boolean containsValue(Object value) {
        return m_map.containsValue(value);
    }
    /** Copies all of the mappings from the specified map to this map.
     * @param t Mappings to be stored in this map.
     */
    public void putAll(Map t) {
        if (t != null) {
            m_map.putAll(t);
            m_list.addAll( t.keySet() );
        }
    }
    /** Compares the specified object with this map for equality.
     * Returns true if the given object is also a ListMap and the two Maps represent the same mappings.
     * @param o object to be compared for equality with this map.
     * @return true if the specified object is equal to this map.
     */
    public boolean equals(Object o) {
        boolean result = false;
        if (o instanceof ListMap) {
            ListMap listMap = (ListMap) o;
            result = m_map.equals(listMap.m_map);
        }
        return result;
    }
    /** Returns true if this map contains no key-value mappings.
     * @return true if this map contains no key-value mappings.
     */
    public boolean isEmpty() {
        return m_map.isEmpty();
    }
    /** Returns the value to which this map maps the specified key.
     * Returns null if the map contains no mapping for this key.
     * A return value of null does not necessarily indicate that the map contains no mapping for the key; it's also possible that the map explicitly maps the key to null.
     * The containsKey operation may be used to distinguish these two cases.
     * @param key key whose associated value is to be returned.
     * @return the value to which this map maps the specified key, or null if the map contains no mapping for this key.
     */
    public Object get(Object key) {
        return m_map.get(key);
    }
    // *** Additional Methods ***
    /** Adds an object to the Map. If the map previously contained a mapping for this key, the old value is replaced by the specified value.
     * @param index The position at which the the object will be added.
     * @param key The key used for adding the object.
     * @param value The object to be added.
     * @return previous value associated with specified key, or null if there was no mapping for key. A null return can also indicate that the map previously associated null with the specified key.
     */
    public Object put(int index, Object key, Object value) {
        Object returnObject = m_map.put(key, value);
        // add to the list, only if it doesn't already exist
        if ( !m_list.contains(key) ) {
            if (index == -1)
                m_list.add(key);
            else
                m_list.add(index, key);
        }
        return returnObject;
    }
    /** Returns the mapping at the specified index.
     * @param index The position at from which the mapping is to be retrieved.
     * @return the mapping at the specified index.
     */
    public Object getByIndex(int index) {
        return get( m_list.get(index) );
    }
    /** Removes the mapping for this index from this map if it is present.
     * @param index The position at from which the mapping is to be removed.
     * @return previous value associated with position, or null if there was no mapping for position.
     */
    public Object remove(int index) {
        return remove( m_list.get(index) );
    }
    /** Returns the index in this Map of the specified key.
     * A '-1' is returned in case no such key exists.
     * @param key The key used for adding the object.
     * @return the index in this Map of the specified key.
     */
    public int indexOf(Object key) {
        return m_list.indexOf(key);
    }
    // *** CLONEABLE INTERFACE METHODS ***
    /** Returns a clone of the Map.
     * @throws CloneNotSupportedException if cloning is not supported. Should never happen.
     * @return a clone of the Map.
     */
    public Object clone() throws CloneNotSupportedException {
        ListMap obj = (ListMap) super.clone();
        if (m_map != null && m_map instanceof HashMap)
            obj.m_map = (HashMap) m_map.clone();
        if (m_list != null && m_list instanceof ListSet)
            obj.m_list = (ListSet) m_list.clone();
        // reset the transient fields
        obj.m_keySet = null;
        obj.m_entrySet = null;
        obj.m_values = null;
        return obj;
    }
    // *** PRIVATE METHODS ***
    private Iterator getIterator(int type) {
        return new ListMap.ListMapIterator(type);
    }
    private Map.Entry getEntry(Object key, Object value) {
        return new ListMap.ListMapEntry(key, value);
    }
    // *** INNER CLASSES ***
    private class ListMapIterator implements Iterator {
        private Iterator m_iterator = null;
        private int m_type;
        private Object m_lastReturned = null;
        private ListMapIterator(int type) {
            m_type = type;
            m_iterator = ListMap.this.m_list.iterator();
        }
        /** Returns true if the iteration has more elements.
         * @return true if the iteration has more elements.
         */
        public boolean hasNext() {
            return m_iterator.hasNext();
        }
        /** Returns the next element in the iteration.
         * @return the next element in the iteration.
         */
        public Object next() {
            m_lastReturned = m_iterator.next();
            Object obj = null;
            switch (m_type) {
                case TYPE_KEY_SET :
                    obj = m_lastReturned;
                    break;
                case TYPE_ENTRY_SET :
                    Object value = ListMap.this.get(m_lastReturned);
                    obj = ListMap.this.getEntry(m_lastReturned, value);
                    break;
                case TYPE_VALUES :
                    obj = ListMap.this.get(m_lastReturned);
                    break;
            }
            return obj;
        }
        /** Removes from the underlying collection the last element returned by the iterator.
         */
        public void remove() {
            m_iterator.remove();
            ListMap.this.remove(m_lastReturned);
        }
    }
    private class KeySet extends AbstractSet {
        /** Returns the number of elements in this set.
         * @return the number of elements in this set.
         */
        public int size() {
            return ListMap.this.size();
        }
        /** Returns true if this set contains the specified element.
         * @param o element whose presence in this set is to be tested.
         * @return true if this set contains the specified element.
         */
        public boolean contains(Object o) {
            return ListMap.this.containsKey(o);
        }
        /** Removes the specified element from this set if it is present.
         * @param o object to be removed from this set, if present.
         * @return true if the set contained the specified element.
         */
        public boolean remove(Object o) {
            int i = size();
            ListMap.this.remove(o);
            return ( size() != i );
        }
        /** Removes all of the elements from this set.*/
        public void clear() {
            ListMap.this.clear();
        }
        /** Returns an iterator over the elements in this set.
         * @return an iterator over the elements in this set.
         */
        public Iterator iterator() {
            return ListMap.this.getIterator(ListMap.TYPE_KEY_SET);
        }
    }
    private class EntrySet extends AbstractSet {
        /** Returns the number of elements in this set.
         * @return the number of elements in this set.
         */
        public int size() {
            return ListMap.this.size();
        }
        /** Returns true if this set contains the specified element.
         * @param o element whose presence in this set is to be tested.
         * @return true if this set contains the specified element.
         */
        public boolean contains(Object o) {
            boolean result = false;
            if (o != null && o instanceof Map.Entry) {
                Map.Entry entry = (Map.Entry) o;
                Object key = entry.getKey();
                if ( ListMap.this.containsKey(key) ) {
                    Object value1 = ListMap.this.get(key);
                    Object value2 = entry.getValue();
                    result = ( value1 == null ? value2 == null : value1.equals(value2) );
                }
            }
            return result;
        }
        /** Removes the specified element from this set if it is present.
         * @param o object to be removed from this set, if present.
         * @return true if the set contained the specified element.
         */
        public boolean remove(Object o) {
            boolean result = false;
            if (o != null && o instanceof Map.Entry) {
                Map.Entry entry = (Map.Entry) o;
                Object key = entry.getKey();
                int i = size();
                ListMap.this.remove(key);
                result = ( i != size() );
            }
            return result;
        }
        /** Removes all of the elements from this set.*/
        public void clear() {
            ListMap.this.clear();
        }
        /** Returns an iterator over the elements in this set.
         * @return an iterator over the elements in this set.
         */
        public Iterator iterator() {
            return ListMap.this.getIterator(ListMap.TYPE_ENTRY_SET);
        }
    }
    private class Values extends AbstractCollection {
        /** Returns the number of elements in this collection.
         * @return the number of elements in this collection.
         */
        public int size() {
            return ListMap.this.size();
        }
        /** Returns true if this collection contains the specified element.
         * @param o element whose presence in this collection is to be tested.
         * @return true if this collection contains the specified element.
         */
        public boolean contains(Object o) {
            return ListMap.this.containsValue(o);
        }
        /** Removes all of the elements from this collection.
         */
        public void clear() {
            ListMap.this.clear();
        }
        /** Returns an iterator over the elements in this collection.
         * @return an iterator over the elements in this collection.
         */
        public Iterator iterator() {
            return ListMap.this.getIterator(ListMap.TYPE_VALUES);
        }
    }
    private class ListMapEntry implements Map.Entry {
        Object m_key = null;
        Object m_value = null;
        private ListMapEntry(Object key, Object value) {
            m_key = key;
            m_value = value;
        }
        /** Returns the key corresponding to this entry.
         * @return the key corresponding to this entry.
         */
        public Object getKey() {
            return m_key;
        }
        /** Returns the hash code value for this map entry.
         * @return the hash code value for this map entry.
         */
        public int hashCode() {
            return (m_key==null ? 0 : m_key.hashCode() )
            + (m_value==null ? 0 : m_value.hashCode() );
        }
        /** Returns the value corresponding to this entry.
         * @return the value corresponding to this entry.
         */
        public Object getValue() {
            return m_value;
        }
        /** This is an Unsupported method. It throws the UnsupportedOperationException.
         * @param value the value to be set.
         * @return old value corresponding to the entry.
         */
        public Object setValue(Object value) {
            throw new UnsupportedOperationException();
        }
        /** Compares the specified object with this entry for equality.
         * Returns true if the given object is also a ListMap.Entry object and the two entries represent the same mapping.
         * @param o object to be compared for equality with this map entry.
         * @return true if the specified object is equal to this map entry.
         */
        public boolean equals(Object o) {
            boolean result = false;
            if (o instanceof ListMap.ListMapEntry) {
                ListMap.ListMapEntry e2 = (ListMap.ListMapEntry) o;
                result =  ( getKey()==null ?
                e2.getKey()==null : getKey().equals( e2.getKey() ) )
                && ( getValue()==null ?
                e2.getValue()==null : getValue().equals(e2.getValue() ) );
            }
            return result;
        }
    }
}
/*
 * 
 * JAFFA - Java Application Framework For All
 *
 * Copyright (C) 2002 JAFFA Development Group
 *
 *     This library is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU Lesser General Public
 *     License as published by the Free Software Foundation; either
 *     version 2.1 of the License, or (at your option) any later version.
 *
 *     This library 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
 *     Lesser General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public
 *     License along with this library; if not, write to the Free Software
 *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Redistribution and use of this software and associated documentation ("Software"),
 * with or without modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain copyright statements and notices.
 *         Redistributions must also contain a copy of this document.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 * 3. The name "JAFFA" must not be used to endorse or promote products derived from
 *  this Software without prior written permission. For written permission,
 *  please contact mail to: jaffagroup@yahoo.com.
 * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
 *  appear in their names without prior written permission.
 * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 */
/**
 * This class is backed by an ArrayList. Features are
 * 1) Ensure the Set functionality of unique elements(including a null) in this data structure
 * 2) Iterate through the list in the order in which the entries were made
 */
class ListSet implements Set, Cloneable, Serializable {
    List m_set = null;
    /** Creates new ListSet */
    public ListSet() {
        m_set = new ArrayList();
    }
    /** Creates new ListSet specifying the initial capacity.
     * @param initialCapacity The initial capacity.
     */
    public ListSet(int initialCapacity) {
        m_set = new ArrayList(initialCapacity);
    }
    /** Creates new ListSet from an existing Collection.
     * @param c An existing collection.
     */
    public ListSet(Collection c) {
        m_set = new ArrayList();
        if (c != null) {
            for (Iterator itr = c.iterator(); itr.hasNext();) {
                Object obj = itr.next();
                if ( !m_set.contains(obj) )
                    m_set.add(obj);
            }
        }
    }
    // *** Set Interface methods ***
    /** Retains only the elements in this set that are contained in the specified collection.
     * @param c collection that defines which elements this set will retain.
     * @return true if this collection changed as a result of the call.
     */
    public boolean retainAll(Collection c) {
        return m_set.retainAll(c);
    }
    /** Returns true if this set contains the specified element.
     * @param o element whose presence in this set is to be tested.
     * @return true if this set contains the specified element.
     */
    public boolean contains(Object o) {
        return m_set.contains(o);
    }
    /** Returns an array containing all of the elements in this set.
     * @return an array containing all of the elements in this set.
     */
    public Object[] toArray() {
        return m_set.toArray();
    }
    /** Returns an array containing all of the elements in this set; the runtime type of the returned array is that of the specified array.
     * @param a the array into which the elements of this set are to be stored, if it is big enough; otherwise, a new array of the same runtime type is allocated for this purpose.
     * @return an array containing all of the elements in this set; the runtime type of the returned array is that of the specified array
     */
    public Object[] toArray(Object[] a) {
        return m_set.toArray(a);
    }
    /** Returns an iterator over the elements in this set.
     * @return an iterator over the elements in this set.
     */
    public Iterator iterator() {
        return m_set.iterator();
    }
    /** Removes from this set all of its elements that are contained in the specified collection.
     * @param c collection that defines which elements will be removed from this set.
     * @return true if this set changed as a result of the call.
     */
    public boolean removeAll(Collection c) {
        return m_set.removeAll(c);
    }
    /** Removes the specified element from this set if it is present.
     * @param o object to be removed from this set, if present.
     * @return true if the set contained the specified element.
     */
    public boolean remove(Object o) {
        return m_set.remove(o);
    }
    /** Removes all of the elements from this set.*/
    public void clear() {
        m_set.clear();
    }
    /** Returns the hash code value for this set.
     * @return the hash code value for this set.
     */
    public int hashCode() {
        return m_set.hashCode();
    }
    /** Adds all of the elements in the specified collection to this set if they're not already present.
     * @param c collection whose elements are to be added to this set.
     * @return true if this set changed as a result of the call.
     */
    public boolean addAll(Collection c) {
        boolean added = false;
        if (c != null) {
            for (Iterator itr = c.iterator(); itr.hasNext();) {
                Object obj = itr.next();
                if ( !m_set.contains(obj) ) {
                    m_set.add(obj);
                    added = true;
                }
            }
        }
        return added;
    }
    /** Returns the number of elements in this set.
     * @return the number of elements in this set.
     */
    public int size() {
        return m_set.size();
    }
    /** Returns true if this set contains all of the elements of the specified collection.
     * @param c collection to be checked for containment in this set.
     * @return true if this set contains all of the elements of the specified collection.
     */
    public boolean containsAll(Collection c) {
        return m_set.containsAll(c);
    }
    /** Adds the specified element to this set if it is not already present.
     * @param o element to be added to this set.
     * @return true if this set did not already contain the specified element.
     */
    public boolean add(Object o) {
        boolean added = false;
        if ( !m_set.contains(o) ) {
            m_set.add(o);
            added = true;
        }
        return added;
    }
    /** Compares the specified object with this set for equality.
     * @param o Object to be compared for equality with this set.
     * @return true if the specified Object is equal to this set.
     */
    public boolean equals(Object o) {
        return m_set.equals(o);
    }
    /** Returns true if this set contains no elements.
     * @return true if this set contains no elements.
     */
    public boolean isEmpty() {
        return m_set.isEmpty();
    }
    // *** Additional Methods ***
    /** Adds the specified element to this set if it is not already present, at the specified index.
     * @param index The position at which the element is to be added.
     * @param o element to be added to this set.
     */
    public void add(int index, Object o) {
        if ( !m_set.contains(o) )
            m_set.add(index, o);
    }
    /** Returns the element from the specified position.
     * @param index The position from which the element is to be retrieved.
     * @return the element from the specified position.
     */
    public Object get(int index) {
        return m_set.get(index);
    }
    /** Remove the element from the specified position.
     * @param index The position from which the element is to be removed.
     * @return the element being removed.
     */
    public Object remove(int index) {
        return m_set.remove(index);
    }
    /** Returns the index of the element in this set.
     * @param o The element whose index is to be found.
     * @return the index of the element in this set.
     */
    public int indexOf(Object o) {
        return m_set.indexOf(o);
    }
    // *** CLONEABLE INTERFACE METHODS ***
    /** Returns a clone of the Set.
     * @throws CloneNotSupportedException if cloning is not supported. Should never happen.
     * @return a clone of the Set.
     */
    public Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();
        if (m_set != null && m_set instanceof Cloneable)
            ( (ListSet) obj ).m_set = (List) ( (ArrayList) m_set ).clone();
        return obj;
    }
}