scolebourne 2003/10/28 16:06:25
Modified: collections/src/java/org/apache/commons/collections
AbstractDualBidiMap.java BidiMap.java
collections/src/test/org/apache/commons/collections
AbstractTestBidiMap.java
collections build.xml
Added: collections/src/java/org/apache/commons/collections
MapIterator.java
Log:
Add MapIterator to BidiMap
Revision Changes Path
1.4 +66 -2
jakarta-commons/collections/src/java/org/apache/commons/collections/AbstractDualBidiMap.java
Index: AbstractDualBidiMap.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/AbstractDualBidiMap.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- AbstractDualBidiMap.java 10 Oct 2003 21:09:49 -0000 1.3
+++ AbstractDualBidiMap.java 29 Oct 2003 00:06:25 -0000 1.4
@@ -214,6 +214,10 @@
// BidiMap
//-----------------------------------------------------------------------
+ public MapIterator mapIterator() {
+ return new BidiMapIterator(this);
+ }
+
public Object getKey(Object value) {
return maps[1].get(value);
}
@@ -435,6 +439,66 @@
public Object setValue(Object value) {
final Object oldValue = super.setValue(value);
+
+ // Gets old key and pairs with new value
+ final Object inverseKey = map.maps[1].remove(oldValue);
+ map.maps[1].put(value, inverseKey);
+
+ return oldValue;
+ }
+ }
+
+ /**
+ * Inner class MapIterator.
+ */
+ protected static class BidiMapIterator extends AbstractIteratorDecorator
implements MapIterator {
+
+ protected final AbstractDualBidiMap map;
+ private Map.Entry last = null;
+ private boolean canRemove = false;
+
+ protected BidiMapIterator(AbstractDualBidiMap map) {
+ super(map.maps[0].entrySet().iterator());
+ this.map = map;
+ }
+
+ public Object next() {
+ last = new MapEntry((Map.Entry) super.next(), map);
+ canRemove = true;
+ return last.getKey();
+ }
+
+ public void remove() {
+ if (canRemove == false) {
+ throw new IllegalStateException("Iterator remove() can only be
called once after next()");
+ }
+ // store value as remove may change the entry in the decorator
(eg.TreeMap)
+ Object value = last.getValue();
+ super.remove();
+ map.maps[1].remove(value);
+ last = null;
+ canRemove = false;
+ }
+
+ public Object getKey() {
+ if (last == null) {
+ throw new IllegalStateException("Iterator getKey() can only be
called after next() and before remove()");
+ }
+ return last.getKey();
+ }
+
+ public Object getValue() {
+ if (last == null) {
+ throw new IllegalStateException("Iterator getValue() can only be
called after next() and before remove()");
+ }
+ return last.getValue();
+ }
+
+ public Object setValue(Object value) {
+ if (last == null) {
+ throw new IllegalStateException("Iterator setValue() can only be
called after next() and before remove()");
+ }
+ Object oldValue = last.setValue(value);
// Gets old key and pairs with new value
final Object inverseKey = map.maps[1].remove(oldValue);
1.4 +20 -4
jakarta-commons/collections/src/java/org/apache/commons/collections/BidiMap.java
Index: BidiMap.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/BidiMap.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- BidiMap.java 6 Oct 2003 23:47:17 -0000 1.3
+++ BidiMap.java 29 Oct 2003 00:06:25 -0000 1.4
@@ -70,8 +70,6 @@
* <p>
* Implementations should allow a value to be looked up from a key and
* a key to be looked up from a value with equal performance.
- * It should be noted that the quickest way to implement the <code>values</code>
- * method is usually to return <code>inverseBidiMap().keySet()</code>.
*
* @see org.apache.commons.collections.DualHashBidiMap
* @since Commons Collections 3.0
@@ -80,6 +78,24 @@
* @author Stephen Colebourne
*/
public interface BidiMap extends Map {
+
+ /**
+ * Obtains a <code>MapIterator</code> over the map.
+ * <p>
+ * A map iterator is an efficient way of iterating over maps.
+ * It does not require that the map is stored using Map Entry objects
+ * which can increase performance.
+ * <pre>
+ * BidiMap map = new DualHashBidiMap();
+ * MapIterator it = map.mapIterator();
+ * Object key = it.next();
+ * Object value = it.getValue();
+ * it.setValue("newValue");
+ * </pre>
+ *
+ * @return a map iterator
+ */
+ MapIterator mapIterator();
/**
* Puts the key-value pair into the map, replacing any previous pair.
1.1
jakarta-commons/collections/src/java/org/apache/commons/collections/MapIterator.java
Index: MapIterator.java
===================================================================
/*
* $Header:
/home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/MapIterator.java,v
1.1 2003/10/29 00:06:25 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 [EMAIL PROTECTED]
*
* 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;
import java.util.Iterator;
/**
* Defines an iterator that operates over a <code>Map</code>.
* <p>
* This iterator is a special version designed for maps. It is much more
* efficient to use this rather than an entry set iterator where the option
* is available. A map that provides this interface may not hold the data
* internally using Map Entry objects, thus this interface can avoid lots
* of object creation.
* <p>
* In use, this iterator iterates through the keys in the map. After each
* call to <code>next()</code>, the <code>getValue()</code> method provides
* direct access to the value. The value can also be set using
* <code>setValue()</code>.
*
* @since Commons Collections 3.0
* @version $Revision: 1.1 $ $Date: 2003/10/29 00:06:25 $
*
* @author Stephen Colebourne
*/
public interface MapIterator extends Iterator {
/**
* Checks to see if there are more entries still to be iterated.
*
* @return <code>true</code> if the iterator has more elements
*/
boolean hasNext();
/**
* Gets the next <em>key</em> from the <code>Map</code>.
*
* @return the next key in the iteration
* @throws NoSuchElementException if the iteration is finished
*/
Object next();
//-----------------------------------------------------------------------
/**
* Gets the current key, which is the key returned by the last call
* to <code>next()</code>.
*
* @return the current key
* @throws IllegalStateException if <code>next()</code> has not yet been called
*/
Object getKey();
/**
* Gets the current value, which is the value associated with the last key
* returned by <code>next()</code>.
*
* @return the current value
* @throws IllegalStateException if <code>next()</code> has not yet been called
*/
Object getValue();
//-----------------------------------------------------------------------
/**
* Removes the last returned key from the underlying <code>Map</code> (optional
operation).
* <p>
* This method can be called once per call to <code>next()</code>.
*
* @throws UnsupportedOperationException if remove is not supported by the map
* @throws IllegalStateException if <code>next()</code> has not yet been called
* @throws IllegalStateException if <code>remove()</code> has already been called
* since the last call to <code>next()</code>
*/
void remove();
/**
* Sets the value associated with the current key.
*
* @param value the new value
* @return the previous value
* @throws IllegalStateException if <code>next()</code> has not yet been called
* @throws IllegalStateException if <code>remove()</code> has been called since
the
* last call to <code>next()</code>
*/
Object setValue(Object value);
}
1.2 +109 -3
jakarta-commons/collections/src/test/org/apache/commons/collections/AbstractTestBidiMap.java
Index: AbstractTestBidiMap.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/AbstractTestBidiMap.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- AbstractTestBidiMap.java 10 Oct 2003 21:11:39 -0000 1.1
+++ AbstractTestBidiMap.java 29 Oct 2003 00:06:25 -0000 1.2
@@ -59,9 +59,10 @@
import java.util.HashMap;
import java.util.Map;
+import java.util.NoSuchElementException;
/**
- * JUnit tests.
+ * Abstract test class for [EMAIL PROTECTED] BidiMap} methods and contracts.
*
* @version $Revision$ $Date$
*
@@ -375,4 +376,109 @@
}
+ //-----------------------------------------------------------------------
+ public void testBidiMapIteratorEmpty() {
+ resetEmpty();
+ BidiMap bidi = (BidiMap) map;
+ MapIterator it = bidi.mapIterator();
+ assertEquals(false, it.hasNext());
+ try {
+ it.next();
+ } catch (NoSuchElementException ex) {}
+ try {
+ it.getKey();
+ } catch (IllegalStateException ex) {
+ }
+ try {
+ it.getValue();
+ } catch (IllegalStateException ex) {
+ }
+ try {
+ it.remove();
+ } catch (UnsupportedOperationException ex) {
+ } catch (IllegalStateException ex) {
+ }
+ try {
+ it.setValue(null);
+ } catch (UnsupportedOperationException ex) {
+ } catch (IllegalStateException ex) {
+ }
+ verify();
+ }
+
+ //-----------------------------------------------------------------------
+ public void testBidiMapIteratorFull() {
+ resetFull();
+ BidiMap bidi = (BidiMap) map;
+ MapIterator it = bidi.mapIterator();
+
+ assertEquals(true, it.hasNext());
+ while (it.hasNext()) {
+ Object key = it.next();
+ assertSame(key, it.getKey());
+
+ Object value = it.getValue();
+ assertSame(bidi.get(key), value);
+ }
+ verify();
+ }
+
+ //-----------------------------------------------------------------------
+ public void testBidiMapIteratorRemove() {
+ resetFull();
+ BidiMap bidi = (BidiMap) map;
+ MapIterator it = bidi.mapIterator();
+ assertEquals(true, it.hasNext());
+ Object key = it.next();
+
+ if (isRemoveSupported() == false) {
+ try {
+ it.remove();
+ } catch (UnsupportedOperationException ex) {
+ }
+ return;
+ }
+
+ it.remove();
+ confirmed.remove(key);
+ assertEquals(false, bidi.containsKey(key));
+ verify();
+
+ try {
+ it.remove(); // second remove fails
+ } catch (IllegalStateException ex) {
+ }
+ verify();
+ }
+
+ //-----------------------------------------------------------------------
+ public void testBidiMapIteratorSet() {
+ resetFull();
+ BidiMap bidi = (BidiMap) map;
+ MapIterator it = bidi.mapIterator();
+ assertEquals(true, it.hasNext());
+ Object key = it.next();
+
+ if (isPutChangeSupported() == false) {
+ try {
+ it.setValue(getOtherValues()[0]);
+ } catch (UnsupportedOperationException ex) {
+ }
+ return;
+ }
+
+ it.setValue(getOtherValues()[0]);
+ confirmed.put(key, getOtherValues()[0]);
+ assertEquals(getOtherValues()[0], bidi.get(key));
+ verify();
+
+ it.remove();
+ confirmed.remove(key);
+ try {
+ it.setValue(getOtherValues()[0]);
+ } catch (IllegalStateException ex) {
+ }
+ verify();
+ }
+
}
1.50 +2 -1 jakarta-commons/collections/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/jakarta-commons/collections/build.xml,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- build.xml 27 Oct 2003 23:08:21 -0000 1.49
+++ build.xml 29 Oct 2003 00:06:25 -0000 1.50
@@ -37,6 +37,7 @@
<patternset id="patternset-testframework-source">
<include name="**/Bag.java"/>
<include name="**/BidiMap.java"/>
+ <include name="**/MapIterator.java"/>
<include name="**/SortedBag.java"/>
<include name="**/AbstractTest*.java"/>
<include name="**/BulkTest*.java"/>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]