• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Guava Authors
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 
17 package com.google.common.collect;
18 
19 import com.google.common.annotations.Beta;
20 import com.google.common.annotations.GwtCompatible;
21 import com.google.common.base.Objects;
22 
23 import java.util.Collection;
24 import java.util.Iterator;
25 import java.util.Map;
26 import java.util.Set;
27 
28 import javax.annotation.Nullable;
29 
30 /**
31  * A map which forwards all its method calls to another map. Subclasses should
32  * override one or more methods to modify the behavior of the backing map as
33  * desired per the <a
34  * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
35  *
36  * <p><i>Warning:</i> The methods of {@code ForwardingMap} forward
37  * <i>indiscriminately</i> to the methods of the delegate. For example,
38  * overriding {@link #put} alone <i>will not</i> change the behavior of {@link
39  * #putAll}, which can lead to unexpected behavior. In this case, you should
40  * override {@code putAll} as well, either providing your own implementation, or
41  * delegating to the provided {@code standardPutAll} method.
42  *
43  * <p>Each of the {@code standard} methods, where appropriate, use {@link
44  * Objects#equal} to test equality for both keys and values. This may not be
45  * the desired behavior for map implementations that use non-standard notions of
46  * key equality, such as a {@code SortedMap} whose comparator is not consistent
47  * with {@code equals}.
48  *
49  * <p>The {@code standard} methods and the collection views they return are not
50  * guaranteed to be thread-safe, even when all of the methods that they depend
51  * on are thread-safe.
52  *
53  * @author Kevin Bourrillion
54  * @author Jared Levy
55  * @author Louis Wasserman
56  * @since 2.0 (imported from Google Collections Library)
57  */
58 @GwtCompatible
59 public abstract class ForwardingMap<K, V> extends ForwardingObject
60     implements Map<K, V> {
61   // TODO(user): identify places where thread safety is actually lost
62 
63   /** Constructor for use by subclasses. */
ForwardingMap()64   protected ForwardingMap() {}
65 
delegate()66   @Override protected abstract Map<K, V> delegate();
67 
68   @Override
size()69   public int size() {
70     return delegate().size();
71   }
72 
73   @Override
isEmpty()74   public boolean isEmpty() {
75     return delegate().isEmpty();
76   }
77 
78   @Override
remove(Object object)79   public V remove(Object object) {
80     return delegate().remove(object);
81   }
82 
83   @Override
clear()84   public void clear() {
85     delegate().clear();
86   }
87 
88   @Override
containsKey(@ullable Object key)89   public boolean containsKey(@Nullable Object key) {
90     return delegate().containsKey(key);
91   }
92 
93   @Override
containsValue(@ullable Object value)94   public boolean containsValue(@Nullable Object value) {
95     return delegate().containsValue(value);
96   }
97 
98   @Override
get(@ullable Object key)99   public V get(@Nullable Object key) {
100     return delegate().get(key);
101   }
102 
103   @Override
put(K key, V value)104   public V put(K key, V value) {
105     return delegate().put(key, value);
106   }
107 
108   @Override
putAll(Map<? extends K, ? extends V> map)109   public void putAll(Map<? extends K, ? extends V> map) {
110     delegate().putAll(map);
111   }
112 
113   @Override
keySet()114   public Set<K> keySet() {
115     return delegate().keySet();
116   }
117 
118   @Override
values()119   public Collection<V> values() {
120     return delegate().values();
121   }
122 
123   @Override
entrySet()124   public Set<Entry<K, V>> entrySet() {
125     return delegate().entrySet();
126   }
127 
equals(@ullable Object object)128   @Override public boolean equals(@Nullable Object object) {
129     return object == this || delegate().equals(object);
130   }
131 
hashCode()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    */
standardPutAll(Map<? extends K, ? extends V> map)144   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    */
standardRemove(@ullable Object key)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    */
standardClear()180   protected void standardClear() {
181     Iterators.clear(entrySet().iterator());
182   }
183 
184   /**
185    * A sensible implementation of {@link Map#keySet} in terms of the following
186    * methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsKey},
187    * {@link ForwardingMap#isEmpty}, {@link ForwardingMap#remove}, {@link
188    * ForwardingMap#size}, and the {@link Set#iterator} method of {@link
189    * ForwardingMap#entrySet}. In many cases, you may wish to override {@link
190    * ForwardingMap#keySet} to forward to this implementation or a subclass
191    * thereof.
192    *
193    * @since 10.0
194    */
195   @Beta
196   protected class StandardKeySet extends Maps.KeySet<K, V> {
197     /** Constructor for use by subclasses. */
StandardKeySet()198     public StandardKeySet() {
199       super(ForwardingMap.this);
200     }
201   }
202 
203   /**
204    * A sensible, albeit inefficient, definition of {@link #containsKey} in terms
205    * of the {@code iterator} method of {@link #entrySet}. If you override {@link
206    * #entrySet}, you may wish to override {@link #containsKey} to forward to
207    * this implementation.
208    *
209    * @since 7.0
210    */
standardContainsKey(@ullable Object key)211   @Beta protected boolean standardContainsKey(@Nullable Object key) {
212     return Maps.containsKeyImpl(this, key);
213   }
214 
215   /**
216    * A sensible implementation of {@link Map#values} in terms of the following
217    * methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsValue},
218    * {@link ForwardingMap#isEmpty}, {@link ForwardingMap#size}, and the {@link
219    * Set#iterator} method of {@link ForwardingMap#entrySet}. In many cases, you
220    * may wish to override {@link ForwardingMap#values} to forward to this
221    * implementation or a subclass thereof.
222    *
223    * @since 10.0
224    */
225   @Beta
226   protected class StandardValues extends Maps.Values<K, V> {
227     /** Constructor for use by subclasses. */
StandardValues()228     public StandardValues() {
229       super(ForwardingMap.this);
230     }
231   }
232 
233   /**
234    * A sensible definition of {@link #containsValue} in terms of the {@code
235    * iterator} method of {@link #entrySet}. If you override {@link #entrySet},
236    * you may wish to override {@link #containsValue} to forward to this
237    * implementation.
238    *
239    * @since 7.0
240    */
standardContainsValue(@ullable Object value)241   protected boolean standardContainsValue(@Nullable Object value) {
242     return Maps.containsValueImpl(this, value);
243   }
244 
245   /**
246    * A sensible implementation of {@link Map#entrySet} in terms of the following
247    * methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsKey},
248    * {@link ForwardingMap#get}, {@link ForwardingMap#isEmpty}, {@link
249    * ForwardingMap#remove}, and {@link ForwardingMap#size}. In many cases, you
250    * may wish to override {@link #entrySet} to forward to this implementation
251    * or a subclass thereof.
252    *
253    * @since 10.0
254    */
255   @Beta
256   protected abstract class StandardEntrySet extends Maps.EntrySet<K, V> {
257     /** Constructor for use by subclasses. */
StandardEntrySet()258     public StandardEntrySet() {}
259 
260     @Override
map()261     Map<K, V> map() {
262       return ForwardingMap.this;
263     }
264   }
265 
266   /**
267    * A sensible definition of {@link #isEmpty} in terms of the {@code iterator}
268    * method of {@link #entrySet}. If you override {@link #entrySet}, you may
269    * wish to override {@link #isEmpty} to forward to this implementation.
270    *
271    * @since 7.0
272    */
standardIsEmpty()273   protected boolean standardIsEmpty() {
274     return !entrySet().iterator().hasNext();
275   }
276 
277   /**
278    * A sensible definition of {@link #equals} in terms of the {@code equals}
279    * method of {@link #entrySet}. If you override {@link #entrySet}, you may
280    * wish to override {@link #equals} to forward to this implementation.
281    *
282    * @since 7.0
283    */
standardEquals(@ullable Object object)284   protected boolean standardEquals(@Nullable Object object) {
285     return Maps.equalsImpl(this, object);
286   }
287 
288   /**
289    * A sensible definition of {@link #hashCode} in terms of the {@code iterator}
290    * method of {@link #entrySet}. If you override {@link #entrySet}, you may
291    * wish to override {@link #hashCode} to forward to this implementation.
292    *
293    * @since 7.0
294    */
standardHashCode()295   protected int standardHashCode() {
296     return Sets.hashCodeImpl(entrySet());
297   }
298 
299   /**
300    * A sensible definition of {@link #toString} in terms of the {@code iterator}
301    * method of {@link #entrySet}. If you override {@link #entrySet}, you may
302    * wish to override {@link #toString} to forward to this implementation.
303    *
304    * @since 7.0
305    */
standardToString()306   protected String standardToString() {
307     return Maps.toStringImpl(this);
308   }
309 }
310