001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.collections4.collection;
018
019import java.io.Serializable;
020import java.util.Collection;
021import java.util.Iterator;
022import java.util.Objects;
023import java.util.function.Predicate;
024
025/**
026 * Decorates another {@code Collection} to provide additional behavior.
027 * <p>
028 * Each method call made on this {@code Collection} is forwarded to the
029 * decorated {@code Collection}. This class is used as a framework on which
030 * to build to extensions such as synchronized and unmodifiable behavior. The
031 * main advantage of decoration is that one decorator can wrap any implementation
032 * of {@code Collection}, whereas sub-classing requires a new class to be
033 * written for each implementation.
034 * </p>
035 * <p>
036 * This implementation does not perform any special processing with
037 * {@link #iterator()}. Instead it simply returns the value from the
038 * wrapped collection. This may be undesirable, for example if you are trying
039 * to write an unmodifiable implementation it might provide a loophole.
040 * </p>
041 * <p>
042 * This implementation does not forward the hashCode and equals methods through
043 * to the backing object, but relies on Object's implementation. This is necessary
044 * to preserve the symmetry of equals. Custom definitions of equality are usually
045 * based on an interface, such as Set or List, so that the implementation of equals
046 * can cast the object being tested for equality to the custom interface.
047 * AbstractCollectionDecorator does not implement such custom interfaces directly;
048 * they are implemented only in subclasses. Therefore, forwarding equals would break
049 * symmetry, as the forwarding object might consider itself equal to the object being
050 * tested, but the reverse could not be true. This behavior is consistent with the
051 * JDK's collection wrappers, such as {@link java.util.Collections#unmodifiableCollection(Collection)}.
052 * Use an interface-specific subclass of AbstractCollectionDecorator, such as
053 * AbstractListDecorator, to preserve equality behavior, or override equals directly.
054 * </p>
055 *
056 * @param <E> The type of the elements in the collection.
057 * @since 3.0
058 */
059public abstract class AbstractCollectionDecorator<E>
060        implements Collection<E>, Serializable {
061
062    /** Serialization version */
063    private static final long serialVersionUID = 6249888059822088500L;
064
065    /** The collection being decorated */
066    private Collection<E> collection;
067
068    /**
069     * Constructor only used in deserialization, do not use otherwise.
070     *
071     * @since 3.1
072     */
073    protected AbstractCollectionDecorator() {
074    }
075
076    /**
077     * Constructs and wraps (not copies).
078     *
079     * @param collection  The collection to decorate, must not be null.
080     * @throws NullPointerException if the collection is null.
081     */
082    protected AbstractCollectionDecorator(final Collection<E> collection) {
083        this.collection = Objects.requireNonNull(collection, "collection");
084    }
085
086    @Override
087    public boolean add(final E object) {
088        return decorated().add(object);
089    }
090
091    @Override
092    public boolean addAll(final Collection<? extends E> coll) {
093        return decorated().addAll(coll);
094    }
095
096    @Override
097    public void clear() {
098        decorated().clear();
099    }
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}