1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
/* Glazed Lists (c) 2003-2006 */
/* http://publicobject.com/glazedlists/ publicobject.com,*/
/* O'Dell Engineering Ltd.*/
package ca.odell.glazedlists.impl;
// the core Glazed Lists package
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.event.ListEvent;
import ca.odell.glazedlists.event.ListEventListener;
import java.util.ListIterator;
import java.util.NoSuchElementException;
/**
* The EventListIterator is an iterator that allows the user to iterate
* on a list <i>that may be changed while it is iterated</i>. This is
* possible because the iterator is a listener for change events to the
* source list.
*
* <p>This iterator simply keeps an index of where it is and what it last
* saw. It knows nothing about the underlying storage performance of the List
* that it iterates, and therefore provides generic, possibly slow access
* to its elements.
*
* @author <a href="mailto:jesse@swank.ca">Jesse Wilson</a>
*/
public class EventListIterator<E> implements ListIterator<E>, ListEventListener<E> {
/** the list being iterated */
private EventList<E> source;
/** the index of the next element to view */
private int nextIndex;
/** the most recently accessed element */
private int lastIndex = -1;
/**
* Create a new event list iterator that iterates over the specified
* source list.
*
* @param source the list to iterate
*/
public EventListIterator(EventList<E> source) {
this(source, 0, true);
}
/**
* Creates a new iterator that starts at the specified index.
*
* @param source the list to iterate
* @param nextIndex the starting point within the list
*/
public EventListIterator(EventList<E> source, int nextIndex) {
this(source, nextIndex, true);
}
/**
* Creates a new iterator that starts at the specified index.
*
* @param source the list to iterate
* @param nextIndex the starting point within the list
* @param automaticallyRemove true if this SubList should deregister itself
* from the ListEventListener list of the source list once it is
* otherwise out of scope.
*
* @see GlazedLists#weakReferenceProxy(EventList, ListEventListener)
*/
public EventListIterator(EventList<E> source, int nextIndex, boolean automaticallyRemove) {
this.source = source;
this.nextIndex = nextIndex;
// listen directly or via a proxy that will do garbage collection
if(automaticallyRemove) {
ListEventListener<E> gcProxy = new WeakReferenceProxy<E>(source, this);
source.addListEventListener(gcProxy);
// do not manage dependencies for iterators, they never have multiple sources
source.getPublisher().removeDependency(source, gcProxy);
} else {
source.addListEventListener(this);
// do not manage dependencies for iterators, they never have multiple sources
source.getPublisher().removeDependency(source, this);
}
}
/**
* Returns true if this list iterator has more elements when traversing the
* list in the forward direction.
*/
public boolean hasNext() {
return nextIndex < source.size();
}
/**
* Returns the next element in the list.
*/
public E next() {
// next shouldn't have been called.
if(nextIndex == source.size()) {
throw new NoSuchElementException("Cannot retrieve element " + nextIndex + " on a list of size " + source.size());
// when next has not been removed
} else {
lastIndex = nextIndex;
nextIndex++;
return source.get(lastIndex);
}
}
/**
* Returns the index of the element that would be returned by a subsequent call to next.
*/
public int nextIndex() {
return nextIndex;
}
/**
* Returns true if this list iterator has more elements when traversing the
* list in the reverse direction.
*/
public boolean hasPrevious() {
return nextIndex > 0;
}
/**
* Returns the previous element in the list.
*/
public E previous() {
// previous shouldn't have been called
if(nextIndex == 0) {
throw new NoSuchElementException("Cannot retrieve element " + nextIndex + " on a list of size " + source.size());
// when previous has not been removed
} else {
nextIndex--;
lastIndex = nextIndex;
return source.get(nextIndex);
}
}
/**
* Returns the index of the element that would be returned by a subsequent call to previous.
*/
public int previousIndex() {
return nextIndex - 1;
}
/**
* Inserts the specified element into the list (optional operation).
*/
public void add(E o) {
source.add(nextIndex, o);
}
/**
* Removes from the list the last element that was returned by next
* or previous (optional operation).
*/
public void remove() {
if(lastIndex == -1) throw new IllegalStateException("Cannot remove() without a prior call to next() or previous()");
source.remove(lastIndex);
}
/**
* Replaces the last element returned by next or previous with the
* specified element (optional operation).
*/
public void set(E o) {
if(lastIndex == -1) throw new IllegalStateException("Cannot set() without a prior call to next() or previous()");
source.set(lastIndex, o);
}
/**
* When the list is changed, the iterator adjusts its index.
*/
public void listChanged(ListEvent<E> listChanges) {
while(listChanges.next()) {
int changeIndex = listChanges.getIndex();
int changeType = listChanges.getType();
// if it is an insert
if(changeType == ListEvent.INSERT) {
if(changeIndex <= nextIndex) nextIndex++;
if(lastIndex != -1 && changeIndex <= lastIndex) lastIndex++;
// if it is a delete
} else if(changeType == ListEvent.DELETE) {
if(changeIndex < nextIndex) nextIndex--;
if(lastIndex != -1 && changeIndex < lastIndex) lastIndex--;
else if(lastIndex != -1 && changeIndex == lastIndex) lastIndex = -1;
}
}
}
}
|