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