View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4.collection;
18  
19  import java.io.Serializable;
20  import java.util.Collection;
21  import java.util.Iterator;
22  import java.util.Objects;
23  import java.util.function.Predicate;
24  
25  /**
26   * Decorates another {@code Collection} to provide additional behavior.
27   * <p>
28   * Each method call made on this {@code Collection} is forwarded to the
29   * decorated {@code Collection}. This class is used as a framework on which
30   * to build to extensions such as synchronized and unmodifiable behavior. The
31   * main advantage of decoration is that one decorator can wrap any implementation
32   * of {@code Collection}, whereas sub-classing requires a new class to be
33   * written for each implementation.
34   * </p>
35   * <p>
36   * This implementation does not perform any special processing with
37   * {@link #iterator()}. Instead it simply returns the value from the
38   * wrapped collection. This may be undesirable, for example if you are trying
39   * to write an unmodifiable implementation it might provide a loophole.
40   * </p>
41   * <p>
42   * This implementation does not forward the hashCode and equals methods through
43   * to the backing object, but relies on Object's implementation. This is necessary
44   * to preserve the symmetry of equals. Custom definitions of equality are usually
45   * based on an interface, such as Set or List, so that the implementation of equals
46   * can cast the object being tested for equality to the custom interface.
47   * AbstractCollectionDecorator does not implement such custom interfaces directly;
48   * they are implemented only in subclasses. Therefore, forwarding equals would break
49   * symmetry, as the forwarding object might consider itself equal to the object being
50   * tested, but the reverse could not be true. This behavior is consistent with the
51   * JDK's collection wrappers, such as {@link java.util.Collections#unmodifiableCollection(Collection)}.
52   * Use an interface-specific subclass of AbstractCollectionDecorator, such as
53   * AbstractListDecorator, to preserve equality behavior, or override equals directly.
54   * </p>
55   *
56   * @param <E> The type of the elements in the collection.
57   * @since 3.0
58   */
59  public abstract class AbstractCollectionDecorator<E>
60          implements Collection<E>, Serializable {
61  
62      /** Serialization version */
63      private static final long serialVersionUID = 6249888059822088500L;
64  
65      /** The collection being decorated */
66      private Collection<E> collection;
67  
68      /**
69       * Constructor only used in deserialization, do not use otherwise.
70       *
71       * @since 3.1
72       */
73      protected AbstractCollectionDecorator() {
74      }
75  
76      /**
77       * Constructs and wraps (not copies).
78       *
79       * @param collection  The collection to decorate, must not be null.
80       * @throws NullPointerException if the collection is null.
81       */
82      protected AbstractCollectionDecorator(final Collection<E> collection) {
83          this.collection = Objects.requireNonNull(collection, "collection");
84      }
85  
86      @Override
87      public boolean add(final E object) {
88          return decorated().add(object);
89      }
90  
91      @Override
92      public boolean addAll(final Collection<? extends E> coll) {
93          return decorated().addAll(coll);
94      }
95  
96      @Override
97      public void clear() {
98          decorated().clear();
99      }
100 
101     @Override
102     public boolean contains(final Object object) {
103         return decorated().contains(object);
104     }
105 
106     @Override
107     public boolean containsAll(final Collection<?> coll) {
108         return decorated().containsAll(coll);
109     }
110 
111     /**
112      * Gets the collection being decorated.
113      * All access to the decorated collection goes via this method.
114      *
115      * @return The decorated collection.
116      */
117     protected Collection<E> decorated() {
118         return collection;
119     }
120 
121     @Override
122     public boolean isEmpty() {
123         return decorated().isEmpty();
124     }
125 
126     @Override
127     public Iterator<E> iterator() {
128         return decorated().iterator();
129     }
130 
131     @Override
132     public boolean remove(final Object object) {
133         return decorated().remove(object);
134     }
135 
136     @Override
137     public boolean removeAll(final Collection<?> coll) {
138         return decorated().removeAll(coll);
139     }
140 
141     /**
142      * @since 4.4
143      */
144     @Override
145     public boolean removeIf(final Predicate<? super E> filter) {
146         return decorated().removeIf(filter);
147     }
148 
149     @Override
150     public boolean retainAll(final Collection<?> coll) {
151         return decorated().retainAll(coll);
152     }
153 
154     /**
155      * Sets the collection being decorated.
156      * <p>
157      * <strong>NOTE:</strong> this method should only be used during deserialization.
158      * </p>
159      *
160      * @param collection  The decorated collection.
161      */
162     protected void setCollection(final Collection<E> collection) {
163         this.collection = collection;
164     }
165 
166     @Override
167     public int size() {
168         return decorated().size();
169     }
170 
171     @Override
172     public Object[] toArray() {
173         return decorated().toArray();
174     }
175 
176     @Override
177     public <T> T[] toArray(final T[] object) {
178         return decorated().toArray(object);
179     }
180 
181     @Override
182     public String toString() {
183         return decorated().toString();
184     }
185 
186 }