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    
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      @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    }