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.function.Predicate;
23  
24  /**
25   * Decorates another <code>Collection</code> to provide additional behaviour.
26   * <p>
27   * Each method call made on this <code>Collection</code> is forwarded to the
28   * decorated <code>Collection</code>. This class is used as a framework on which
29   * to build to extensions such as synchronized and unmodifiable behaviour. The
30   * main advantage of decoration is that one decorator can wrap any implementation
31   * of <code>Collection</code>, whereas sub-classing requires a new class to be
32   * written for each implementation.
33   * </p>
34   * <p>
35   * This implementation does not perform any special processing with
36   * {@link #iterator()}. Instead it simply returns the value from the
37   * wrapped collection. This may be undesirable, for example if you are trying
38   * to write an unmodifiable implementation it might provide a loophole.
39   * </p>
40   * <p>
41   * This implementation does not forward the hashCode and equals methods through
42   * to the backing object, but relies on Object's implementation. This is necessary
43   * to preserve the symmetry of equals. Custom definitions of equality are usually
44   * based on an interface, such as Set or List, so that the implementation of equals
45   * can cast the object being tested for equality to the custom interface.
46   * AbstractCollectionDecorator does not implement such custom interfaces directly;
47   * they are implemented only in subclasses. Therefore, forwarding equals would break
48   * symmetry, as the forwarding object might consider itself equal to the object being
49   * tested, but the reverse could not be true. This behavior is consistent with the
50   * JDK's collection wrappers, such as {@link java.util.Collections#unmodifiableCollection(Collection)}.
51   * Use an interface-specific subclass of AbstractCollectionDecorator, such as
52   * AbstractListDecorator, to preserve equality behavior, or override equals directly.
53   * </p>
54   *
55   * @param <E> the type of the elements in the collection
56   * @since 3.0
57   */
58  public abstract class AbstractCollectionDecorator<E>
59          implements Collection<E>, Serializable {
60  
61      /** Serialization version */
62      private static final long serialVersionUID = 6249888059822088500L;
63  
64      /** The collection being decorated */
65      private Collection<E> collection;
66  
67      /**
68       * Constructor only used in deserialization, do not use otherwise.
69       * @since 3.1
70       */
71      protected AbstractCollectionDecorator() {
72          super();
73      }
74  
75      /**
76       * Constructor that wraps (not copies).
77       *
78       * @param coll  the collection to decorate, must not be null
79       * @throws NullPointerException if the collection is null
80       */
81      protected AbstractCollectionDecorator(final Collection<E> coll) {
82          if (coll == null) {
83              throw new NullPointerException("Collection must not be null.");
84          }
85          this.collection = coll;
86      }
87  
88      /**
89       * Gets the collection being decorated.
90       * All access to the decorated collection goes via this method.
91       *
92       * @return the decorated collection
93       */
94      protected Collection<E> decorated() {
95          return collection;
96      }
97  
98      /**
99       * Sets the collection being decorated.
100      * <p>
101      * <b>NOTE:</b> this method should only be used during deserialization
102      *
103      * @param coll  the decorated collection
104      */
105     protected void setCollection(final Collection<E> coll) {
106         this.collection = coll;
107     }
108 
109     //-----------------------------------------------------------------------
110 
111     @Override
112     public boolean add(final E object) {
113         return decorated().add(object);
114     }
115 
116     @Override
117     public boolean addAll(final Collection<? extends E> coll) {
118         return decorated().addAll(coll);
119     }
120 
121     @Override
122     public void clear() {
123         decorated().clear();
124     }
125 
126     @Override
127     public boolean contains(final Object object) {
128         return decorated().contains(object);
129     }
130 
131     @Override
132     public boolean isEmpty() {
133         return decorated().isEmpty();
134     }
135 
136     @Override
137     public Iterator<E> iterator() {
138         return decorated().iterator();
139     }
140 
141     @Override
142     public boolean remove(final Object object) {
143         return decorated().remove(object);
144     }
145 
146     @Override
147     public int size() {
148         return decorated().size();
149     }
150 
151     @Override
152     public Object[] toArray() {
153         return decorated().toArray();
154     }
155 
156     @Override
157     public <T> T[] toArray(final T[] object) {
158         return decorated().toArray(object);
159     }
160 
161     @Override
162     public boolean containsAll(final Collection<?> coll) {
163         return decorated().containsAll(coll);
164     }
165 
166     /**
167      * @since 4.4
168      */
169     @Override
170     public boolean removeIf(final Predicate<? super E> filter) {
171         return decorated().removeIf(filter);
172     }
173 
174     @Override
175     public boolean removeAll(final Collection<?> coll) {
176         return decorated().removeAll(coll);
177     }
178 
179     @Override
180     public boolean retainAll(final Collection<?> coll) {
181         return decorated().retainAll(coll);
182     }
183 
184     @Override
185     public String toString() {
186         return decorated().toString();
187     }
188 
189 }