001: /*
002: * Copyright 2006 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.List;
019: import java.util.ListIterator;
020:
021: import org.apache.commons.collections.ResettableListIterator;
022:
023: /**
024: * Iterates backwards through a List, starting with the last element
025: * and continuing to the first. This is useful for looping around
026: * a list in reverse order without needing to actually reverse the list.
027: * <p>
028: * The first call to <code>next()</code> will return the last element
029: * from the list, and so on. The <code>hasNext()</code> method works
030: * in concert with the <code>next()</code> method as expected.
031: * However, the <code>nextIndex()</code> method returns the correct
032: * index in the list, thus it starts high and reduces as the iteration
033: * continues. The previous methods work similarly.
034: *
035: * @author Serge Knystautas
036: * @author Stephen Colebourne
037: * @since Commons Collections 3.2
038: * @version $Revision: $ $Date: 2006-05-12 23:52:43 +0100 (Fri, 12 May 2006) $
039: */
040: public class ReverseListIterator implements ResettableListIterator {
041:
042: /** The list being wrapped. */
043: private final List list;
044: /** The list iterator being wrapped. */
045: private ListIterator iterator;
046: /** Flag to indicate if updating is possible at the moment. */
047: private boolean validForUpdate = true;
048:
049: /**
050: * Constructor that wraps a list.
051: *
052: * @param list the list to create a reversed iterator for
053: * @throws NullPointerException if the list is null
054: */
055: public ReverseListIterator(List list) {
056: super ();
057: this .list = list;
058: iterator = list.listIterator(list.size());
059: }
060:
061: //-----------------------------------------------------------------------
062: /**
063: * Checks whether there is another element.
064: *
065: * @return true if there is another element
066: */
067: public boolean hasNext() {
068: return iterator.hasPrevious();
069: }
070:
071: /**
072: * Gets the next element.
073: * The next element is the previous in the list.
074: *
075: * @return the next element in the iterator
076: */
077: public Object next() {
078: Object obj = iterator.previous();
079: validForUpdate = true;
080: return obj;
081: }
082:
083: /**
084: * Gets the index of the next element.
085: *
086: * @return the index of the next element in the iterator
087: */
088: public int nextIndex() {
089: return iterator.previousIndex();
090: }
091:
092: /**
093: * Checks whether there is a previous element.
094: *
095: * @return true if there is a previous element
096: */
097: public boolean hasPrevious() {
098: return iterator.hasNext();
099: }
100:
101: /**
102: * Gets the previous element.
103: * The next element is the previous in the list.
104: *
105: * @return the previous element in the iterator
106: */
107: public Object previous() {
108: Object obj = iterator.next();
109: validForUpdate = true;
110: return obj;
111: }
112:
113: /**
114: * Gets the index of the previous element.
115: *
116: * @return the index of the previous element in the iterator
117: */
118: public int previousIndex() {
119: return iterator.nextIndex();
120: }
121:
122: /**
123: * Removes the last returned element.
124: *
125: * @throws UnsupportedOperationException if the list is unmodifiable
126: * @throws IllegalStateException if there is no element to remove
127: */
128: public void remove() {
129: if (validForUpdate == false) {
130: throw new IllegalStateException(
131: "Cannot remove from list until next() or previous() called");
132: }
133: iterator.remove();
134: }
135:
136: /**
137: * Replaces the last returned element.
138: *
139: * @param obj the object to set
140: * @throws UnsupportedOperationException if the list is unmodifiable
141: * @throws IllegalStateException if the iterator is not in a valid state for set
142: */
143: public void set(Object obj) {
144: if (validForUpdate == false) {
145: throw new IllegalStateException(
146: "Cannot set to list until next() or previous() called");
147: }
148: iterator.set(obj);
149: }
150:
151: /**
152: * Adds a new element to the list between the next and previous elements.
153: *
154: * @param obj the object to add
155: * @throws UnsupportedOperationException if the list is unmodifiable
156: * @throws IllegalStateException if the iterator is not in a valid state for set
157: */
158: public void add(Object obj) {
159: // the validForUpdate flag is needed as the necessary previous()
160: // method call re-enables remove and add
161: if (validForUpdate == false) {
162: throw new IllegalStateException(
163: "Cannot add to list until next() or previous() called");
164: }
165: validForUpdate = false;
166: iterator.add(obj);
167: iterator.previous();
168: }
169:
170: /**
171: * Resets the iterator back to the start (which is the
172: * end of the list as this is a reversed iterator)
173: */
174: public void reset() {
175: iterator = list.listIterator(list.size());
176: }
177:
178: }
|