001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.collections.iterators;
017:
018: import java.util.ListIterator;
019: import java.util.NoSuchElementException;
020:
021: import org.apache.commons.collections.Predicate;
022:
023: /**
024: * Decorates another {@link ListIterator} using a predicate to filter elements.
025: * <p>
026: * This iterator decorates the underlying iterator, only allowing through
027: * those elements that match the specified {@link Predicate Predicate}.
028: *
029: * @since Commons Collections 2.0
030: * @version $Revision: 348018 $ $Date: 2005-11-21 23:34:37 +0000 (Mon, 21 Nov 2005) $
031: *
032: * @author Rodney Waldhoff
033: */
034: public class FilterListIterator implements ListIterator {
035:
036: /** The iterator being used */
037: private ListIterator iterator;
038:
039: /** The predicate being used */
040: private Predicate predicate;
041:
042: /**
043: * The value of the next (matching) object, when
044: * {@link #nextObjectSet} is true.
045: */
046: private Object nextObject;
047:
048: /**
049: * Whether or not the {@link #nextObject} has been set
050: * (possibly to <code>null</code>).
051: */
052: private boolean nextObjectSet = false;
053:
054: /**
055: * The value of the previous (matching) object, when
056: * {@link #previousObjectSet} is true.
057: */
058: private Object previousObject;
059:
060: /**
061: * Whether or not the {@link #previousObject} has been set
062: * (possibly to <code>null</code>).
063: */
064: private boolean previousObjectSet = false;
065:
066: /**
067: * The index of the element that would be returned by {@link #next}.
068: */
069: private int nextIndex = 0;
070:
071: //-----------------------------------------------------------------------
072: /**
073: * Constructs a new <code>FilterListIterator</code> that will not function
074: * until {@link #setListIterator(ListIterator) setListIterator}
075: * and {@link #setPredicate(Predicate) setPredicate} are invoked.
076: */
077: public FilterListIterator() {
078: super ();
079: }
080:
081: /**
082: * Constructs a new <code>FilterListIterator</code> that will not
083: * function until {@link #setPredicate(Predicate) setPredicate} is invoked.
084: *
085: * @param iterator the iterator to use
086: */
087: public FilterListIterator(ListIterator iterator) {
088: super ();
089: this .iterator = iterator;
090: }
091:
092: /**
093: * Constructs a new <code>FilterListIterator</code>.
094: *
095: * @param iterator the iterator to use
096: * @param predicate the predicate to use
097: */
098: public FilterListIterator(ListIterator iterator, Predicate predicate) {
099: super ();
100: this .iterator = iterator;
101: this .predicate = predicate;
102: }
103:
104: /**
105: * Constructs a new <code>FilterListIterator</code> that will not function
106: * until {@link #setListIterator(ListIterator) setListIterator} is invoked.
107: *
108: * @param predicate the predicate to use.
109: */
110: public FilterListIterator(Predicate predicate) {
111: super ();
112: this .predicate = predicate;
113: }
114:
115: //-----------------------------------------------------------------------
116: /** Not supported. */
117: public void add(Object o) {
118: throw new UnsupportedOperationException(
119: "FilterListIterator.add(Object) is not supported.");
120: }
121:
122: public boolean hasNext() {
123: if (nextObjectSet) {
124: return true;
125: } else {
126: return setNextObject();
127: }
128: }
129:
130: public boolean hasPrevious() {
131: if (previousObjectSet) {
132: return true;
133: } else {
134: return setPreviousObject();
135: }
136: }
137:
138: public Object next() {
139: if (!nextObjectSet) {
140: if (!setNextObject()) {
141: throw new NoSuchElementException();
142: }
143: }
144: nextIndex++;
145: Object temp = nextObject;
146: clearNextObject();
147: return temp;
148: }
149:
150: public int nextIndex() {
151: return nextIndex;
152: }
153:
154: public Object previous() {
155: if (!previousObjectSet) {
156: if (!setPreviousObject()) {
157: throw new NoSuchElementException();
158: }
159: }
160: nextIndex--;
161: Object temp = previousObject;
162: clearPreviousObject();
163: return temp;
164: }
165:
166: public int previousIndex() {
167: return (nextIndex - 1);
168: }
169:
170: /** Not supported. */
171: public void remove() {
172: throw new UnsupportedOperationException(
173: "FilterListIterator.remove() is not supported.");
174: }
175:
176: /** Not supported. */
177: public void set(Object o) {
178: throw new UnsupportedOperationException(
179: "FilterListIterator.set(Object) is not supported.");
180: }
181:
182: //-----------------------------------------------------------------------
183: /**
184: * Gets the iterator this iterator is using.
185: *
186: * @return the iterator.
187: */
188: public ListIterator getListIterator() {
189: return iterator;
190: }
191:
192: /**
193: * Sets the iterator for this iterator to use.
194: * If iteration has started, this effectively resets the iterator.
195: *
196: * @param iterator the iterator to use
197: */
198: public void setListIterator(ListIterator iterator) {
199: this .iterator = iterator;
200: }
201:
202: //-----------------------------------------------------------------------
203: /**
204: * Gets the predicate this iterator is using.
205: *
206: * @return the predicate.
207: */
208: public Predicate getPredicate() {
209: return predicate;
210: }
211:
212: /**
213: * Sets the predicate this the iterator to use.
214: *
215: * @param predicate the transformer to use
216: */
217: public void setPredicate(Predicate predicate) {
218: this .predicate = predicate;
219: }
220:
221: //-----------------------------------------------------------------------
222: private void clearNextObject() {
223: nextObject = null;
224: nextObjectSet = false;
225: }
226:
227: private boolean setNextObject() {
228: // if previousObjectSet,
229: // then we've walked back one step in the
230: // underlying list (due to a hasPrevious() call)
231: // so skip ahead one matching object
232: if (previousObjectSet) {
233: clearPreviousObject();
234: if (!setNextObject()) {
235: return false;
236: } else {
237: clearNextObject();
238: }
239: }
240:
241: while (iterator.hasNext()) {
242: Object object = iterator.next();
243: if (predicate.evaluate(object)) {
244: nextObject = object;
245: nextObjectSet = true;
246: return true;
247: }
248: }
249: return false;
250: }
251:
252: private void clearPreviousObject() {
253: previousObject = null;
254: previousObjectSet = false;
255: }
256:
257: private boolean setPreviousObject() {
258: // if nextObjectSet,
259: // then we've walked back one step in the
260: // underlying list (due to a hasNext() call)
261: // so skip ahead one matching object
262: if (nextObjectSet) {
263: clearNextObject();
264: if (!setPreviousObject()) {
265: return false;
266: } else {
267: clearPreviousObject();
268: }
269: }
270:
271: while (iterator.hasPrevious()) {
272: Object object = iterator.previous();
273: if (predicate.evaluate(object)) {
274: previousObject = object;
275: previousObjectSet = true;
276: return true;
277: }
278: }
279: return false;
280: }
281:
282: }
|