FW: [jdom-interest] & in namespace

Rolf Lear rlear at algorithmics.com
Wed May 3 12:14:20 PDT 2006


Skipped content of type multipart/alternative-------------- next part --------------
Index: ContentList.java
===================================================================
RCS file: /home/cvspublic/jdom/src/java/org/jdom/ContentList.java,v
retrieving revision 1.39
diff -u -r1.39 ContentList.java
--- ContentList.java	28 Feb 2004 03:30:27 -0000	1.39
+++ ContentList.java	22 Apr 2005 21:06:47 -0000
@@ -84,19 +84,6 @@
 
     private static final int INITIAL_ARRAY_SIZE = 5;
 
-    /**
-     * Used inner class FilterListIterator to help hasNext and
-     * hasPrevious the next index of our cursor (must be here
-     * for JDK1.1).
-     */
-    private static final int CREATE  = 0;
-    private static final int HASPREV = 1;
-    private static final int HASNEXT = 2;
-    private static final int PREV    = 3;
-    private static final int NEXT    = 4;
-    private static final int ADD     = 5;
-    private static final int REMOVE  = 6;
-
     /** Our backing list */
 //    protected ArrayList list;
     private Content elementData[];
@@ -719,77 +706,95 @@
         /** The Filter that applies */
         Filter filter;
 
-        /** The last operation performed */
-        int lastOperation;
-
-        /** Initial start index in backing list */
-        int initialCursor;
-
+        /** Whether this iterator is in forward or reverse. */
+        private boolean forward = false;
+        /** Whether a call to remove() is valid */
+        private boolean canremove = false;
+        /** Whether a call to set() is valid */
+        private boolean canset = false;
+        
         /** Index in backing list of next object */
