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 }