/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 java.util; import java.io.Serializable; /** * An EnumSet is a specialized Set to be used with enums as keys. */ public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> implements Cloneable, Serializable { private static final long serialVersionUID = 1009687484059888093L; final Class<E> elementClass; EnumSet(Class<E> cls) { elementClass = cls; } /** * Creates an empty enum set. The permitted elements are of type * Class<E>. * * @param elementType * the class object for the elements contained. * @return an empty enum set, with permitted elements of type {@code * elementType}. * @throws ClassCastException * if the specified element type is not and enum type. */ public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) { if (!elementType.isEnum()) { throw new ClassCastException(elementType.getClass().getName() + " is not an Enum"); } E[] enums = Enum.getSharedConstants(elementType); if (enums.length <= 64) { return new MiniEnumSet<E>(elementType, enums); } return new HugeEnumSet<E>(elementType, enums); } /** * Creates an enum set filled with all the enum elements of the specified * {@code elementType}. * * @param elementType * the class object for the elements contained. * @return an enum set with elements solely from the specified element type. * @throws ClassCastException * if the specified element type is not and enum type. */ public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) { EnumSet<E> set = noneOf(elementType); set.complement(); return set; } /** * Creates an enum set. All the contained elements are of type * Class<E>, and the contained elements are the same as those * contained in {@code s}. * * @param s * the enum set from which to copy. * @return an enum set with all the elements from the specified enum set. * @throws ClassCastException * if the specified element type is not and enum type. */ public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) { EnumSet<E> set = EnumSet.noneOf(s.elementClass); set.addAll(s); return set; } /** * Creates an enum set. The contained elements are the same as those * contained in collection {@code c}. If c is an enum set, invoking this * method is the same as invoking {@link #copyOf(EnumSet)}. * * @param c * the collection from which to copy. if it is not an enum set, * it must not be empty. * @return an enum set with all the elements from the specified collection. * @throws IllegalArgumentException * if c is not an enum set and contains no elements at all. * @throws NullPointerException * if {@code c} is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) { if (c instanceof EnumSet) { return copyOf((EnumSet<E>) c); } if (c.isEmpty()) { throw new IllegalArgumentException("empty collection"); } Iterator<E> iterator = c.iterator(); E element = iterator.next(); EnumSet<E> set = EnumSet.noneOf(element.getDeclaringClass()); set.add(element); while (iterator.hasNext()) { set.add(iterator.next()); } return set; } /** * Creates an enum set. All the contained elements complement those from the * specified enum set. * * @param s * the specified enum set. * @return an enum set with all the elements complementary to those from the * specified enum set. * @throws NullPointerException * if {@code s} is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) { EnumSet<E> set = EnumSet.noneOf(s.elementClass); set.addAll(s); set.complement(); return set; } abstract void complement(); /** * Creates a new enum set, containing only the specified element. There are * six overloadings of the method. They accept from one to five elements * respectively. The sixth one receives an arbitrary number of elements, and * runs slower than those that only receive a fixed number of elements. * * @param e * the element to be initially contained. * @return an enum set containing the specified element. * @throws NullPointerException * if {@code e} is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> of(E e) { EnumSet<E> set = EnumSet.noneOf(e.getDeclaringClass()); set.add(e); return set; } /** * Creates a new enum set, containing only the specified elements. There are * six overloadings of the method. They accept from one to five elements * respectively. The sixth one receives an arbitrary number of elements, and * runs slower than those that only receive a fixed number of elements. * * @param e1 * the initially contained element. * @param e2 * another initially contained element. * @return an enum set containing the specified elements. * @throws NullPointerException * if any of the specified elements is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) { EnumSet<E> set = of(e1); set.add(e2); return set; } /** * Creates a new enum set, containing only the specified elements. There are * six overloadings of the method. They accept from one to five elements * respectively. The sixth one receives an arbitrary number of elements, and * runs slower than those that only receive a fixed number of elements. * * @param e1 * the initially contained element. * @param e2 * another initially contained element. * @param e3 * another initially contained element. * @return an enum set containing the specified elements. * @throws NullPointerException * if any of the specified elements is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) { EnumSet<E> set = of(e1, e2); set.add(e3); return set; } /** * Creates a new enum set, containing only the specified elements. There are * six overloadings of the method. They accept from one to five elements * respectively. The sixth one receives an arbitrary number of elements, and * runs slower than those that only receive a fixed number of elements. * * @param e1 * the initially contained element. * @param e2 * another initially contained element. * @param e3 * another initially contained element. * @param e4 * another initially contained element. * @return an enum set containing the specified elements. * @throws NullPointerException * if any of the specified elements is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4) { EnumSet<E> set = of(e1, e2, e3); set.add(e4); return set; } /** * Creates a new enum set, containing only the specified elements. There are * six overloadings of the method. They accept from one to five elements * respectively. The sixth one receives an arbitrary number of elements, and * runs slower than those that only receive a fixed number of elements. * * @param e1 * the initially contained element. * @param e2 * another initially contained element. * @param e3 * another initially contained element. * @param e4 * another initially contained element. * @param e5 * another initially contained element. * @return an enum set containing the specified elements. * @throws NullPointerException * if any of the specified elements is {@code null}. */ public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5) { EnumSet<E> set = of(e1, e2, e3, e4); set.add(e5); return set; } /** * Creates a new enum set, containing only the specified elements. It can * receive an arbitrary number of elements, and runs slower than those only * receiving a fixed number of elements. * * @param start * the first initially contained element. * @param others * the other initially contained elements. * @return an enum set containing the specified elements. * @throws NullPointerException * if any of the specified elements is {@code null}. */ @SafeVarargs public static <E extends Enum<E>> EnumSet<E> of(E start, E... others) { EnumSet<E> set = of(start); for (E e : others) { set.add(e); } return set; } /** * Creates an enum set containing all the elements within the range defined * by {@code start} and {@code end} (inclusive). All the elements must be in * order. * * @param start * the element used to define the beginning of the range. * @param end * the element used to define the end of the range. * @return an enum set with elements in the range from start to end. * @throws NullPointerException * if any one of {@code start} or {@code end} is {@code null}. * @throws IllegalArgumentException * if {@code start} is behind {@code end}. */ public static <E extends Enum<E>> EnumSet<E> range(E start, E end) { if (start.compareTo(end) > 0) { throw new IllegalArgumentException("start is behind end"); } EnumSet<E> set = EnumSet.noneOf(start.getDeclaringClass()); set.setRange(start, end); return set; } abstract void setRange(E start, E end); /** * Creates a new enum set with the same elements as those contained in this * enum set. * * @return a new enum set with the same elements as those contained in this * enum set. */ @SuppressWarnings("unchecked") @Override public EnumSet<E> clone() { try { return (EnumSet<E>) super.clone(); } catch (CloneNotSupportedException e) { throw new AssertionError(e); } } boolean isValidType(Class<?> cls) { return cls == elementClass || cls.getSuperclass() == elementClass; } private static class SerializationProxy<E extends Enum<E>> implements Serializable { private static final long serialVersionUID = 362491234563181265L; private Class<E> elementType; private E[] elements; private Object readResolve() { EnumSet<E> set = EnumSet.noneOf(elementType); for (E e : elements) { set.add(e); } return set; } } @SuppressWarnings("unchecked") Object writeReplace() { SerializationProxy proxy = new SerializationProxy(); proxy.elements = toArray(new Enum[0]); proxy.elementType = elementClass; return proxy; } }