-        int cursor;
-
-        /** Index in backing list of last object returned */
-        int last;
-
-        /** Expected modCount in our backing list */
-        int expected;
+        private int cursor = -1;
+        /** the backing index to use if we actually DO move */
+        private int tmpcursor = -1;
+        /** Index in ListIterator */
+        private int index = -1;
+ 
+         /** Expected modCount in our backing list */
+        private int expected = -1;
+        
+        /** Number of elements matching the filter. */
+        private int fsize = 0;
 
         /**
          * Default constructor
          */
         FilterListIterator(Filter filter, int start) {
             this.filter = filter;
-            initialCursor = initializeCursor(start);
-            last = -1;
-            expected = ContentList.this.getModCount();
-            lastOperation = CREATE;
+             expected = ContentList.this.getModCount();
+            // always start list iterators in backward mode ....
+            // it makes sense... really.
+            forward = false;
+            
+            if (start < 0) {
+                throw new IndexOutOfBoundsException("Index: " + start);
+            }
+
+            // the number of matching elements....
+            fsize = 0;
+            
+            // go through the list, count the matching elements...
+            for (int i = 0; i < ContentList.this.size(); i++) {
+                if (filter.matches(ContentList.this.get(i))) {
+                    if (start == fsize) {
+                        // set the back-end cursor to the matching element....
+                        cursor = i;
+                        // set the front-end cursor too.
+                        index = fsize;
+                    }
+                    fsize++;
+                }
+            }
+
+            if (start > fsize) {
+                throw new IndexOutOfBoundsException("Index: " + start +
+                                                    " Size: " + fsize);
+            }
+            
+            if (cursor == -1) {
+                // implies that start == fsize (i.e. after the last element
+                // put the insertion point at the end of the Underlying
+                // content list ....
+                // i.e. an add() at this point may potentially end up with
+                // filtered content between previous() and next()
+                // the alternative is to put the cursor on the Content after
+                // the last Content that the filter passed
+                // The implications are ambiguous.
+                cursor = ContentList.this.size();
+                index = fsize;
+            }
+            
         }
 
         /**
          * Returns <code>true</code> if this list iterator has a next element.
          */
         public boolean hasNext() {
-            checkConcurrentModification();
-
-            switch(lastOperation) {
-            case CREATE:  cursor = initialCursor;
-                          break;
-            case PREV:    cursor = last;
-                          break;
-            case ADD:
-            case NEXT:    cursor = moveForward(last + 1);
-                          break;
-            case REMOVE:  cursor = moveForward(last);
-                          break;
-            case HASPREV: cursor = moveForward(cursor + 1);
-                          break;
-            case HASNEXT: break;
-            default:      throw new IllegalStateException("Unknown operation");
-            }
-
-            if (lastOperation != CREATE) {
-                lastOperation = HASNEXT;
-            }
-
-            return (cursor < ContentList.this.size()) ? true : false;
+            return nextIndex() < fsize;
         }
 
         /**
          * Returns the next element in the list.
          */
         public Object next() {
-            checkConcurrentModification();
-
-            if (hasNext()) {
-                last = cursor;
-            }
-            else {
-                last = ContentList.this.size();
-                throw new NoSuchElementException();
-            }
-
-            lastOperation = NEXT;
-            return ContentList.this.get(last);
+            if (! hasNext()) throw new NoSuchElementException("next() is beyond " +
+                    "the end of the Iterator.");
+            index = nextIndex();
+            cursor = tmpcursor;
+            forward = true;
+            canremove = true;
+            canset = true;
+            return ContentList.this.get(cursor);
         }
 
         /**
@@ -797,50 +802,21 @@
          * elements when traversing the list in the reverse direction.
          */
         public boolean hasPrevious() {
-            checkConcurrentModification();
-
-            switch(lastOperation) {
-            case CREATE:  cursor = initialCursor;
-                          int size = ContentList.this.size();
-                          if (cursor >= size) {
-                              cursor = moveBackward(size - 1);
-                          }
-                          break;
-            case PREV:
-            case REMOVE:  cursor = moveBackward(last - 1);
-                          break;
-            case HASNEXT: cursor = moveBackward(cursor - 1);
-                          break;
-            case ADD:
-            case NEXT:    cursor = last;
-                          break;
-            case HASPREV: break;
-            default:      throw new IllegalStateException("Unknown operation");
-            }
-
-            if (lastOperation != CREATE) {
-                lastOperation = HASPREV;
-            }
-
-            return (cursor < 0) ? false : true;
+            return previousIndex() >= 0;
         }
 
         /**
          * Returns the previous element in the list.
          */
         public Object previous() {
-            checkConcurrentModification();
-
-            if (hasPrevious()) {
-                last = cursor;
-            }
-            else {
-                last = -1;
-                throw new NoSuchElementException();
-            }
-
-            lastOperation = PREV;
-            return ContentList.this.get(last);
+            if (! hasPrevious()) throw new NoSuchElementException("previous() is " +
+                    "before the start of the Iterator.");
+            index = previousIndex();
+            cursor = tmpcursor;
+            forward = false;
+            canremove = true;
+            canset = true;
+            return ContentList.this.get(cursor);
         }
 
         /**
@@ -849,19 +825,24 @@
          */
         public int nextIndex() {
             checkConcurrentModification();
-            hasNext();
-
-            int count = 0;
-            for (int i = 0; i < ContentList.this.size(); i++) {
-                if (filter.matches(ContentList.this.get(i))) {
-                    if (i == cursor) {
-                        return count;
+            
+            if (forward) {
+                // starting with next possibility ....
+                for (int i = cursor + 1; i < ContentList.this.size(); i++) {
+                    if (filter.matches(ContentList.this.get(i))) {
+                        tmpcursor = i;
+                        return index + 1;
                     }
-                    count++;
                 }
-            }
-            expected = ContentList.this.getModCount();
-            return count;
+                // never found another match.... put the insertion point at 
+                // the end of the list....
+                tmpcursor = ContentList.this.size();
+                return index + 1;
+            }
+            
+            // we've been going back... so nextIndex() returns the same element.
+            tmpcursor = cursor;
+            return index;
         }
 
         /**
@@ -871,37 +852,41 @@
          */
         public int previousIndex() {
             checkConcurrentModification();
+            if (!forward) {
+                // starting with next possibility ....
+                for (int i = cursor - 1; i >= 0; i--) {
+                     if (filter.matches(ContentList.this.get(i))) {
+                        tmpcursor = i;
+                        return index - 1;
+                     }
+                 }
+                // never found another match.... put the insertion point at
+                // the start of the list....
+                tmpcursor = -1;
+                return index -1;
+            }
+            
+            // we've been going forwards... so previousIndex() returns same element.
+            tmpcursor = cursor;
+            return index;
 
-            if (hasPrevious()) {
-                int count = 0;
-                for (int i = 0; i < ContentList.this.size(); i++) {
-                    if (filter.matches(ContentList.this.get(i))) {
-                        if (i == cursor) {
-                            return count;
-                        }
-                        count++;
-                    }
-                }
-            }
-            return -1;
         }
 
         /**
          * Inserts the specified element into the list.
          */
         public void add(Object obj) {
-            checkConcurrentModification();
-
-            if (filter.matches(obj)) {
-                last = cursor + 1;
-                ContentList.this.add(last, obj);
-            }
-            else {
-                throw new IllegalAddException("Filter won't allow add of " +
-                                              (obj.getClass()).getName());
-            }
+            // call to nextIndex() will check concurrent.
+            nextIndex();
+            // tmpcursor is the backing cursor of the next element
+            // remember that List.add(index,obj) is really an insert....
+            ContentList.this.add(tmpcursor, obj);
+            forward = true;
             expected = ContentList.this.getModCount();
-            lastOperation = ADD;
+            canremove = canset = false;
+            index = nextIndex();
+            cursor = tmpcursor;
+            fsize++;
         }
 
         /**
@@ -910,28 +895,17 @@
          * the last call to <code>next</code> or <code>previous</code>.
          */
         public void remove() {
-            checkConcurrentModification();
-
-            if ((last < 0) || (lastOperation == REMOVE)) {
-                throw new IllegalStateException("no preceeding call to " +
-                                                "prev() or next()");
-            }
-
-            if (lastOperation == ADD) {
-                throw new IllegalStateException("cannot call remove() " +
-                                                "after add()");
-            }
-
-            Object old = ContentList.this.get(last);
-            if (filter.matches(old)) {
-                ContentList.this.remove(last);
-            }
-            else throw new IllegalAddException("Filter won't allow " +
-                                                (old.getClass()).getName() +
-                                                " (index " + last +
-                                                ") to be removed");
+            if (!canremove) throw new IllegalStateException("Can not remove an " +
+                    "element unless either next() or previous() has been called " +
+                    "since the last remove()");
+            nextIndex(); // to get out cursor ...
+            ContentList.this.remove(cursor);
+            cursor = tmpcursor - 1;
             expected = ContentList.this.getModCount();
-            lastOperation = REMOVE;
+            forward = false;
+            canremove = false;
+            canset = false;
+            fsize--;
         }
 
         /**
@@ -939,98 +913,17 @@
          * <code>previous</code> with the specified element.
          */
         public void set(Object obj) {
+            if (!canset) throw new IllegalStateException("Can not set an element " +
+                    "unless either next() or previous() has been called since the " +
+                    "last remove() or set()");
             checkConcurrentModification();
 
-            if ((lastOperation == ADD) || (lastOperation == REMOVE)) {
-                throw new IllegalStateException("cannot call set() after " +
-                                                "add() or remove()");
-            }
-
-            if (last < 0) {
-                throw new IllegalStateException("no preceeding call to " +
-                                                "prev() or next()");
-            }
-
-            if (filter.matches(obj)) {
-                Object old = ContentList.this.get(last);
-                if (!filter.matches(old)) {
-                    throw new IllegalAddException("Filter won't allow " +
-                                  (old.getClass()).getName() + " (index " +
-                                  last + ") to be removed");
-                }
-                ContentList.this.set(last, obj);
-            }
-            else {
+            
+            if (!filter.matches(obj)) {
                 throw new IllegalAddException("Filter won't allow index " +
-                                              last + " to be set to " +
+                                              index + " to be set to " +
                                               (obj.getClass()).getName());
             }
-
-            expected = ContentList.this.getModCount();
-            // Don't set lastOperation
-        }
-
-        /**
-         * Returns index in the backing list by moving forward start
-         * objects that match our filter.
-         */
-        private int initializeCursor(int start) {
-            if (start < 0) {
-                throw new IndexOutOfBoundsException("Index: " + start);
-            }
-
-            int count = 0;
-            for (int i = 0; i < ContentList.this.size(); i++) {
-                Object obj = ContentList.this.get(i);
-                if (filter.matches(obj)) {
-                    if (start == count) {
-                        return i;
-                    }
-                    count++;
-                }
-            }
-
-            if (start > count) {
-                throw new IndexOutOfBoundsException("Index: " + start +
-                                                    " Size: " + count);
-            }
-
-            return ContentList.this.size();
-        }
-
-        /**
-         * Returns index in the backing list of the next object matching
-         * our filter, starting at the given index and moving forwards.
-         */
-        private int moveForward(int start) {
-            if (start < 0) {
-                start = 0;
-            }
-            for (int i = start; i < ContentList.this.size(); i++) {
-                Object obj = ContentList.this.get(i);
-                if (filter.matches(obj)) {
-                    return i;
-                }
-            }
-            return ContentList.this.size();
-        }
-
-        /**
-         * Returns index in the backing list of the next object matching
-         * our filter, starting at the given index and moving backwards.
-         */
-        private int moveBackward(int start) {
-            if (start >= ContentList.this.size()) {
-                start = ContentList.this.size() - 1;
-            }
-
-            for (int i = start; i >= 0; --i) {
-                Object obj = ContentList.this.get(i);
-                if (filter.matches(obj)) {
-                    return i;
-                }
-            }
-            return -1;
         }
 
         /**


More information about the jdom-interest mailing list