• 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.GwtCompatible;
20 import com.google.common.base.Objects;
21 import com.google.errorprone.annotations.CanIgnoreReturnValue;
22 import java.util.Collection;
23 import java.util.Iterator;
24 import java.util.Set;
25 import javax.annotation.CheckForNull;
26 import org.checkerframework.checker.nullness.qual.Nullable;
27 
28 /**
29  * A multiset which forwards all its method calls to another multiset. Subclasses should override
30  * one or more methods to modify the behavior of the backing multiset as desired per the <a
31  * href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator pattern</a>.
32  *
33  * <p><b>Warning:</b> The methods of {@code ForwardingMultiset} forward <b>indiscriminately</b> to
34  * the methods of the delegate. For example, overriding {@link #add(Object, int)} alone <b>will
35  * not</b> change the behavior of {@link #add(Object)}, which can lead to unexpected behavior. In
36  * this case, you should override {@code add(Object)} as well, either providing your own
37  * implementation, or delegating to the provided {@code standardAdd} method.
38  *
39  * <p><b>{@code default} method warning:</b> This class does <i>not</i> forward calls to {@code
40  * default} methods. Instead, it inherits their default implementations. When those implementations
41  * invoke methods, they invoke methods on the {@code ForwardingMultiset}.
42  *
43  * <p>The {@code standard} methods and any collection views they return are not guaranteed to be
44  * thread-safe, even when all of the methods that they depend on are thread-safe.
45  *
46  * @author Kevin Bourrillion
47  * @author Louis Wasserman
48  * @since 2.0
49  */
50 @GwtCompatible
51 @ElementTypesAreNonnullByDefault
52 public abstract class ForwardingMultiset<E extends @Nullable Object> extends ForwardingCollection<E>
53     implements Multiset<E> {
54 
55   /** Constructor for use by subclasses. */
ForwardingMultiset()56   protected ForwardingMultiset() {}
57 
58   @Override
delegate()59   protected abstract Multiset<E> delegate();
60 
61   @Override
count(@heckForNull Object element)62   public int count(@CheckForNull Object element) {
63     return delegate().count(element);
64   }
65 
66   @CanIgnoreReturnValue
67   @Override
add(@arametricNullness E element, int occurrences)68   public int add(@ParametricNullness E element, int occurrences) {
69     return delegate().add(element, occurrences);
70   }
71 
72   @CanIgnoreReturnValue
73   @Override
remove(@heckForNull Object element, int occurrences)74   public int remove(@CheckForNull Object element, int occurrences) {
75     return delegate().remove(element, occurrences);
76   }
77 
78   @Override
elementSet()79   public Set<E> elementSet() {
80     return delegate().elementSet();
81   }
82 
83   @Override
entrySet()84   public Set<Entry<E>> entrySet() {
85     return delegate().entrySet();
86   }
87 
88   @Override
equals(@heckForNull Object object)89   public boolean equals(@CheckForNull Object object) {
90     return object == this || delegate().equals(object);
91   }
92 
93   @Override
hashCode()94   public int hashCode() {
95     return delegate().hashCode();
96   }
97 
98   @CanIgnoreReturnValue
99   @Override
setCount(@arametricNullness E element, int count)100   public int setCount(@ParametricNullness E element, int count) {
101     return delegate().setCount(element, count);
102   }
103 
104   @CanIgnoreReturnValue
105   @Override
setCount(@arametricNullness E element, int oldCount, int newCount)106   public boolean setCount(@ParametricNullness E element, int oldCount, int newCount) {
107     return delegate().setCount(element, oldCount, newCount);
108   }
109 
110   /**
111    * A sensible definition of {@link #contains} in terms of {@link #count}. If you override {@link
112    * #count}, you may wish to override {@link #contains} to forward to this implementation.
113    *
114    * @since 7.0
115    */
116   @Override
standardContains(@heckForNull Object object)117   protected boolean standardContains(@CheckForNull Object object) {
118     return count(object) > 0;
119   }
120 
121   /**
122    * A sensible definition of {@link #clear} in terms of the {@code iterator} method of {@link
123    * #entrySet}. If you override {@link #entrySet}, you may wish to override {@link #clear} to
124    * forward to this implementation.
125    *
126    * @since 7.0
127    */
128   @Override
standardClear()129   protected void standardClear() {
130     Iterators.clear(entrySet().iterator());
131   }
132 
133   /**
134    * A sensible, albeit inefficient, definition of {@link #count} in terms of {@link #entrySet}. If
135    * you override {@link #entrySet}, you may wish to override {@link #count} to forward to this
136    * implementation.
137    *
138    * @since 7.0
139    */
standardCount(@heckForNull Object object)140   protected int standardCount(@CheckForNull Object object) {
141     for (Entry<?> entry : this.entrySet()) {
142       if (Objects.equal(entry.getElement(), object)) {
143         return entry.getCount();
144       }
145     }
146     return 0;
147   }
148 
149   /**
150    * A sensible definition of {@link #add(Object)} in terms of {@link #add(Object, int)}. If you
151    * override {@link #add(Object, int)}, you may wish to override {@link #add(Object)} to forward to
152    * this implementation.
153    *
154    * @since 7.0
155    */
standardAdd(@arametricNullness E element)156   protected boolean standardAdd(@ParametricNullness E element) {
157     add(element, 1);
158     return true;
159   }
160 
161   /**
162    * A sensible definition of {@link #addAll(Collection)} in terms of {@link #add(Object)} and
163    * {@link #add(Object, int)}. If you override either of these methods, you may wish to override
164    * {@link #addAll(Collection)} to forward to this implementation.
165    *
166    * @since 7.0
167    */
168   @Override
standardAddAll(Collection<? extends E> elementsToAdd)169   protected boolean standardAddAll(Collection<? extends E> elementsToAdd) {
170     return Multisets.addAllImpl(this, elementsToAdd);
171   }
172 
173   /**
174    * A sensible definition of {@link #remove(Object)} in terms of {@link #remove(Object, int)}. If
175    * you override {@link #remove(Object, int)}, you may wish to override {@link #remove(Object)} to
176    * forward to this implementation.
177    *
178    * @since 7.0
179    */
180   @Override
standardRemove(@heckForNull Object element)181   protected boolean standardRemove(@CheckForNull Object element) {
182     return remove(element, 1) > 0;
183   }
184 
185   /**
186    * A sensible definition of {@link #removeAll} in terms of the {@code removeAll} method of {@link
187    * #elementSet}. If you override {@link #elementSet}, you may wish to override {@link #removeAll}
188    * to forward to this implementation.
189    *
190    * @since 7.0
191    */
192   @Override
standardRemoveAll(Collection<?> elementsToRemove)193   protected boolean standardRemoveAll(Collection<?> elementsToRemove) {
194     return Multisets.removeAllImpl(this, elementsToRemove);
195   }
196 
197   /**
198    * A sensible definition of {@link #retainAll} in terms of the {@code retainAll} method of {@link
199    * #elementSet}. If you override {@link #elementSet}, you may wish to override {@link #retainAll}
200    * to forward to this implementation.
201    *
202    * @since 7.0
203    */
204   @Override
standardRetainAll(Collection<?> elementsToRetain)205   protected boolean standardRetainAll(Collection<?> elementsToRetain) {
206     return Multisets.retainAllImpl(this, elementsToRetain);
207   }
208 
209   /**
210    * A sensible definition of {@link #setCount(Object, int)} in terms of {@link #count(Object)},
211    * {@link #add(Object, int)}, and {@link #remove(Object, int)}. {@link #entrySet()}. If you
212    * override any of these methods, you may wish to override {@link #setCount(Object, int)} to
213    * forward to this implementation.
214    *
215    * @since 7.0
216    */
standardSetCount(@arametricNullness E element, int count)217   protected int standardSetCount(@ParametricNullness E element, int count) {
218     return Multisets.setCountImpl(this, element, count);
219   }
220 
221   /**
222    * A sensible definition of {@link #setCount(Object, int, int)} in terms of {@link #count(Object)}
223    * and {@link #setCount(Object, int)}. If you override either of these methods, you may wish to
224    * override {@link #setCount(Object, int, int)} to forward to this implementation.
225    *
226    * @since 7.0
227    */
standardSetCount(@arametricNullness E element, int oldCount, int newCount)228   protected boolean standardSetCount(@ParametricNullness E element, int oldCount, int newCount) {
229     return Multisets.setCountImpl(this, element, oldCount, newCount);
230   }
231 
232   /**
233    * A sensible implementation of {@link Multiset#elementSet} in terms of the following methods:
234    * {@link ForwardingMultiset#clear}, {@link ForwardingMultiset#contains}, {@link
235    * ForwardingMultiset#containsAll}, {@link ForwardingMultiset#count}, {@link
236    * ForwardingMultiset#isEmpty}, the {@link Set#size} and {@link Set#iterator} methods of {@link
237    * ForwardingMultiset#entrySet}, and {@link ForwardingMultiset#remove(Object, int)}. In many
238    * situations, you may wish to override {@link ForwardingMultiset#elementSet} to forward to this
239    * implementation or a subclass thereof.
240    *
241    * @since 10.0
242    */
243   protected class StandardElementSet extends Multisets.ElementSet<E> {
244     /** Constructor for use by subclasses. */
StandardElementSet()245     public StandardElementSet() {}
246 
247     @Override
multiset()248     Multiset<E> multiset() {
249       return ForwardingMultiset.this;
250     }
251 
252     @Override
iterator()253     public Iterator<E> iterator() {
254       return Multisets.elementIterator(multiset().entrySet().iterator());
255     }
256   }
257 
258   /**
259    * A sensible definition of {@link #iterator} in terms of {@link #entrySet} and {@link
260    * #remove(Object)}. If you override either of these methods, you may wish to override {@link
261    * #iterator} to forward to this implementation.
262    *
263    * @since 7.0
264    */
standardIterator()265   protected Iterator<E> standardIterator() {
266     return Multisets.iteratorImpl(this);
267   }
268 
269   /**
270    * A sensible, albeit inefficient, definition of {@link #size} in terms of {@link #entrySet}. If
271    * you override {@link #entrySet}, you may wish to override {@link #size} to forward to this
272    * implementation.
273    *
274    * @since 7.0
275    */
standardSize()276   protected int standardSize() {
277     return Multisets.linearTimeSizeImpl(this);
278   }
279 
280   /**
281    * A sensible, albeit inefficient, definition of {@link #equals} in terms of {@code
282    * entrySet().size()} and {@link #count}. If you override either of these methods, you may wish to
283    * override {@link #equals} to forward to this implementation.
284    *
285    * @since 7.0
286    */
standardEquals(@heckForNull Object object)287   protected boolean standardEquals(@CheckForNull Object object) {
288     return Multisets.equalsImpl(this, object);
289   }
290 
291   /**
292    * A sensible definition of {@link #hashCode} as {@code entrySet().hashCode()} . If you override
293    * {@link #entrySet}, you may wish to override {@link #hashCode} to forward to this
294    * implementation.
295    *
296    * @since 7.0
297    */
standardHashCode()298   protected int standardHashCode() {
299     return entrySet().hashCode();
300   }
301 
302   /**
303    * A sensible definition of {@link #toString} as {@code entrySet().toString()} . If you override
304    * {@link #entrySet}, you may wish to override {@link #toString} to forward to this
305    * implementation.
306    *
307    * @since 7.0
308    */
309   @Override
standardToString()310   protected String standardToString() {
311     return entrySet().toString();
312   }
313 }
314