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 * <strong>NOTE:</strong> this method should only be used during deserialization
157 *
158 * @param collection the decorated collection
159 */
160 protected void setCollection(final Collection<E> collection) {
161 this.collection = collection;
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 }