001: /* Licensed to the Apache Software Foundation (ASF) under one or more
002: * contributor license agreements. See the NOTICE file distributed with
003: * this work for additional information regarding copyright ownership.
004: * The ASF licenses this file to You under the Apache License, Version 2.0
005: * (the "License"); you may not use this file except in compliance with
006: * the License. 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: package java.util;
017:
018: import java.io.Serializable;
019:
020: public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
021: implements Cloneable, Serializable {
022:
023: private static final long serialVersionUID = 4782406773684236311L;
024:
025: final Class<E> elementClass;
026:
027: EnumSet(Class<E> cls) {
028: elementClass = cls;
029: }
030:
031: /**
032: * Creates an empty enum set. The permitted elements are of type Class<E>.
033: *
034: * @param elementType
035: * the class object for the elements contained
036: * @return an empty enum set, with permitted elements of the specified
037: * elementType
038: * @throws NullPointerException
039: * if the specified elementType is null
040: */
041: public static <E extends Enum<E>> EnumSet<E> noneOf(
042: Class<E> elementType) {
043: if (!elementType.isEnum()) {
044: throw new ClassCastException();
045: }
046: if (elementType.getEnumConstants().length <= 64) {
047: return new MiniEnumSet<E>(elementType);
048: }
049: return new HugeEnumSet<E>(elementType);
050: }
051:
052: /**
053: * Creates an enum set. Element is contained in this enum set if and only if
054: * it is a member of the specified element type.
055: *
056: * @param elementType
057: * the class object for the elements contained
058: * @return an enum set with elements solely from the specified element type
059: * @throws NullPointerException
060: * if the specified elementType is null
061: */
062: public static <E extends Enum<E>> EnumSet<E> allOf(
063: Class<E> elementType) {
064: EnumSet<E> set = noneOf(elementType);
065: set.complement();
066: return set;
067: }
068:
069: /**
070: * Creates an enum set. All the contained elements are of type Class<E>,
071: * and the contained elements are the same as those contained in s.
072: *
073: * @param s
074: * the enum set from which to copy
075: * @return an enum set with all the elements from the specified enum set
076: * @throws NullPointerException
077: * if the specified enum set is null
078: */
079: public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) {
080: EnumSet<E> set = EnumSet.noneOf(s.elementClass);
081: set.addAll(s);
082: return set;
083: }
084:
085: /**
086: * Creates an enum set. The contained elements are the same as those
087: * contained in collection c. If c is an enum set, invoking this method is
088: * the same as invoking {@link #copyOf(EnumSet)}.
089: *
090: * @param c
091: * the collection from which to copy
092: * @return an enum set with all the elements from the specified collection
093: * @throws IllegalArgumentException
094: * if c is not an enum set and contains no elements at all
095: * @throws NullPointerException
096: * if the specified collection is null
097: */
098: public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) {
099: if (c instanceof EnumSet) {
100: return copyOf((EnumSet<E>) c);
101: }
102: if (0 == c.size()) {
103: throw new IllegalArgumentException();
104: }
105: Iterator<E> iterator = c.iterator();
106: E element = iterator.next();
107: EnumSet<E> set = EnumSet.noneOf(element.getDeclaringClass());
108: set.add(element);
109: while (iterator.hasNext()) {
110: set.add(iterator.next());
111: }
112: return set;
113: }
114:
115: /**
116: * Creates an enum set. All the contained elements complement those from the
117: * specified enum set.
118: *
119: * @param s
120: * the specified enum set
121: * @return an enum set with all the elements complement those from the
122: * specified enum set
123: * @throws NullPointerException
124: * if the specified enum set is null
125: */
126: public static <E extends Enum<E>> EnumSet<E> complementOf(
127: EnumSet<E> s) {
128: EnumSet<E> set = EnumSet.noneOf(s.elementClass);
129: set.addAll(s);
130: set.complement();
131: return set;
132: }
133:
134: abstract void complement();
135:
136: /**
137: * Creates a new enum set, containing only the specified element. There are
138: * six overloadings of the method. They accept from one to five elements
139: * respectively. The sixth one receives arbitrary number of elements, and
140: * runs slower than those only receive fixed number of elements.
141: *
142: * @param e
143: * the initially contained element
144: * @return an enum set containing the specified element
145: * @throws NullPointerException
146: * if the specified element is null
147: */
148: public static <E extends Enum<E>> EnumSet<E> of(E e) {
149: EnumSet<E> set = EnumSet.noneOf(e.getDeclaringClass());
150: set.add(e);
151: return set;
152: }
153:
154: /**
155: * Creates a new enum set, containing only the specified elements. There are
156: * six overloadings of the method. They accept from one to five elements
157: * respectively. The sixth one receives arbitrary number of elements, and
158: * runs slower than those only receive fixed number of elements.
159: *
160: * @param e1
161: * the initially contained element
162: * @param e2
163: * another initially contained element
164: * @return an enum set containing the specified elements
165: * @throws NullPointerException
166: * if any of the specified elements is null
167: */
168: public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) {
169: EnumSet<E> set = of(e1);
170: set.add(e2);
171: return set;
172: }
173:
174: /**
175: * Creates a new enum set, containing only the specified elements. There are
176: * six overloadings of the method. They accept from one to five elements
177: * respectively. The sixth one receives arbitrary number of elements, and
178: * runs slower than those only receive fixed number of elements.
179: *
180: * @param e1
181: * the initially contained element
182: * @param e2
183: * another initially contained element
184: * @param e3
185: * another initially contained element
186: * @return an enum set containing the specified elements
187: * @throws NullPointerException
188: * if any of the specified elements is null
189: */
190: public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) {
191: EnumSet<E> set = of(e1, e2);
192: set.add(e3);
193: return set;
194: }
195:
196: /**
197: * Creates a new enum set, containing only the specified elements. There are
198: * six overloadings of the method. They accept from one to five elements
199: * respectively. The sixth one receives arbitrary number of elements, and
200: * runs slower than those only receive fixed number of elements.
201: *
202: * @param e1
203: * the initially contained element
204: * @param e2
205: * another initially contained element
206: * @param e3
207: * another initially contained element
208: * @param e4
209: * another initially contained element
210: * @return an enum set containing the specified elements
211: * @throws NullPointerException
212: * if any of the specified elements is null
213: */
214: public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3,
215: E e4) {
216: EnumSet<E> set = of(e1, e2, e3);
217: set.add(e4);
218: return set;
219: }
220:
221: /**
222: * Creates a new enum set, containing only the specified elements. There are
223: * six overloadings of the method. They accept from one to five elements
224: * respectively. The sixth one receives arbitrary number of elements, and
225: * runs slower than those only receive fixed number of elements.
226: *
227: * @param e1
228: * the initially contained element
229: * @param e2
230: * another initially contained element
231: * @param e3
232: * another initially contained element
233: * @param e4
234: * another initially contained element
235: * @param e5
236: * another initially contained element
237: * @return an enum set containing the specified elements
238: * @throws NullPointerException
239: * if any of the specified elements is null
240: */
241: public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3,
242: E e4, E e5) {
243: EnumSet<E> set = of(e1, e2, e3, e4);
244: set.add(e5);
245: return set;
246: }
247:
248: /**
249: * Creates a new enum set, containing only the specified elements. It
250: * receives arbitrary number of elements, and runs slower than those only
251: * receive fixed number of elements.
252: *
253: * @param start
254: * the first initially contained element
255: * @param others
256: * the other initially contained elements
257: * @return an enum set containing the specified elements
258: * @throws NullPointerException
259: * if any of the specified elements is null
260: */
261: public static <E extends Enum<E>> EnumSet<E> of(E start,
262: E... others) {
263: EnumSet<E> set = of(start);
264: for (E e : others) {
265: set.add(e);
266: }
267: return set;
268: }
269:
270: /**
271: * Creates an enum set containing all the elements within the range defined
272: * by start and end (inclusive). All the elements must be in order.
273: *
274: * @param start
275: * the element used to define the beginning of the range
276: * @param end
277: * the element used to define the end of the range
278: * @return an enum set with elements in the range from start to end
279: * @throws NullPointerException
280: * if any one of start or end is null
281: * @throws IllegalArgumentException
282: * if start is behind end
283: */
284: public static <E extends Enum<E>> EnumSet<E> range(E start, E end) {
285: if (start.compareTo(end) > 0) {
286: throw new IllegalArgumentException();
287: }
288: EnumSet<E> set = EnumSet.noneOf(start.getDeclaringClass());
289: set.setRange(start, end);
290: return set;
291: }
292:
293: abstract void setRange(E start, E end);
294:
295: /**
296: * Creates a new enum set with the same elements as those contained in this
297: * enum set.
298: *
299: * @return a new enum set with the same elements as those contained in this
300: * enum set
301: */
302: @SuppressWarnings("unchecked")
303: @Override
304: public EnumSet<E> clone() {
305: try {
306: Object set = super .clone();
307: return (EnumSet<E>) set;
308: } catch (CloneNotSupportedException e) {
309: return null;
310: }
311: }
312:
313: @SuppressWarnings("unchecked")
314: boolean isValidType(Class cls) {
315: return cls == elementClass
316: || cls.getSuperclass() == elementClass;
317: }
318:
319: private static class SerializationProxy<E extends Enum<E>>
320: implements Serializable {
321:
322: private static final long serialVersionUID = 362491234563181265L;
323:
324: private Class<E> elementType;
325:
326: private E[] elements;
327:
328: private Object readResolve() {
329: EnumSet<E> set = EnumSet.noneOf(elementType);
330: for (E e : elements) {
331: set.add(e);
332: }
333: return set;
334: }
335: }
336:
337: @SuppressWarnings("unchecked")
338: Object writeReplace() {
339: SerializationProxy proxy = new SerializationProxy();
340: proxy.elements = toArray(new Enum[0]);
341: proxy.elementType = elementClass;
342: return proxy;
343: }
344: }
|