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