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 * https://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.collections4.iterators;
18
19 import java.util.ListIterator;
20 import java.util.NoSuchElementException;
21
22 import org.apache.commons.collections4.ResettableListIterator;
23
24 /**
25 * {@code SingletonIterator} is an {@link ListIterator} over a single
26 * object instance.
27 *
28 * @param <E> The type of elements returned by this iterator.
29 * @since 2.1
30 */
31 public class SingletonListIterator<E> implements ResettableListIterator<E> {
32
33 private boolean beforeFirst = true;
34 private boolean nextCalled;
35 private boolean removed;
36 private E object;
37
38 /**
39 * Constructs a new {@code SingletonListIterator}.
40 *
41 * @param object The single object to return from the iterator
42 */
43 public SingletonListIterator(final E object) {
44 this.object = object;
45 }
46
47 /**
48 * Always throws {@link UnsupportedOperationException}.
49 *
50 * @param obj Ignored.
51 * @throws UnsupportedOperationException Always thrown.
52 */
53 @Override
54 public void add(final E obj) {
55 throw new UnsupportedOperationException("add() is not supported by this iterator");
56 }
57
58 /**
59 * Is another object available from the iterator?
60 * <p>
61 * This returns true if the single object hasn't been returned yet.
62 *
63 * @return true if the single object hasn't been returned yet
64 */
65 @Override
66 public boolean hasNext() {
67 return beforeFirst && !removed;
68 }
69
70 /**
71 * Is a previous object available from the iterator?
72 * <p>
73 * This returns true if the single object has been returned.
74 *
75 * @return true if the single object has been returned
76 */
77 @Override
78 public boolean hasPrevious() {
79 return !beforeFirst && !removed;
80 }
81
82 /**
83 * Gets the next object from the iterator.
84 * <p>
85 * This returns the single object if it hasn't been returned yet.
86 *
87 * @return The single object
88 * @throws NoSuchElementException if the single object has already
89 * been returned
90 */
91 @Override
92 public E next() {
93 if (!beforeFirst || removed) {
94 throw new NoSuchElementException();
95 }
96 beforeFirst = false;
97 nextCalled = true;
98 return object;
99 }
100
101 /**
102 * Returns the index of the element that would be returned by a subsequent
103 * call to {@code next}.
104 *
105 * @return 0 or 1 depending on current state.
106 */
107 @Override
108 public int nextIndex() {
109 return beforeFirst ? 0 : 1;
110 }
111
112 /**
113 * Gets the previous object from the iterator.
114 * <p>
115 * This returns the single object if it has been returned.
116 *
117 * @return The single object
118 * @throws NoSuchElementException if the single object has not already
119 * been returned
120 */
121 @Override
122 public E previous() {
123 if (beforeFirst || removed) {
124 throw new NoSuchElementException();
125 }
126 beforeFirst = true;
127 return object;
128 }
129
130 /**
131 * Returns the index of the element that would be returned by a subsequent
132 * call to {@code previous}. A return value of -1 indicates that the iterator is currently at
133 * the start.
134 *
135 * @return 0 or -1 depending on current state.
136 */
137 @Override
138 public int previousIndex() {
139 return beforeFirst ? -1 : 0;
140 }
141
142 /**
143 * Remove the object from this iterator.
144 *
145 * @throws IllegalStateException if the {@code next} or {@code previous}
146 * method has not yet been called, or the {@code remove} method
147 * has already been called after the last call to {@code next}
148 * or {@code previous}.
149 */
150 @Override
151 public void remove() {
152 if (!nextCalled || removed) {
153 throw new IllegalStateException();
154 }
155 object = null;
156 removed = true;
157 }
158
159 /**
160 * Reset the iterator back to the start.
161 */
162 @Override
163 public void reset() {
164 beforeFirst = true;
165 nextCalled = false;
166 }
167
168 /**
169 * Sets sets the value of the singleton.
170 *
171 * @param object The object to set
172 * @throws IllegalStateException if {@code next} has not been called
173 * or the object has been removed
174 */
175 @Override
176 public void set(final E object) {
177 if (!nextCalled || removed) {
178 throw new IllegalStateException();
179 }
180 this.object = object;
181 }
182
183 }