From 40bdd8fe80d882b1b76c2d26d26bb69b032e86a3 Mon Sep 17 00:00:00 2001
From: James Strachan A {@link java.util.HashMap} whose keys are sequenced. The
+ * sequencing of the keys allow easy access to the values in the order
+ * which they were added in. This class is thread safe. Implementing the List interface is not possible due to a instance
+ * method name clash between the Collection and the List interface:
+ *
+ *
+ *
+ *
+ * Collections boolean remove(Object o)
+ * Lists Object remove(Object o)
So one cannot implement both interfaces at the same, which is + * unfortunate because the List interface would be very nice in + * conjuction with Velocity.
+ * + *A slightly more complex implementation and interface could involve
+ * the use of a list of Map.Entry
objects.
clone()
'd.
+ *
+ * @return A clone of this instance.
+ */
+ public Object clone ()
+ {
+ SequencedHashMap seqHash = (SequencedHashMap) super.clone();
+ seqHash.keySequence = (LinkedList) keySequence.clone();
+ return seqHash;
+ }
+
+ /**
+ * Returns the key at the specified index.
+ */
+ public Object get (int index)
+ {
+ return keySequence.get(index);
+ }
+
+ /**
+ * Returns the value at the specified index.
+ */
+ public Object getValue (int index)
+ {
+ return get(get(index));
+ }
+
+ /**
+ * Returns the index of the specified key.
+ */
+ public int indexOf (Object key)
+ {
+ return keySequence.indexOf(key);
+ }
+
+ /**
+ * Returns a key iterator.
+ */
+ public Iterator iterator ()
+ {
+ return keySequence.iterator();
+ }
+
+ /**
+ * Returns the last index of the specified key.
+ */
+ public int lastIndexOf (Object key)
+ {
+ return keySequence.lastIndexOf(key);
+ }
+
+ /**
+ * Returns the ordered sequence of keys.
+ *
+ * This method is meant to be used for retrieval of Key / Value pairs
+ * in e.g. Velocity:
+ * + * ## $table contains a sequenced hashtable + * #foreach ($key in $table.sequence()) + * <TR> + * <TD>Key: $key</TD> + * </TD>Value: $table.get($key)</TD> + * </TR> + * #end + *+ * + * @return The ordered list of keys. + */ + public List sequence() + { + return keySequence; + } + + /** + * Stores the provided key/value pair. Freshens the sequence of existing + * elements. + * + * @param key The key to the provided value. + * @param value The value to store. + * @return The previous value for the specified key, or + *
null
if none.
+ */
+ public Object put (Object key, Object value)
+ {
+ Object prevValue = super.put(key, value);
+ freshenSequence(key, prevValue);
+ return prevValue;
+ }
+
+ /**
+ * Freshens the sequence of the element value
if
+ * value
is not null
.
+ *
+ * @param key The key whose sequence to freshen.
+ * @param value The value whose existance to check before removing the old
+ * key sequence.
+ */
+ protected void freshenSequence(Object key, Object value)
+ {
+ if (value != null)
+ {
+ // Freshening existing element's sequence.
+ keySequence.remove(key);
+ }
+ keySequence.add(key);
+ }
+
+ /**
+ * Stores the provided key/value pairs.
+ *
+ * @param t The key/value pairs to store.
+ */
+ public void putAll (Map t)
+ {
+ Set set = t.entrySet();
+ for (Iterator iter = set.iterator(); iter.hasNext(); )
+ {
+ Map.Entry e = (Map.Entry)iter.next();
+ put(e.getKey(), e.getValue());
+ }
+ }
+
+ /**
+ * Removes the element at the specified index.
+ *
+ * @param index The index of the object to remove.
+ * @return The previous value coressponding the key
, or
+ * null
if none existed.
+ */
+ public Object remove (int index)
+ {
+ return remove(index, null);
+ }
+
+ /**
+ * Removes the element with the specified key.
+ *
+ * @param key The Map
key of the object to remove.
+ * @return The previous value coressponding the key
, or
+ * null
if none existed.
+ */
+ public Object remove (Object key)
+ {
+ return remove(UNKNOWN_INDEX, key);
+ }
+
+ /**
+ * Removes the element with the specified key or index.
+ *
+ * @param index The index of the object to remove, or
+ * UNKNOWN_INDEX
if not known.
+ * @param key The Map
key of the object to remove.
+ * @return The previous value coressponding the key
, or
+ * null
if none existed.
+ */
+ private final Object remove (int index, Object key)
+ {
+ if (index == UNKNOWN_INDEX)
+ {
+ index = indexOf(key);
+ }
+ if (key == null)
+ {
+ key = get(index);
+ }
+ if (index != UNKNOWN_INDEX)
+ {
+ keySequence.remove(index);
+ }
+ return super.remove(key);
+ }
+}
+
diff --git a/src/test/org/apache/commons/collections/TestAll.java b/src/test/org/apache/commons/collections/TestAll.java
index 3dea4ec5f..bdc89389b 100644
--- a/src/test/org/apache/commons/collections/TestAll.java
+++ b/src/test/org/apache/commons/collections/TestAll.java
@@ -1,7 +1,7 @@
/*
- * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/TestAll.java,v 1.11 2001/08/29 15:28:07 jstrachan Exp $
- * $Revision: 1.11 $
- * $Date: 2001/08/29 15:28:07 $
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/TestAll.java,v 1.12 2001/09/17 16:43:49 jstrachan Exp $
+ * $Revision: 1.12 $
+ * $Date: 2001/09/17 16:43:49 $
*
* ====================================================================
*
@@ -66,7 +66,7 @@ import junit.framework.*;
/**
* Entry point for all Collections tests.
* @author Rodney Waldhoff
- * @version $Id: TestAll.java,v 1.11 2001/08/29 15:28:07 jstrachan Exp $
+ * @version $Id: TestAll.java,v 1.12 2001/09/17 16:43:49 jstrachan Exp $
*/
public class TestAll extends TestCase {
public TestAll(String testName) {
@@ -90,6 +90,7 @@ public class TestAll extends TestCase {
suite.addTest(TestFastTreeMap1.suite());
suite.addTest(TestHashBag.suite());
suite.addTest(TestHashMap.suite());
+ suite.addTest(TestSequencedHashMap.suite());
suite.addTest(TestSingletonIterator.suite());
suite.addTest(TestTreeBag.suite());
suite.addTest(TestTreeMap.suite());
diff --git a/src/test/org/apache/commons/collections/TestSequencedHashMap.java b/src/test/org/apache/commons/collections/TestSequencedHashMap.java
new file mode 100644
index 000000000..071ffa9a2
--- /dev/null
+++ b/src/test/org/apache/commons/collections/TestSequencedHashMap.java
@@ -0,0 +1,153 @@
+package org.apache.commons.collections;
+
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 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 end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache Turbine" must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * "Apache Turbine", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * 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 software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ *