View Javadoc

1   package cz.cuni.amis.utils.iterators;
2   
3   import java.util.Iterator;
4   import java.util.List;
5   import java.util.ListIterator;
6   
7   /**
8    * Implements a circular iterator that iterates over any List instance instance.
9    * Useful for obtaining bidirectional ListIterator<E>.
10   * Not fully tested!
11   * @author Radek 'Black_Hand' Pibil
12   *
13   * @param <E> contents of the iterable
14   */
15  public class CircularListIterator<E> implements ListIterator<E> {
16  
17  	protected boolean passedEnd = false;
18  	protected boolean passedBeginning = false;
19  	
20  	protected boolean moved = false;
21  
22  	private int index = 0;
23  	private List<E> toIterateOver;
24  	private ListIterator<E> iterator;
25  
26  	/**
27  	 * Constructs an instance of an CircularListIterator.
28  	 * @param toIterateOver List to be iterated over
29  	 */	
30  	public CircularListIterator(List<E> toIterateOver) {
31  		if (toIterateOver == null)
32  			throw new NullPointerException("List<E> to be iterated over cannot be null.");
33  			
34  		this.toIterateOver = toIterateOver;
35  		iterator = toIterateOver.listIterator();
36  	}
37  
38  	/**
39  	 * Constructs an instance of an CircularListIterator.
40  	 * @param toIterateOver List to be iterated over
41  	 * @param index an index to begin iteration at
42  	 */
43  	public CircularListIterator(List<E> toIterateOver, int index) {
44  		if (toIterateOver == null)
45  			throw new IllegalArgumentException("List<E> to be iterated over cannot be null.");
46  		
47  		if (index < 0 && index > toIterateOver.size())
48  			throw new IllegalArgumentException("Index parameter cannot be outside toIterateOver parameter.");
49  		
50  		this.toIterateOver = toIterateOver;
51  		iterator = toIterateOver.listIterator(index);
52  		this.index = index;
53  	}
54  
55  	/**
56  	 * Copy constructor for CircularListIterator.
57  	 * @param source
58  	 */	
59  	public CircularListIterator(CircularListIterator<E> source) {
60  		this.passedEnd = source.passedEnd;
61  		this.passedBeginning = source.passedBeginning;
62  		this.index = source.index;
63  		this.toIterateOver = source.toIterateOver;
64  		
65  		int currentIndex = source.currentIndex();
66  			
67  		this.iterator = toIterateOver.listIterator(
68  				(currentIndex == -1 ? toIterateOver.size() - 1 : currentIndex));
69  	}
70  
71  	@Override
72  	public boolean hasNext() {
73  		return toIterateOver.size() > 0;
74  	}
75  
76  	@Override
77  	public E next() {
78  		
79  		if (currentIndex() == toIterateOver.size()) {
80  			restartIteratorBeginning();
81  		}
82  
83  		E value = iterator.next();
84  
85  		if (currentIndex() == index && moved)
86  			passedEnd = true;
87  		
88  		moved = true;
89  
90  		return value;
91  	}
92  
93  	@Override
94  	public void remove() {
95  		
96  		iterator.remove();
97  
98  		if (currentIndex() == index)
99  			passedEnd = true;
100 
101 		if (currentIndex() == toIterateOver.size()) {
102 			restartIteratorBeginning();
103 		}
104 
105 	}
106 
107 	public boolean hasPassedEnd() {
108 		if (passedEnd) {
109 			passedEnd = false;
110 			return passedEnd;
111 		}
112 		return false;
113 	}
114 
115 	public boolean hasPassedBeginning() {
116 		if (passedBeginning) {
117 			passedBeginning = false;
118 			return passedBeginning;
119 		}
120 		return false;
121 	}
122 
123 	protected Iterable<E> getIterable() {
124 		return toIterateOver;
125 	}
126 
127 	protected Iterator<E> getIterator() {
128 		return iterator;
129 	}
130 
131 	protected void restartIteratorBeginning() {
132 		iterator = toIterateOver.listIterator();
133 	}
134 
135 	protected void restartIteratorEnd() {
136 		iterator = toIterateOver.listIterator(toIterateOver.size());
137 	}
138 
139 	@Override
140 	public void add(E e) {
141 		iterator.add(e);
142 	}
143 
144 	@Override
145 	public boolean hasPrevious() {
146 		return hasNext();
147 	}
148 
149 	@Override
150 	public int nextIndex() {
151 		return (iterator.nextIndex() % toIterateOver.size());
152 	}
153 
154 	@Override
155 	public E previous() {
156 		
157 		if (currentIndex() == 0) {
158 			restartIteratorEnd();
159 		}
160 		
161 		E value = iterator.previous();
162 
163 		if (currentIndex() == index && moved)
164 			passedBeginning = true;
165 		
166 		moved = true;
167 
168 		return value;
169 	}
170 
171 	@Override
172 	public int previousIndex() {
173 		int previous = iterator.previousIndex();
174 		return (previous == -1 ? toIterateOver.size() - 1 : previous);
175 	}
176 
177 	@Override
178 	public void set(E e) {
179 		iterator.set(e);
180 	}
181 	
182 	public int currentIndex() {
183 		int next = nextIndex() - 1;
184 		
185 		return (next == toIterateOver.size() ? 0 : (nextIndex() - 1));
186 	}
187 	
188 	public CircularListIterator<E> previousIter() {
189 		this.previous();
190 		return this;
191 	}
192 	
193 	public CircularListIterator<E> nextIter() {
194 		this.next();
195 		return this;
196 	}
197 }