You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sc...@apache.org on 2003/11/20 01:03:06 UTC
cvs commit: jakarta-commons/collections/src/test/org/apache/commons/collections/map TestListOrderedMap.java
scolebourne 2003/11/19 16:03:06
Modified: collections/src/test/org/apache/commons/collections/iterators
AbstractTestMapIterator.java
collections/src/java/org/apache/commons/collections/map
ListOrderedMap.java
collections/src/test/org/apache/commons/collections/map
TestListOrderedMap.java
Added: collections/src/test/org/apache/commons/collections/iterators
AbstractTestOrderedMapIterator.java
Log:
Make ListOrderedMap implement OrderedMap
Improve associated tests
Revision Changes Path
1.5 +5 -2 jakarta-commons/collections/src/test/org/apache/commons/collections/iterators/AbstractTestMapIterator.java
Index: AbstractTestMapIterator.java
===================================================================
RCS file: /home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/iterators/AbstractTestMapIterator.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- AbstractTestMapIterator.java 18 Nov 2003 22:37:14 -0000 1.4
+++ AbstractTestMapIterator.java 20 Nov 2003 00:03:05 -0000 1.5
@@ -261,6 +261,9 @@
assertSame("Key must not change after setValue", key, it.getKey());
assertSame("Value must be changed after setValue", newValue, it.getValue());
assertSame("setValue must return old value", value, old);
+ assertEquals("Map must contain key", true, map.containsKey(key));
+ assertEquals("Map must not contain old value", false, map.containsValue(old));
+ assertEquals("Map must contain old value", true, map.containsValue(newValue));
verify();
it.setValue(newValue); // same value - should be OK
1.1 jakarta-commons/collections/src/test/org/apache/commons/collections/iterators/AbstractTestOrderedMapIterator.java
Index: AbstractTestOrderedMapIterator.java
===================================================================
/*
* $Header: /home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/iterators/AbstractTestOrderedMapIterator.java,v 1.1 2003/11/20 00:03:05 scolebourne Exp $
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001-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 acknowledgement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgement may appear in the software itself,
* if and wherever such third-party acknowledgements 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
* <http://www.apache.org/>.
*
*/
package org.apache.commons.collections.iterators;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* Abstract class for testing the OrderedMapIterator interface.
* <p>
* This class provides a framework for testing an implementation of MapIterator.
* Concrete subclasses must provide the list iterator to be tested.
* They must also specify certain details of how the list iterator operates by
* overriding the supportsXxx() methods if necessary.
*
* @since Commons Collections 3.0
* @version $Revision: 1.1 $ $Date: 2003/11/20 00:03:05 $
*
* @author Stephen Colebourne
*/
public abstract class AbstractTestOrderedMapIterator extends AbstractTestMapIterator {
/**
* JUnit constructor.
*
* @param testName the test class name
*/
public AbstractTestOrderedMapIterator(String testName) {
super(testName);
}
//-----------------------------------------------------------------------
/**
* Test that the empty list iterator contract is correct.
*/
public void testEmptyMapIterator() {
if (supportsEmptyIterator() == false) {
return;
}
super.testEmptyMapIterator();
OrderedMapIterator it = (OrderedMapIterator) makeEmptyMapIterator();
Map map = getMap();
assertEquals(false, it.hasPrevious());
try {
it.previous();
fail();
} catch (NoSuchElementException ex) {}
}
//-----------------------------------------------------------------------
/**
* Test that the full list iterator contract is correct.
*/
public void testFullMapIterator() {
if (supportsFullIterator() == false) {
return;
}
super.testFullMapIterator();
OrderedMapIterator it = (OrderedMapIterator) makeFullMapIterator();
Map map = getMap();
assertEquals(true, it.hasNext());
assertEquals(false, it.hasPrevious());
Set set = new HashSet();
while (it.hasNext()) {
// getKey
Object key = it.next();
assertSame("it.next() should equals getKey()", key, it.getKey());
assertTrue("Key must be in map", map.containsKey(key));
assertTrue("Key must be unique", set.add(key));
// getValue
Object value = it.getValue();
assertSame("Value must be mapped to key", map.get(key), value);
assertTrue("Value must be in map", map.containsValue(value));
assertSame("Value must be mapped to key", map.get(key), value);
assertEquals(true, it.hasPrevious());
verify();
}
while (it.hasPrevious()) {
// getKey
Object key = it.previous();
assertSame("it.previous() should equals getKey()", key, it.getKey());
assertTrue("Key must be in map", map.containsKey(key));
assertTrue("Key must be unique", set.remove(key));
// getValue
Object value = it.getValue();
assertSame("Value must be mapped to key", map.get(key), value);
assertTrue("Value must be in map", map.containsValue(value));
assertSame("Value must be mapped to key", map.get(key), value);
assertEquals(true, it.hasNext());
verify();
}
}
//-----------------------------------------------------------------------
/**
* Test that the iterator order matches the keySet order.
*/
public void testMapIteratorOrder() {
if (supportsFullIterator() == false) {
return;
}
OrderedMapIterator it = (OrderedMapIterator) makeFullMapIterator();
Map map = getMap();
assertEquals("keySet() not consistent", new ArrayList(map.keySet()), new ArrayList(map.keySet()));
Iterator it2 = map.keySet().iterator();
assertEquals(true, it.hasNext());
assertEquals(true, it2.hasNext());
List list = new ArrayList();
while (it.hasNext()) {
Object key = it.next();
assertEquals(it2.next(), key);
list.add(key);
}
while (it.hasPrevious()) {
Object key = it.previous();
assertEquals(list.get(list.size() - 1), key);
list.remove(list.size() - 1);
}
}
}
1.2 +164 -17 jakarta-commons/collections/src/java/org/apache/commons/collections/map/ListOrderedMap.java
Index: ListOrderedMap.java
===================================================================
RCS file: /home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/map/ListOrderedMap.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ListOrderedMap.java 16 Nov 2003 00:05:45 -0000 1.1
+++ ListOrderedMap.java 20 Nov 2003 00:03:05 -0000 1.2
@@ -63,12 +63,15 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Set;
import org.apache.commons.collections.iterators.AbstractIteratorDecorator;
-import org.apache.commons.collections.iterators.EntrySetMapIterator;
import org.apache.commons.collections.iterators.MapIterator;
+import org.apache.commons.collections.iterators.OrderedMapIterator;
+import org.apache.commons.collections.iterators.ResettableIterator;
import org.apache.commons.collections.pairs.AbstractMapEntry;
/**
@@ -76,6 +79,8 @@
* <p>
* The order will be used via the iterators and toArray methods on the views.
* The order is also returned by the <code>MapIterator</code>.
+ * The <code>orderedMapIterator()</code> method accesses an iterator that can
+ * iterate both forwards and backwards through the map.
* <p>
* If an object is added to the Map for a second time, it will remain in the
* original position in the iteration.
@@ -86,7 +91,7 @@
* @author Henri Yandell
* @author Stephen Colebourne
*/
-public class ListOrderedMap extends AbstractMapDecorator implements Map {
+public class ListOrderedMap extends AbstractMapDecorator implements OrderedMap {
/** Internal list to hold the sequence of objects */
protected final List insertOrder = new ArrayList();
@@ -115,6 +120,72 @@
insertOrder.addAll(getMap().keySet());
}
+ // Implement OrderedMap
+ //-----------------------------------------------------------------------
+ public MapIterator mapIterator() {
+ return orderedMapIterator();
+ }
+
+ public OrderedMapIterator orderedMapIterator() {
+ return new ListOrderedMapIterator(this);
+ }
+
+ /**
+ * Gets the first key in this map by insert order.
+ *
+ * @return the first key currently in this map
+ * @throws NoSuchElementException if this map is empty
+ */
+ public Object firstKey() {
+ if (size() == 0) {
+ throw new NoSuchElementException("Map is empty");
+ }
+ return insertOrder.get(0);
+ }
+
+ /**
+ * Gets the last key in this map by insert order.
+ *
+ * @return the last key currently in this map
+ * @throws NoSuchElementException if this map is empty
+ */
+ public Object lastKey() {
+ if (size() == 0) {
+ throw new NoSuchElementException("Map is empty");
+ }
+ return insertOrder.get(size() - 1);
+ }
+
+ /**
+ * Gets the next key to the one specified using insert order.
+ * This method performs a list search to find the key and is O(n).
+ *
+ * @param key the key to find previous for
+ * @return the next key, null if no match or at start
+ */
+ public Object nextKey(Object key) {
+ int index = insertOrder.indexOf(key);
+ if (index >= 0 && index < size() - 1) {
+ return insertOrder.get(index + 1);
+ }
+ return null;
+ }
+
+ /**
+ * Gets the previous key to the one specified using insert order.
+ * This method performs a list search to find the key and is O(n).
+ *
+ * @param key the key to find previous for
+ * @return the previous key, null if no match or at start
+ */
+ public Object previousKey(Object key) {
+ int index = insertOrder.indexOf(key);
+ if (index > 0) {
+ return insertOrder.get(index - 1);
+ }
+ return null;
+ }
+
//-----------------------------------------------------------------------
public Object put(Object key, Object value) {
if (getMap().containsKey(key)) {
@@ -147,10 +218,6 @@
}
//-----------------------------------------------------------------------
- public MapIterator mapIterator() {
- return new EntrySetMapIterator(this);
- }
-
public Set keySet() {
return new KeySetView(this);
}
@@ -181,14 +248,14 @@
Map.Entry entry = (Map.Entry) it.next();
Object key = entry.getKey();
Object value = entry.getValue();
- buf.append(key == this ? "(this Map)" : key);
- buf.append('=');
- buf.append(value == this ? "(this Map)" : value);
if (first) {
first = false;
} else {
buf.append(", ");
}
+ buf.append(key == this ? "(this Map)" : key);
+ buf.append('=');
+ buf.append(value == this ? "(this Map)" : value);
}
buf.append('}');
return buf.toString();
@@ -320,22 +387,23 @@
}
public Iterator iterator() {
- return new OrderedIterator(parent, insertOrder);
+ return new ListOrderedIterator(parent, insertOrder);
}
}
- static class OrderedIterator extends AbstractIteratorDecorator {
+ //-----------------------------------------------------------------------
+ static class ListOrderedIterator extends AbstractIteratorDecorator {
private final ListOrderedMap parent;
private Object last = null;
- OrderedIterator(ListOrderedMap parent, List insertOrder) {
+ ListOrderedIterator(ListOrderedMap parent, List insertOrder) {
super(insertOrder.iterator());
this.parent = parent;
}
public Object next() {
last = super.next();
- return new OrderedMapEntry(parent, last);
+ return new ListOrderedMapEntry(parent, last);
}
public void remove() {
@@ -344,10 +412,11 @@
}
}
- static class OrderedMapEntry extends AbstractMapEntry {
+ //-----------------------------------------------------------------------
+ static class ListOrderedMapEntry extends AbstractMapEntry {
private final ListOrderedMap parent;
- OrderedMapEntry(ListOrderedMap parent, Object key) {
+ ListOrderedMapEntry(ListOrderedMap parent, Object key) {
super(key, null);
this.parent = parent;
}
@@ -361,4 +430,82 @@
}
}
+ //-----------------------------------------------------------------------
+ static class ListOrderedMapIterator implements OrderedMapIterator, ResettableIterator {
+ private final ListOrderedMap parent;
+ private ListIterator iterator;
+ private Object last = null;
+ private boolean readable = false;
+
+ ListOrderedMapIterator(ListOrderedMap parent) {
+ super();
+ this.parent = parent;
+ this.iterator = parent.insertOrder.listIterator();
+ }
+
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ public Object next() {
+ last = iterator.next();
+ readable = true;
+ return last;
+ }
+
+ public boolean hasPrevious() {
+ return iterator.hasPrevious();
+ }
+
+ public Object previous() {
+ last = iterator.previous();
+ readable = true;
+ return last;
+ }
+
+ public void remove() {
+ if (readable == false) {
+ throw new IllegalStateException("Iterator remove() can only be called after next() and before remove()");
+ }
+ iterator.remove();
+ parent.map.remove(last);
+ readable = false;
+ }
+
+ public Object getKey() {
+ if (readable == false) {
+ throw new IllegalStateException("Iterator getKey() can only be called after next() and before remove()");
+ }
+ return last;
+ }
+
+ public Object getValue() {
+ if (readable == false) {
+ throw new IllegalStateException("Iterator getValue() can only be called after next() and before remove()");
+ }
+ return parent.get(last);
+ }
+
+ public Object setValue(Object value) {
+ if (readable == false) {
+ throw new IllegalStateException("Iterator setValue() can only be called after next() and before remove()");
+ }
+ return parent.map.put(last, value);
+ }
+
+ public void reset() {
+ iterator = parent.insertOrder.listIterator();
+ last = null;
+ readable = false;
+ }
+
+ public String toString() {
+ if (readable == true) {
+ return "MapIterator[" + getKey() + "=" + getValue() + "]";
+ } else {
+ return "MapIterator[]";
+ }
+ }
+ }
+
}
1.4 +8 -85 jakarta-commons/collections/src/test/org/apache/commons/collections/map/TestListOrderedMap.java
Index: TestListOrderedMap.java
===================================================================
RCS file: /home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/map/TestListOrderedMap.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- TestListOrderedMap.java 18 Nov 2003 22:37:17 -0000 1.3
+++ TestListOrderedMap.java 20 Nov 2003 00:03:06 -0000 1.4
@@ -67,7 +67,7 @@
import junit.framework.Test;
import org.apache.commons.collections.BulkTest;
-import org.apache.commons.collections.iterators.AbstractTestMapIterator;
+import org.apache.commons.collections.iterators.AbstractTestOrderedMapIterator;
import org.apache.commons.collections.iterators.MapIterator;
/**
@@ -101,12 +101,13 @@
//-----------------------------------------------------------------------
public BulkTest bulkTestMapIterator() {
- return new TestOrderedMapIterator();
+ return new TestListOrderedMapIterator();
}
- public class TestOrderedMapIterator extends AbstractTestMapIterator {
- public TestOrderedMapIterator() {
- super("TestOrderedMapIterator");
+ // TODO: Test mapIterator() and orderedMapIterator() separately
+ public class TestListOrderedMapIterator extends AbstractTestOrderedMapIterator {
+ public TestListOrderedMapIterator() {
+ super("TestListOrderedMapIterator");
}
public boolean supportsRemove() {
@@ -143,84 +144,6 @@
}
}
- //-----------------------------------------------------------------------
- public void testMapIteratorRemove() {
- resetFull();
- ListOrderedMap testMap = (ListOrderedMap) map;
- MapIterator it = testMap.mapIterator();
- assertEquals(true, it.hasNext());
- Object key = it.next();
-
- if (isRemoveSupported() == false) {
- try {
- it.remove();
- fail();
- } catch (UnsupportedOperationException ex) {
- }
- return;
- }
-
- it.remove();
- confirmed.remove(key);
- assertEquals(false, testMap.containsKey(key));
- verify();
-
- try {
- it.remove(); // second remove fails
- } catch (IllegalStateException ex) {
- }
- verify();
- }
-
- //-----------------------------------------------------------------------
- public void testMapIteratorSet() {
- Object newValue1 = getOtherValues()[0];
- Object newValue2 = getOtherValues()[1];
-
- resetFull();
- ListOrderedMap testMap = (ListOrderedMap) map;
- MapIterator it = testMap.mapIterator();
- assertEquals(true, it.hasNext());
- Object key1 = it.next();
-
- if (isSetValueSupported() == false) {
- try {
- it.setValue(newValue1);
- fail();
- } catch (UnsupportedOperationException ex) {
- }
- return;
- }
-
- it.setValue(newValue1);
- confirmed.put(key1, newValue1);
- assertSame(key1, it.getKey());
- assertSame(newValue1, it.getValue());
- assertEquals(true, testMap.containsKey(key1));
- assertEquals(true, testMap.containsValue(newValue1));
- assertEquals(newValue1, testMap.get(key1));
- verify();
-
- it.setValue(newValue1); // same value - should be OK
- confirmed.put(key1, newValue1);
- assertSame(key1, it.getKey());
- assertSame(newValue1, it.getValue());
- assertEquals(true, testMap.containsKey(key1));
- assertEquals(true, testMap.containsValue(newValue1));
- assertEquals(newValue1, testMap.get(key1));
- verify();
-
- Object key2 = it.next();
- it.setValue(newValue2);
- confirmed.put(key2, newValue2);
- assertSame(key2, it.getKey());
- assertSame(newValue2, it.getValue());
- assertEquals(true, testMap.containsKey(key2));
- assertEquals(true, testMap.containsValue(newValue2));
- assertEquals(newValue2, testMap.get(key2));
- verify();
- }
-
//-----------------------------------------------------------------------
// Creates a known series of Objects, puts them in
// an OrderedMap and ensures that all three Collection
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org