001 /*
002 * Copyright (C) 2008 Google Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package com.google.common.collect;
018
019 import com.google.common.annotations.GwtCompatible;
020
021 import java.io.Serializable;
022 import java.util.Collection;
023 import java.util.Iterator;
024
025 import javax.annotation.Nullable;
026
027 /**
028 * An immutable collection. Does not permit null elements.
029 *
030 * <p>In addition to the {@link Collection} methods, this class has an {@link
031 * #asList()} method, which returns a list view of the collection's elements.
032 *
033 * <p><b>Note</b>: Although this class is not final, it cannot be subclassed
034 * outside of this package as it has no public or protected constructors. Thus,
035 * instances of this type are guaranteed to be immutable.
036 *
037 * @author Jesse Wilson
038 * @since 2 (imported from Google Collections Library)
039 */
040 @GwtCompatible(emulated = true)
041 @SuppressWarnings("serial") // we're overriding default serialization
042 public abstract class ImmutableCollection<E>
043 implements Collection<E>, Serializable {
044 static final ImmutableCollection<Object> EMPTY_IMMUTABLE_COLLECTION
045 = new EmptyImmutableCollection();
046
047 ImmutableCollection() {}
048
049 /**
050 * Returns an unmodifiable iterator across the elements in this collection.
051 */
052 public abstract UnmodifiableIterator<E> iterator();
053
054 public Object[] toArray() {
055 return ObjectArrays.toArrayImpl(this);
056 }
057
058 public <T> T[] toArray(T[] other) {
059 return ObjectArrays.toArrayImpl(this, other);
060 }
061
062 public boolean contains(@Nullable Object object) {
063 return object != null && Iterators.contains(iterator(), object);
064 }
065
066 public boolean containsAll(Collection<?> targets) {
067 return Collections2.containsAllImpl(this, targets);
068 }
069
070 public boolean isEmpty() {
071 return size() == 0;
072 }
073
074 @Override public String toString() {
075 return Collections2.toStringImpl(this);
076 }
077
078 /**
079 * Guaranteed to throw an exception and leave the collection unmodified.
080 *
081 * @throws UnsupportedOperationException always
082 */
083 public final boolean add(E e) {
084 throw new UnsupportedOperationException();
085 }
086
087 /**
088 * Guaranteed to throw an exception and leave the collection unmodified.
089 *
090 * @throws UnsupportedOperationException always
091 */
092 public final boolean remove(Object object) {
093 throw new UnsupportedOperationException();
094 }
095
096 /**
097 * Guaranteed to throw an exception and leave the collection unmodified.
098 *
099 * @throws UnsupportedOperationException always
100 */
101 public final boolean addAll(Collection<? extends E> newElements) {
102 throw new UnsupportedOperationException();
103 }
104
105 /**
106 * Guaranteed to throw an exception and leave the collection unmodified.
107 *
108 * @throws UnsupportedOperationException always
109 */
110 public final boolean removeAll(Collection<?> oldElements) {
111 throw new UnsupportedOperationException();
112 }
113
114 /**
115 * Guaranteed to throw an exception and leave the collection unmodified.
116 *
117 * @throws UnsupportedOperationException always
118 */
119 public final boolean retainAll(Collection<?> elementsToKeep) {
120 throw new UnsupportedOperationException();
121 }
122
123 /**
124 * Guaranteed to throw an exception and leave the collection unmodified.
125 *
126 * @throws UnsupportedOperationException always
127 */
128 public final void clear() {
129 throw new UnsupportedOperationException();
130 }
131
132 /*
133 * TODO(kevinb): Restructure code so ImmutableList doesn't contain this
134 * variable, which it doesn't use.
135 */
136 private transient ImmutableList<E> asList;
137
138 /**
139 * Returns a list view of the collection.
140 *
141 * @since 2
142 */
143 public ImmutableList<E> asList() {
144 ImmutableList<E> list = asList;
145 return (list == null) ? (asList = createAsList()) : list;
146 }
147
148 ImmutableList<E> createAsList() {
149 switch (size()) {
150 case 0:
151 return ImmutableList.of();
152 case 1:
153 return ImmutableList.of(iterator().next());
154 default:
155 return new ImmutableAsList<E>(toArray(), this);
156 }
157 }
158
159 abstract boolean isPartialView();
160
161 private static class EmptyImmutableCollection
162 extends ImmutableCollection<Object> {
163 public int size() {
164 return 0;
165 }
166
167 @Override public boolean isEmpty() {
168 return true;
169 }
170
171 @Override public boolean contains(@Nullable Object object) {
172 return false;
173 }
174
175 @Override public UnmodifiableIterator<Object> iterator() {
176 return Iterators.EMPTY_ITERATOR;
177 }
178
179 private static final Object[] EMPTY_ARRAY = new Object[0];
180
181 @Override public Object[] toArray() {
182 return EMPTY_ARRAY;
183 }
184
185 @Override public <T> T[] toArray(T[] array) {
186 if (array.length > 0) {
187 array[0] = null;
188 }
189 return array;
190 }
191
192 @Override ImmutableList<Object> createAsList() {
193 return ImmutableList.of();
194 }
195
196 @Override boolean isPartialView() {
197 return false;
198 }
199 }
200
201 /**
202 * Nonempty collection stored in an array.
203 */
204 private static class ArrayImmutableCollection<E>
205 extends ImmutableCollection<E> {
206 private final E[] elements;
207
208 ArrayImmutableCollection(E[] elements) {
209 this.elements = elements;
210 }
211
212 public int size() {
213 return elements.length;
214 }
215
216 @Override public boolean isEmpty() {
217 return false;
218 }
219
220 @Override public UnmodifiableIterator<E> iterator() {
221 return Iterators.forArray(elements);
222 }
223
224 @Override ImmutableList<E> createAsList() {
225 return elements.length == 1 ? new SingletonImmutableList<E>(elements[0])
226 : new RegularImmutableList<E>(elements);
227 }
228
229 @Override boolean isPartialView() {
230 return false;
231 }
232 }
233
234 /*
235 * Serializes ImmutableCollections as their logical contents. This ensures
236 * that implementation types do not leak into the serialized representation.
237 */
238 private static class SerializedForm implements Serializable {
239 final Object[] elements;
240 SerializedForm(Object[] elements) {
241 this.elements = elements;
242 }
243 Object readResolve() {
244 return elements.length == 0
245 ? EMPTY_IMMUTABLE_COLLECTION
246 : new ArrayImmutableCollection<Object>(Platform.clone(elements));
247 }
248 private static final long serialVersionUID = 0;
249 }
250
251 Object writeReplace() {
252 return new SerializedForm(toArray());
253 }
254
255 /**
256 * Abstract base class for builders of {@link ImmutableCollection} types.
257 */
258 abstract static class Builder<E> {
259 /**
260 * Adds {@code element} to the {@code ImmutableCollection} being built.
261 *
262 * <p>Note that each builder class covariantly returns its own type from
263 * this method.
264 *
265 * @param element the element to add
266 * @return this {@code Builder} instance
267 * @throws NullPointerException if {@code element} is null
268 */
269 public abstract Builder<E> add(E element);
270
271 /**
272 * Adds each element of {@code elements} to the {@code ImmutableCollection}
273 * being built.
274 *
275 * <p>Note that each builder class overrides this method in order to
276 * covariantly return its own type.
277 *
278 * @param elements the elements to add
279 * @return this {@code Builder} instance
280 * @throws NullPointerException if {@code elements} is null or contains a
281 * null element
282 */
283 public Builder<E> add(E... elements) {
284 for (E element : elements) {
285 add(element);
286 }
287 return this;
288 }
289
290 /**
291 * Adds each element of {@code elements} to the {@code ImmutableCollection}
292 * being built.
293 *
294 * <p>Note that each builder class overrides this method in order to
295 * covariantly return its own type.
296 *
297 * @param elements the elements to add
298 * @return this {@code Builder} instance
299 * @throws NullPointerException if {@code elements} is null or contains a
300 * null element
301 */
302 public Builder<E> addAll(Iterable<? extends E> elements) {
303 for (E element : elements) {
304 add(element);
305 }
306 return this;
307 }
308
309 /**
310 * Adds each element of {@code elements} to the {@code ImmutableCollection}
311 * being built.
312 *
313 * <p>Note that each builder class overrides this method in order to
314 * covariantly return its own type.
315 *
316 * @param elements the elements to add
317 * @return this {@code Builder} instance
318 * @throws NullPointerException if {@code elements} is null or contains a
319 * null element
320 */
321 public Builder<E> addAll(Iterator<? extends E> elements) {
322 while (elements.hasNext()) {
323 add(elements.next());
324 }
325 return this;
326 }
327
328 /**
329 * Returns a newly-created {@code ImmutableCollection} of the appropriate
330 * type, containing the elements provided to this builder.
331 *
332 * <p>Note that each builder class covariantly returns the appropriate type
333 * of {@code ImmutableCollection} from this method.
334 */
335 public abstract ImmutableCollection<E> build();
336 }
337 }