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