1/*
2 * Copyright (C) 2008 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.collect;
18
19import com.google.common.annotations.GwtCompatible;
20
21import java.io.Serializable;
22import java.util.Collection;
23import java.util.Iterator;
24
25import javax.annotation.Nullable;
26
27/**
28 * An immutable collection. Does not permit null elements.
29 *
30 * <p>In addition to the {@link Collection} methods, this class has an {@link
31 * #asList()} method, which returns a list view of the collection's elements.
32 *
33 * <p><b>Note:</b> Although this class is not final, it cannot be subclassed
34 * outside of this package as it has no public or protected constructors. Thus,
35 * instances of this type are guaranteed to be immutable.
36 *
37 * @author Jesse Wilson
38 * @since 2.0 (imported from Google Collections Library)
39 */
40@GwtCompatible(emulated = true)
41@SuppressWarnings("serial") // we're overriding default serialization
42public abstract class ImmutableCollection<E>
43    implements Collection<E>, Serializable {
44  static final ImmutableCollection<Object> EMPTY_IMMUTABLE_COLLECTION
45      = new EmptyImmutableCollection();
46
47  ImmutableCollection() {}
48
49  /**
50   * Returns an unmodifiable iterator across the elements in this collection.
51   */
52  @Override
53  public abstract UnmodifiableIterator<E> iterator();
54
55  @Override
56  public Object[] toArray() {
57    return ObjectArrays.toArrayImpl(this);
58  }
59
60  @Override
61  public <T> T[] toArray(T[] other) {
62    return ObjectArrays.toArrayImpl(this, other);
63  }
64
65  @Override
66  public boolean contains(@Nullable Object object) {
67    return object != null && Iterators.contains(iterator(), object);
68  }
69
70  @Override
71  public boolean containsAll(Collection<?> targets) {
72    return Collections2.containsAllImpl(this, targets);
73  }
74
75  @Override
76  public boolean isEmpty() {
77    return size() == 0;
78  }
79
80  @Override public String toString() {
81    return Collections2.toStringImpl(this);
82  }
83
84  /**
85   * Guaranteed to throw an exception and leave the collection unmodified.
86   *
87   * @throws UnsupportedOperationException always
88   */
89  @Override
90  public final boolean add(E e) {
91    throw new UnsupportedOperationException();
92  }
93
94  /**
95   * Guaranteed to throw an exception and leave the collection unmodified.
96   *
97   * @throws UnsupportedOperationException always
98   */
99  @Override
100  public final boolean remove(Object object) {
101    throw new UnsupportedOperationException();
102  }
103
104  /**
105   * Guaranteed to throw an exception and leave the collection unmodified.
106   *
107   * @throws UnsupportedOperationException always
108   */
109  @Override
110  public final boolean addAll(Collection<? extends E> newElements) {
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  @Override
120  public final boolean removeAll(Collection<?> oldElements) {
121    throw new UnsupportedOperationException();
122  }
123
124  /**
125   * Guaranteed to throw an exception and leave the collection unmodified.
126   *
127   * @throws UnsupportedOperationException always
128   */
129  @Override
130  public final boolean retainAll(Collection<?> elementsToKeep) {
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  @Override
140  public final void clear() {
141    throw new UnsupportedOperationException();
142  }
143
144  /*
145   * TODO(kevinb): Restructure code so ImmutableList doesn't contain this
146   * variable, which it doesn't use.
147   */
148  private transient ImmutableList<E> asList;
149
150  /**
151   * Returns a list view of the collection.
152   *
153   * @since 2.0
154   */
155  public ImmutableList<E> asList() {
156    ImmutableList<E> list = asList;
157    return (list == null) ? (asList = createAsList()) : list;
158  }
159
160  ImmutableList<E> createAsList() {
161    switch (size()) {
162      case 0:
163        return ImmutableList.of();
164      case 1:
165        return ImmutableList.of(iterator().next());
166      default:
167        return new ImmutableAsList<E>(toArray(), this);
168    }
169  }
170
171  abstract boolean isPartialView();
172
173  private static class EmptyImmutableCollection
174      extends ImmutableCollection<Object> {
175    @Override
176    public int size() {
177      return 0;
178    }
179
180    @Override public boolean isEmpty() {
181      return true;
182    }
183
184    @Override public boolean contains(@Nullable Object object) {
185      return false;
186    }
187
188    @Override public UnmodifiableIterator<Object> iterator() {
189      return Iterators.EMPTY_ITERATOR;
190    }
191
192    private static final Object[] EMPTY_ARRAY = new Object[0];
193
194    @Override public Object[] toArray() {
195      return EMPTY_ARRAY;
196    }
197
198    @Override public <T> T[] toArray(T[] array) {
199      if (array.length > 0) {
200        array[0] = null;
201      }
202      return array;
203    }
204
205    @Override ImmutableList<Object> createAsList() {
206      return ImmutableList.of();
207    }
208
209    @Override boolean isPartialView() {
210      return false;
211    }
212  }
213
214  /**
215   * Nonempty collection stored in an array.
216   */
217  private static class ArrayImmutableCollection<E>
218      extends ImmutableCollection<E> {
219    private final E[] elements;
220
221    ArrayImmutableCollection(E[] elements) {
222      this.elements = elements;
223    }
224
225    @Override
226    public int size() {
227      return elements.length;
228    }
229
230    @Override public boolean isEmpty() {
231      return false;
232    }
233
234    @Override public UnmodifiableIterator<E> iterator() {
235      return Iterators.forArray(elements);
236    }
237
238    @Override ImmutableList<E> createAsList() {
239      return elements.length == 1 ? new SingletonImmutableList<E>(elements[0])
240          : new RegularImmutableList<E>(elements);
241    }
242
243    @Override boolean isPartialView() {
244      return false;
245    }
246  }
247
248  /*
249   * Serializes ImmutableCollections as their logical contents. This ensures
250   * that implementation types do not leak into the serialized representation.
251   */
252  private static class SerializedForm implements Serializable {
253    final Object[] elements;
254    SerializedForm(Object[] elements) {
255      this.elements = elements;
256    }
257    Object readResolve() {
258      return elements.length == 0
259          ? EMPTY_IMMUTABLE_COLLECTION
260          : new ArrayImmutableCollection<Object>(Platform.clone(elements));
261    }
262    private static final long serialVersionUID = 0;
263  }
264
265  Object writeReplace() {
266    return new SerializedForm(toArray());
267  }
268
269  /**
270   * Abstract base class for builders of {@link ImmutableCollection} types.
271   *
272   * @since 10.0
273   */
274  public abstract static class Builder<E> {
275
276    Builder() {
277    }
278
279    /**
280     * Adds {@code element} to the {@code ImmutableCollection} being built.
281     *
282     * <p>Note that each builder class covariantly returns its own type from
283     * this method.
284     *
285     * @param element the element to add
286     * @return this {@code Builder} instance
287     * @throws NullPointerException if {@code element} is null
288     */
289    public abstract Builder<E> add(E element);
290
291    /**
292     * Adds each element of {@code elements} to the {@code ImmutableCollection}
293     * being built.
294     *
295     * <p>Note that each builder class overrides this method in order to
296     * covariantly return its own type.
297     *
298     * @param elements the elements to add
299     * @return this {@code Builder} instance
300     * @throws NullPointerException if {@code elements} is null or contains a
301     *     null element
302     */
303    public Builder<E> add(E... elements) {
304      for (E element : elements) {
305        add(element);
306      }
307      return this;
308    }
309
310    /**
311     * Adds each element of {@code elements} to the {@code ImmutableCollection}
312     * being built.
313     *
314     * <p>Note that each builder class overrides this method in order to
315     * covariantly return its own type.
316     *
317     * @param elements the elements to add
318     * @return this {@code Builder} instance
319     * @throws NullPointerException if {@code elements} is null or contains a
320     *     null element
321     */
322    public Builder<E> addAll(Iterable<? extends E> elements) {
323      for (E element : elements) {
324        add(element);
325      }
326      return this;
327    }
328
329    /**
330     * Adds each element of {@code elements} to the {@code ImmutableCollection}
331     * being built.
332     *
333     * <p>Note that each builder class overrides this method in order to
334     * covariantly return its own type.
335     *
336     * @param elements the elements to add
337     * @return this {@code Builder} instance
338     * @throws NullPointerException if {@code elements} is null or contains a
339     *     null element
340     */
341    public Builder<E> addAll(Iterator<? extends E> elements) {
342      while (elements.hasNext()) {
343        add(elements.next());
344      }
345      return this;
346    }
347
348    /**
349     * Returns a newly-created {@code ImmutableCollection} of the appropriate
350     * type, containing the elements provided to this builder.
351     *
352     * <p>Note that each builder class covariantly returns the appropriate type
353     * of {@code ImmutableCollection} from this method.
354     */
355    public abstract ImmutableCollection<E> build();
356  }
357}
358