diff --git a/src/java/org/apache/commons/collections/MultiKey.java b/src/java/org/apache/commons/collections/MultiKey.java
new file mode 100644
index 000000000..74b9867e9
--- /dev/null
+++ b/src/java/org/apache/commons/collections/MultiKey.java
@@ -0,0 +1,227 @@
+/*
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/Attic/MultiKey.java,v 1.1 2003/03/09 00:06:44 scolebourne Exp $
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 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 "The Jakarta Project", "Commons", and "Apache Software
+ * Foundation" 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"
+ * nor may "Apache" appear in their names 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
+ * MultiKey
allows multiple map keys to be merged together.
+ *
+ * The purpose of this class is to avoid the need to write code to handle + * maps of maps. An example might be the need to lookup a filename by + * key and locale. The typical solution might be nested maps. This class + * can be used instead by creating an instance passing in the key and locale. + * + * @since Commons Collections 2.2 + * @version $Revision: 1.1 $ $Date: 2003/03/09 00:06:44 $ + * + * @author Howard Lewis Ship + * @author Stephen Colebourne + */ +public class MultiKey implements Serializable { + + private static final long serialVersionUID = 4465448607415788805L; + + /** The individual keys */ + private final Object[] keys; + /** The cached hashCode */ + private final int hashCode; + + /** + * Constructor taking two keys. + * + * @param key1 the first key + * @param key2 the second key + */ + public MultiKey(Object key1, Object key2) { + this(new Object[] {key1, key2}, false); + } + + /** + * Constructor taking three keys. + * + * @param key1 the first key + * @param key2 the second key + * @param key3 the third key + */ + public MultiKey(Object key1, Object key2, Object key3) { + this(new Object[] {key1, key2, key3}, false); + } + + /** + * Constructor taking four keys. + * + * @param key1 the first key + * @param key2 the second key + * @param key3 the third key + * @param key4 the fourth key + */ + public MultiKey(Object key1, Object key2, Object key3, Object key4) { + this(new Object[] {key1, key2, key3, key4}, false); + } + + /** + * Constructor taking five keys. + * + * @param key1 the first key + * @param key2 the second key + * @param key3 the third key + * @param key4 the fourth key + * @param key5 the fifth key + */ + public MultiKey(Object key1, Object key2, Object key3, Object key4, Object key5) { + this(new Object[] {key1, key2, key3, key4, key5}, false); + } + + /** + * Constructor taking an array of keys. + * + * @param keys the array of keys + * @throws IllegalArgumentException if the key array is null + */ + public MultiKey(Object[] keys) { + this(keys, true); + } + + /** + * Constructor taking an array of keys. + *
+ * If the array is not copied, then it must not be modified. + * + * @param keys the array of keys + * @param makeCopy true to copy the array, false to assign it + * @throws IllegalArgumentException if the key array is null + */ + protected MultiKey(Object[] keys, boolean makeCopy) { + super(); + if (keys == null) { + throw new IllegalArgumentException("The array of keys must not be null"); + } + if (makeCopy) { + this.keys = (Object[]) keys.clone(); + } else { + this.keys = keys; + } + + int total = 0; + for (int i = 0; i < keys.length; i++) { + if (keys[i] != null) { + if (i == 0) { + total = keys[i].hashCode(); + } else { + total ^= keys[i].hashCode(); + } + } + } + hashCode = total; + } + + /** + * Gets a copy of the individual keys. + * + * @return the individual keys + */ + public Object[] getKeys() { + return (Object[]) keys.clone(); + } + + /** + * Compares this object to another. + *
+ * To be equal, the other object must be a MultiKey
with the
+ * same number of keys which are also equal.
+ *
+ * @param other the other object to compare to
+ * @return true if equal
+ */
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (other instanceof MultiKey) {
+ MultiKey otherMulti = (MultiKey) other;
+ return Arrays.equals(keys, otherMulti.keys);
+ }
+ return false;
+ }
+
+ /**
+ * Gets the combined hashcode that is computed from all the keys.
+ *
+ * This value is computed once and then cached, so elements should not
+ * change their hash codes once created (note that this is the same
+ * constraint that would be used if the individual keys elements were
+ * themselves {@link java.util.Map Map} keys.
+ *
+ * @return the hashcode
+ */
+ public int hashCode() {
+ return hashCode;
+ }
+
+ /**
+ * Gets a debugging string version of the key.
+ *
+ * @return a debugging string
+ */
+ public String toString() {
+ return "MultiKey" + Arrays.asList(keys).toString();
+ }
+
+}
diff --git a/src/test/org/apache/commons/collections/TestAll.java b/src/test/org/apache/commons/collections/TestAll.java
index a1e088698..a68f34ce7 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.40 2003/02/19 20:33:11 scolebourne Exp $
- * $Revision: 1.40 $
- * $Date: 2003/02/19 20:33:11 $
+ * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/TestAll.java,v 1.41 2003/03/09 00:07:41 scolebourne Exp $
+ * $Revision: 1.41 $
+ * $Date: 2003/03/09 00:07:41 $
*
* ====================================================================
*
@@ -68,7 +68,7 @@ import junit.framework.TestSuite;
/**
* Entry point for all Collections tests.
* @author Rodney Waldhoff
- * @version $Id: TestAll.java,v 1.40 2003/02/19 20:33:11 scolebourne Exp $
+ * @version $Id: TestAll.java,v 1.41 2003/03/09 00:07:41 scolebourne Exp $
*/
public class TestAll extends TestCase {
public TestAll(String testName) {
@@ -100,6 +100,7 @@ public class TestAll extends TestCase {
suite.addTest(TestHashBag.suite());
suite.addTest(TestLRUMap.suite());
suite.addTest(TestMultiHashMap.suite());
+ suite.addTest(TestMultiKey.suite());
suite.addTest(TestNodeCachingLinkedList.suite());
suite.addTest(TestSequencedHashMap.suite());
suite.addTest(TestStaticBucketMap.suite());
diff --git a/src/test/org/apache/commons/collections/TestMultiKey.java b/src/test/org/apache/commons/collections/TestMultiKey.java
new file mode 100644
index 000000000..40aceeb42
--- /dev/null
+++ b/src/test/org/apache/commons/collections/TestMultiKey.java
@@ -0,0 +1,146 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 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
+ *