001/*
002 * Copyright (C) 2008 The Guava Authors
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
017package com.google.common.collect;
018
019import com.google.common.annotations.GwtCompatible;
020
021import java.io.Serializable;
022import java.util.Collection;
023import java.util.Iterator;
024
025import 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
042public 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  @Override
053  public abstract UnmodifiableIterator<E> iterator();
054
055  @Override
056  public Object[] toArray() {
057    return ObjectArrays.toArrayImpl(this);
058  }
059
060  @Override
061  public <T> T[] toArray(T[] other) {
062    return ObjectArrays.toArrayImpl(this, other);
063  }
064
065  @Override
066  public boolean contains(@Nullable Object object) {
067    return object != null && Iterators.contains(iterator(), object);
068  }
069
070  @Override
071  public boolean containsAll(Collection<?> targets) {
072    return Collections2.containsAllImpl(this, targets);
073  }
074
075  @Override
076  public boolean isEmpty() {
077    return size() == 0;
078  }
079
080  @Override public String toString() {
081    return Collections2.toStringImpl(this);
082  }
083
084  /**
085   * Guaranteed to throw an exception and leave the collection unmodified.
086   *
087   * @throws UnsupportedOperationException always
088   */
089  @Override
090  public final boolean add(E e) {
091    throw new UnsupportedOperationException();
092  }
093
094  /**
095   * Guaranteed to throw an exception and leave the collection unmodified.
096   *
097   * @throws UnsupportedOperationException always
098   */
099  @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
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  abstract static class Builder<E> {
273    /**
274     * Adds {@code element} to the {@code ImmutableCollection} being built.
275     *
276     * <p>Note that each builder class covariantly returns its own type from
277     * this method.
278     *
279     * @param element the element to add
280     * @return this {@code Builder} instance
281     * @throws NullPointerException if {@code element} is null
282     */
283    public abstract Builder<E> add(E element);
284
285    /**
286     * Adds each element of {@code elements} to the {@code ImmutableCollection}
287     * being built.
288     *
289     * <p>Note that each builder class overrides this method in order to
290     * covariantly return its own type.
291     *
292     * @param elements the elements to add
293     * @return this {@code Builder} instance
294     * @throws NullPointerException if {@code elements} is null or contains a
295     *     null element
296     */
297    public Builder<E> add(E... elements) {
298      for (E element : elements) {
299        add(element);
300      }
301      return this;
302    }
303
304    /**
305     * Adds each element of {@code elements} to the {@code ImmutableCollection}
306     * being built.
307     *
308     * <p>Note that each builder class overrides this method in order to
309     * covariantly return its own type.
310     *
311     * @param elements the elements to add
312     * @return this {@code Builder} instance
313     * @throws NullPointerException if {@code elements} is null or contains a
314     *     null element
315     */
316    public Builder<E> addAll(Iterable<? extends E> elements) {
317      for (E element : elements) {
318        add(element);
319      }
320      return this;
321    }
322
323    /**
324     * Adds each element of {@code elements} to the {@code ImmutableCollection}
325     * being built.
326     *
327     * <p>Note that each builder class overrides this method in order to
328     * covariantly return its own type.
329     *
330     * @param elements the elements to add
331     * @return this {@code Builder} instance
332     * @throws NullPointerException if {@code elements} is null or contains a
333     *     null element
334     */
335    public Builder<E> addAll(Iterator<? extends E> elements) {
336      while (elements.hasNext()) {
337        add(elements.next());
338      }
339      return this;
340    }
341
342    /**
343     * Returns a newly-created {@code ImmutableCollection} of the appropriate
344     * type, containing the elements provided to this builder.
345     *
346     * <p>Note that each builder class covariantly returns the appropriate type
347     * of {@code ImmutableCollection} from this method.
348     */
349    public abstract ImmutableCollection<E> build();
350  }
351}