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 * https://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.ListIterator; 020import java.util.NoSuchElementException; 021 022import org.apache.commons.collections4.ResettableListIterator; 023 024/** 025 * {@code SingletonIterator} is an {@link ListIterator} over a single 026 * object instance. 027 * 028 * @param <E> The type of elements returned by this iterator. 029 * @since 2.1 030 */ 031public class SingletonListIterator<E> implements ResettableListIterator<E> { 032 033 private boolean beforeFirst = true; 034 private boolean nextCalled; 035 private boolean removed; 036 private E object; 037 038 /** 039 * Constructs a new {@code SingletonListIterator}. 040 * 041 * @param object The single object to return from the iterator 042 */ 043 public SingletonListIterator(final E object) { 044 this.object = object; 045 } 046 047 /** 048 * Always throws {@link UnsupportedOperationException}. 049 * 050 * @param obj Ignored. 051 * @throws UnsupportedOperationException Always thrown. 052 */ 053 @Override 054 public void add(final E obj) { 055 throw new UnsupportedOperationException("add() is not supported by this iterator"); 056 } 057 058 /** 059 * Is another object available from the iterator? 060 * <p> 061 * This returns true if the single object hasn't been returned yet. 062 * 063 * @return true if the single object hasn't been returned yet 064 */ 065 @Override 066 public boolean hasNext() { 067 return beforeFirst && !removed; 068 } 069 070 /** 071 * Is a previous object available from the iterator? 072 * <p> 073 * This returns true if the single object has been returned. 074 * 075 * @return true if the single object has been returned 076 */ 077 @Override 078 public boolean hasPrevious() { 079 return !beforeFirst && !removed; 080 } 081 082 /** 083 * Gets the next object from the iterator. 084 * <p> 085 * This returns the single object if it hasn't been returned yet. 086 * 087 * @return The single object 088 * @throws NoSuchElementException if the single object has already 089 * been returned 090 */ 091 @Override 092 public E next() { 093 if (!beforeFirst || removed) { 094 throw new NoSuchElementException(); 095 } 096 beforeFirst = false; 097 nextCalled = true; 098 return object; 099 } 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}