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}