1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.collections.iterators;
18
19 import java.util.ListIterator;
20 import java.util.NoSuchElementException;
21
22 import org.apache.commons.collections.ResettableListIterator;
23
24 /**
25 * <code>SingletonIterator</code> is an {@link ListIterator} over a single
26 * object instance.
27 *
28 * @since 2.1
29 * @version $Id: SingletonListIterator.java 1429905 2013-01-07 17:15:14Z ggregory $
30 */
31 public class SingletonListIterator<E> implements ListIterator<E>, ResettableListIterator<E> {
32
33 private boolean beforeFirst = true;
34 private boolean nextCalled = false;
35 private boolean removed = false;
36 private E object;
37
38 /**
39 * Constructs a new <code>SingletonListIterator</code>.
40 *
41 * @param object the single object to return from the iterator
42 */
43 public SingletonListIterator(final E object) {
44 super();
45 this.object = object;
46 }
47
48 /**
49 * Is another object available from the iterator?
50 * <p>
51 * This returns true if the single object hasn't been returned yet.
52 *
53 * @return true if the single object hasn't been returned yet
54 */
55 public boolean hasNext() {
56 return beforeFirst && !removed;
57 }
58
59 /**
60 * Is a previous object available from the iterator?
61 * <p>
62 * This returns true if the single object has been returned.
63 *
64 * @return true if the single object has been returned
65 */
66 public boolean hasPrevious() {
67 return !beforeFirst && !removed;
68 }
69
70 /**
71 * Returns the index of the element that would be returned by a subsequent
72 * call to <tt>next</tt>.
73 *
74 * @return 0 or 1 depending on current state.
75 */
76 public int nextIndex() {
77 return beforeFirst ? 0 : 1;
78 }
79
80 /**
81 * Returns the index of the element that would be returned by a subsequent
82 * call to <tt>previous</tt>. A return value of -1 indicates that the iterator is currently at
83 * the start.
84 *
85 * @return 0 or -1 depending on current state.
86 */
87 public int previousIndex() {
88 return beforeFirst ? -1 : 0;
89 }
90
91 /**
92 * Get the next object from the iterator.
93 * <p>
94 * This returns the single object if it hasn't been returned yet.
95 *
96 * @return the single object
97 * @throws NoSuchElementException if the single object has already
98 * been returned
99 */
100 public E next() {
101 if (!beforeFirst || removed) {
102 throw new NoSuchElementException();
103 }
104 beforeFirst = false;
105 nextCalled = true;
106 return object;
107 }
108
109 /**
110 * Get the previous object from the iterator.
111 * <p>
112 * This returns the single object if it has been returned.
113 *
114 * @return the single object
115 * @throws NoSuchElementException if the single object has not already
116 * been returned
117 */
118 public E previous() {
119 if (beforeFirst || removed) {
120 throw new NoSuchElementException();
121 }
122 beforeFirst = true;
123 return object;
124 }
125
126 /**
127 * Remove the object from this iterator.
128 * @throws IllegalStateException if the <tt>next</tt> or <tt>previous</tt>
129 * method has not yet been called, or the <tt>remove</tt> method
130 * has already been called after the last call to <tt>next</tt>
131 * or <tt>previous</tt>.
132 */
133 public void remove() {
134 if(!nextCalled || removed) {
135 throw new IllegalStateException();
136 } else {
137 object = null;
138 removed = true;
139 }
140 }
141
142 /**
143 * Add always throws {@link UnsupportedOperationException}.
144 *
145 * @param obj the object to add
146 * @throws UnsupportedOperationException always
147 */
148 public void add(final E obj) {
149 throw new UnsupportedOperationException("add() is not supported by this iterator");
150 }
151
152 /**
153 * Set sets the value of the singleton.
154 *
155 * @param obj the object to set
156 * @throws IllegalStateException if <tt>next</tt> has not been called
157 * or the object has been removed
158 */
159 public void set(final E obj) {
160 if (!nextCalled || removed) {
161 throw new IllegalStateException();
162 }
163 this.object = obj;
164 }
165
166 /**
167 * Reset the iterator back to the start.
168 */
169 public void reset() {
170 beforeFirst = true;
171 nextCalled = false;
172 }
173
174 }