Home | History | Annotate | Download | only in collect
      1 /*
      2  * Copyright (C) 2009 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.collect;
     18 
     19 import com.google.common.annotations.GwtCompatible;
     20 
     21 import java.io.Serializable;
     22 import java.util.Collection;
     23 import java.util.EnumSet;
     24 import java.util.Set;
     25 
     26 /**
     27  * Implementation of {@link ImmutableSet} backed by a non-empty {@link
     28  * java.util.EnumSet}.
     29  *
     30  * @author Jared Levy
     31  */
     32 @GwtCompatible(serializable = true)
     33 @SuppressWarnings("serial") // we're overriding default serialization
     34 final class ImmutableEnumSet<E /*extends Enum<E>*/> extends ImmutableSet<E> {
     35   /*
     36    * Notes on EnumSet and <E extends Enum<E>>:
     37    *
     38    * This class isn't an arbitrary ForwardingImmutableSet because we need to
     39    * know that calling {@code clone()} during deserialization will return an
     40    * object that no one else has a reference to, allowing us to guarantee
     41    * immutability. Hence, we support only {@link EnumSet}.
     42    *
     43    * GWT complicates matters. If we declare the class's type parameter as
     44    * <E extends Enum<E>> (as is necessary to declare a field of type
     45    * EnumSet<E>), GWT generates serializers for every available enum. This
     46    * increases the size of some applications' JavaScript by over 10%. To avoid
     47    * this, we declare the type parameter as just <E> and the field as just
     48    * Set<E>. writeReplace() must then use an unchecked cast to return to
     49    * EnumSet, guaranteeing immutability as described above.
     50    */
     51   private final transient Set<E> delegate;
     52 
     53   ImmutableEnumSet(Set<E> delegate) {
     54     this.delegate = delegate;
     55   }
     56 
     57   @Override public UnmodifiableIterator<E> iterator() {
     58     return Iterators.unmodifiableIterator(delegate.iterator());
     59   }
     60 
     61   public int size() {
     62     return delegate.size();
     63   }
     64 
     65   @Override public boolean contains(Object object) {
     66     return delegate.contains(object);
     67   }
     68 
     69   @Override public boolean containsAll(Collection<?> collection) {
     70     return delegate.containsAll(collection);
     71   }
     72 
     73   @Override public boolean isEmpty() {
     74     return delegate.isEmpty();
     75   }
     76 
     77   @Override public Object[] toArray() {
     78     return delegate.toArray();
     79   }
     80 
     81   @Override public <T> T[] toArray(T[] array) {
     82     return delegate.toArray(array);
     83   }
     84 
     85   @Override public boolean equals(Object object) {
     86     return object == this || delegate.equals(object);
     87   }
     88 
     89   private transient int hashCode;
     90 
     91   @Override public int hashCode() {
     92     int result = hashCode;
     93     return (result == 0) ? hashCode = delegate.hashCode() : result;
     94   }
     95 
     96   @Override public String toString() {
     97     return delegate.toString();
     98   }
     99 
    100   // All callers of the constructor are restricted to <E extends Enum<E>>.
    101   @SuppressWarnings("unchecked")
    102   @Override Object writeReplace() {
    103     return new EnumSerializedForm((EnumSet) delegate);
    104   }
    105 
    106   /*
    107    * This class is used to serialize ImmutableEnumSet instances.
    108    */
    109   private static class EnumSerializedForm<E extends Enum<E>>
    110       implements Serializable {
    111     final EnumSet<E> delegate;
    112     EnumSerializedForm(EnumSet<E> delegate) {
    113       this.delegate = delegate;
    114     }
    115     Object readResolve() {
    116       // EJ2 #76: Write readObject() methods defensively.
    117       return new ImmutableEnumSet<E>(delegate.clone());
    118     }
    119     private static final long serialVersionUID = 0;
    120   }
    121 }
    122