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.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 * Creates 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 * Creates 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 * </p> 078 * 079 * @param <E> The type of the elements in the collection. 080 * @param collection The {@code BoundedCollection} to decorate, must not be null. 081 * @return A new unmodifiable bounded collection. 082 * @throws NullPointerException if coll is null. 083 * @throws IllegalArgumentException if coll is not a {@code BoundedCollection}. 084 * @since 4.0 085 */ 086 @SuppressWarnings("unchecked") 087 public static <E> BoundedCollection<E> unmodifiableBoundedCollection(Collection<? extends E> collection) { 088 Objects.requireNonNull(collection, "collection"); 089 090 // handle decorators 091 for (int i = 0; i < 1000; i++) { // counter to prevent infinite looping 092 if (collection instanceof BoundedCollection) { 093 break; // normal loop exit 094 } 095 if (collection instanceof AbstractCollectionDecorator) { 096 collection = ((AbstractCollectionDecorator<E>) collection).decorated(); 097 } else if (collection instanceof SynchronizedCollection) { 098 collection = ((SynchronizedCollection<E>) collection).decorated(); 099 } 100 } 101 102 if (!(collection instanceof BoundedCollection)) { 103 throw new IllegalArgumentException("Collection is not a bounded collection."); 104 } 105 return new UnmodifiableBoundedCollection<>((BoundedCollection<E>) collection); 106 } 107 108 /** 109 * Constructs and wraps (not copies). 110 * 111 * @param coll The collection to decorate, must not be null. 112 * @throws NullPointerException if coll is null. 113 */ 114 @SuppressWarnings("unchecked") // safe to upcast 115 private UnmodifiableBoundedCollection(final BoundedCollection<? extends E> coll) { 116 super((BoundedCollection<E>) coll); 117 } 118 119 /** 120 * Always throws {@link UnsupportedOperationException}. 121 * 122 * @param object Ignored. 123 * @throws UnsupportedOperationException Always thrown. 124 */ 125 @Override 126 public boolean add(final E object) { 127 throw new UnsupportedOperationException(); 128 } 129 130 /** 131 * Always throws {@link UnsupportedOperationException}. 132 * 133 * @param coll Ignored. 134 * @throws UnsupportedOperationException Always thrown. 135 */ 136 @Override 137 public boolean addAll(final Collection<? extends E> coll) { 138 throw new UnsupportedOperationException(); 139 } 140 141 /** 142 * Always throws {@link UnsupportedOperationException}. 143 * 144 * @throws UnsupportedOperationException Always thrown. 145 */ 146 @Override 147 public void clear() { 148 throw new UnsupportedOperationException(); 149 } 150 151 @Override 152 protected BoundedCollection<E> decorated() { 153 return (BoundedCollection<E>) super.decorated(); 154 } 155 156 @Override 157 public boolean isFull() { 158 return decorated().isFull(); 159 } 160 161 @Override 162 public Iterator<E> iterator() { 163 return UnmodifiableIterator.unmodifiableIterator(decorated().iterator()); 164 } 165 166 @Override 167 public int maxSize() { 168 return decorated().maxSize(); 169 } 170 171 /** 172 * Always throws {@link UnsupportedOperationException}. 173 * 174 * @param object Ignored. 175 * @throws UnsupportedOperationException Always thrown. 176 */ 177 @Override 178 public boolean remove(final Object object) { 179 throw new UnsupportedOperationException(); 180 } 181 182 /** 183 * Always throws {@link UnsupportedOperationException}. 184 * 185 * @param coll Ignored. 186 * @throws UnsupportedOperationException Always thrown. 187 */ 188 @Override 189 public boolean removeAll(final Collection<?> coll) { 190 throw new UnsupportedOperationException(); 191 } 192 193 /** 194 * Always throws {@link UnsupportedOperationException}. 195 * 196 * @param filter Ignored. 197 * @throws UnsupportedOperationException Always thrown. 198 * @since 4.4 199 */ 200 @Override 201 public boolean removeIf(final Predicate<? super E> filter) { 202 throw new UnsupportedOperationException(); 203 } 204 205 /** 206 * Always throws {@link UnsupportedOperationException}. 207 * 208 * @param Ignored. 209 * @throws UnsupportedOperationException Always thrown. 210 */ 211 @Override 212 public boolean retainAll(final Collection<?> coll) { 213 throw new UnsupportedOperationException(); 214 } 215}