    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.0 (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.0
    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       * @since 10.0
    273       */
    274      public abstract static class Builder<E> {
    275
    276        Builder() {
    277        }
    278
    279        /**
    280         * Adds {@code element} to the {@code ImmutableCollection} being built.
    281         *
    282         * <p>Note that each builder class covariantly returns its own type from
    283         * this method.
    284         *
    285         * @param element the element to add
    286         * @return this {@code Builder} instance
    287         * @throws NullPointerException if {@code element} is null
    288         */
    289        public abstract Builder<E> add(E element);
    290
    291        /**
    292         * Adds each element of {@code elements} to the {@code ImmutableCollection}
    293         * being built.
    294         *
    295         * <p>Note that each builder class overrides this method in order to
    296         * covariantly return its own type.
    297         *
    298         * @param elements the elements to add
    299         * @return this {@code Builder} instance
    300         * @throws NullPointerException if {@code elements} is null or contains a
    301         *     null element
    302         */
    303        public Builder<E> add(E... elements) {
    304          for (E element : elements) {
    305            add(element);
    306          }
    307          return this;
    308        }
    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> addAll(Iterable<? extends 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(Iterator<? extends E> elements) {
    342          while (elements.hasNext()) {
    343            add(elements.next());
    344          }
    345          return this;
    346        }
    347
    348        /**
    349         * Returns a newly-created {@code ImmutableCollection} of the appropriate
    350         * type, containing the elements provided to this builder.
    351         *
    352         * <p>Note that each builder class covariantly returns the appropriate type
    353         * of {@code ImmutableCollection} from this method.
    354         */
    355        public abstract ImmutableCollection<E> build();
    356      }
    357    }