    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 *      http://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.util.Collection;
    020import java.util.Iterator;
    021import java.util.Objects;
    022import java.util.function.Predicate;
    023
    024import org.apache.commons.collections4.BoundedCollection;
    025import org.apache.commons.collections4.Unmodifiable;
    026import org.apache.commons.collections4.iterators.UnmodifiableIterator;
    027
    028/**
    029 * {@link UnmodifiableBoundedCollection} decorates another
    030 * {@link BoundedCollection} to ensure it can't be altered.
    031 * <p>
    032 * If a BoundedCollection is first wrapped in some other collection decorator,
    033 * such as synchronized or predicated, the BoundedCollection methods are no
    034 * longer accessible.
    035 * The factory on this class will attempt to retrieve the bounded nature by
    036 * examining the package scope variables.
    037 * </p>
    038 * <p>
    039 * This class is Serializable from Commons Collections 3.1.
    040 * </p>
    041 * <p>
    042 * Attempts to modify it will result in an UnsupportedOperationException.
    043 * </p>
    044 *
    045 * @param <E> the type of elements in this collection
    046 * @since 3.0
    047 */
    048public final class UnmodifiableBoundedCollection<E> extends AbstractCollectionDecorator<E>
    049        implements BoundedCollection<E>, Unmodifiable {
    050
    051    /** Serialization version */
    052    private static final long serialVersionUID = -7112672385450340330L;
    053
    054    /**
    055     * Factory method to create an unmodifiable bounded collection.
    056     *
    057     * @param <E> the type of the elements in the collection
    058     * @param coll  the {@code BoundedCollection} to decorate, must not be null
    059     * @return a new unmodifiable bounded collection
    060     * @throws NullPointerException if {@code coll} is {@code null}
    061     * @since 4.0
    062     */
    063    public static <E> BoundedCollection<E> unmodifiableBoundedCollection(final BoundedCollection<? extends E> coll) {
    064        if (coll instanceof Unmodifiable) {
    065            @SuppressWarnings("unchecked") // safe to upcast
    066            final BoundedCollection<E> tmpColl = (BoundedCollection<E>) coll;
    067            return tmpColl;
    068        }
    069        return new UnmodifiableBoundedCollection<>(coll);
    070    }
    071
    072    /**
    073     * Factory method to create an unmodifiable bounded collection.
    074     * <p>
    075     * This method is capable of drilling down through up to 1000 other decorators
    076     * to find a suitable BoundedCollection.
    077     *
    078     * @param <E> the type of the elements in the collection
    079     * @param collection  the {@code BoundedCollection} to decorate, must not be null
    080     * @return a new unmodifiable bounded collection
    081     * @throws NullPointerException if coll is null
    082     * @throws IllegalArgumentException if coll is not a {@code BoundedCollection}
    083     * @since 4.0
    084     */
    085    @SuppressWarnings("unchecked")
    086    public static <E> BoundedCollection<E> unmodifiableBoundedCollection(Collection<? extends E> collection) {
    087        Objects.requireNonNull(collection, "collection");
    088
    089        // handle decorators
    090        for (int i = 0; i < 1000; i++) {  // counter to prevent infinite looping
    091            if (collection instanceof BoundedCollection) {
    092                break;  // normal loop exit
    093            }
    094            if (collection instanceof AbstractCollectionDecorator) {
    095                collection = ((AbstractCollectionDecorator<E>) collection).decorated();
    096            } else if (collection instanceof SynchronizedCollection) {
    097                collection = ((SynchronizedCollection<E>) collection).decorated();
    098            }
    099        }
    100
    101        if (!(collection instanceof BoundedCollection)) {
    102            throw new IllegalArgumentException("Collection is not a bounded collection.");
    103        }
    104        return new UnmodifiableBoundedCollection<>((BoundedCollection<E>) collection);
    105    }
    106
    107    /**
    108     * Constructor that wraps (not copies).
    109     *
    110     * @param coll  the collection to decorate, must not be null
    111     * @throws NullPointerException if coll is null
    112     */
    113    @SuppressWarnings("unchecked") // safe to upcast
    114    private UnmodifiableBoundedCollection(final BoundedCollection<? extends E> coll) {
    115        super((BoundedCollection<E>) coll);
    116    }
    117
    118    @Override
    119    public boolean add(final E object) {
    120        throw new UnsupportedOperationException();
    121    }
    122
    123    @Override
    124    public boolean addAll(final Collection<? extends E> coll) {
    125        throw new UnsupportedOperationException();
    126    }
    127
    128    @Override
    129    public void clear() {
    130        throw new UnsupportedOperationException();
    131    }
    132
    133    @Override
    134    protected BoundedCollection<E> decorated() {
    135        return (BoundedCollection<E>) super.decorated();
    136    }
    137
    138    @Override
    139    public boolean isFull() {
    140        return decorated().isFull();
    141    }
    142
    143    @Override
    144    public Iterator<E> iterator() {
    145        return UnmodifiableIterator.unmodifiableIterator(decorated().iterator());
    146    }
    147
    148    @Override
    149    public int maxSize() {
    150        return decorated().maxSize();
    151    }
    152
    153    @Override
    154    public boolean remove(final Object object) {
    155        throw new UnsupportedOperationException();
    156    }
    157
    158    @Override
    159    public boolean removeAll(final Collection<?> coll) {
    160        throw new UnsupportedOperationException();
    161    }
    162
    163    /**
    164     * @since 4.4
    165     */
    166    @Override
    167    public boolean removeIf(final Predicate<? super E> filter) {
    168        throw new UnsupportedOperationException();
    169    }
    170
    171    @Override
    172    public boolean retainAll(final Collection<?> coll) {
    173        throw new UnsupportedOperationException();
    174    }
    175}