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}