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    import com.google.common.annotations.VisibleForTesting;
021    
022    import java.io.Serializable;
023    import java.util.Collection;
024    import java.util.Iterator;
025    
026    import javax.annotation.Nullable;
027    
028    /**
029     * An immutable collection. Does not permit null elements.
030     *
031     * <p>In addition to the {@link Collection} methods, this class has an {@link
032     * #asList()} method, which returns a list view of the collection's elements.
033     *
034     * <p><b>Note:</b> Although this class is not final, it cannot be subclassed
035     * outside of this package as it has no public or protected constructors. Thus,
036     * instances of this type are guaranteed to be immutable.
037     *
038     * @author Jesse Wilson
039     * @since 2.0 (imported from Google Collections Library)
040     */
041    @GwtCompatible(emulated = true)
042    @SuppressWarnings("serial") // we're overriding default serialization
043    public abstract class ImmutableCollection<E>
044        implements Collection<E>, Serializable {
045      static final ImmutableCollection<Object> EMPTY_IMMUTABLE_COLLECTION
046          = new EmptyImmutableCollection();
047    
048      ImmutableCollection() {}
049    
050      /**
051       * Returns an unmodifiable iterator across the elements in this collection.
052       */
053      public abstract UnmodifiableIterator<E> iterator();
054    
055      public Object[] toArray() {
056        return ObjectArrays.toArrayImpl(this);
057      }
058    
059      public <T> T[] toArray(T[] other) {
060        return ObjectArrays.toArrayImpl(this, other);
061      }
062    
063      public boolean contains(@Nullable Object object) {
064        return object != null && Iterators.contains(iterator(), object);
065      }
066    
067      public boolean containsAll(Collection<?> targets) {
068        return Collections2.containsAllImpl(this, targets);
069      }
070    
071      public boolean isEmpty() {
072        return size() == 0;
073      }
074    
075      
076      @Override
077      public String toString() {
078        return Collections2.toStringImpl(this);
079      }
080    
081      /**
082       * Guaranteed to throw an exception and leave the collection unmodified.
083       *
084       * @throws UnsupportedOperationException always
085       */
086      public final boolean add(E e) {
087        throw new UnsupportedOperationException();
088      }
089    
090      /**
091       * Guaranteed to throw an exception and leave the collection unmodified.
092       *
093       * @throws UnsupportedOperationException always
094       */
095      public final boolean remove(Object object) {
096        throw new UnsupportedOperationException();
097      }
098    
099      /**
100       * Guaranteed to throw an exception and leave the collection unmodified.
101       *
102       * @throws UnsupportedOperationException always
103       */
104      public final boolean addAll(Collection<? extends E> newElements) {
105        throw new UnsupportedOperationException();
106      }
107    
108      /**
109       * Guaranteed to throw an exception and leave the collection unmodified.
110       *
111       * @throws UnsupportedOperationException always
112       */
113      public final boolean removeAll(Collection<?> oldElements) {
114        throw new UnsupportedOperationException();
115      }
116    
117      /**
118       * Guaranteed to throw an exception and leave the collection unmodified.
119       *
120       * @throws UnsupportedOperationException always
121       */
122      public final boolean retainAll(Collection<?> elementsToKeep) {
123        throw new UnsupportedOperationException();
124      }
125    
126      /**
127       * Guaranteed to throw an exception and leave the collection unmodified.
128       *
129       * @throws UnsupportedOperationException always
130       */
131      public final void clear() {
132        throw new UnsupportedOperationException();
133      }
134    
135      /*
136       * TODO(kevinb): Restructure code so ImmutableList doesn't contain this
137       * variable, which it doesn't use.
138       */
139      private transient ImmutableList<E> asList;
140    
141      /**
142       * Returns a list view of the collection.
143       *
144       * @since 2.0
145       */
146      public ImmutableList<E> asList() {
147        ImmutableList<E> list = asList;
148        return (list == null) ? (asList = createAsList()) : list;
149      }
150    
151      ImmutableList<E> createAsList() {
152        switch (size()) {
153          case 0:
154            return ImmutableList.of();
155          case 1:
156            return ImmutableList.of(iterator().next());
157          default:
158            return new RegularImmutableAsList<E>(this, toArray());
159        }
160      }
161    
162      abstract boolean isPartialView();
163    
164      private static class EmptyImmutableCollection
165          extends ImmutableCollection<Object> {
166        public int size() {
167          return 0;
168        }
169    
170        
171        @Override
172        public boolean isEmpty() {
173          return true;
174        }
175    
176        
177        @Override
178        public boolean contains(@Nullable Object object) {
179          return false;
180        }
181    
182        @Override
183        public UnmodifiableIterator<Object> iterator() {
184          return Iterators.EMPTY_LIST_ITERATOR;
185        }
186    
187        private static final Object[] EMPTY_ARRAY = new Object[0];
188    
189        
190        @Override
191        public Object[] toArray() {
192          return EMPTY_ARRAY;
193        }
194    
195        
196        @Override
197        public <T> T[] toArray(T[] array) {
198          if (array.length > 0) {
199            array[0] = null;
200          }
201          return array;
202        }
203    
204        
205        @Override
206        ImmutableList<Object> createAsList() {
207          return ImmutableList.of();
208        }
209    
210        
211        @Override
212        boolean isPartialView() {
213          return false;
214        }
215      }
216    
217      /**
218       * Nonempty collection stored in an array.
219       */
220      private static class ArrayImmutableCollection<E>
221          extends ImmutableCollection<E> {
222        private final E[] elements;
223    
224        ArrayImmutableCollection(E[] elements) {
225          this.elements = elements;
226        }
227    
228        public int size() {
229          return elements.length;
230        }
231    
232        
233        @Override
234        public boolean isEmpty() {
235          return false;
236        }
237    
238        
239        @Override
240        public UnmodifiableIterator<E> iterator() {
241          return Iterators.forArray(elements);
242        }
243    
244        
245        @Override
246        ImmutableList<E> createAsList() {
247          return elements.length == 1 ? new SingletonImmutableList<E>(elements[0])
248              : new RegularImmutableList<E>(elements);
249        }
250    
251        
252        @Override
253        boolean isPartialView() {
254          return false;
255        }
256      }
257    
258      /*
259       * Serializes ImmutableCollections as their logical contents. This ensures
260       * that implementation types do not leak into the serialized representation.
261       */
262      private static class SerializedForm implements Serializable {
263        final Object[] elements;
264        SerializedForm(Object[] elements) {
265          this.elements = elements;
266        }
267        Object readResolve() {
268          return elements.length == 0
269              ? EMPTY_IMMUTABLE_COLLECTION
270              : new ArrayImmutableCollection<Object>(Platform.clone(elements));
271        }
272        private static final long serialVersionUID = 0;
273      }
274    
275      Object writeReplace() {
276        return new SerializedForm(toArray());
277      }
278    
279      /**
280       * Abstract base class for builders of {@link ImmutableCollection} types.
281       *
282       * @since 10.0
283       */
284      public abstract static class Builder<E> {
285        static final int DEFAULT_INITIAL_CAPACITY = 4;
286    
287        @VisibleForTesting
288        static int expandedCapacity(int oldCapacity, int minCapacity) {
289          if (minCapacity < 0) {
290            throw new AssertionError("cannot store more than MAX_VALUE elements");
291          }
292          // careful of overflow!
293          int newCapacity = oldCapacity + (oldCapacity >> 1) + 1;
294          if (newCapacity < minCapacity) {
295            newCapacity = Integer.highestOneBit(minCapacity - 1) << 1;
296          }
297          if (newCapacity < 0) {
298            newCapacity = Integer.MAX_VALUE;
299            // guaranteed to be >= newCapacity
300          }
301          return newCapacity;
302        }
303    
304        Builder() {
305        }
306    
307        /**
308         * Adds {@code element} to the {@code ImmutableCollection} being built.
309         *
310         * <p>Note that each builder class covariantly returns its own type from
311         * this method.
312         *
313         * @param element the element to add
314         * @return this {@code Builder} instance
315         * @throws NullPointerException if {@code element} is null
316         */
317        public abstract Builder<E> add(E element);
318    
319        /**
320         * Adds each element of {@code elements} to the {@code ImmutableCollection}
321         * being built.
322         *
323         * <p>Note that each builder class overrides this method in order to
324         * covariantly return its own type.
325         *
326         * @param elements the elements to add
327         * @return this {@code Builder} instance
328         * @throws NullPointerException if {@code elements} is null or contains a
329         *     null element
330         */
331        public Builder<E> add(E... elements) {
332          for (E element : elements) {
333            add(element);
334          }
335          return this;
336        }
337    
338        /**
339         * Adds each element of {@code elements} to the {@code ImmutableCollection}
340         * being built.
341         *
342         * <p>Note that each builder class overrides this method in order to
343         * covariantly return its own type.
344         *
345         * @param elements the elements to add
346         * @return this {@code Builder} instance
347         * @throws NullPointerException if {@code elements} is null or contains a
348         *     null element
349         */
350        public Builder<E> addAll(Iterable<? extends E> elements) {
351          for (E element : elements) {
352            add(element);
353          }
354          return this;
355        }
356    
357        /**
358         * Adds each element of {@code elements} to the {@code ImmutableCollection}
359         * being built.
360         *
361         * <p>Note that each builder class overrides this method in order to
362         * covariantly return its own type.
363         *
364         * @param elements the elements to add
365         * @return this {@code Builder} instance
366         * @throws NullPointerException if {@code elements} is null or contains a
367         *     null element
368         */
369        public Builder<E> addAll(Iterator<? extends E> elements) {
370          while (elements.hasNext()) {
371            add(elements.next());
372          }
373          return this;
374        }
375    
376        /**
377         * Returns a newly-created {@code ImmutableCollection} of the appropriate
378         * type, containing the elements provided to this builder.
379         *
380         * <p>Note that each builder class covariantly returns the appropriate type
381         * of {@code ImmutableCollection} from this method.
382         */
383        public abstract ImmutableCollection<E> build();
384      }
385    }