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        return ObjectArrays.toArrayImpl(this);
056      }
057    
058      public <T> T[] toArray(T[] other) {
059        return ObjectArrays.toArrayImpl(this, other);
060      }
061    
062      public boolean contains(@Nullable Object object) {
063        return object != null && Iterators.contains(iterator(), object);
064      }
065    
066      public boolean containsAll(Collection<?> targets) {
067        return Collections2.containsAllImpl(this, targets);
068      }
069    
070      public boolean isEmpty() {
071        return size() == 0;
072      }
073    
074      @Override public String toString() {
075        return Collections2.toStringImpl(this);
076      }
077    
078      /**
079       * Guaranteed to throw an exception and leave the collection unmodified.
080       *
081       * @throws UnsupportedOperationException always
082       */
083      public final boolean add(E e) {
084        throw new UnsupportedOperationException();
085      }
086    
087      /**
088       * Guaranteed to throw an exception and leave the collection unmodified.
089       *
090       * @throws UnsupportedOperationException always
091       */
092      public final boolean remove(Object object) {
093        throw new UnsupportedOperationException();
094      }
095    
096      /**
097       * Guaranteed to throw an exception and leave the collection unmodified.
098       *
099       * @throws UnsupportedOperationException always
100       */
101      public final boolean addAll(Collection<? extends E> newElements) {
102        throw new UnsupportedOperationException();
103      }
104    
105      /**
106       * Guaranteed to throw an exception and leave the collection unmodified.
107       *
108       * @throws UnsupportedOperationException always
109       */
110      public final boolean removeAll(Collection<?> oldElements) {
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      public final boolean retainAll(Collection<?> elementsToKeep) {
120        throw new UnsupportedOperationException();
121      }
122    
123      /**
124       * Guaranteed to throw an exception and leave the collection unmodified.
125       *
126       * @throws UnsupportedOperationException always
127       */
128      public final void clear() {
129        throw new UnsupportedOperationException();
130      }
131    
132      /*
133       * TODO(kevinb): Restructure code so ImmutableList doesn't contain this
134       * variable, which it doesn't use.
135       */
136      private transient ImmutableList<E> asList;
137    
138      /**
139       * Returns a list view of the collection.
140       *
141       * @since 2
142       */
143      public ImmutableList<E> asList() {
144        ImmutableList<E> list = asList;
145        return (list == null) ? (asList = createAsList()) : list;
146      }
147    
148      ImmutableList<E> createAsList() {
149        switch (size()) {
150          case 0:
151            return ImmutableList.of();
152          case 1:
153            return ImmutableList.of(iterator().next());
154          default:
155            return new ImmutableAsList<E>(toArray(), this);
156        }
157      }
158    
159      abstract boolean isPartialView();
160    
161      private static class EmptyImmutableCollection
162          extends ImmutableCollection<Object> {
163        public int size() {
164          return 0;
165        }
166    
167        @Override public boolean isEmpty() {
168          return true;
169        }
170    
171        @Override public boolean contains(@Nullable Object object) {
172          return false;
173        }
174    
175        @Override public UnmodifiableIterator<Object> iterator() {
176          return Iterators.EMPTY_ITERATOR;
177        }
178    
179        private static final Object[] EMPTY_ARRAY = new Object[0];
180    
181        @Override public Object[] toArray() {
182          return EMPTY_ARRAY;
183        }
184    
185        @Override public <T> T[] toArray(T[] array) {
186          if (array.length > 0) {
187            array[0] = null;
188          }
189          return array;
190        }
191    
192        @Override ImmutableList<Object> createAsList() {
193          return ImmutableList.of();
194        }
195    
196        @Override boolean isPartialView() {
197          return false;
198        }
199      }
200    
201      /**
202       * Nonempty collection stored in an array.
203       */
204      private static class ArrayImmutableCollection<E>
205          extends ImmutableCollection<E> {
206        private final E[] elements;
207    
208        ArrayImmutableCollection(E[] elements) {
209          this.elements = elements;
210        }
211    
212        public int size() {
213          return elements.length;
214        }
215    
216        @Override public boolean isEmpty() {
217          return false;
218        }
219    
220        @Override public UnmodifiableIterator<E> iterator() {
221          return Iterators.forArray(elements);
222        }
223    
224        @Override ImmutableList<E> createAsList() {
225          return elements.length == 1 ? new SingletonImmutableList<E>(elements[0])
226              : new RegularImmutableList<E>(elements);
227        }
228    
229        @Override boolean isPartialView() {
230          return false;
231        }
232      }
233    
234      /*
235       * Serializes ImmutableCollections as their logical contents. This ensures
236       * that implementation types do not leak into the serialized representation.
237       */
238      private static class SerializedForm implements Serializable {
239        final Object[] elements;
240        SerializedForm(Object[] elements) {
241          this.elements = elements;
242        }
243        Object readResolve() {
244          return elements.length == 0
245              ? EMPTY_IMMUTABLE_COLLECTION
246              : new ArrayImmutableCollection<Object>(Platform.clone(elements));
247        }
248        private static final long serialVersionUID = 0;
249      }
250    
251      Object writeReplace() {
252        return new SerializedForm(toArray());
253      }
254    
255      /**
256       * Abstract base class for builders of {@link ImmutableCollection} types.
257       */
258      abstract static class Builder<E> {
259        /**
260         * Adds {@code element} to the {@code ImmutableCollection} being built.
261         *
262         * <p>Note that each builder class covariantly returns its own type from
263         * this method.
264         *
265         * @param element the element to add
266         * @return this {@code Builder} instance
267         * @throws NullPointerException if {@code element} is null
268         */
269        public abstract Builder<E> add(E element);
270    
271        /**
272         * Adds each element of {@code elements} to the {@code ImmutableCollection}
273         * being built.
274         *
275         * <p>Note that each builder class overrides this method in order to
276         * covariantly return its own type.
277         *
278         * @param elements the elements to add
279         * @return this {@code Builder} instance
280         * @throws NullPointerException if {@code elements} is null or contains a
281         *     null element
282         */
283        public Builder<E> add(E... elements) {
284          for (E element : elements) {
285            add(element);
286          }
287          return this;
288        }
289    
290        /**
291         * Adds each element of {@code elements} to the {@code ImmutableCollection}
292         * being built.
293         *
294         * <p>Note that each builder class overrides this method in order to
295         * covariantly return its own type.
296         *
297         * @param elements the elements to add
298         * @return this {@code Builder} instance
299         * @throws NullPointerException if {@code elements} is null or contains a
300         *     null element
301         */
302        public Builder<E> addAll(Iterable<? extends E> elements) {
303          for (E element : elements) {
304            add(element);
305          }
306          return this;
307        }
308    
309        /**
310         * Adds each element of {@code elements} to the {@code ImmutableCollection}
311         * being built.
312         *
313         * <p>Note that each builder class overrides this method in order to
314         * covariantly return its own type.
315         *
316         * @param elements the elements to add
317         * @return this {@code Builder} instance
318         * @throws NullPointerException if {@code elements} is null or contains a
319         *     null element
320         */
321        public Builder<E> addAll(Iterator<? extends E> elements) {
322          while (elements.hasNext()) {
323            add(elements.next());
324          }
325          return this;
326        }
327    
328        /**
329         * Returns a newly-created {@code ImmutableCollection} of the appropriate
330         * type, containing the elements provided to this builder.
331         *
332         * <p>Note that each builder class covariantly returns the appropriate type
333         * of {@code ImmutableCollection} from this method.
334         */
335        public abstract ImmutableCollection<E> build();
336      }
337    }