1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.collections4.collection;
18
19 import java.util.Collection;
20 import java.util.Iterator;
21 import java.util.Objects;
22 import java.util.function.Predicate;
23
24 import org.apache.commons.collections4.BoundedCollection;
25 import org.apache.commons.collections4.Unmodifiable;
26 import org.apache.commons.collections4.iterators.UnmodifiableIterator;
27
28 /**
29 * {@link UnmodifiableBoundedCollection} decorates another
30 * {@link BoundedCollection} to ensure it can't be altered.
31 * <p>
32 * If a BoundedCollection is first wrapped in some other collection decorator,
33 * such as synchronized or predicated, the BoundedCollection methods are no
34 * longer accessible.
35 * The factory on this class will attempt to retrieve the bounded nature by
36 * examining the package scope variables.
37 * </p>
38 * <p>
39 * This class is Serializable from Commons Collections 3.1.
40 * </p>
41 * <p>
42 * Attempts to modify it will result in an UnsupportedOperationException.
43 * </p>
44 *
45 * @param <E> The type of elements in this collection.
46 * @since 3.0
47 */
48 public final class UnmodifiableBoundedCollection<E> extends AbstractCollectionDecorator<E>
49 implements BoundedCollection<E>, Unmodifiable {
50
51 /** Serialization version */
52 private static final long serialVersionUID = -7112672385450340330L;
53
54 /**
55 * Creates an unmodifiable bounded collection.
56 *
57 * @param <E> The type of the elements in the collection.
58 * @param coll The {@code BoundedCollection} to decorate, must not be null.
59 * @return A new unmodifiable bounded collection.
60 * @throws NullPointerException if {@code coll} is {@code null}.
61 * @since 4.0
62 */
63 public static <E> BoundedCollection<E> unmodifiableBoundedCollection(final BoundedCollection<? extends E> coll) {
64 if (coll instanceof Unmodifiable) {
65 @SuppressWarnings("unchecked") // safe to upcast
66 final BoundedCollection<E> tmpColl = (BoundedCollection<E>) coll;
67 return tmpColl;
68 }
69 return new UnmodifiableBoundedCollection<>(coll);
70 }
71
72 /**
73 * Creates an unmodifiable bounded collection.
74 * <p>
75 * This method is capable of drilling down through up to 1000 other decorators
76 * to find a suitable BoundedCollection.
77 * </p>
78 *
79 * @param <E> The type of the elements in the collection.
80 * @param collection The {@code BoundedCollection} to decorate, must not be null.
81 * @return A new unmodifiable bounded collection.
82 * @throws NullPointerException if coll is null.
83 * @throws IllegalArgumentException if coll is not a {@code BoundedCollection}.
84 * @since 4.0
85 */
86 @SuppressWarnings("unchecked")
87 public static <E> BoundedCollection<E> unmodifiableBoundedCollection(Collection<? extends E> collection) {
88 Objects.requireNonNull(collection, "collection");
89
90 // handle decorators
91 for (int i = 0; i < 1000; i++) { // counter to prevent infinite looping
92 if (collection instanceof BoundedCollection) {
93 break; // normal loop exit
94 }
95 if (collection instanceof AbstractCollectionDecorator) {
96 collection = ((AbstractCollectionDecorator<E>) collection).decorated();
97 } else if (collection instanceof SynchronizedCollection) {
98 collection = ((SynchronizedCollection<E>) collection).decorated();
99 }
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 }