001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.collections4.iterators; 018 019import java.util.NoSuchElementException; 020 021import org.apache.commons.collections4.ResettableListIterator; 022 023/** 024 * {@code SingletonIterator} is an {@link java.util.ListIterator} over a single 025 * object instance. 026 * 027 * @param <E> the type of elements returned by this iterator. 028 * @since 2.1 029 */ 030public class SingletonListIterator<E> implements ResettableListIterator<E> { 031 032 private boolean beforeFirst = true; 033 private boolean nextCalled; 034 private boolean removed; 035 private E object; 036 037 /** 038 * Constructs a new {@code SingletonListIterator}. 039 * 040 * @param object the single object to return from the iterator 041 */ 042 public SingletonListIterator(final E object) { 043 this.object = object; 044 } 045 046 /** 047 * Add always throws {@link UnsupportedOperationException}. 048 * 049 * @param obj the object to add 050 * @throws UnsupportedOperationException always 051 */ 052 @Override 053 public void add(final E obj) { 054 throw new UnsupportedOperationException("add() is not supported by this iterator"); 055 } 056 057 /** 058 * Is another object available from the iterator? 059 * <p> 060 * This returns true if the single object hasn't been returned yet. 061 * 062 * @return true if the single object hasn't been returned yet 063 */ 064 @Override 065 public boolean hasNext() { 066 return beforeFirst && !removed; 067 } 068 069 /** 070 * Is a previous object available from the iterator? 071 * <p> 072 * This returns true if the single object has been returned. 073 * 074 * @return true if the single object has been returned 075 */ 076 @Override 077 public boolean hasPrevious() { 078 return !beforeFirst && !removed; 079 } 080 081 /** 082 * Gets the next object from the iterator. 083 * <p> 084 * This returns the single object if it hasn't been returned yet. 085 * 086 * @return the single object 087 * @throws NoSuchElementException if the single object has already 088 * been returned 089 */ 090 @Override 091 public E next() { 092 if (!beforeFirst || removed) { 093 throw new NoSuchElementException(); 094 } 095 beforeFirst = false; 096 nextCalled = true; 097 return object; 098 } 099 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 obj 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 obj) { 175 if (!nextCalled || removed) { 176 throw new IllegalStateException(); 177 } 178 this.object = obj; 179 } 180 181}