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 Object[] newArray = new Object[size()];
056 return toArray(newArray);
057 }
058
059 public <T> T[] toArray(T[] other) {
060 int size = size();
061 if (other.length < size) {
062 other = ObjectArrays.newArray(other, size);
063 } else if (other.length > size) {
064 other[size] = null;
065 }
066
067 // Writes will produce ArrayStoreException when the toArray() doc requires.
068 Object[] otherAsObjectArray = other;
069 int index = 0;
070 for (E element : this) {
071 otherAsObjectArray[index++] = element;
072 }
073 return other;
074 }
075
076 public boolean contains(@Nullable Object object) {
077 if (object == null) {
078 return false;
079 }
080 for (E element : this) {
081 if (element.equals(object)) {
082 return true;
083 }
084 }
085 return false;
086 }
087
088 public boolean containsAll(Collection<?> targets) {
089 for (Object target : targets) {
090 if (!contains(target)) {
091 return false;
092 }
093 }
094 return true;
095 }
096
097 public boolean isEmpty() {
098 return size() == 0;
099 }
100
101 @Override public String toString() {
102 StringBuilder sb = new StringBuilder(size() * 16).append('[');
103 Collections2.standardJoiner.appendTo(sb, this);
104 return sb.append(']').toString();
105 }
106
107 /**
108 * Guaranteed to throw an exception and leave the collection unmodified.
109 *
110 * @throws UnsupportedOperationException always
111 */
112 public final boolean add(E e) {
113 throw new UnsupportedOperationException();
114 }
115
116 /**
117 * Guaranteed to throw an exception and leave the collection unmodified.
118 *
119 * @throws UnsupportedOperationException always
120 */
121 public final boolean remove(Object object) {
122 throw new UnsupportedOperationException();
123 }
124
125 /**
126 * Guaranteed to throw an exception and leave the collection unmodified.
127 *
128 * @throws UnsupportedOperationException always
129 */
130 public final boolean addAll(Collection<? extends E> newElements) {
131 throw new UnsupportedOperationException();
132 }
133
134 /**
135 * Guaranteed to throw an exception and leave the collection unmodified.
136 *
137 * @throws UnsupportedOperationException always
138 */
139 public final boolean removeAll(Collection<?> oldElements) {
140 throw new UnsupportedOperationException();
141 }
142
143 /**
144 * Guaranteed to throw an exception and leave the collection unmodified.
145 *
146 * @throws UnsupportedOperationException always
147 */
148 public final boolean retainAll(Collection<?> elementsToKeep) {
149 throw new UnsupportedOperationException();
150 }
151
152 /**
153 * Guaranteed to throw an exception and leave the collection unmodified.
154 *
155 * @throws UnsupportedOperationException always
156 */
157 public final void clear() {
158 throw new UnsupportedOperationException();
159 }
160
161 // TODO: Restructure code so ImmutableList doesn't contain this variable,
162 // which it doesn't use.
163 private transient ImmutableList<E> asList;
164
165 /**
166 * Returns a list view of the collection.
167 *
168 * @since 2
169 */
170 @GwtCompatible(serializable = false)
171 public ImmutableList<E> asList() {
172 ImmutableList<E> list = asList;
173 return (list == null) ? (asList = createAsList()) : list;
174 }
175
176 ImmutableList<E> createAsList() {
177 switch (size()) {
178 case 0:
179 return ImmutableList.of();
180 case 1:
181 return ImmutableList.of(iterator().next());
182 default:
183 return new ImmutableAsList<E>(toArray(), this);
184 }
185 }
186
187 private static class EmptyImmutableCollection
188 extends ImmutableCollection<Object> {
189 public int size() {
190 return 0;
191 }
192
193 @Override public boolean isEmpty() {
194 return true;
195 }
196
197 @Override public boolean contains(@Nullable Object object) {
198 return false;
199 }
200
201 @Override public UnmodifiableIterator<Object> iterator() {
202 return Iterators.EMPTY_ITERATOR;
203 }
204
205 private static final Object[] EMPTY_ARRAY = new Object[0];
206
207 @Override public Object[] toArray() {
208 return EMPTY_ARRAY;
209 }
210
211 @Override public <T> T[] toArray(T[] array) {
212 if (array.length > 0) {
213 array[0] = null;
214 }
215 return array;
216 }
217 }
218
219 private static class ArrayImmutableCollection<E>
220 extends ImmutableCollection<E> {
221 private final E[] elements;
222
223 ArrayImmutableCollection(E[] elements) {
224 this.elements = elements;
225 }
226
227 public int size() {
228 return elements.length;
229 }
230
231 @Override public boolean isEmpty() {
232 return false;
233 }
234
235 @Override public UnmodifiableIterator<E> iterator() {
236 return Iterators.forArray(elements);
237 }
238 }
239
240 /*
241 * Serializes ImmutableCollections as their logical contents. This ensures
242 * that implementation types do not leak into the serialized representation.
243 */
244 private static class SerializedForm implements Serializable {
245 final Object[] elements;
246 SerializedForm(Object[] elements) {
247 this.elements = elements;
248 }
249 Object readResolve() {
250 return elements.length == 0
251 ? EMPTY_IMMUTABLE_COLLECTION
252 : new ArrayImmutableCollection<Object>(Platform.clone(elements));
253 }
254 private static final long serialVersionUID = 0;
255 }
256
257 Object writeReplace() {
258 return new SerializedForm(toArray());
259 }
260
261 /**
262 * Abstract base class for builders of {@link ImmutableCollection} types.
263 */
264 abstract static class Builder<E> {
265 /**
266 * Adds {@code element} to the {@code ImmutableCollection} being built.
267 *
268 * <p>Note that each builder class covariantly returns its own type from
269 * this method.
270 *
271 * @param element the element to add
272 * @return this {@code Builder} instance
273 * @throws NullPointerException if {@code element} is null
274 */
275 public abstract Builder<E> add(E element);
276
277 /**
278 * Adds each element of {@code elements} to the {@code ImmutableCollection}
279 * being built.
280 *
281 * <p>Note that each builder class overrides this method in order to
282 * covariantly return its own type.
283 *
284 * @param elements the elements to add
285 * @return this {@code Builder} instance
286 * @throws NullPointerException if {@code elements} is null or contains a
287 * null element
288 */
289 public Builder<E> add(E... elements) {
290 for (E element : elements) {
291 add(element);
292 }
293 return this;
294 }
295
296 /**
297 * Adds each element of {@code elements} to the {@code ImmutableCollection}
298 * being built.
299 *
300 * <p>Note that each builder class overrides this method in order to
301 * covariantly return its own type.
302 *
303 * @param elements the elements to add
304 * @return this {@code Builder} instance
305 * @throws NullPointerException if {@code elements} is null or contains a
306 * null element
307 */
308 public Builder<E> addAll(Iterable<? extends E> elements) {
309 for (E element : elements) {
310 add(element);
311 }
312 return this;
313 }
314
315 /**
316 * Adds each element of {@code elements} to the {@code ImmutableCollection}
317 * being built.
318 *
319 * <p>Note that each builder class overrides this method in order to
320 * covariantly return its own type.
321 *
322 * @param elements the elements to add
323 * @return this {@code Builder} instance
324 * @throws NullPointerException if {@code elements} is null or contains a
325 * null element
326 */
327 public Builder<E> addAll(Iterator<? extends E> elements) {
328 while (elements.hasNext()) {
329 add(elements.next());
330 }
331 return this;
332 }
333
334 /**
335 * Returns a newly-created {@code ImmutableCollection} of the appropriate
336 * type, containing the elements provided to this builder.
337 *
338 * <p>Note that each builder class covariantly returns the appropriate type
339 * of {@code ImmutableCollection} from this method.
340 */
341 public abstract ImmutableCollection<E> build();
342 }
343 }