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    *      http://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       * @since 3.1
71       */
72      protected AbstractCollectionDecorator() {
73      }
74  
75      /**
76       * Constructor that wraps (not copies).
77       *
78       * @param collection  the collection to decorate, must not be null
79       * @throws NullPointerException if the collection is null
80       */
81      protected AbstractCollectionDecorator(final Collection<E> collection) {
82          this.collection = Objects.requireNonNull(collection, "collection");
83      }
84  
85      @Override
86      public boolean add(final E object) {
87          return decorated().add(object);
88      }
89  
90      @Override
91      public boolean addAll(final Collection<? extends E> coll) {
92          return decorated().addAll(coll);
93      }
94  
95      @Override
96      public void clear() {
97          decorated().clear();
98      }
99  
100     @Override
101     public boolean contains(final Object object) {
102         return decorated().contains(object);
103     }
104 
105     @Override
106     public boolean containsAll(final Collection<?> coll) {
107         return decorated().containsAll(coll);
108     }
109 
110     /**
111      * Gets the collection being decorated.
112      * All access to the decorated collection goes via this method.
113      *
114      * @return the decorated collection
115      */
116     protected Collection<E> decorated() {
117         return collection;
118     }
119 
120     @Override
121     public boolean isEmpty() {
122         return decorated().isEmpty();
123     }
124 
125     @Override
126     public Iterator<E> iterator() {
127         return decorated().iterator();
128     }
129 
130     @Override
131     public boolean remove(final Object object) {
132         return decorated().remove(object);
133     }
134 
135     @Override
136     public boolean removeAll(final Collection<?> coll) {
137         return decorated().removeAll(coll);
138     }
139 
140     /**
141      * @since 4.4
142      */
143     @Override
144     public boolean removeIf(final Predicate<? super E> filter) {
145         return decorated().removeIf(filter);
146     }
147 
148     @Override
149     public boolean retainAll(final Collection<?> coll) {
150         return decorated().retainAll(coll);
151     }
152 
153     /**
154      * Sets the collection being decorated.
155      * <p>
156      * <b>NOTE:</b> this method should only be used during deserialization
157      *
158      * @param coll  the decorated collection
159      */
160     protected void setCollection(final Collection<E> coll) {
161         this.collection = coll;
162     }
163 
164     @Override
165     public int size() {
166         return decorated().size();
167     }
168 
169     @Override
170     public Object[] toArray() {
171         return decorated().toArray();
172     }
173 
174     @Override
175     public <T> T[] toArray(final T[] object) {
176         return decorated().toArray(object);
177     }
178 
179     @Override
180     public String toString() {
181         return decorated().toString();
182     }
183 
184 }