123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944 |
- /*--
-
- $Id: ContentList.java,v 1.42 2007/11/10 05:28:58 jhunter Exp $
-
- Copyright (C) 2000-2007 Jason Hunter & Brett McLaughlin.
- 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 disclaimer that follows
- these conditions in the documentation and/or other materials
- provided with the distribution.
-
- 3. The name "JDOM" must not be used to endorse or promote products
- derived from this software without prior written permission. For
- written permission, please contact <request_AT_jdom_DOT_org>.
-
- 4. Products derived from this software may not be called "JDOM", nor
- may "JDOM" appear in their name, without prior written permission
- from the JDOM Project Management <request_AT_jdom_DOT_org).
-
- In addition, we request (but do not require) that you include in the
- end-user documentation provided with the redistribution and/or in the
- software itself an acknowledgement equivalent to the following:
- "This product includes software developed by the
- JDOM Project (http://www.jdom.org/)."
- Alternatively, the acknowledgment may be graphical using the logos
- available at http://www.jdom.org/images/logos.
-
- 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 JDOM AUTHORS OR THE PROJECT
- 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 JDOM Project and was originally
- created by Jason Hunter <jhunter_AT_jdom_DOT_org> and
- Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information
- on the JDOM Project, please see <http://www.jdom.org/>.
-
- */
-
- package org.jdom;
-
- import java.util.*;
-
- import org.jdom.filter.*;
-
- /**
- * A non-public list implementation holding only legal JDOM content, including
- * content for Document or Element nodes. Users see this class as a simple List
- * implementation.
- *
- * @see CDATA
- * @see Comment
- * @see Element
- * @see EntityRef
- * @see ProcessingInstruction
- * @see Text
- *
- * @version $Revision: 1.42 $, $Date: 2007/11/10 05:28:58 $
- * @author Alex Rosen
- * @author Philippe Riand
- * @author Bradley S. Huffman
- */
- final class ContentList extends AbstractList implements java.io.Serializable {
-
- private static final String CVS_ID =
- "@(#) $RCSfile: ContentList.java,v $ $Revision: 1.42 $ $Date: 2007/11/10 05:28:58 $ $Name: jdom_1_1 $";
-
- private static final long serialVersionUID = 1L;
-
- private static final int INITIAL_ARRAY_SIZE = 5;
-
- /** Our backing list */
- private Content elementData[];
- private int size;
-
- /** Document or Element this list belongs to */
- private Parent parent;
-
- /** Force either a Document or Element parent */
- ContentList(Parent parent) {
- this.parent = parent;
- }
-
- /**
- * Package internal method to support building from sources that are
- * 100% trusted.
- *
- * @param c content to add without any checks
- */
- final void uncheckedAddContent(Content c) {
- c.parent = parent;
- ensureCapacity(size + 1);
- elementData[size++] = c;
- modCount++;
- }
-
- /**
- * Inserts the specified object at the specified position in this list.
- * Shifts the object currently at that position (if any) and any
- * subsequent objects to the right (adds one to their indices).
- *
- * @param index The location to set the value to.
- * @param obj The object to insert into the list.
- * throws IndexOutOfBoundsException if index < 0 || index > size()
- */
- public void add(int index, Object obj) {
- if (obj == null) {
- throw new IllegalAddException("Cannot add null object");
- }
- if (obj instanceof String) { // String is OK to add as special case
- obj = new Text(obj.toString()); // wrap it as a Content
- }
- if ((obj instanceof Content)) {
- add(index, (Content) obj);
- } else {
- throw new IllegalAddException("Class " +
- obj.getClass().getName() +
- " is of unrecognized type and cannot be added");
- }
- }
-
- /**
- * @see org.jdom.ContentList#add(int, org.jdom.Content)
- */
- private void documentCanContain(int index, Content child) throws IllegalAddException {
- if (child instanceof Element) {
- if (indexOfFirstElement() >= 0) {
- throw new IllegalAddException(
- "Cannot add a second root element, only one is allowed");
- }
- if (indexOfDocType() > index) {
- throw new IllegalAddException(
- "A root element cannot be added before the DocType");
- }
- }
- if (child instanceof DocType) {
- if (indexOfDocType() >= 0) {
- throw new IllegalAddException(
- "Cannot add a second doctype, only one is allowed");
- }
- int firstElt = indexOfFirstElement();
- if (firstElt != -1 && firstElt < index) {
- throw new IllegalAddException(
- "A DocType cannot be added after the root element");
- }
- }
- if (child instanceof CDATA) {
- throw new IllegalAddException("A CDATA is not allowed at the document root");
- }
-
- if (child instanceof Text) {
- throw new IllegalAddException("A Text is not allowed at the document root");
- }
-
- if (child instanceof EntityRef) {
- throw new IllegalAddException("An EntityRef is not allowed at the document root");
- }
- }
-
- private static void elementCanContain(int index, Content child) throws IllegalAddException {
- if (child instanceof DocType) {
- throw new IllegalAddException(
- "A DocType is not allowed except at the document level");
- }
- }
-
- /**
- * Check and add the <code>Element</code> to this list at
- * the given index.
- *
- * @param index index where to add <code>Element</code>
- * @param child <code>Element</code> to add
- */
- void add(int index, Content child) {
- if (child == null) {
- throw new IllegalAddException("Cannot add null object");
- }
- if (parent instanceof Document) {
- documentCanContain(index, child);
- }
- else {
- elementCanContain(index, child);
- }
-
- if (child.getParent() != null) {
- Parent p = child.getParent();
- if (p instanceof Document) {
- throw new IllegalAddException((Element)child,
- "The Content already has an existing parent document");
- }
- else {
- throw new IllegalAddException(
- "The Content already has an existing parent \"" +
- ((Element)p).getQualifiedName() + "\"");
- }
- }
-
- if (child == parent) {
- throw new IllegalAddException(
- "The Element cannot be added to itself");
- }
-
- // Detect if we have <a><b><c/></b></a> and c.add(a)
- if ((parent instanceof Element && child instanceof Element) &&
- ((Element) child).isAncestor((Element)parent)) {
- throw new IllegalAddException(
- "The Element cannot be added as a descendent of itself");
- }
-
- if (index<0 || index>size) {
- throw new IndexOutOfBoundsException("Index: " + index +
- " Size: " + size());
- }
-
- child.setParent(parent);
-
- ensureCapacity(size+1);
- if( index==size ) {
- elementData[size++] = child;
- } else {
- System.arraycopy(elementData, index, elementData, index + 1, size - index);
- elementData[index] = child;
- size++;
- }
- modCount++;
- }
-
- /**
- * Add the specified collecton to the end of this list.
- *
- * @param collection The collection to add to the list.
- * @return <code>true</code> if the list was modified as a result of
- * the add.
- */
- public boolean addAll(Collection collection) {
- return addAll(size(), collection);
- }
-
- /**
- * Inserts the specified collecton at the specified position in this list.
- * Shifts the object currently at that position (if any) and any
- * subsequent objects to the right (adds one to their indices).
- *
- * @param index The offset to start adding the data in the collection
- * @param collection The collection to insert into the list.
- * @return <code>true</code> if the list was modified as a result of
- * the add.
- * throws IndexOutOfBoundsException if index < 0 || index > size()
- */
- public boolean addAll(int index, Collection collection) {
- if (index<0 || index>size) {
- throw new IndexOutOfBoundsException("Index: " + index +
- " Size: " + size());
- }
-
- if ((collection == null) || (collection.size() == 0)) {
- return false;
- }
- ensureCapacity(size() + collection.size());
-
- int count = 0;
- try {
- Iterator i = collection.iterator();
- while (i.hasNext()) {
- Object obj = i.next();
- add(index + count, obj);
- count++;
- }
- }
- catch (RuntimeException exception) {
- for (int i = 0; i < count; i++) {
- remove(index);
- }
- throw exception;
- }
-
- return true;
- }
-
- /**
- * Clear the current list.
- */
- public void clear() {
- if (elementData != null) {
- for (int i = 0; i < size; i++) {
- Content obj = elementData[i];
- removeParent(obj);
- }
- elementData = null;
- size = 0;
- }
- modCount++;
- }
-
- /**
- * Clear the current list and set it to the contents
- * of the <code>Collection</code>.
- * object.
- *
- * @param collection The collection to use.
- */
- void clearAndSet(Collection collection) {
- Content[] old = elementData;
- int oldSize = size;
-
- elementData = null;
- size = 0;
-
- if ((collection != null) && (collection.size() != 0)) {
- ensureCapacity(collection.size());
- try {
- addAll(0, collection);
- }
- catch (RuntimeException exception) {
- elementData = old;
- size = oldSize;
- throw exception;
- }
- }
-
- if (old != null) {
- for (int i = 0; i < oldSize; i++) {
- removeParent(old[i]);
- }
- }
- modCount++;
- }
-
- /**
- * Increases the capacity of this <code>ContentList</code> instance,
- * if necessary, to ensure that it can hold at least the number of
- * items specified by the minimum capacity argument.
- *
- * @param minCapacity the desired minimum capacity.
- */
- void ensureCapacity(int minCapacity) {
- if( elementData==null ) {
- elementData = new Content[Math.max(minCapacity, INITIAL_ARRAY_SIZE)];
- } else {
- int oldCapacity = elementData.length;
- if (minCapacity > oldCapacity) {
- Object oldData[] = elementData;
- int newCapacity = (oldCapacity * 3)/2 + 1;
- if (newCapacity < minCapacity)
- newCapacity = minCapacity;
- elementData = new Content[newCapacity];
- System.arraycopy(oldData, 0, elementData, 0, size);
- }
- }
- }
-
- /**
- * Return the object at the specified offset.
- *
- * @param index The offset of the object.
- * @return The Object which was returned.
- */
- public Object get(int index) {
- if (index<0 || index>=size) {
- throw new IndexOutOfBoundsException("Index: " + index +
- " Size: " + size());
- }
- return elementData[index];
- }
-
- /**
- * Return a view of this list based on the given filter.
- *
- * @param filter <code>Filter</code> for this view.
- * @return a list representing the rules of the <code>Filter</code>.
- */
- List getView(Filter filter) {
- return new FilterList(filter);
- }
-
- /**
- * Return the index of the first Element in the list. If the parent
- * is a <code>Document</code> then the element is the root element.
- * If the list contains no Elements, it returns -1.
- *
- * @return index of first element, or -1 if one doesn't exist
- */
- int indexOfFirstElement() {
- if( elementData!=null ) {
- for (int i = 0; i < size; i++) {
- if (elementData[i] instanceof Element) {
- return i;
- }
- }
- }
- return -1;
- }
-
- /**
- * Return the index of the DocType element in the list. If the list contains
- * no DocType, it returns -1.
- *
- * @return index of the DocType, or -1 if it doesn't
- * exist
- */
- int indexOfDocType() {
- if (elementData != null) {
- for (int i = 0; i < size; i++) {
- if (elementData[i] instanceof DocType) {
- return i;
- }
- }
- }
- return -1;
- }
-
- /**
- * Remove the object at the specified offset.
- *
- * @param index The offset of the object.
- * @return The Object which was removed.
- */
- public Object remove(int index) {
- if (index<0 || index>=size)
- throw new IndexOutOfBoundsException("Index: " + index +
- " Size: " + size());
-
- Content old = elementData[index];
- removeParent(old);
- int numMoved = size - index - 1;
- if (numMoved > 0)
- System.arraycopy(elementData, index+1, elementData, index,numMoved);
- elementData[--size] = null; // Let gc do its work
- modCount++;
- return old;
- }
-
-
- /** Remove the parent of a Object */
- private static void removeParent(Content c) {
- c.setParent(null);
- }
-
- /**
- * Set the object at the specified location to the supplied
- * object.
- *
- * @param index The location to set the value to.
- * @param obj The location to set the value to.
- * @return The object which was replaced.
- * throws IndexOutOfBoundsException if index < 0 || index >= size()
- */
- public Object set(int index, Object obj) {
- if (index<0 || index>=size)
- throw new IndexOutOfBoundsException("Index: " + index +
- " Size: " + size());
-
- if ((obj instanceof Element) && (parent instanceof Document)) {
- int root = indexOfFirstElement();
- if ((root >= 0) && (root != index)) {
- throw new IllegalAddException(
- "Cannot add a second root element, only one is allowed");
- }
- }
-
- if ((obj instanceof DocType) && (parent instanceof Document)) {
- int docTypeIndex = indexOfDocType();
- if ((docTypeIndex >= 0) && (docTypeIndex != index)) {
- throw new IllegalAddException(
- "Cannot add a second doctype, only one is allowed");
- }
- }
-
- Object old = remove(index);
- try {
- add(index, obj);
- }
- catch (RuntimeException exception) {
- add(index, old);
- throw exception;
- }
- return old;
- }
-
- /**
- * Return the number of items in this list
- *
- * @return The number of items in this list.
- */
- public int size() {
- return size;
- }
-
- /**
- * Return this list as a <code>String</code>
- *
- * @return The number of items in this list.
- */
- public String toString() {
- return super.toString();
- }
-
- /** Give access of ContentList.modCount to FilterList */
- private int getModCount() {
- return modCount;
- }
-
- /* * * * * * * * * * * * * FilterList * * * * * * * * * * * * * * * */
- /* * * * * * * * * * * * * FilterList * * * * * * * * * * * * * * * */
-
- /**
- * <code>FilterList</code> represents legal JDOM content, including content
- * for <code>Document</code>s or <code>Element</code>s.
- */
-
- class FilterList extends AbstractList implements java.io.Serializable {
-
- /** The Filter */
- Filter filter;
-
- /** Current number of items in this view */
- int count = 0;
-
- /** Expected modCount in our backing list */
- int expected = -1;
-
- // Implementation Note: Directly after size() is called, expected
- // is sync'd with ContentList.modCount and count provides
- // the true size of this view. Before the first call to
- // size() or if the backing list is modified outside this
- // FilterList, both might contain bogus values and should
- // not be used without first calling size();
-
- /**
- * Create a new instance of the FilterList with the specified Filter.
- */
- FilterList(Filter filter) {
- this.filter = filter;
- }
-
- /**
- * Inserts the specified object at the specified position in this list.
- * Shifts the object currently at that position (if any) and any
- * subsequent objects to the right (adds one to their indices).
- *
- * @param index The location to set the value to.
- * @param obj The object to insert into the list.
- * throws IndexOutOfBoundsException if index < 0 || index > size()
- */
- public void add(int index, Object obj) {
- if (filter.matches(obj)) {
- int adjusted = getAdjustedIndex(index);
- ContentList.this.add(adjusted, obj);
- expected++;
- count++;
- }
- else throw new IllegalAddException("Filter won't allow the " +
- obj.getClass().getName() +
- " '" + obj + "' to be added to the list");
- }
-
- /**
- * Return the object at the specified offset.
- *
- * @param index The offset of the object.
- * @return The Object which was returned.
- */
- public Object get(int index) {
- int adjusted = getAdjustedIndex(index);
- return ContentList.this.get(adjusted);
- }
-
- public Iterator iterator() {
- return new FilterListIterator(filter, 0);
- }
-
- public ListIterator listIterator() {
- return new FilterListIterator(filter, 0);
- }
-
- public ListIterator listIterator(int index) {
- return new FilterListIterator(filter, index);
- }
-
- /**
- * Remove the object at the specified offset.
- *
- * @param index The offset of the object.
- * @return The Object which was removed.
- */
- public Object remove(int index) {
- int adjusted = getAdjustedIndex(index);
- Object old = ContentList.this.get(adjusted);
- if (filter.matches(old)) {
- old = ContentList.this.remove(adjusted);
- expected++;
- count--;
- }
- else {
- throw new IllegalAddException("Filter won't allow the " +
- (old.getClass()).getName() +
- " '" + old + "' (index " + index +
- ") to be removed");
- }
- return old;
- }
-
- /**
- * Set the object at the specified location to the supplied
- * object.
- *
- * @param index The location to set the value to.
- * @param obj The location to set the value to.
- * @return The object which was replaced.
- * throws IndexOutOfBoundsException if index < 0 || index >= size()
- */
- public Object set(int index, Object obj) {
- Object old = null;
- if (filter.matches(obj)) {
- int adjusted = getAdjustedIndex(index);
- old = ContentList.this.get(adjusted);
- if (!filter.matches(old)) {
- throw new IllegalAddException("Filter won't allow the " +
- (old.getClass()).getName() +
- " '" + old + "' (index " + index +
- ") to be removed");
- }
- old = ContentList.this.set(adjusted, obj);
- expected += 2;
- }
- else {
- throw new IllegalAddException("Filter won't allow index " +
- index + " to be set to " +
- (obj.getClass()).getName());
- }
- return old;
- }
-
- /**
- * Return the number of items in this list
- *
- * @return The number of items in this list.
- */
- public int size() {
- // Implementation Note: Directly after size() is called, expected
- // is sync'd with ContentList.modCount and count provides
- // the true size of this view. Before the first call to
- // size() or if the backing list is modified outside this
- // FilterList, both might contain bogus values and should
- // not be used without first calling size();
-
- if (expected == ContentList.this.getModCount()) {
- return count;
- }
-
- count = 0;
- for (int i = 0; i < ContentList.this.size(); i++) {
- Object obj = ContentList.this.elementData[i];
- if (filter.matches(obj)) {
- count++;
- }
- }
- expected = ContentList.this.getModCount();
- return count;
- }
-
- /**
- * Return the adjusted index
- *
- * @param index Index of in this view.
- * @return True index in backing list
- */
- final private int getAdjustedIndex(int index) {
- int adjusted = 0;
- for (int i = 0; i < ContentList.this.size; i++) {
- Object obj = ContentList.this.elementData[i];
- if (filter.matches(obj)) {
- if (index == adjusted) {
- return i;
- }
- adjusted++;
- }
- }
-
- if (index == adjusted) {
- return ContentList.this.size;
- }
-
- return ContentList.this.size + 1;
- }
- }
-
- /* * * * * * * * * * * * * FilterListIterator * * * * * * * * * * * */
- /* * * * * * * * * * * * * FilterListIterator * * * * * * * * * * * */
-
- class FilterListIterator implements ListIterator {
-
- /** The Filter that applies */
- Filter filter;
-
- /** 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 */
- 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;
- 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() {
- return nextIndex() < fsize;
- }
-
- /**
- * Returns the next element in the list.
- */
- public Object next() {
- 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);
- }
-
- /**
- * Returns <code>true</code> if this list iterator has more elements
- * when traversing the list in the reverse direction.
- */
- public boolean hasPrevious() {
- return previousIndex() >= 0;
- }
-
- /**
- * Returns the previous element in the list.
- */
- public Object previous() {
- 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);
- }
-
- /**
- * Returns the index of the element that would be returned by a
- * subsequent call to <code>next</code>.
- */
- public int nextIndex() {
- checkConcurrentModification();
- 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;
- }
- }
- // 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;
- }
-
- /**
- * Returns the index of the element that would be returned by a
- * subsequent call to <code>previous</code>. (Returns -1 if the
- * list iterator is at the beginning of the list.)
- */
- 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;
- }
-
- /**
- * Inserts the specified element into the list.
- */
- public void add(Object obj) {
- // 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();
- canremove = canset = false;
- index = nextIndex();
- cursor = tmpcursor;
- fsize++;
- }
-
- /**
- * Removes from the list the last element that was returned by
- * the last call to <code>next</code> or <code>previous</code>.
- */
- public void remove() {
- 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();
-
- forward = false;
- canremove = false;
- canset = false;
- fsize--;
- }
-
- /**
- * Replaces the last element returned by <code>next</code> or
- * <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 (!filter.matches(obj)) {
- throw new IllegalAddException("Filter won't allow index " + index + " to be set to "
- + (obj.getClass()).getName());
- }
-
- ContentList.this.set(cursor, obj);
- expected = ContentList.this.getModCount();
-
- }
-
- /**
- * Check if are backing list is being modified by someone else.
- */
- private void checkConcurrentModification() {
- if (expected != ContentList.this.getModCount()) {
- throw new ConcurrentModificationException();
- }
- }
- }
- }
|