Home | History | Annotate | Download | only in util
      1 /* Licensed to the Apache Software Foundation (ASF) under one or more
      2  * contributor license agreements.  See the NOTICE file distributed with
      3  * this work for additional information regarding copyright ownership.
      4  * The ASF licenses this file to You under the Apache License, Version 2.0
      5  * (the "License"); you may not use this file except in compliance with
      6  * the License.  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 package java.util;
     17 
     18 // BEGIN android-added
     19 import org.apache.harmony.kernel.vm.LangAccess;
     20 // END android-added
     21 
     22 import java.io.Serializable;
     23 
     24 /**
     25  * An EnumSet is a specialized Set to be used with enums as keys.
     26  */
     27 public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
     28         implements Cloneable, Serializable {
     29     // BEGIN android-added
     30     /*
     31      * null-ok; package access to {@code java.lang}, set during
     32      * first need. This shouldn't be used directly. Instead, use {@link
     33      * SpecialAccess#LANG}, which is guaranteed to be initialized.
     34      */
     35     static /*package*/ LangAccess LANG_BOOTSTRAP = null;
     36     // END android-added
     37 
     38     private static final long serialVersionUID = 1009687484059888093L;
     39 
     40     final Class<E> elementClass;
     41 
     42     EnumSet(Class<E> cls) {
     43         elementClass = cls;
     44     }
     45 
     46     /**
     47      * Creates an empty enum set. The permitted elements are of type
     48      * Class&lt;E&gt;.
     49      *
     50      * @param elementType
     51      *            the class object for the elements contained.
     52      * @return an empty enum set, with permitted elements of type {@code
     53      *         elementType}.
     54      * @throws ClassCastException
     55      *             if the specified element type is not and enum type.
     56      */
     57     public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
     58         if (!elementType.isEnum()) {
     59             throw new ClassCastException();
     60         }
     61         // BEGIN android-changed
     62         E[] enums = SpecialAccess.LANG.getEnumValuesInOrder(elementType);
     63         if (enums.length <= 64) {
     64             return new MiniEnumSet<E>(elementType, enums);
     65         }
     66         return new HugeEnumSet<E>(elementType, enums);
     67         // END android-changed
     68     }
     69 
     70     /**
     71      * Creates an enum set filled with all the enum elements of the specified
     72      * {@code elementType}.
     73      *
     74      * @param elementType
     75      *            the class object for the elements contained.
     76      * @return an enum set with elements solely from the specified element type.
     77      * @throws ClassCastException
     78      *             if the specified element type is not and enum type.
     79      */
     80     public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) {
     81         EnumSet<E> set = noneOf(elementType);
     82         set.complement();
     83         return set;
     84     }
     85 
     86     /**
     87      * Creates an enum set. All the contained elements are of type
     88      * Class&lt;E&gt;, and the contained elements are the same as those
     89      * contained in {@code s}.
     90      *
     91      * @param s
     92      *            the enum set from which to copy.
     93      * @return an enum set with all the elements from the specified enum set.
     94      * @throws ClassCastException
     95      *             if the specified element type is not and enum type.
     96      */
     97     public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) {
     98         EnumSet<E> set = EnumSet.noneOf(s.elementClass);
     99         set.addAll(s);
    100         return set;
    101     }
    102 
    103     /**
    104      * Creates an enum set. The contained elements are the same as those
    105      * contained in collection {@code c}. If c is an enum set, invoking this
    106      * method is the same as invoking {@link #copyOf(EnumSet)}.
    107      *
    108      * @param c
    109      *            the collection from which to copy. if it is not an enum set,
    110      *            it must not be empty.
    111      * @return an enum set with all the elements from the specified collection.
    112      * @throws IllegalArgumentException
    113      *             if c is not an enum set and contains no elements at all.
    114      * @throws NullPointerException
    115      *             if {@code c} is {@code null}.
    116      */
    117     public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) {
    118         if (c instanceof EnumSet) {
    119             return copyOf((EnumSet<E>) c);
    120         }
    121         if (c.isEmpty()) {
    122             throw new IllegalArgumentException();
    123         }
    124         Iterator<E> iterator = c.iterator();
    125         E element = iterator.next();
    126         EnumSet<E> set = EnumSet.noneOf(element.getDeclaringClass());
    127         set.add(element);
    128         while (iterator.hasNext()) {
    129             set.add(iterator.next());
    130         }
    131         return set;
    132     }
    133 
    134     /**
    135      * Creates an enum set. All the contained elements complement those from the
    136      * specified enum set.
    137      *
    138      * @param s
    139      *            the specified enum set.
    140      * @return an enum set with all the elements complementary to those from the
    141      *         specified enum set.
    142      * @throws NullPointerException
    143      *             if {@code s} is {@code null}.
    144      */
    145     public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) {
    146         EnumSet<E> set = EnumSet.noneOf(s.elementClass);
    147         set.addAll(s);
    148         set.complement();
    149         return set;
    150     }
    151 
    152     abstract void complement();
    153 
    154     /**
    155      * Creates a new enum set, containing only the specified element. There are
    156      * six overloadings of the method. They accept from one to five elements
    157      * respectively. The sixth one receives an arbitrary number of elements, and
    158      * runs slower than those that only receive a fixed number of elements.
    159      *
    160      * @param e
    161      *            the element to be initially contained.
    162      * @return an enum set containing the specified element.
    163      * @throws NullPointerException
    164      *             if {@code e} is {@code null}.
    165      */
    166     public static <E extends Enum<E>> EnumSet<E> of(E e) {
    167         EnumSet<E> set = EnumSet.noneOf(e.getDeclaringClass());
    168         set.add(e);
    169         return set;
    170     }
    171 
    172     /**
    173      * Creates a new enum set, containing only the specified elements. There are
    174      * six overloadings of the method. They accept from one to five elements
    175      * respectively. The sixth one receives an arbitrary number of elements, and
    176      * runs slower than those that only receive a fixed number of elements.
    177      *
    178      * @param e1
    179      *            the initially contained element.
    180      * @param e2
    181      *            another initially contained element.
    182      * @return an enum set containing the specified elements.
    183      * @throws NullPointerException
    184      *             if any of the specified elements is {@code null}.
    185      */
    186     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) {
    187         EnumSet<E> set = of(e1);
    188         set.add(e2);
    189         return set;
    190     }
    191 
    192     /**
    193      * Creates a new enum set, containing only the specified elements. There are
    194      * six overloadings of the method. They accept from one to five elements
    195      * respectively. The sixth one receives an arbitrary number of elements, and
    196      * runs slower than those that only receive a fixed number of elements.
    197      *
    198      * @param e1
    199      *            the initially contained element.
    200      * @param e2
    201      *            another initially contained element.
    202      * @param e3
    203      *            another initially contained element.
    204      * @return an enum set containing the specified elements.
    205      * @throws NullPointerException
    206      *             if any of the specified elements is {@code null}.
    207      */
    208     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) {
    209         EnumSet<E> set = of(e1, e2);
    210         set.add(e3);
    211         return set;
    212     }
    213 
    214     /**
    215      * Creates a new enum set, containing only the specified elements. There are
    216      * six overloadings of the method. They accept from one to five elements
    217      * respectively. The sixth one receives an arbitrary number of elements, and
    218      * runs slower than those that only receive a fixed number of elements.
    219      *
    220      * @param e1
    221      *            the initially contained element.
    222      * @param e2
    223      *            another initially contained element.
    224      * @param e3
    225      *            another initially contained element.
    226      * @param e4
    227      *            another initially contained element.
    228      * @return an enum set containing the specified elements.
    229      * @throws NullPointerException
    230      *             if any of the specified elements is {@code null}.
    231      */
    232     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4) {
    233         EnumSet<E> set = of(e1, e2, e3);
    234         set.add(e4);
    235         return set;
    236     }
    237 
    238     /**
    239      * Creates a new enum set, containing only the specified elements. There are
    240      * six overloadings of the method. They accept from one to five elements
    241      * respectively. The sixth one receives an arbitrary number of elements, and
    242      * runs slower than those that only receive a fixed number of elements.
    243      *
    244      * @param e1
    245      *            the initially contained element.
    246      * @param e2
    247      *            another initially contained element.
    248      * @param e3
    249      *            another initially contained element.
    250      * @param e4
    251      *            another initially contained element.
    252      * @param e5
    253      *            another initially contained element.
    254      * @return an enum set containing the specified elements.
    255      * @throws NullPointerException
    256      *             if any of the specified elements is {@code null}.
    257      */
    258     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5) {
    259         EnumSet<E> set = of(e1, e2, e3, e4);
    260         set.add(e5);
    261         return set;
    262     }
    263 
    264     /**
    265      * Creates a new enum set, containing only the specified elements. It can
    266      * receive an arbitrary number of elements, and runs slower than those only
    267      * receiving a fixed number of elements.
    268      *
    269      * @param start
    270      *            the first initially contained element.
    271      * @param others
    272      *            the other initially contained elements.
    273      * @return an enum set containing the specified elements.
    274      * @throws NullPointerException
    275      *             if any of the specified elements is {@code null}.
    276      */
    277     public static <E extends Enum<E>> EnumSet<E> of(E start, E... others) {
    278         EnumSet<E> set = of(start);
    279         for (E e : others) {
    280             set.add(e);
    281         }
    282         return set;
    283     }
    284 
    285     /**
    286      * Creates an enum set containing all the elements within the range defined
    287      * by {@code start} and {@code end} (inclusive). All the elements must be in
    288      * order.
    289      *
    290      * @param start
    291      *            the element used to define the beginning of the range.
    292      * @param end
    293      *            the element used to define the end of the range.
    294      * @return an enum set with elements in the range from start to end.
    295      * @throws NullPointerException
    296      *             if any one of {@code start} or {@code end} is {@code null}.
    297      * @throws IllegalArgumentException
    298      *             if {@code start} is behind {@code end}.
    299      */
    300     public static <E extends Enum<E>> EnumSet<E> range(E start, E end) {
    301         if (start.compareTo(end) > 0) {
    302             throw new IllegalArgumentException();
    303         }
    304         EnumSet<E> set = EnumSet.noneOf(start.getDeclaringClass());
    305         set.setRange(start, end);
    306         return set;
    307     }
    308 
    309     abstract void setRange(E start, E end);
    310 
    311     /**
    312      * Creates a new enum set with the same elements as those contained in this
    313      * enum set.
    314      *
    315      * @return a new enum set with the same elements as those contained in this
    316      *         enum set.
    317      */
    318     @SuppressWarnings("unchecked")
    319     @Override
    320     public EnumSet<E> clone() {
    321         try {
    322             return (EnumSet<E>) super.clone();
    323         } catch (CloneNotSupportedException e) {
    324             throw new AssertionError(e);
    325         }
    326     }
    327 
    328     boolean isValidType(Class<?> cls) {
    329         return cls == elementClass || cls.getSuperclass() == elementClass;
    330     }
    331 
    332     private static class SerializationProxy<E extends Enum<E>> implements
    333             Serializable {
    334 
    335         private static final long serialVersionUID = 362491234563181265L;
    336 
    337         private Class<E> elementType;
    338 
    339         private E[] elements;
    340 
    341         private Object readResolve() {
    342             EnumSet<E> set = EnumSet.noneOf(elementType);
    343             for (E e : elements) {
    344                 set.add(e);
    345             }
    346             return set;
    347         }
    348     }
    349 
    350     @SuppressWarnings("unchecked")
    351     Object writeReplace() {
    352         SerializationProxy proxy = new SerializationProxy();
    353         proxy.elements = toArray(new Enum[0]);
    354         proxy.elementType = elementClass;
    355         return proxy;
    356     }
    357 }
    358