FW: [jdom-interest] & in namespace
Jason Hunter
jhunter at xquery.com
Wed May 3 15:57:06 PDT 2006
Thanks.
-jh-
Rolf Lear wrote:
> Just resubmitting a patch for the List Iterator in the Content.
>
> keeps falling through cracks..
>
>
>
> -----Original Message-----
> From: jdom-interest-bounces at jdom.org
> [mailto:jdom-interest-bounces at jdom.org]On Behalf Of Jason Hunter
> Sent: Wednesday, May 03, 2006 12:44 PM
> To: Bradley S. Huffman
> Cc: jdom-interest at jdom.org; Deshpande,Aniruddha
> Subject: Re: FW: [jdom-interest] & in namespace
>
>
> Bradley S. Huffman wrote:
> > "Deshpande, Aniruddha" writes:
> >
> >> What do you feel? Is this a bug in JDOM? How should we proceed?
> >
> > You look at the code to see what's going on, and if needed make a patch
> > like this. Brad
> >
> > *** XMLOutputter.java Fri Dec 10 19:31:50 2004
> > --- XMLOutputter.new Wed May 3 09:03:19 2006
> > ***************
> > *** 1118,1124 ****
> > out.write(prefix);
> > }
> > out.write("=\"");
> > ! out.write(uri);
> > out.write("\"");
> > namespaces.push(ns);
> > }
> > --- 1118,1124 ----
> > out.write(prefix);
> > }
> > out.write("=\"");
> > ! out.write(escapeAttributeEntities(uri));
> > out.write("\"");
> > namespaces.push(ns);
> > }
>
> Bingo. Anyone see a reason this wouldn't be spec conformant?
>
> BTW, JDOM's not dead. I'm still engaged, just need to get off my duff
> and do a 1.0.1 with the few small bugs we fixed since 1.0. There hasn't
> been much interest expressed in a 1.1 release. JDOM already does
> everything *I* care about. Are there things people want in a 1.1 or
> 2.0, or should we stay in happy maintenance mode.
>
> -jh-
> _______________________________________________
> To control your jdom-interest membership:
> http://www.jdom.org/mailman/options/jdom-interest/youraddr@yourhost.com
>
> This email and any files transmitted with it are confidential and
> proprietary to Algorithmics Incorporated and its affiliates
> ("Algorithmics"). If received in error, use is prohibited. Please
> destroy, and notify sender. Sender does not waive confidentiality or
> privilege. Internet communications cannot be guaranteed to be timely,
> secure, error or virus-free. Algorithmics does not accept liability for
> any errors or omissions. Any commitment intended to bind Algorithmics
> must be reduced to writing and signed by an authorized signatory.
>
>
>
>
>
>
> ------------------------------------------------------------------------
>
> 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