Open Source Repository

Home /guava/guava-10.0 | Repository Home


com/google/common/collect/ImmutableCollection.java
/*
 * Copyright (C) 2008 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.collect;

import com.google.common.annotations.GwtCompatible;

import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;

import javax.annotation.Nullable;

/**
 * An immutable collection. Does not permit null elements.
 *
 <p>In addition to the {@link Collection} methods, this class has an {@link
 * #asList()} method, which returns a list view of the collection's elements.
 *
 <p><b>Note:</b> Although this class is not final, it cannot be subclassed
 * outside of this package as it has no public or protected constructors. Thus,
 * instances of this type are guaranteed to be immutable.
 *
 @author Jesse Wilson
 @since 2.0 (imported from Google Collections Library)
 */
@GwtCompatible(emulated = true)
@SuppressWarnings("serial"// we're overriding default serialization
public abstract class ImmutableCollection<E>
    implements Collection<E>, Serializable {
  static final ImmutableCollection<Object> EMPTY_IMMUTABLE_COLLECTION
      new EmptyImmutableCollection();

  ImmutableCollection() {}

  /**
   * Returns an unmodifiable iterator across the elements in this collection.
   */
  @Override
  public abstract UnmodifiableIterator<E> iterator();

  @Override
  public Object[] toArray() {
    return ObjectArrays.toArrayImpl(this);
  }

  @Override
  public <T> T[] toArray(T[] other) {
    return ObjectArrays.toArrayImpl(this, other);
  }

  @Override
  public boolean contains(@Nullable Object object) {
    return object != null && Iterators.contains(iterator(), object);
  }

  @Override
  public boolean containsAll(Collection<?> targets) {
    return Collections2.containsAllImpl(this, targets);
  }

  @Override
  public boolean isEmpty() {
    return size() == 0;
  }

  @Override public String toString() {
    return Collections2.toStringImpl(this);
  }

  /**
   * Guaranteed to throw an exception and leave the collection unmodified.
   *
   @throws UnsupportedOperationException always
   */
  @Override
  public final boolean add(E e) {
    throw new UnsupportedOperationException();
  }

  /**
   * Guaranteed to throw an exception and leave the collection unmodified.
   *
   @throws UnsupportedOperationException always
   */
  @Override
  public final boolean remove(Object object) {
    throw new UnsupportedOperationException();
  }

  /**
   * Guaranteed to throw an exception and leave the collection unmodified.
   *
   @throws UnsupportedOperationException always
   */
  @Override
  public final boolean addAll(Collection<? extends E> newElements) {
    throw new UnsupportedOperationException();
  }

  /**
   * Guaranteed to throw an exception and leave the collection unmodified.
   *
   @throws UnsupportedOperationException always
   */
  @Override
  public final boolean removeAll(Collection<?> oldElements) {
    throw new UnsupportedOperationException();
  }

  /**
   * Guaranteed to throw an exception and leave the collection unmodified.
   *
   @throws UnsupportedOperationException always
   */
  @Override
  public final boolean retainAll(Collection<?> elementsToKeep) {
    throw new UnsupportedOperationException();
  }

  /**
   * Guaranteed to throw an exception and leave the collection unmodified.
   *
   @throws UnsupportedOperationException always
   */
  @Override
  public final void clear() {
    throw new UnsupportedOperationException();
  }

  /*
   * TODO(kevinb): Restructure code so ImmutableList doesn't contain this
   * variable, which it doesn't use.
   */
  private transient ImmutableList<E> asList;

  /**
   * Returns a list view of the collection.
   *
   @since 2.0
   */
  public ImmutableList<E> asList() {
    ImmutableList<E> list = asList;
    return (list == null(asList = createAsList()) : list;
  }

  ImmutableList<E> createAsList() {
    switch (size()) {
      case 0:
        return ImmutableList.of();
      case 1:
        return ImmutableList.of(iterator().next());
      default:
        return new ImmutableAsList<E>(toArray()this);
    }
  }

  abstract boolean isPartialView();

  private static class EmptyImmutableCollection
      extends ImmutableCollection<Object> {
    @Override
    public int size() {
      return 0;
    }

    @Override public boolean isEmpty() {
      return true;
    }

    @Override public boolean contains(@Nullable Object object) {
      return false;
    }

    @Override public UnmodifiableIterator<Object> iterator() {
      return Iterators.EMPTY_ITERATOR;
    }

    private static final Object[] EMPTY_ARRAY = new Object[0];

    @Override public Object[] toArray() {
      return EMPTY_ARRAY;
    }

    @Override public <T> T[] toArray(T[] array) {
      if (array.length > 0) {
        array[0null;
      }
      return array;
    }

    @Override ImmutableList<Object> createAsList() {
      return ImmutableList.of();
    }

    @Override boolean isPartialView() {
      return false;
    }
  }

  /**
   * Nonempty collection stored in an array.
   */
  private static class ArrayImmutableCollection<E>
      extends ImmutableCollection<E> {
    private final E[] elements;

    ArrayImmutableCollection(E[] elements) {
      this.elements = elements;
    }

    @Override
    public int size() {
      return elements.length;
    }

    @Override public boolean isEmpty() {
      return false;
    }

    @Override public UnmodifiableIterator<E> iterator() {
      return Iterators.forArray(elements);
    }

    @Override ImmutableList<E> createAsList() {
      return elements.length == new SingletonImmutableList<E>(elements[0])
          new RegularImmutableList<E>(elements);
    }

    @Override boolean isPartialView() {
      return false;
    }
  }

  /*
   * Serializes ImmutableCollections as their logical contents. This ensures
   * that implementation types do not leak into the serialized representation.
   */
  private static class SerializedForm implements Serializable {
    final Object[] elements;
    SerializedForm(Object[] elements) {
      this.elements = elements;
    }
    Object readResolve() {
      return elements.length == 0
          ? EMPTY_IMMUTABLE_COLLECTION
          new ArrayImmutableCollection<Object>(Platform.clone(elements));
    }
    private static final long serialVersionUID = 0;
  }

  Object writeReplace() {
    return new SerializedForm(toArray());
  }

  /**
   * Abstract base class for builders of {@link ImmutableCollection} types.
   *
   @since 10.0
   */
  public abstract static class Builder<E> {

    Builder() {
    }

    /**
     * Adds {@code element} to the {@code ImmutableCollection} being built.
     *
     <p>Note that each builder class covariantly returns its own type from
     * this method.
     *
     @param element the element to add
     @return this {@code Builder} instance
     @throws NullPointerException if {@code element} is null
     */
    public abstract Builder<E> add(E element);

    /**
     * Adds each element of {@code elements} to the {@code ImmutableCollection}
     * being built.
     *
     <p>Note that each builder class overrides this method in order to
     * covariantly return its own type.
     *
     @param elements the elements to add
     @return this {@code Builder} instance
     @throws NullPointerException if {@code elements} is null or contains a
     *     null element
     */
    public Builder<E> add(E... elements) {
      for (E element : elements) {
        add(element);
      }
      return this;
    }

    /**
     * Adds each element of {@code elements} to the {@code ImmutableCollection}
     * being built.
     *
     <p>Note that each builder class overrides this method in order to
     * covariantly return its own type.
     *
     @param elements the elements to add
     @return this {@code Builder} instance
     @throws NullPointerException if {@code elements} is null or contains a
     *     null element
     */
    public Builder<E> addAll(Iterable<? extends E> elements) {
      for (E element : elements) {
        add(element);
      }
      return this;
    }

    /**
     * Adds each element of {@code elements} to the {@code ImmutableCollection}
     * being built.
     *
     <p>Note that each builder class overrides this method in order to
     * covariantly return its own type.
     *
     @param elements the elements to add
     @return this {@code Builder} instance
     @throws NullPointerException if {@code elements} is null or contains a
     *     null element
     */
    public Builder<E> addAll(Iterator<? extends E> elements) {
      while (elements.hasNext()) {
        add(elements.next());
      }
      return this;
    }

    /**
     * Returns a newly-created {@code ImmutableCollection} of the appropriate
     * type, containing the elements provided to this builder.
     *
     <p>Note that each builder class covariantly returns the appropriate type
     * of {@code ImmutableCollection} from this method.
     */
    public abstract ImmutableCollection<E> build();
  }
}