Author: skestle
Date: Thu Nov 8 14:49:02 2007
New Revision: 593347
URL: http://svn.apache.org/viewvc?rev=593347&view=rev
Log:
Added initial IndexedCollection - still needs quite a bit of work - see TODO
comments
JIRA: COLLECTIONS-275
Added:
commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/IndexedCollection.java
commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/AbstractDecoratedCollectionTest.java
commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestIndexedCollection.java
Modified:
commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestAll.java
Added:
commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/IndexedCollection.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/IndexedCollection.java?rev=593347&view=auto
==============================================================================
---
commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/IndexedCollection.java
(added)
+++
commons/proper/collections/branches/collections_jdk5_branch/src/java/org/apache/commons/collections/IndexedCollection.java
Thu Nov 8 14:49:02 2007
@@ -0,0 +1,116 @@
+package org.apache.commons.collections;
+
+import java.util.Collection;
+import java.util.HashMap;
+
+import org.apache.commons.collections.collection.AbstractCollectionDecorator;
+
+/**
+ * An IndexedCollection is a Map-like view onto a Collection. It accepts a
+ * keyTransformer to define how the keys are converted from the values.
+ * <p>
+ * Modifications made to this decorator modify the index as well as the
+ * decorated [EMAIL PROTECTED] Collection}. However, modifications to the
underlying
+ * [EMAIL PROTECTED] Collection} will not updated the index and it will get
out of sync.
+ * <p>
+ * If modification to the decorated [EMAIL PROTECTED] Collection} is
unavoidable, then a
+ * call to [EMAIL PROTECTED] #reindex()} will update the index to the current
contents of
+ * the [EMAIL PROTECTED] Collection}.
+ *
+ * @param K the type of object in the index.
+ * @param C the type of object in the collection.
+ * @author Stephen Kestle
+ */
+// TODO support MultiMap/non-unique index behavior
+// TODO add support for remove and clear
+public class IndexedCollection<K, C> extends AbstractCollectionDecorator<C> {
+ /**
+ * .
+ */
+ private static final long serialVersionUID = -5512610452568370038L;
+
+ /**
+ * Create an [EMAIL PROTECTED] IndexedCollection} for a unique index.
+ *
+ * @param <K> the index object type.
+ * @param <C> the collection type.
+ * @param coll the decorated [EMAIL PROTECTED] Collection}.
+ * @param keyTransformer the [EMAIL PROTECTED] Transformer} for generating
index keys.
+ * @return the created [EMAIL PROTECTED] IndexedCollection}.
+ */
+ public static <K, C> IndexedCollection<K, C> uniqueIndexedCollection(final
Collection<C> coll, final Transformer<C, K> keyTransformer) {
+ return new IndexedCollection<K, C>(coll, keyTransformer, new
HashMap<K, C>());
+ }
+
+ /**
+ * The [EMAIL PROTECTED] Transformer} for generating index keys.
+ */
+ private final Transformer<C, K> keyTransformer;
+
+ /**
+ * The map of indexes to collected objects.
+ */
+ private final HashMap<K, C> index;
+
+ /**
+ * Create a [EMAIL PROTECTED] IndexedCollection} for a unique index.
+ *
+ * @param coll the decorated [EMAIL PROTECTED] Collection}.
+ * @param keyTransformer the [EMAIL PROTECTED] Transformer} for generating
index keys.
+ * @return the created [EMAIL PROTECTED] IndexedCollection}.
+ */
+ public IndexedCollection(Collection<C> coll, Transformer<C, K>
keyTransformer, HashMap<K, C> map) {
+ super(coll);
+ this.keyTransformer = keyTransformer;
+ this.index = map;
+ reindex();
+ }
+
+ /**
+ * Clears the index and re-indexes the entire decorated [EMAIL PROTECTED]
Collection}.
+ */
+ public void reindex() {
+ index.clear();
+ for (C c : decorated()) {
+ addIndex(c);
+ }
+ }
+
+ /**
+ * Adds an object to the collection and index.
+ */
+ @Override
+ // TODO: Add error handling for when super.add() fails
+ public boolean add(C object) {
+ addIndex(object);
+ return super.add(object);
+ }
+
+ /**
+ * Adds an entire collection to the collection and index.
+ */
+ @Override
+ // TODO: Add error handling for when super.addAll() fails
+ public boolean addAll(Collection<? extends C> coll) {
+ for (C c : coll) {
+ addIndex(c);
+ }
+ return super.addAll(coll);
+ }
+
+ /**
+ * Provides checking for adding the index.
+ *
+ * @param object the object to index.
+ */
+ private void addIndex(C object) {
+ final C existingObject = index.put(keyTransformer.transform(object),
object);
+ if (existingObject != null) {
+ throw new IllegalArgumentException("Duplicate key in uniquely
indexed collection.");
+ }
+ }
+
+ public C get(K key) {
+ return index.get(key);
+ }
+}
Added:
commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/AbstractDecoratedCollectionTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/AbstractDecoratedCollectionTest.java?rev=593347&view=auto
==============================================================================
---
commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/AbstractDecoratedCollectionTest.java
(added)
+++
commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/AbstractDecoratedCollectionTest.java
Thu Nov 8 14:49:02 2007
@@ -0,0 +1,22 @@
+package org.apache.commons.collections;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.junit.Before;
+
+public abstract class AbstractDecoratedCollectionTest<C> {
+ /**
+ * The [EMAIL PROTECTED] Collection} being decorated.
+ */
+ protected Collection<C> original;
+ /**
+ * The Collection under test that decorates [EMAIL PROTECTED] #original}.
+ */
+ protected Collection<C> decorated;
+
+ @Before
+ public void setUpDecoratedCollection() throws Exception {
+ original = new ArrayList<C>();
+ }
+}
Modified:
commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestAll.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestAll.java?rev=593347&r1=593346&r2=593347&view=diff
==============================================================================
---
commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestAll.java
(original)
+++
commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestAll.java
Thu Nov 8 14:49:02 2007
@@ -44,6 +44,7 @@
TestSetUtils.class,
TestTransformerUtils.class,
TestArrayStack.class,
- TestExtendedProperties.class})
+ TestExtendedProperties.class,
+ TestIndexedCollection.class})
public class TestAll extends TestCase {
}
Added:
commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestIndexedCollection.java
URL:
http://svn.apache.org/viewvc/commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestIndexedCollection.java?rev=593347&view=auto
==============================================================================
---
commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestIndexedCollection.java
(added)
+++
commons/proper/collections/branches/collections_jdk5_branch/src/test/org/apache/commons/collections/TestIndexedCollection.java
Thu Nov 8 14:49:02 2007
@@ -0,0 +1,73 @@
+package org.apache.commons.collections;
+
+import static java.util.Arrays.asList;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestIndexedCollection extends
AbstractDecoratedCollectionTest<String> {
+ private IndexedCollection<Integer, String> indexed;
+
+ @Before
+ public void setUp() throws Exception {
+ indexed = IndexedCollection.uniqueIndexedCollection(original, new
Transformer<String, Integer>() {
+ public Integer transform(String input) {
+ return Integer.parseInt(input);
+ }
+ });
+ decorated = indexed;
+ }
+
+ @Test
+ public void addedObjectsCanBeRetrievedByKey() throws Exception {
+ decorated.add("12");
+ decorated.add("16");
+ decorated.add("1");
+ decorated.addAll(asList("2","3","4"));
+ assertEquals("12", indexed.get(12));
+ assertEquals("16", indexed.get(16));
+ assertEquals("1", indexed.get(1));
+ assertEquals("2", indexed.get(2));
+ assertEquals("3", indexed.get(3));
+ assertEquals("4", indexed.get(4));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void ensureDuplicateObjectsCauseException() throws Exception {
+ decorated.add("1");
+ decorated.add("1");
+ }
+
+ @Test
+ public void decoratedCollectionIsIndexedOnCreation() throws Exception {
+ original.add("1");
+ original.add("2");
+ original.add("3");
+
+ indexed = IndexedCollection.uniqueIndexedCollection(original, new
Transformer<String, Integer>() {
+ public Integer transform(String input) {
+ return Integer.parseInt(input);
+ }
+ });
+ assertEquals("1", indexed.get(1));
+ assertEquals("2", indexed.get(2));
+ assertEquals("3", indexed.get(3));
+ }
+
+ @Test
+ public void
reindexUpdatesIndexWhenTheDecoratedCollectionIsModifiedSeparately() throws
Exception {
+ original.add("1");
+ original.add("2");
+ original.add("3");
+
+ assertNull(indexed.get(1));
+ assertNull(indexed.get(2));
+ assertNull(indexed.get(3));
+ indexed.reindex();
+ assertEquals("1", indexed.get(1));
+ assertEquals("2", indexed.get(2));
+ assertEquals("3", indexed.get(3));
+ }
+}