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 */
017 package org.apache.commons.collections.iterators;
018
019 import java.util.Iterator;
020 import java.util.Map;
021
022 import org.apache.commons.collections.MapIterator;
023 import org.apache.commons.collections.ResettableIterator;
024
025 /**
026 * Implements a <code>MapIterator</code> using a Map entrySet.
027 * Reverse iteration is not supported.
028 * <pre>
029 * MapIterator it = map.mapIterator();
030 * while (it.hasNext()) {
031 * Object key = it.next();
032 * Object value = it.getValue();
033 * it.setValue(newValue);
034 * }
035 * </pre>
036 *
037 * @since Commons Collections 3.0
038 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
039 *
040 * @author Stephen Colebourne
041 */
042 public class EntrySetMapIterator implements MapIterator, ResettableIterator {
043
044 private final Map map;
045 private Iterator iterator;
046 private Map.Entry last;
047 private boolean canRemove = false;
048
049 /**
050 * Constructor.
051 *
052 * @param map the map to iterate over
053 */
054 public EntrySetMapIterator(Map map) {
055 super();
056 this.map = map;
057 this.iterator = map.entrySet().iterator();
058 }
059
060 //-----------------------------------------------------------------------
061 /**
062 * Checks to see if there are more entries still to be iterated.
063 *
064 * @return <code>true</code> if the iterator has more elements
065 */
066 public boolean hasNext() {
067 return iterator.hasNext();
068 }
069
070 /**
071 * Gets the next <em>key</em> from the <code>Map</code>.
072 *
073 * @return the next key in the iteration
074 * @throws java.util.NoSuchElementException if the iteration is finished
075 */
076 public Object next() {
077 last = (Map.Entry) iterator.next();
078 canRemove = true;
079 return last.getKey();
080 }
081
082 //-----------------------------------------------------------------------
083 /**
084 * Removes the last returned key from the underlying <code>Map</code>.
085 * <p>
086 * This method can be called once per call to <code>next()</code>.
087 *
088 * @throws UnsupportedOperationException if remove is not supported by the map
089 * @throws IllegalStateException if <code>next()</code> has not yet been called
090 * @throws IllegalStateException if <code>remove()</code> has already been called
091 * since the last call to <code>next()</code>
092 */
093 public void remove() {
094 if (canRemove == false) {
095 throw new IllegalStateException("Iterator remove() can only be called once after next()");
096 }
097 iterator.remove();
098 last = null;
099 canRemove = false;
100 }
101
102 //-----------------------------------------------------------------------
103 /**
104 * Gets the current key, which is the key returned by the last call
105 * to <code>next()</code>.
106 *
107 * @return the current key
108 * @throws IllegalStateException if <code>next()</code> has not yet been called
109 */
110 public Object getKey() {
111 if (last == null) {
112 throw new IllegalStateException("Iterator getKey() can only be called after next() and before remove()");
113 }
114 return last.getKey();
115 }
116
117 /**
118 * Gets the current value, which is the value associated with the last key
119 * returned by <code>next()</code>.
120 *
121 * @return the current value
122 * @throws IllegalStateException if <code>next()</code> has not yet been called
123 */
124 public Object getValue() {
125 if (last == null) {
126 throw new IllegalStateException("Iterator getValue() can only be called after next() and before remove()");
127 }
128 return last.getValue();
129 }
130
131 /**
132 * Sets the value associated with the current key.
133 *
134 * @param value the new value
135 * @return the previous value
136 * @throws UnsupportedOperationException if setValue is not supported by the map
137 * @throws IllegalStateException if <code>next()</code> has not yet been called
138 * @throws IllegalStateException if <code>remove()</code> has been called since the
139 * last call to <code>next()</code>
140 */
141 public Object setValue(Object value) {
142 if (last == null) {
143 throw new IllegalStateException("Iterator setValue() can only be called after next() and before remove()");
144 }
145 return last.setValue(value);
146 }
147
148 //-----------------------------------------------------------------------
149 /**
150 * Resets the state of the iterator.
151 */
152 public void reset() {
153 iterator = map.entrySet().iterator();
154 last = null;
155 canRemove = false;
156 }
157
158 /**
159 * Gets the iterator as a String.
160 *
161 * @return a string version of the iterator
162 */
163 public String toString() {
164 if (last != null) {
165 return "MapIterator[" + getKey() + "=" + getValue() + "]";
166 } else {
167 return "MapIterator[]";
168 }
169 }
170
171 }