Index: src/org/openide/util/Enumerations.java =================================================================== RCS file: src/org/openide/util/Enumerations.java diff -N src/org/openide/util/Enumerations.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/openide/util/Enumerations.java 20 Mar 2004 08:05:04 -0000 @@ -0,0 +1,286 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun + * Microsystems, Inc. All Rights Reserved. + */ +package org.openide.util; + +import java.util.*; +import java.util.Enumeration; +import java.util.Map; +import java.util.Set; + +/** Factory methods for various types of java.util.Enumeration + * + * @author Jaroslav Tulach + */ +public final class Enumerations extends Object { + /** No instances */ + private Enumerations () { + } + + public static Enumeration EMPTY = Collections.enumeration (Collections.EMPTY_LIST); + + public static Enumeration singleton (Object obj) { + return Collections.enumeration (Collections.singleton (obj)); + } + public static Enumeration concat (Enumeration en1, Enumeration en2) { + return new SeqEn (en1, en2); + } + public static Enumeration concat (Enumeration enumOfEnums) { + return new SeqEn (enumOfEnums); + } + public static Enumeration removeDuplicates (Enumeration en) { + class HashSetWithInverseContains extends HashSet { + public boolean contains (Object o) { + // returns true if the object is not yet there + return super.add (o); + } + } + + return filter (en, new HashSetWithInverseContains ()); + } + + public static Enumeration array (Object[] arr) { + return Collections.enumeration (Arrays.asList (arr)); + } + public static Enumeration convert (Enumeration en, Map map) { + return new AltEn (en, map); + } + public static Enumeration removeNulls (Enumeration en) { + return new FilEn (en); + } + public static Enumeration filter (Enumeration en, Set filter) { + return new FilEn (en, filter); + } + public static Enumeration process (Enumeration en, Processor p) { + return new ProEn (en, p); + } + + /** Interface processor of enumerations. + */ + public static interface Processor { + /** @param obj original object + * @param toAdd additional objects can be add or addAll to the end of current enumeration + * @return object that should be returned from the enum instead of obj + */ + public Object process (Object obj, List toAdd); + } + + private static final class AltEn extends Object implements Enumeration { + /** enumeration to filter */ + private Enumeration en; + /** map to alter */ + private java.util.Map map; + + /** + * @param en enumeration to filter + */ + public AltEn (Enumeration en, java.util.Map map) { + this.en = en; + this.map = map; + } + + /** @return true if there is more elements in the enumeration + */ + public boolean hasMoreElements () { + return en.hasMoreElements (); + } + + /** @return next object in the enumeration + * @exception NoSuchElementException can be thrown if there is no next object + * in the enumeration + */ + public Object nextElement () { + return map.get (en.nextElement ()); + } + } // end of AltEn + + private static final class SeqEn extends Object implements Enumeration { + /** enumeration of Enumerations */ + private Enumeration en; + /** current enumeration */ + private Enumeration current; + + /** is {@link #current} up-to-date and has more elements? + * The combination current == null and + * checked == true means there are no more elements + * in this enumeration. + */ + private boolean checked = false; + + /** Constructs new enumeration from already existing. The elements + * of en should be also enumerations. The resulting + * enumeration contains elements of such enumerations. + * + * @param en enumeration of Enumerations that should be sequenced + */ + public SeqEn (Enumeration en) { + this.en = en; + } + + /** Composes two enumerations into one. + * @param first first enumeration + * @param second second enumeration + */ + public SeqEn (Enumeration first, Enumeration second) { + this (array (new Enumeration[] { first, second })); + } + + /** Ensures that current enumeration is set. If there aren't more + * elements in the Enumerations, sets the field current to null. + */ + private void ensureCurrent () { + while (current == null || !current.hasMoreElements ()) { + if (en.hasMoreElements ()) { + current = (Enumeration)en.nextElement (); + } else { + // no next valid enumeration + current = null; + return; + } + } + } + + /** @return true if we have more elements */ + public boolean hasMoreElements () { + if( !checked ) { + ensureCurrent (); + checked = true; + } + return current != null; + } + + /** @return next element + * @exception NoSuchElementException if there is no next element + */ + public synchronized Object nextElement () { + if( !checked ) { + ensureCurrent (); + } + if( current != null ) { + checked = false; + return current.nextElement (); + } else { + checked = true; + throw new java.util.NoSuchElementException (); + } + } + } // end of SeqEn + + private static final class FilEn extends Object implements Enumeration { + /** marker object stating there is no nexte element prepared */ + private static final Object EMPTY = new Object(); + + /** enumeration to filter */ + private Enumeration en; + + /** element to be returned next time or {@link #EMPTY} if there is + * no such element prepared */ + private Object next = EMPTY; + + /** the set to use as filter */ + private java.util.Set filter; + + /** Remove nulls. + * @param en enumeration to filter + */ + public FilEn (Enumeration en) { + this.en = en; + } + + /** + * @param en enumeration to filter + */ + public FilEn (Enumeration en, java.util.Set filter) { + if (filter == null) throw new NullPointerException (); + this.en = en; + this.filter = filter; + } + + /** @return true if there is more elements in the enumeration + */ + public boolean hasMoreElements () { + if (next != EMPTY) { + // there is a object already prepared + return true; + } + while (en.hasMoreElements ()) { + // read next + next = en.nextElement (); + if (filter != null) { + if (filter.contains (next)) { + // if the object is accepted + return true; + } + } else { + // filter out nulls + if (next != null) { + return true; + } + } + } + next = EMPTY; + return false; + } + + /** @return next object in the enumeration + * @exception NoSuchElementException can be thrown if there is no next object + * in the enumeration + */ + public Object nextElement () { + if( next == EMPTY && !hasMoreElements() ) { + throw new NoSuchElementException (); + } + Object res = next; + next = EMPTY; + return res; + } + } // end of FilEn + + /** Processor enumeration. + */ + private static final class ProEn extends java.util.LinkedList + implements java.util.Enumeration { + private Processor processor; + private Enumeration delegate; + + public ProEn (Enumeration en, Processor p) { + this.processor = p; + this.delegate = en; + } + + public boolean hasMoreElements () { + if (delegate != null && delegate.hasMoreElements ()) { + return true; + } + return !isEmpty (); + } + + public Object nextElement () { + Object ret; + if (delegate != null) { + ret = delegate.nextElement (); + if (!delegate.hasMoreElements ()) { + delegate = null; + } + } else { + + if (isEmpty ()) { + throw new NoSuchElementException (); + } + ret = this.removeFirst (); + } + ret = processor.process (ret, this); + return ret; + } + + } // end of ProEn +} Index: test/unit/src/org/openide/util/EnumerationsTest.java =================================================================== RCS file: test/unit/src/org/openide/util/EnumerationsTest.java diff -N test/unit/src/org/openide/util/EnumerationsTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ test/unit/src/org/openide/util/EnumerationsTest.java 20 Mar 2004 08:05:04 -0000 @@ -0,0 +1,394 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun + * Microsystems, Inc. All Rights Reserved. + */ +package org.openide.util; + +import java.util.*; +import java.util.Enumeration; +import java.util.Map; +import java.util.Set; + +/** This is the base test for new and old enumerations. It contains + * factory methods for various kinds of enumerations and set of tests + * that use them. Factory methods are overriden in OldEnumerationsTest + * + * @author Jaroslav Tulach + */ +public class EnumerationsTest extends org.netbeans.junit.NbTestCase { + + /** Creates a new instance of EnumerationsTest */ + public EnumerationsTest (String testName) { + super(testName); + } + + public static void main(java.lang.String[] args) { + junit.textui.TestRunner.run(new org.netbeans.junit.NbTestSuite(EnumerationsTest.class)); + } + + // + // Factory methods + // + + protected Enumeration singleton (Object obj) { + return Enumerations.singleton (obj); + } + protected Enumeration concat (Enumeration en1, Enumeration en2) { + return Enumerations.concat (en1, en2); + } + protected Enumeration concat (Enumeration enumOfEnums) { + return Enumerations.concat (enumOfEnums); + } + protected Enumeration removeDuplicates (Enumeration en) { + return Enumerations.removeDuplicates (en); + } + protected Enumeration empty () { + return Enumerations.EMPTY; + } + protected Enumeration array (Object[] arr) { + return Enumerations.array (arr); + } + protected Enumeration convert (Enumeration en, Map map) { + return Enumerations.convert (en, map); + } + protected Enumeration removeNulls (Enumeration en) { + return Enumerations.removeNulls (en); + } + protected Enumeration filter (Enumeration en, Set filter) { + return Enumerations.filter (en, filter); + } + protected Enumeration queue (List initial, final QueueProcessor processor) { + return Enumerations.process ( + java.util.Collections.enumeration (initial), new Enumerations.Processor() { + public Object process (Object obj, List toAdd) { + return processor.process (obj, toAdd); + } + } + ); + } + + public static interface QueueProcessor { + /** @param obj Object object on output + * @param addItemsHere allows to add or addAll aditional items to the end of current enum + * @return object to be returned + */ + public Object process (Object obj, List addItemsHere); + } + + // + // The tests + // + + public void testEmptyIsEmpty () { + Enumeration e = empty (); + assertFalse (e.hasMoreElements ()); + try { + e.nextElement (); + fail ("No elements"); + } catch (java.util.NoSuchElementException ex) { + // ok + } + } + + public void testSingleIsSingle () { + Enumeration e = singleton (this); + assertTrue (e.hasMoreElements ()); + assertEquals ("Returns me", this, e.nextElement ()); + assertFalse ("Now it is empty", e.hasMoreElements ()); + try { + e.nextElement (); + fail ("No elements"); + } catch (java.util.NoSuchElementException ex) { + // ok + } + } + + public void testConcatTwoAndArray () { + Object[] one = { new Integer (1), new Integer (2), new Integer (3) }; + Object[] two = { "1", "2", "3" }; + + ArrayList list = new ArrayList (Arrays.asList (one)); + list.addAll (Arrays.asList (two)); + + assertEnums ( + concat (array (one), array (two)), + Collections.enumeration (list) + ); + } + + public void testConcatTwoAndArrayAndTakeOnlyStrings () { + Object[] one = { new Integer (1), new Integer (2), new Integer (3) }; + Object[] two = { "1", "2", "3" }; + Object[] three = { new Long (1) }; + Object[] four = { "Kuk" }; + + ArrayList list = new ArrayList (Arrays.asList (two)); + list.addAll (Arrays.asList (four)); + + Enumeration[] alls = { + array (one), array (two), array (three), array (four) + }; + + assertEnums ( + filter (concat (array (alls)), new OnlyStrings()), + Collections.enumeration (list) + ); + } + + public void testRemoveDuplicates () { + Object[] one = { new Integer (1), new Integer (2), new Integer (3) }; + Object[] two = { "1", "2", "3" }; + Object[] three = { new Integer (1) }; + Object[] four = { "2", "3", "4" }; + + Enumeration[] alls = { + array (one), array (two), array (three), array (four) + }; + + assertEnums ( + removeDuplicates (concat (array (alls))), + array (new Object[] { new Integer (1), new Integer (2), new Integer (3), "1", "2", "3", "4" }) + ); + + } + + + public void testConvertIntegersToStringRemoveNulls () { + Object[] garbage = { new Integer (1), "kuk", "hle", new Integer (5) }; + + assertEnums ( + convert (array (garbage), new MapIntegers ()), + array (new Object[] { "1", null, null, "5" }) + ); + + assertEnums ( + removeNulls (convert (array (garbage), new MapIntegers ())), + array (new Object[] { "1", "5" }) + ); + } + + public void testQueueEnum () { + Object obj = new Integer (5); + class AddOneTill10 implements QueueProcessor { + public Object process (Object obj, List toAddTo) { + Integer i = (Integer)obj; + if (i.intValue () < 10) { + toAddTo.add (new Integer (i.intValue () + 1)); + } + return i; + } + } + Enumeration en = queue (Collections.nCopies (1, obj), new AddOneTill10 ()); + + assertEnums (en, array (new Object[] { + new Integer (5), new Integer (6), new Integer (7), new Integer (8), new Integer (9), new Integer (10) + })); + + } + + public void testQueueEnumDoesWideSearchFirst () { + Object[] obj = { + new Integer (1), + new Object[] { + new Integer (4), + new Object[] { + new Integer (7), + new Integer (8), + }, + new Integer (5), + }, + new Integer (2), + new Object[] { new Integer (6) }, + new Integer (3), + }; + class AddArray implements QueueProcessor { + public Object process (Object obj, List toAddTo) { + if (obj instanceof Object[]) { + toAddTo.addAll (Arrays.asList ((Object[])obj)); + return null; + } else { + return obj; + } + } + } + + + Enumeration en = removeNulls ( + queue (Collections.nCopies (1, obj), new AddArray ()) + ); + + for (int i = 1; i < 9; i++) { + Integer number = (Integer)en.nextElement (); + assertEquals (i, number.intValue ()); + } + + } + + private static void assertEnums (Enumeration e1, Enumeration e2) { + int indx = 0; + while (e1.hasMoreElements () && e2.hasMoreElements ()) { + assertEquals (indx++ + "th: ", e1.nextElement (), e2.nextElement ()); + } + + if (e1.hasMoreElements ()) { + fail ("first one contains another element: " + e1.nextElement ()); + } + if (e2.hasMoreElements ()) { + fail ("second one contains another element: " + e2.nextElement ()); + } + + try { + e1.nextElement (); + fail ("First one should throw exception, but nothing happend"); + } catch (java.util.NoSuchElementException ex) { + // ok + } + + try { + e2.nextElement (); + fail ("Second one should throw exception, but nothing happend"); + } catch (java.util.NoSuchElementException ex) { + // ok + } + } + + /** Filters only strings. + */ + private static final class OnlyStrings implements java.util.Set { + public boolean add (Object o) { + fail ("Should not be every called"); + return false; + } + + public boolean addAll (Collection c) { + fail ("Should not be every called"); + return false; + } + + public void clear () { + fail ("Should not be every called"); + } + + public boolean contains (Object o) { + return o instanceof String; + } + + public boolean containsAll (Collection c) { + fail ("Should not be every called"); + return false; + } + + public boolean isEmpty () { + fail ("Should not be every called"); + return false; + } + + public Iterator iterator () { + fail ("Should not be every called"); + return null; + } + + public boolean remove (Object o) { + fail ("Should not be every called"); + return false; + } + + public boolean removeAll (Collection c) { + fail ("Should not be every called"); + return false; + } + + public boolean retainAll (Collection c) { + fail ("Should not be every called"); + return false; + } + + public int size () { + fail ("Should not be every called"); + return 1; + } + + public Object[] toArray () { + fail ("Should not be every called"); + return null; + } + + public Object[] toArray (Object[] a) { + fail ("Should not be every called"); + return null; + } + } + + /** Filters only strings. + */ + private static final class MapIntegers implements java.util.Map { + public boolean containsKey (Object key) { + fail ("Should not be every called"); + return false; + } + + public boolean containsValue (Object value) { + fail ("Should not be every called"); + return false; + } + + public Set entrySet () { + fail ("Should not be every called"); + return null; + } + + public Object get (Object key) { + if (key instanceof Integer) { + return key.toString (); + } + return null; + } + + public Set keySet () { + fail ("Should not be every called"); + return null; + } + + public Object put (Object key, Object value) { + fail ("Should not be every called"); + return null; + } + + public void putAll (Map t) { + fail ("Should not be every called"); + } + + public Collection values () { + fail ("Should not be every called"); + return null; + } + + public void clear () { + fail ("Should not be every called"); + } + + public boolean isEmpty () { + fail ("Should not be every called"); + return false; + } + + public Object remove (Object key) { + fail ("Should not be every called"); + return null; + } + + public int size () { + fail ("Should not be every called"); + return 1; + } + + } +} Index: test/unit/src/org/openide/util/OldEnumerationsTest.java =================================================================== RCS file: test/unit/src/org/openide/util/OldEnumerationsTest.java diff -N test/unit/src/org/openide/util/OldEnumerationsTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ test/unit/src/org/openide/util/OldEnumerationsTest.java 20 Mar 2004 08:05:04 -0000 @@ -0,0 +1,202 @@ +/* + * Sun Public License Notice + * + * The contents of this file are subject to the Sun Public License + * Version 1.0 (the "License"). You may not use this file except in + * compliance with the License. A copy of the License is available at + * http://www.sun.com/ + * + * The Original Code is NetBeans. The Initial Developer of the Original + * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun + * Microsystems, Inc. All Rights Reserved. + */ +package org.openide.util; + +import org.openide.util.enum.*; + +/** Implement factory methods from EnumerationsTest, shares the same tests + * with EnumerationsTest. + * + * @author Jaroslav Tulach + */ +public class OldEnumerationsTest extends EnumerationsTest { + + /** Creates a new instance of EnumerationsTest */ + public OldEnumerationsTest (String testName) { + super(testName); + } + + public static void main(java.lang.String[] args) { + junit.textui.TestRunner.run(new org.netbeans.junit.NbTestSuite(OldEnumerationsTest.class)); + } + + protected java.util.Enumeration singleton (Object obj) { + return new SingletonEnumeration (obj); + } + + protected java.util.Enumeration convert (java.util.Enumeration en, final java.util.Map map) { + return new AlterEnumeration (en) { + protected Object alter (Object o) { + return map.get (o); + } + }; + } + + protected java.util.Enumeration removeDuplicates (java.util.Enumeration en) { + return new RemoveDuplicatesEnumeration (en); + } + + protected java.util.Enumeration removeNulls (java.util.Enumeration en) { + return new FilterEnumeration (en); + } + + protected java.util.Enumeration concat (java.util.Enumeration en1, java.util.Enumeration en2) { + return new SequenceEnumeration (en1, en2); + } + + protected java.util.Enumeration array (Object[] arr) { + return new ArrayEnumeration (arr); + } + + protected java.util.Enumeration filter (java.util.Enumeration en, final java.util.Set filter) { + return new FilterEnumeration (en) { + protected boolean accept (Object obj) { + return filter.contains (obj); + } + }; + } + + protected java.util.Enumeration concat (java.util.Enumeration enumOfEnums) { + return new SequenceEnumeration (enumOfEnums); + } + + protected java.util.Enumeration empty () { + return new EmptyEnumeration (); + } + + protected java.util.Enumeration queue (java.util.List initial, QueueProcessor processor) { + QE en = new QE (processor); + en.put (initial.toArray ()); + return en; + } + + class QE extends QueueEnumeration implements java.util.List { + private QueueProcessor processor; + private Object orig; + private Object replace; + + public QE (QueueProcessor p) { + this.processor = p; + } + + public Object nextElement () { + Object ret = super.nextElement (); + if (ret == orig) { + return replace; + } else { + return ret; + } + } + + + protected void process (Object obj) { + orig = obj; + replace = processor.process (obj, this); + } + + public boolean add (Object o) { + put (o); + return true; + } + + public void add (int index, Object element) { + throw new UnsupportedOperationException (); + } + + public boolean addAll (java.util.Collection c) { + put (c.toArray ()); + return !c.isEmpty (); + } + + public boolean addAll (int index, java.util.Collection c) { + throw new UnsupportedOperationException (); + } + + public void clear () { + throw new UnsupportedOperationException (); + } + + public boolean contains (Object o) { + throw new UnsupportedOperationException (); + } + + public boolean containsAll (java.util.Collection c) { + throw new UnsupportedOperationException (); + } + + public Object get (int index) { + throw new UnsupportedOperationException (); + } + + public int indexOf (Object o) { + throw new UnsupportedOperationException (); + } + + public boolean isEmpty () { + throw new UnsupportedOperationException (); + } + + public java.util.Iterator iterator () { + throw new UnsupportedOperationException (); + } + + public int lastIndexOf (Object o) { + throw new UnsupportedOperationException (); + } + + public java.util.ListIterator listIterator () { + throw new UnsupportedOperationException (); + } + + public java.util.ListIterator listIterator (int index) { + throw new UnsupportedOperationException (); + } + + public boolean remove (Object o) { + throw new UnsupportedOperationException (); + } + + public Object remove (int index) { + throw new UnsupportedOperationException (); + } + + public boolean removeAll (java.util.Collection c) { + throw new UnsupportedOperationException (); + } + + public boolean retainAll (java.util.Collection c) { + throw new UnsupportedOperationException (); + } + + public Object set (int index, Object element) { + throw new UnsupportedOperationException (); + } + + public int size () { + throw new UnsupportedOperationException (); + } + + public java.util.List subList (int fromIndex, int toIndex) { + throw new UnsupportedOperationException (); + } + + public Object[] toArray () { + throw new UnsupportedOperationException (); + } + + public Object[] toArray (Object[] a) { + throw new UnsupportedOperationException (); + } + } // end of QE + +}