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