scolebourne    2003/10/03 17:50:35

  Modified:    collections/src/test/org/apache/commons/collections/decorators
                        TestSetList.java
               collections/src/java/org/apache/commons/collections/decorators
                        SetList.java
  Log:
  Refactor SetList to be a subclass of the abstract decorator
  
  Revision  Changes    Path
  1.2       +153 -13   
jakarta-commons/collections/src/test/org/apache/commons/collections/decorators/TestSetList.java
  
  Index: TestSetList.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/collections/src/test/org/apache/commons/collections/decorators/TestSetList.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TestSetList.java  2 Oct 2003 22:34:44 -0000       1.1
  +++ TestSetList.java  4 Oct 2003 00:50:35 -0000       1.2
  @@ -59,13 +59,16 @@
   
   import java.util.ArrayList;
   import java.util.Arrays;
  +import java.util.HashSet;
  +import java.util.List;
   import java.util.ListIterator;
   
   import junit.framework.Test;
  -import junit.framework.TestCase;
   import junit.framework.TestSuite;
   import junit.textui.TestRunner;
   
  +import org.apache.commons.collections.AbstractTestList;
  +
   /**
    * JUnit tests.
    *
  @@ -74,7 +77,7 @@
    * 
    * @author Matthew Hawthorne
    */
  -public class TestSetList extends TestCase {
  +public class TestSetList extends AbstractTestList {
   
       public static void main(String[] args) {
           TestRunner.run(suite());
  @@ -89,16 +92,153 @@
       }
   
       //-----------------------------------------------------------------------
  -    public void testConstructor() {
  -        final SetList lset =
  -            new SetList(
  -                Arrays.asList(new Integer[] { new Integer(1), new Integer(1)}));
  +    protected List makeEmptyList() {
  +        return new SetList(new ArrayList(), new HashSet());
  +    }
   
  -        assertEquals("Duplicate element was added.", 1, lset.size());
  +    public void testListIteratorSet() {
  +        // override to block
  +        resetFull();
  +        ListIterator it = getList().listIterator();
  +        it.next();
  +        try {
  +            it.set(null);
  +            fail();
  +        } catch (UnsupportedOperationException ex) {}
  +    }
  +    
  +    protected Object[] getFullNonNullElements() {
  +        // override to avoid duplicate "One"
  +        return new Object[] {
  +            new String(""),
  +            new String("One"),
  +            new Integer(2),
  +            "Three",
  +            new Integer(4),
  +            new Double(5),
  +            new Float(6),
  +            "Seven",
  +            "Eight",
  +            new String("Nine"),
  +            new Integer(10),
  +            new Short((short)11),
  +            new Long(12),
  +            "Thirteen",
  +            "14",
  +            "15",
  +            new Byte((byte)16)
  +        };
  +    }
  +    
  +    public void testListIteratorAdd() {
  +        // override to cope with Set behaviour
  +        resetEmpty();
  +        List list1 = getList();
  +        List list2 = getConfirmedList();
  +
  +        Object[] elements = getOtherElements();  // changed here
  +        ListIterator iter1 = list1.listIterator();
  +        ListIterator iter2 = list2.listIterator();
  +
  +        for (int i = 0; i < elements.length; i++) {
  +            iter1.add(elements[i]);
  +            iter2.add(elements[i]);
  +            super.verify();  // changed here
  +        }
  +
  +        resetFull();
  +        iter1 = getList().listIterator();
  +        iter2 = getConfirmedList().listIterator();
  +        for (int i = 0; i < elements.length; i++) {
  +            iter1.next();
  +            iter2.next();
  +            iter1.add(elements[i]);
  +            iter2.add(elements[i]);
  +            super.verify();  // changed here
  +        }
  +    }
  +    
  +    public void testCollectionAddAll() {
  +        // override for set behaviour
  +        resetEmpty();
  +        Object[] elements = getFullElements();
  +        boolean r = collection.addAll(Arrays.asList(elements));
  +        confirmed.addAll(Arrays.asList(elements));
  +        verify();
  +        assertTrue("Empty collection should change after addAll", r);
  +        for (int i = 0; i < elements.length; i++) {
  +            assertTrue("Collection should contain added element",
  +                       collection.contains(elements[i]));
  +        }
  +
  +        resetFull();
  +        int size = collection.size();
  +        elements = getOtherElements();
  +        r = collection.addAll(Arrays.asList(elements));
  +        confirmed.addAll(Arrays.asList(elements));
  +        verify();
  +        assertTrue("Full collection should change after addAll", r);
  +        for (int i = 0; i < elements.length; i++) {
  +            assertTrue("Full collection should contain added element " + i,
  +                       collection.contains(elements[i]));
  +        }
  +        assertEquals("Size should increase after addAll", 
  +                     size + elements.length, collection.size());
  +    }
  +    
  +    public void testListSetByIndex() {
  +        // override for set behaviour
  +        resetFull();
  +        int size = collection.size();
  +        getList().set(0, new Long(1000));
  +        assertEquals(size, collection.size());
  +
  +        getList().set(2, new Long(1000));
  +        assertEquals(size - 1, collection.size());
  +        assertEquals(new Long(1000), getList().get(1));  // set into 2, but shifted 
down to 1
  +    }
  +    
  +    boolean extraVerify = true;
  +    public void testCollectionIteratorRemove() {
  +        try {
  +            extraVerify = false;
  +            super.testCollectionIteratorRemove();
  +        } finally {
  +            extraVerify = true;
  +        }
  +    }
  +    
  +    protected void verify() {
  +        super.verify();
  +        
  +        if (extraVerify) {
  +            int size = collection.size();
  +            getList().add(new Long(1000));
  +            assertEquals(size + 1, collection.size());
  +
  +            getList().add(new Long(1000));
  +            assertEquals(size + 1, collection.size());
  +            assertEquals(new Long(1000), getList().get(size));
  +        
  +            getList().remove(size);
  +        }
  +    }
  +    
  +    //-----------------------------------------------------------------------
  +    public void testFactory() {
  +        Integer[] array = new Integer[] {new Integer(1), new Integer(2), new 
Integer(1)};
  +        ArrayList list = new ArrayList(Arrays.asList(array));
  +        final SetList lset = SetList.decorate(list);
  +
  +        assertEquals("Duplicate element was added.", 2, lset.size());
  +        assertEquals(new Integer(1), lset.get(0));
  +        assertEquals(new Integer(2), lset.get(1));
  +        assertEquals(new Integer(1), list.get(0));
  +        assertEquals(new Integer(2), list.get(1));
       }
   
       public void testAdd() {
  -        final SetList lset = new SetList(new ArrayList());
  +        final SetList lset = new SetList(new ArrayList(), new HashSet());
   
           // Duplicate element
           final Object obj = new Integer(1);
  @@ -112,7 +252,7 @@
       }
   
       public void testAddAll() {
  -        final SetList lset = new SetList(new ArrayList());
  +        final SetList lset = new SetList(new ArrayList(), new HashSet());
   
           lset.addAll(
               Arrays.asList(new Integer[] { new Integer(1), new Integer(1)}));
  @@ -121,7 +261,7 @@
       }
   
       public void testSet() {
  -        final SetList lset = new SetList(new ArrayList());
  +        final SetList lset = new SetList(new ArrayList(), new HashSet());
   
           // Duplicate element
           final Object obj1 = new Integer(1);
  @@ -159,7 +299,7 @@
       }
   
       public void testListIterator() {
  -        final SetList lset = new SetList(new ArrayList());
  +        final SetList lset = new SetList(new ArrayList(), new HashSet());
   
           final Object obj1 = new Integer(1);
           final Object obj2 = new Integer(2);
  
  
  
  1.2       +178 -33   
jakarta-commons/collections/src/java/org/apache/commons/collections/decorators/SetList.java
  
  Index: SetList.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-commons/collections/src/java/org/apache/commons/collections/decorators/SetList.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SetList.java      2 Oct 2003 22:34:44 -0000       1.1
  +++ SetList.java      4 Oct 2003 00:50:35 -0000       1.2
  @@ -57,12 +57,13 @@
    */
   package org.apache.commons.collections.decorators;
   
  -import java.util.AbstractList;
   import java.util.ArrayList;
   import java.util.Collection;
  +import java.util.Collections;
   import java.util.HashSet;
   import java.util.Iterator;
   import java.util.List;
  +import java.util.ListIterator;
   import java.util.Set;
   
   /**
  @@ -78,11 +79,6 @@
    * class provides an alternative approach, by wrapping an existing Set and
    * retaining insertion order in the iterator. This class offers the 
<code>List</code>
    * interface implementation as well.
  - * <p>
  - * If the <code>Set</code> aspects are important to you (fast add/contains/remove)
  - * then <code>OrderedSet</code> is a better choice.
  - * This implementation is based solely on <code>ArrayList</code>, and so has
  - * slow add/contains/remove operations for all except small lists.
    *
    * @since Commons Collections 3.0
    * @version $Revision$ $Date$
  @@ -90,32 +86,63 @@
    * @author Matthew Hawthorne
    * @author Stephen Colebourne
    */
  -public class SetList extends AbstractList {
  +public class SetList extends AbstractListDecorator {
   
       /**
  -     * Delegate list.
  +     * Internal Set to maintain uniqueness.
        */
  -    private final List delegate = new ArrayList();
  +    protected final Set set;
   
       /**
  -     * Helps to maintain uniqueness.
  +     * Factory method to create a SetList using the supplied list to retain order.
  +     * <p>
  +     * If the list contains duplicates, these are removed (first indexed one kept).
  +     * A <code>HashSet</code> is used for the set behaviour.
  +     * 
  +     * @param list  the list to decorate, must not be null
  +     * @throws IllegalArgumentException if list is null
        */
  -    private final Set set = new HashSet();
  +    public static SetList decorate(List list) {
  +        if (list == null) {
  +            throw new IllegalArgumentException("List must not be null");
  +        }
  +        if (list.isEmpty()) {
  +            return new SetList(list, new HashSet());
  +        } else {
  +            List temp = new ArrayList(list);
  +            list.clear();
  +            SetList sl = new SetList(list, new HashSet());
  +            sl.addAll(temp);
  +            return sl;
  +        }
  +    }
   
  +    //-----------------------------------------------------------------------
       /**
  -     * Factory method to create a SetList.
  -     * @param list the list to decorate
  +     * Constructor that wraps (not copies) the List and specifies the set to use.
  +     * <p>
  +     * The set and list must both be correctly initialised to the same elements.
  +     * 
  +     * @param set  the set to decorate, must not be null
  +     * @param list  the list to decorate, must not be null
  +     * @throws IllegalArgumentException if set or list is null
        */
  -    public static SetList decorate(List list) {
  -        return new SetList(list);
  +    protected SetList(List list, Set set) {
  +        super(list);
  +        if (set == null) {
  +            throw new IllegalArgumentException("Set must not be null");
  +        }
  +        this.set = set;
       }
   
  +    //-----------------------------------------------------------------------
       /**
  -     * Contructs an new list copying the specified elements.
  -     * @param coll  a collection to copy
  +     * Gets an unmodifiable view as a Set.
  +     * 
  +     * @return an unmodifiable set view
        */
  -    protected SetList(List list) {
  -        addAll(list);
  +    public Set asSet() {
  +        return Collections.unmodifiableSet(set);
       }
   
       //-----------------------------------------------------------------------
  @@ -152,14 +179,27 @@
        * @param object  the object to add
        */
       public void add(int index, Object object) {
  -        // Adds element if it is not contained already
  -        if (!set.contains(object)) {
  -            delegate.add(index, object);
  +        // adds element if it is not contained already
  +        if (set.contains(object) == false) {
  +            super.add(index, object);
               set.add(object);
           }
       }
   
  -    //-----------------------------------------------------------------------
  +    /**
  +     * Adds an element to the end of the list if it is not already present.
  +     * <p>
  +     * <i>(Violation)</i>
  +     * The <code>List</code> interface makes the assumption that the element is
  +     * always inserted. This may not happen with this implementation.
  +     * 
  +     * @param index  the index to insert at
  +     * @param object  the object to add
  +     */
  +    public boolean addAll(Collection coll) {
  +        return addAll(size(), coll);
  +    }
  +
       /**
        * Adds a collection of objects to the end of the list avoiding duplicates.
        * <p>
  @@ -202,28 +242,133 @@
        */
       public Object set(int index, Object object) {
           int pos = indexOf(object);
  -        Object result = delegate.set(index, object);
  +        Object result = super.set(index, object);
           if (pos == -1 || pos == index) {
               return result;
           }
           return remove(pos);
       }
   
  -    public Object get(int index) {
  -        return delegate.get(index);
  +    public boolean remove(Object object) {
  +        boolean result = super.remove(object);
  +        set.remove(object);
  +        return result;
       }
   
  -    public int size() {
  -        return delegate.size();
  +    public Object remove(int index) {
  +        Object result = super.remove(index);
  +        set.remove(result);
  +        return result;
       }
   
  -    public Object remove(int index) {
  -        return delegate.remove(index);
  +    public boolean removeAll(Collection coll) {
  +        boolean result = super.removeAll(coll);
  +        set.removeAll(coll);
  +        return result;
  +    }
  +
  +    public boolean retainAll(Collection coll) {
  +        boolean result = super.retainAll(coll);
  +        set.retainAll(coll);
  +        return result;
       }
   
       public void clear() {
  -        delegate.clear();
  +        super.clear();
           set.clear();
       }
   
  +    public boolean contains(Object object) {
  +        return set.contains(object);
  +    }
  +
  +    public boolean containsAll(Collection coll) {
  +        return set.containsAll(coll);
  +    }
  +
  +    public Iterator iterator() {
  +        return new SetListIterator(super.iterator(), set);
  +    }
  +
  +    public ListIterator listIterator() {
  +        return new SetListListIterator(super.listIterator(), set);
  +    }
  +
  +    public ListIterator listIterator(int index) {
  +        return new SetListListIterator(super.listIterator(index), set);
  +    }
  +
  +    public List subList(int fromIndex, int toIndex) {
  +        return new SetList(super.subList(fromIndex, toIndex), set);
  +    }
  +
  +    //-----------------------------------------------------------------------
  +    /**
  +     * Inner class iterator.
  +     */
  +    protected static class SetListIterator extends AbstractIteratorDecorator {
  +        
  +        protected final Set set;
  +        protected Object last = null;
  +        
  +        protected SetListIterator(Iterator it, Set set) {
  +            super(it);
  +            this.set = set;
  +        }
  +        
  +        public Object next() {
  +            last = super.next();
  +            return last;
  +        }
  +
  +        public void remove() {
  +            super.remove();
  +            set.remove(last);
  +            last = null;
  +        }
  +
  +    }
  +    
  +    /**
  +     * Inner class iterator.
  +     */
  +    protected static class SetListListIterator extends 
AbstractListIteratorDecorator {
  +        
  +        protected final Set set;
  +        protected Object last = null;
  +        
  +        protected SetListListIterator(ListIterator it, Set set) {
  +            super(it);
  +            this.set = set;
  +        }
  +        
  +        public Object next() {
  +            last = super.next();
  +            return last;
  +        }
  +
  +        public Object previous() {
  +            last = super.previous();
  +            return last;
  +        }
  +
  +        public void remove() {
  +            super.remove();
  +            set.remove(last);
  +            last = null;
  +        }
  +
  +        public void add(Object object) {
  +            if (set.contains(object) == false) {
  +                super.add(object);
  +                set.add(object);
  +            }
  +        }
  +        
  +        public void set(Object object) {
  +            throw new UnsupportedOperationException("ListIterator does not support 
set");
  +        }
  +
  +    }
  +    
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to