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    }