001    /*
002     * Copyright (C) 2007 The Guava Authors
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package com.google.common.collect;
018    
019    import com.google.common.annotations.Beta;
020    import com.google.common.annotations.GwtCompatible;
021    import com.google.common.base.Objects;
022    
023    import java.util.Collection;
024    import java.util.Iterator;
025    import java.util.Map;
026    import java.util.Set;
027    
028    import javax.annotation.Nullable;
029    
030    /**
031     * A map which forwards all its method calls to another map. Subclasses should
032     * override one or more methods to modify the behavior of the backing map as
033     * desired per the <a
034     * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
035     *
036     * <p><i>Warning:</i> The methods of {@code ForwardingMap} forward
037     * <i>indiscriminately</i> to the methods of the delegate. For example,
038     * overriding {@link #put} alone <i>will not</i> change the behavior of {@link
039     * #putAll}, which can lead to unexpected behavior. In this case, you should
040     * override {@code putAll} as well, either providing your own implementation, or
041     * delegating to the provided {@code standardPutAll} method.
042     *
043     * <p>Each of the {@code standard} methods, where appropriate, use {@link
044     * Objects#equal} to test equality for both keys and values. This may not be
045     * the desired behavior for map implementations that use non-standard notions of
046     * key equality, such as a {@code SortedMap} whose comparator is not consistent
047     * with {@code equals}.
048     *
049     * <p>The {@code standard} methods and the collection views they return are not
050     * guaranteed to be thread-safe, even when all of the methods that they depend
051     * on are thread-safe.
052     *
053     * @author Kevin Bourrillion
054     * @author Jared Levy
055     * @author Louis Wasserman
056     * @since 2.0 (imported from Google Collections Library)
057     */
058    @GwtCompatible
059    public abstract class ForwardingMap<K, V> extends ForwardingObject
060        implements Map<K, V> {
061      // TODO(user): identify places where thread safety is actually lost
062    
063      /** Constructor for use by subclasses. */
064      protected ForwardingMap() {}
065    
066      @Override protected abstract Map<K, V> delegate();
067    
068      @Override
069      public int size() {
070        return delegate().size();
071      }
072    
073      @Override
074      public boolean isEmpty() {
075        return delegate().isEmpty();
076      }
077    
078      @Override
079      public V remove(Object object) {
080        return delegate().remove(object);
081      }
082    
083      @Override
084      public void clear() {
085        delegate().clear();
086      }
087    
088      @Override
089      public boolean containsKey(Object key) {
090        return delegate().containsKey(key);
091      }
092    
093      @Override
094      public boolean containsValue(Object value) {
095        return delegate().containsValue(value);
096      }
097    
098      @Override
099      public V get(Object key) {
100        return delegate().get(key);
101      }
102    
103      @Override
104      public V put(K key, V value) {
105        return delegate().put(key, value);
106      }
107    
108      @Override
109      public void putAll(Map<? extends K, ? extends V> map) {
110        delegate().putAll(map);
111      }
112    
113      @Override
114      public Set<K> keySet() {
115        return delegate().keySet();
116      }
117    
118      @Override
119      public Collection<V> values() {
120        return delegate().values();
121      }
122    
123      @Override
124      public Set<Entry<K, V>> entrySet() {
125        return delegate().entrySet();
126      }
127    
128      @Override public boolean equals(@Nullable Object object) {
129        return object == this || delegate().equals(object);
130      }
131    
132      @Override public int hashCode() {
133        return delegate().hashCode();
134      }
135    
136      /**
137       * A sensible definition of {@link #putAll(Map)} in terms of {@link
138       * #put(Object, Object)}. If you override {@link #put(Object, Object)}, you
139       * may wish to override {@link #putAll(Map)} to forward to this
140       * implementation.
141       *
142       * @since 7.0
143       */
144      @Beta protected void standardPutAll(Map<? extends K, ? extends V> map) {
145        Maps.putAllImpl(this, map);
146      }
147    
148      /**
149       * A sensible, albeit inefficient, definition of {@link #remove} in terms of
150       * the {@code iterator} method of {@link #entrySet}. If you override {@link
151       * #entrySet}, you may wish to override {@link #remove} to forward to this
152       * implementation.
153       *
154       * <p>Alternately, you may wish to override {@link #remove} with {@code
155       * keySet().remove}, assuming that approach would not lead to an infinite
156       * loop.
157       *
158       * @since 7.0
159       */
160      @Beta protected V standardRemove(@Nullable Object key) {
161        Iterator<Entry<K, V>> entryIterator = entrySet().iterator();
162        while (entryIterator.hasNext()) {
163          Entry<K, V> entry = entryIterator.next();
164          if (Objects.equal(entry.getKey(), key)) {
165            V value = entry.getValue();
166            entryIterator.remove();
167            return value;
168          }
169        }
170        return null;
171      }
172    
173      /**
174       * A sensible definition of {@link #clear} in terms of the {@code iterator}
175       * method of {@link #entrySet}. In many cases, you may wish to override
176       * {@link #clear} to forward to this implementation.
177       *
178       * @since 7.0
179       */
180      @Beta protected void standardClear() {
181        Iterator<Entry<K, V>> entryIterator = entrySet().iterator();
182        while (entryIterator.hasNext()) {
183          entryIterator.next();
184          entryIterator.remove();
185        }
186      }
187    
188      /**
189       * A sensible implementation of {@link Map#keySet} in terms of the following
190       * methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsKey},
191       * {@link ForwardingMap#isEmpty}, {@link ForwardingMap#remove}, {@link
192       * ForwardingMap#size}, and the {@link Set#iterator} method of {@link
193       * ForwardingMap#entrySet}. In many cases, you may wish to override {@link
194       * ForwardingMap#keySet} to forward to this implementation or a subclass
195       * thereof.
196       *
197       * @since 10.0
198       */
199      @Beta
200      protected class StandardKeySet extends Maps.KeySet<K, V> {
201        public StandardKeySet() {}
202    
203        @Override
204        Map<K, V> map() {
205          return ForwardingMap.this;
206        }
207      }
208    
209      /**
210       * A sensible, albeit inefficient, definition of {@link #containsKey} in terms
211       * of the {@code iterator} method of {@link #entrySet}. If you override {@link
212       * #entrySet}, you may wish to override {@link #containsKey} to forward to
213       * this implementation.
214       *
215       * @since 7.0
216       */
217      @Beta protected boolean standardContainsKey(@Nullable Object key) {
218        return Maps.containsKeyImpl(this, key);
219      }
220    
221      /**
222       * A sensible implementation of {@link Map#values} in terms of the following
223       * methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsValue},
224       * {@link ForwardingMap#isEmpty}, {@link ForwardingMap#size}, and the {@link
225       * Set#iterator} method of {@link ForwardingMap#entrySet}. In many cases, you
226       * may wish to override {@link ForwardingMap#values} to forward to this
227       * implementation or a subclass thereof.
228       *
229       * @since 10.0
230       */
231      @Beta
232      protected class StandardValues extends Maps.Values<K, V> {
233        public StandardValues() {}
234    
235        @Override
236        Map<K, V> map() {
237          return ForwardingMap.this;
238        }
239      }
240    
241      /**
242       * A sensible definition of {@link #containsValue} in terms of the {@code
243       * iterator} method of {@link #entrySet}. If you override {@link #entrySet},
244       * you may wish to override {@link #containsValue} to forward to this
245       * implementation.
246       *
247       * @since 7.0
248       */
249      @Beta protected boolean standardContainsValue(@Nullable Object value) {
250        return Maps.containsValueImpl(this, value);
251      }
252    
253      /**
254       * A sensible implementation of {@link Map#entrySet} in terms of the following
255       * methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsKey},
256       * {@link ForwardingMap#get}, {@link ForwardingMap#isEmpty}, {@link
257       * ForwardingMap#remove}, and {@link ForwardingMap#size}. In many cases, you
258       * may wish to override {@link #entrySet} to forward to this implementation
259       * or a subclass thereof.
260       *
261       * @since 10.0
262       */
263      @Beta
264      protected abstract class StandardEntrySet extends Maps.EntrySet<K, V> {
265        public StandardEntrySet() {}
266    
267        @Override
268        Map<K, V> map() {
269          return ForwardingMap.this;
270        }
271      }
272    
273      /**
274       * A sensible definition of {@link #isEmpty} in terms of the {@code iterator}
275       * method of {@link #entrySet}. If you override {@link #entrySet}, you may
276       * wish to override {@link #isEmpty} to forward to this implementation.
277       *
278       * @since 7.0
279       */
280      @Beta protected boolean standardIsEmpty() {
281        return !entrySet().iterator().hasNext();
282      }
283    
284      /**
285       * A sensible definition of {@link #equals} in terms of the {@code equals}
286       * method of {@link #entrySet}. If you override {@link #entrySet}, you may
287       * wish to override {@link #equals} to forward to this implementation.
288       *
289       * @since 7.0
290       */
291      @Beta protected boolean standardEquals(@Nullable Object object) {
292        return Maps.equalsImpl(this, object);
293      }
294    
295      /**
296       * A sensible definition of {@link #hashCode} in terms of the {@code iterator}
297       * method of {@link #entrySet}. If you override {@link #entrySet}, you may
298       * wish to override {@link #hashCode} to forward to this implementation.
299       *
300       * @since 7.0
301       */
302      @Beta protected int standardHashCode() {
303        return Sets.hashCodeImpl(entrySet());
304      }
305    
306      /**
307       * A sensible definition of {@link #toString} in terms of the {@code iterator}
308       * method of {@link #entrySet}. If you override {@link #entrySet}, you may
309       * wish to override {@link #toString} to forward to this implementation.
310       *
311       * @since 7.0
312       */
313      @Beta protected String standardToString() {
314        return Maps.toStringImpl(this);
315      }
316    }