View Javadoc

1   /*
2      Copyright 2010 Ramon Servadei
3   
4      Licensed under the Apache License, Version 2.0 (the "License");
5      you may not use this file except in compliance with the License.
6      You may obtain a copy of the License at
7   
8          http://www.apache.org/licenses/LICENSE-2.0
9   
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15   */
16  package mirrormap.collections;
17  
18  import java.util.Collection;
19  import java.util.Iterator;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.Map.Entry;
23  
24  /**
25   * A base class for an iterator that can be returned from the {@link Collection}
26   * objects returned from the methods {@link NotifyingMap#keySet()},
27   * {@link NotifyingMap#values()} and {@link NotifyingMap#entrySet()}. This
28   * iterator will fire {@link IMapListener#willRemove(Object)} and
29   * {@link IMapListener#didRemove(Object, Object)} events when items from the
30   * underlying {@link Map} of the {@link NotifyingMap} are removed by this
31   * iterator.
32   * 
33   * @author Ramon Servadei
34   * @param <IteratorType>
35   *            the type the {@link Iterator} returns
36   * @param <K>
37   *            the key type of the backing {@link Map} the iterator operates on
38   * @param <V>
39   *            the value type of the backing {@link Map} the iterator operates on
40   */
41  abstract class AbstractNotifyingIterator<IteratorType, K, V> implements
42      Iterator<IteratorType>
43  {
44      /** The {@link NotifyingMap} this entry set iterator operates on */
45      protected final NotifyingMap<K, V> notifyingMap;
46  
47      /** The iterator returned from the {@link #notifyingMap} */
48      private final Iterator<Entry<K, V>> entryIterator;
49  
50      /** Tracks the current iteration item */
51      private Entry<K, V> current;
52  
53      AbstractNotifyingIterator(NotifyingMap<K, V> notifyingMap)
54      {
55          this.notifyingMap = notifyingMap;
56          this.entryIterator = notifyingMap.getBackingEntrySet().iterator();
57      }
58  
59      public boolean hasNext()
60      {
61          return this.entryIterator.hasNext();
62      }
63  
64      public IteratorType next()
65      {
66          final Entry<K, V> next = this.entryIterator.next();
67          this.current = next;
68          return getValueForNext(this.current);
69      }
70  
71      public void remove()
72      {
73          final List<IMapListener<K, V>> listeners =
74              this.notifyingMap.getListeners();
75          for (IMapListener<K, V> listener : listeners)
76          {
77              listener.willRemove(this.current.getKey());
78          }
79          this.entryIterator.remove();
80          for (IMapListener<K, V> listener : listeners)
81          {
82              listener.didRemove(this.current.getKey(), this.current.getValue());
83          }
84      }
85  
86      /**
87       * Called from the {@link #next()} method to return the correct value from
88       * the current map entry.
89       * 
90       * @param currentEntry
91       *            the current map entry the iterator is pointing to after the
92       *            delegate iterator's call to {@link #next()}
93       * @return the correct value from the current map entry
94       */
95      protected abstract IteratorType getValueForNext(Entry<K, V> currentEntry);
96  }