1090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/*
2090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Copyright (C) 2008 Google Inc.
3090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson *
4090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * you may not use this file except in compliance with the License.
6090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * You may obtain a copy of the License at
7090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson *
8090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0
9090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson *
10090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * Unless required by applicable law or agreed to in writing, software
11090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * See the License for the specific language governing permissions and
14090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * limitations under the License.
15090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */
16090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
17090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonpackage com.google.common.collect;
18090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
19090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport com.google.common.annotations.GwtCompatible;
20090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport static com.google.common.base.Preconditions.checkNotNull;
21090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
22090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.io.Serializable;
23090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Collection;
24090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport java.util.Iterator;
25090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
26090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonimport javax.annotation.Nullable;
27090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
28090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson/**
29090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * An immutable collection. Does not permit null elements.
30090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson *
31bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * <p>In addition to the {@link Collection} methods, this class has an {@link
32bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * #asList()} method, which returns a list view of the collection's elements.
33bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor *
34090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * <p><b>Note</b>: Although this class is not final, it cannot be subclassed
35090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * outside of this package as it has no public or protected constructors. Thus,
36090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * instances of this type are guaranteed to be immutable.
37090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson *
38090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson * @author Jesse Wilson
39bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor * @since 2010.01.04 <b>stable</b> (imported from Google Collections Library)
40090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson */
41090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson@GwtCompatible
42090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson@SuppressWarnings("serial") // we're overriding default serialization
43090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilsonpublic abstract class ImmutableCollection<E>
44090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    implements Collection<E>, Serializable {
45090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  static final ImmutableCollection<Object> EMPTY_IMMUTABLE_COLLECTION
46090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      = new EmptyImmutableCollection();
47090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
48090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  ImmutableCollection() {}
49090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
50090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
51090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Returns an unmodifiable iterator across the elements in this collection.
52090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
53090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public abstract UnmodifiableIterator<E> iterator();
54090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
55090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public Object[] toArray() {
56090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Object[] newArray = new Object[size()];
57090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return toArray(newArray);
58090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
59090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
60090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public <T> T[] toArray(T[] other) {
61090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    int size = size();
62090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    if (other.length < size) {
63090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      other = ObjectArrays.newArray(other, size);
64090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    } else if (other.length > size) {
65090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      other[size] = null;
66090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
67090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
68090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    // Writes will produce ArrayStoreException when the toArray() doc requires.
69090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Object[] otherAsObjectArray = other;
70090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    int index = 0;
71090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    for (E element : this) {
72090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      otherAsObjectArray[index++] = element;
73090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
74090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return other;
75090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
76090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
77090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public boolean contains(@Nullable Object object) {
78090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    if (object == null) {
79090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return false;
80090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
81090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    for (E element : this) {
82090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      if (element.equals(object)) {
83090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        return true;
84090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      }
85090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
86090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return false;
87090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
88090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
89090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public boolean containsAll(Collection<?> targets) {
90090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    for (Object target : targets) {
91090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      if (!contains(target)) {
92090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        return false;
93090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      }
94090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
95090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return true;
96090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
97090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
98090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public boolean isEmpty() {
99090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return size() == 0;
100090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
101090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
102090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  @Override public String toString() {
103090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    StringBuilder sb = new StringBuilder(size() * 16).append('[');
104090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Collections2.standardJoiner.appendTo(sb, this);
105090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return sb.append(']').toString();
106090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
107090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
108090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
109090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Guaranteed to throw an exception and leave the collection unmodified.
110090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
111090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws UnsupportedOperationException always
112090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
113090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public final boolean add(E e) {
114090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    throw new UnsupportedOperationException();
115090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
116090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
117090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
118090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Guaranteed to throw an exception and leave the collection unmodified.
119090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
120090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws UnsupportedOperationException always
121090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
122090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public final boolean remove(Object object) {
123090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    throw new UnsupportedOperationException();
124090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
125090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
126090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
127090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Guaranteed to throw an exception and leave the collection unmodified.
128090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
129090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws UnsupportedOperationException always
130090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
131090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public final boolean addAll(Collection<? extends E> newElements) {
132090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    throw new UnsupportedOperationException();
133090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
134090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
135090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
136090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Guaranteed to throw an exception and leave the collection unmodified.
137090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
138090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws UnsupportedOperationException always
139090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
140090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public final boolean removeAll(Collection<?> oldElements) {
141090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    throw new UnsupportedOperationException();
142090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
143090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
144090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
145090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Guaranteed to throw an exception and leave the collection unmodified.
146090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
147090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws UnsupportedOperationException always
148090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
149090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public final boolean retainAll(Collection<?> elementsToKeep) {
150090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    throw new UnsupportedOperationException();
151090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
152090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
153090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
154090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Guaranteed to throw an exception and leave the collection unmodified.
155090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   *
156090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * @throws UnsupportedOperationException always
157090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
158090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  public final void clear() {
159090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    throw new UnsupportedOperationException();
160090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
161090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
162bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  // TODO: Restructure code so ImmutableList doesn't contain this variable,
163bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  // which it doesn't use.
164bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  private transient ImmutableList<E> asList;
165bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
166bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  /**
167bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * Returns a list view of the collection.
168bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   *
169bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   * @since 2010.01.04 <b>tentative</b>
170bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor   */
171bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  public ImmutableList<E> asList() {
172bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    ImmutableList<E> list = asList;
173bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    return (list == null) ? (asList = createAsList()) : list;
174bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
175bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
176bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  ImmutableList<E> createAsList() {
177bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    switch (size()) {
178bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      case 0:
179bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return ImmutableList.of();
180bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      case 1:
181bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return ImmutableList.of(iterator().next());
182bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor      default:
183bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor        return new ImmutableAsList<E>(toArray(), this);
184bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor    }
185bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor  }
186bfe2dd089341dcb4c1fb65a5b6b077ad0ebbf6dcDan Egnor
187090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private static class EmptyImmutableCollection
188090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      extends ImmutableCollection<Object> {
189090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    public int size() {
190090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return 0;
191090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
192090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
193090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    @Override public boolean isEmpty() {
194090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return true;
195090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
196090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
197090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    @Override public boolean contains(@Nullable Object object) {
198090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return false;
199090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
200090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
201090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    @Override public UnmodifiableIterator<Object> iterator() {
202090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return Iterators.EMPTY_ITERATOR;
203090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
204090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
205090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    private static final Object[] EMPTY_ARRAY = new Object[0];
206090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
207090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    @Override public Object[] toArray() {
208090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return EMPTY_ARRAY;
209090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
210090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
211090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    @Override public <T> T[] toArray(T[] array) {
212090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      if (array.length > 0) {
213090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        array[0] = null;
214090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      }
215090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return array;
216090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
217090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
218090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
219090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private static class ArrayImmutableCollection<E>
220090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      extends ImmutableCollection<E> {
221090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    private final E[] elements;
222090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
223090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    ArrayImmutableCollection(E[] elements) {
224090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      this.elements = elements;
225090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
226090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
227090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    public int size() {
228090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return elements.length;
229090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
230090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
231090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    @Override public boolean isEmpty() {
232090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return false;
233090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
234090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
235090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    @Override public UnmodifiableIterator<E> iterator() {
236090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return Iterators.forArray(elements);
237090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
238090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
239090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
240090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /*
241090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Serializes ImmutableCollections as their logical contents. This ensures
242090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * that implementation types do not leak into the serialized representation.
243090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
244090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  private static class SerializedForm implements Serializable {
245090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    final Object[] elements;
246090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    SerializedForm(Object[] elements) {
247090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      this.elements = elements;
248090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
249090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    Object readResolve() {
250090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return elements.length == 0
251090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson          ? EMPTY_IMMUTABLE_COLLECTION
252090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson          : new ArrayImmutableCollection<Object>(Platform.clone(elements));
253090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
254090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    private static final long serialVersionUID = 0;
255090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
256090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
257090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  Object writeReplace() {
258090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    return new SerializedForm(toArray());
259090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
260090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
261090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  /**
262090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   * Abstract base class for builders of {@link ImmutableCollection} types.
263090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson   */
264090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  abstract static class Builder<E> {
265090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    /**
266090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * Adds {@code element} to the {@code ImmutableCollection} being built.
267090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
268090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * <p>Note that each builder class covariantly returns its own type from
269090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * this method.
270090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
271090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @param element the element to add
272090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @return this {@code Builder} instance
273090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @throws NullPointerException if {@code element} is null
274090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     */
275090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    public abstract Builder<E> add(E element);
276090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
277090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    /**
278090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * Adds each element of {@code elements} to the {@code ImmutableCollection}
279090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * being built.
280090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
281090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * <p>Note that each builder class overrides this method in order to
282090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * covariantly return its own type.
283090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
284090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @param elements the elements to add
285090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @return this {@code Builder} instance
286090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @throws NullPointerException if {@code elements} is null or contains a
287090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *     null element
288090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     */
289090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    public Builder<E> add(E... elements) {
290090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      checkNotNull(elements); // for GWT
291090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      for (E element : elements) {
292090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        add(element);
293090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      }
294090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return this;
295090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
296090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
297090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    /**
298090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * Adds each element of {@code elements} to the {@code ImmutableCollection}
299090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * being built.
300090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
301090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * <p>Note that each builder class overrides this method in order to
302090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * covariantly return its own type.
303090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
304090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @param elements the elements to add
305090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @return this {@code Builder} instance
306090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @throws NullPointerException if {@code elements} is null or contains a
307090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *     null element
308090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     */
309090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    public Builder<E> addAll(Iterable<? extends E> elements) {
310090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      checkNotNull(elements); // for GWT
311090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      for (E element : elements) {
312090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        add(element);
313090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      }
314090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return this;
315090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
316090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
317090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    /**
318090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * Adds each element of {@code elements} to the {@code ImmutableCollection}
319090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * being built.
320090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
321090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * <p>Note that each builder class overrides this method in order to
322090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * covariantly return its own type.
323090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
324090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @param elements the elements to add
325090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @return this {@code Builder} instance
326090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * @throws NullPointerException if {@code elements} is null or contains a
327090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *     null element
328090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     */
329090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    public Builder<E> addAll(Iterator<? extends E> elements) {
330090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      checkNotNull(elements); // for GWT
331090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      while (elements.hasNext()) {
332090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson        add(elements.next());
333090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      }
334090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson      return this;
335090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    }
336090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson
337090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    /**
338090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * Returns a newly-created {@code ImmutableCollection} of the appropriate
339090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * type, containing the elements provided to this builder.
340090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     *
341090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * <p>Note that each builder class covariantly returns the appropriate type
342090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     * of {@code ImmutableCollection} from this method.
343090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson     */
344090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson    public abstract ImmutableCollection<E> build();
345090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson  }
346090f9b4c879985bc747c214f82c62471e60c7742Jesse Wilson}
347