# HG changeset patch # User Jaroslav Tulach # Date 1379879382 -7200 # Node ID 9cf04876e4a576df00d2171100a2b2f8099ba481 # Parent c1e76ee3136005dbe8d3966cfa7df535a8d388c8 Need EnumMap, EnumSet for the javac diff -r c1e76ee31360 -r 9cf04876e4a5 emul/compact/src/main/java/java/util/EnumMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/EnumMap.java Sun Sep 22 21:49:42 2013 +0200 @@ -0,0 +1,799 @@ +/* + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util; + +import java.util.Map.Entry; +import sun.misc.SharedSecrets; + +/** + * A specialized {@link Map} implementation for use with enum type keys. All + * of the keys in an enum map must come from a single enum type that is + * specified, explicitly or implicitly, when the map is created. Enum maps + * are represented internally as arrays. This representation is extremely + * compact and efficient. + * + *

Enum maps are maintained in the natural order of their keys + * (the order in which the enum constants are declared). This is reflected + * in the iterators returned by the collections views ({@link #keySet()}, + * {@link #entrySet()}, and {@link #values()}). + * + *

Iterators returned by the collection views are weakly consistent: + * they will never throw {@link ConcurrentModificationException} and they may + * or may not show the effects of any modifications to the map that occur while + * the iteration is in progress. + * + *

Null keys are not permitted. Attempts to insert a null key will + * throw {@link NullPointerException}. Attempts to test for the + * presence of a null key or to remove one will, however, function properly. + * Null values are permitted. + + *

Like most collection implementations EnumMap is not + * synchronized. If multiple threads access an enum map concurrently, and at + * least one of the threads modifies the map, it should be synchronized + * externally. This is typically accomplished by synchronizing on some + * object that naturally encapsulates the enum map. If no such object exists, + * the map should be "wrapped" using the {@link Collections#synchronizedMap} + * method. This is best done at creation time, to prevent accidental + * unsynchronized access: + * + *

+ *     Map<EnumKey, V> m
+ *         = Collections.synchronizedMap(new EnumMap<EnumKey, V>(...));
+ * 
+ * + *

Implementation note: All basic operations execute in constant time. + * They are likely (though not guaranteed) to be faster than their + * {@link HashMap} counterparts. + * + *

This class is a member of the + * + * Java Collections Framework. + * + * @author Josh Bloch + * @see EnumSet + * @since 1.5 + */ +public class EnumMap, V> extends AbstractMap + implements java.io.Serializable, Cloneable +{ + /** + * The Class object for the enum type of all the keys of this map. + * + * @serial + */ + private final Class keyType; + + /** + * All of the values comprising K. (Cached for performance.) + */ + private transient K[] keyUniverse; + + /** + * Array representation of this map. The ith element is the value + * to which universe[i] is currently mapped, or null if it isn't + * mapped to anything, or NULL if it's mapped to null. + */ + private transient Object[] vals; + + /** + * The number of mappings in this map. + */ + private transient int size = 0; + + /** + * Distinguished non-null value for representing null values. + */ + private static final Object NULL = new Integer(0); + + private Object maskNull(Object value) { + return (value == null ? NULL : value); + } + + private V unmaskNull(Object value) { + return (V) (value == NULL ? null : value); + } + + private static final Enum[] ZERO_LENGTH_ENUM_ARRAY = new Enum[0]; + + /** + * Creates an empty enum map with the specified key type. + * + * @param keyType the class object of the key type for this enum map + * @throws NullPointerException if keyType is null + */ + public EnumMap(Class keyType) { + this.keyType = keyType; + keyUniverse = getKeyUniverse(keyType); + vals = new Object[keyUniverse.length]; + } + + /** + * Creates an enum map with the same key type as the specified enum + * map, initially containing the same mappings (if any). + * + * @param m the enum map from which to initialize this enum map + * @throws NullPointerException if m is null + */ + public EnumMap(EnumMap m) { + keyType = m.keyType; + keyUniverse = m.keyUniverse; + vals = m.vals.clone(); + size = m.size; + } + + /** + * Creates an enum map initialized from the specified map. If the + * specified map is an EnumMap instance, this constructor behaves + * identically to {@link #EnumMap(EnumMap)}. Otherwise, the specified map + * must contain at least one mapping (in order to determine the new + * enum map's key type). + * + * @param m the map from which to initialize this enum map + * @throws IllegalArgumentException if m is not an + * EnumMap instance and contains no mappings + * @throws NullPointerException if m is null + */ + public EnumMap(Map m) { + if (m instanceof EnumMap) { + EnumMap em = (EnumMap) m; + keyType = em.keyType; + keyUniverse = em.keyUniverse; + vals = em.vals.clone(); + size = em.size; + } else { + if (m.isEmpty()) + throw new IllegalArgumentException("Specified map is empty"); + keyType = m.keySet().iterator().next().getDeclaringClass(); + keyUniverse = getKeyUniverse(keyType); + vals = new Object[keyUniverse.length]; + putAll(m); + } + } + + // Query Operations + + /** + * Returns the number of key-value mappings in this map. + * + * @return the number of key-value mappings in this map + */ + public int size() { + return size; + } + + /** + * Returns true if this map maps one or more keys to the + * specified value. + * + * @param value the value whose presence in this map is to be tested + * @return true if this map maps one or more keys to this value + */ + public boolean containsValue(Object value) { + value = maskNull(value); + + for (Object val : vals) + if (value.equals(val)) + return true; + + return false; + } + + /** + * Returns true if this map contains a mapping for the specified + * key. + * + * @param key the key whose presence in this map is to be tested + * @return true if this map contains a mapping for the specified + * key + */ + public boolean containsKey(Object key) { + return isValidKey(key) && vals[((Enum)key).ordinal()] != null; + } + + private boolean containsMapping(Object key, Object value) { + return isValidKey(key) && + maskNull(value).equals(vals[((Enum)key).ordinal()]); + } + + /** + * Returns the value to which the specified key is mapped, + * or {@code null} if this map contains no mapping for the key. + * + *

More formally, if this map contains a mapping from a key + * {@code k} to a value {@code v} such that {@code (key == k)}, + * then this method returns {@code v}; otherwise it returns + * {@code null}. (There can be at most one such mapping.) + * + *

A return value of {@code null} does not necessarily + * indicate that the map contains no mapping for the key; it's also + * possible that the map explicitly maps the key to {@code null}. + * The {@link #containsKey containsKey} operation may be used to + * distinguish these two cases. + */ + public V get(Object key) { + return (isValidKey(key) ? + unmaskNull(vals[((Enum)key).ordinal()]) : null); + } + + // Modification Operations + + /** + * Associates the specified value with the specified key in this map. + * If the map previously contained a mapping for this key, the old + * value is replaced. + * + * @param key the key with which the specified value is to be associated + * @param value the value to be associated with the specified key + * + * @return the previous value associated with specified key, or + * null if there was no mapping for key. (A null + * return can also indicate that the map previously associated + * null with the specified key.) + * @throws NullPointerException if the specified key is null + */ + public V put(K key, V value) { + typeCheck(key); + + int index = key.ordinal(); + Object oldValue = vals[index]; + vals[index] = maskNull(value); + if (oldValue == null) + size++; + return unmaskNull(oldValue); + } + + /** + * Removes the mapping for this key from this map if present. + * + * @param key the key whose mapping is to be removed from the map + * @return the previous value associated with specified key, or + * null if there was no entry for key. (A null + * return can also indicate that the map previously associated + * null with the specified key.) + */ + public V remove(Object key) { + if (!isValidKey(key)) + return null; + int index = ((Enum)key).ordinal(); + Object oldValue = vals[index]; + vals[index] = null; + if (oldValue != null) + size--; + return unmaskNull(oldValue); + } + + private boolean removeMapping(Object key, Object value) { + if (!isValidKey(key)) + return false; + int index = ((Enum)key).ordinal(); + if (maskNull(value).equals(vals[index])) { + vals[index] = null; + size--; + return true; + } + return false; + } + + /** + * Returns true if key is of the proper type to be a key in this + * enum map. + */ + private boolean isValidKey(Object key) { + if (key == null) + return false; + + // Cheaper than instanceof Enum followed by getDeclaringClass + Class keyClass = key.getClass(); + return keyClass == keyType || keyClass.getSuperclass() == keyType; + } + + // Bulk Operations + + /** + * Copies all of the mappings from the specified map to this map. + * These mappings will replace any mappings that this map had for + * any of the keys currently in the specified map. + * + * @param m the mappings to be stored in this map + * @throws NullPointerException the specified map is null, or if + * one or more keys in the specified map are null + */ + public void putAll(Map m) { + if (m instanceof EnumMap) { + EnumMap em = + (EnumMap)m; + if (em.keyType != keyType) { + if (em.isEmpty()) + return; + throw new ClassCastException(em.keyType + " != " + keyType); + } + + for (int i = 0; i < keyUniverse.length; i++) { + Object emValue = em.vals[i]; + if (emValue != null) { + if (vals[i] == null) + size++; + vals[i] = emValue; + } + } + } else { + super.putAll(m); + } + } + + /** + * Removes all mappings from this map. + */ + public void clear() { + Arrays.fill(vals, null); + size = 0; + } + + // Views + + /** + * This field is initialized to contain an instance of the entry set + * view the first time this view is requested. The view is stateless, + * so there's no reason to create more than one. + */ + private transient Set> entrySet = null; + + /** + * Returns a {@link Set} view of the keys contained in this map. + * The returned set obeys the general contract outlined in + * {@link Map#keySet()}. The set's iterator will return the keys + * in their natural order (the order in which the enum constants + * are declared). + * + * @return a set view of the keys contained in this enum map + */ + public Set keySet() { + Set ks = keySet; + if (ks != null) + return ks; + else + return keySet = new KeySet(); + } + + private class KeySet extends AbstractSet { + public Iterator iterator() { + return new KeyIterator(); + } + public int size() { + return size; + } + public boolean contains(Object o) { + return containsKey(o); + } + public boolean remove(Object o) { + int oldSize = size; + EnumMap.this.remove(o); + return size != oldSize; + } + public void clear() { + EnumMap.this.clear(); + } + } + + /** + * Returns a {@link Collection} view of the values contained in this map. + * The returned collection obeys the general contract outlined in + * {@link Map#values()}. The collection's iterator will return the + * values in the order their corresponding keys appear in map, + * which is their natural order (the order in which the enum constants + * are declared). + * + * @return a collection view of the values contained in this map + */ + public Collection values() { + Collection vs = values; + if (vs != null) + return vs; + else + return values = new Values(); + } + + private class Values extends AbstractCollection { + public Iterator iterator() { + return new ValueIterator(); + } + public int size() { + return size; + } + public boolean contains(Object o) { + return containsValue(o); + } + public boolean remove(Object o) { + o = maskNull(o); + + for (int i = 0; i < vals.length; i++) { + if (o.equals(vals[i])) { + vals[i] = null; + size--; + return true; + } + } + return false; + } + public void clear() { + EnumMap.this.clear(); + } + } + + /** + * Returns a {@link Set} view of the mappings contained in this map. + * The returned set obeys the general contract outlined in + * {@link Map#keySet()}. The set's iterator will return the + * mappings in the order their keys appear in map, which is their + * natural order (the order in which the enum constants are declared). + * + * @return a set view of the mappings contained in this enum map + */ + public Set> entrySet() { + Set> es = entrySet; + if (es != null) + return es; + else + return entrySet = new EntrySet(); + } + + private class EntrySet extends AbstractSet> { + public Iterator> iterator() { + return new EntryIterator(); + } + + public boolean contains(Object o) { + if (!(o instanceof Map.Entry)) + return false; + Map.Entry entry = (Map.Entry)o; + return containsMapping(entry.getKey(), entry.getValue()); + } + public boolean remove(Object o) { + if (!(o instanceof Map.Entry)) + return false; + Map.Entry entry = (Map.Entry)o; + return removeMapping(entry.getKey(), entry.getValue()); + } + public int size() { + return size; + } + public void clear() { + EnumMap.this.clear(); + } + public Object[] toArray() { + return fillEntryArray(new Object[size]); + } + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) { + int size = size(); + if (a.length < size) + a = (T[])java.lang.reflect.Array + .newInstance(a.getClass().getComponentType(), size); + if (a.length > size) + a[size] = null; + return (T[]) fillEntryArray(a); + } + private Object[] fillEntryArray(Object[] a) { + int j = 0; + for (int i = 0; i < vals.length; i++) + if (vals[i] != null) + a[j++] = new AbstractMap.SimpleEntry<>( + keyUniverse[i], unmaskNull(vals[i])); + return a; + } + } + + private abstract class EnumMapIterator implements Iterator { + // Lower bound on index of next element to return + int index = 0; + + // Index of last returned element, or -1 if none + int lastReturnedIndex = -1; + + public boolean hasNext() { + while (index < vals.length && vals[index] == null) + index++; + return index != vals.length; + } + + public void remove() { + checkLastReturnedIndex(); + + if (vals[lastReturnedIndex] != null) { + vals[lastReturnedIndex] = null; + size--; + } + lastReturnedIndex = -1; + } + + private void checkLastReturnedIndex() { + if (lastReturnedIndex < 0) + throw new IllegalStateException(); + } + } + + private class KeyIterator extends EnumMapIterator { + public K next() { + if (!hasNext()) + throw new NoSuchElementException(); + lastReturnedIndex = index++; + return keyUniverse[lastReturnedIndex]; + } + } + + private class ValueIterator extends EnumMapIterator { + public V next() { + if (!hasNext()) + throw new NoSuchElementException(); + lastReturnedIndex = index++; + return unmaskNull(vals[lastReturnedIndex]); + } + } + + private class EntryIterator extends EnumMapIterator> { + private Entry lastReturnedEntry = null; + + public Map.Entry next() { + if (!hasNext()) + throw new NoSuchElementException(); + lastReturnedEntry = new Entry(index++); + return lastReturnedEntry; + } + + public void remove() { + lastReturnedIndex = + ((null == lastReturnedEntry) ? -1 : lastReturnedEntry.index); + super.remove(); + lastReturnedEntry.index = lastReturnedIndex; + lastReturnedEntry = null; + } + + private class Entry implements Map.Entry { + private int index; + + private Entry(int index) { + this.index = index; + } + + public K getKey() { + checkIndexForEntryUse(); + return keyUniverse[index]; + } + + public V getValue() { + checkIndexForEntryUse(); + return unmaskNull(vals[index]); + } + + public V setValue(V value) { + checkIndexForEntryUse(); + V oldValue = unmaskNull(vals[index]); + vals[index] = maskNull(value); + return oldValue; + } + + public boolean equals(Object o) { + if (index < 0) + return o == this; + + if (!(o instanceof Map.Entry)) + return false; + + Map.Entry e = (Map.Entry)o; + V ourValue = unmaskNull(vals[index]); + Object hisValue = e.getValue(); + return (e.getKey() == keyUniverse[index] && + (ourValue == hisValue || + (ourValue != null && ourValue.equals(hisValue)))); + } + + public int hashCode() { + if (index < 0) + return super.hashCode(); + + return entryHashCode(index); + } + + public String toString() { + if (index < 0) + return super.toString(); + + return keyUniverse[index] + "=" + + unmaskNull(vals[index]); + } + + private void checkIndexForEntryUse() { + if (index < 0) + throw new IllegalStateException("Entry was removed"); + } + } + } + + // Comparison and hashing + + /** + * Compares the specified object with this map for equality. Returns + * true if the given object is also a map and the two maps + * represent the same mappings, as specified in the {@link + * Map#equals(Object)} contract. + * + * @param o the object to be compared for equality with this map + * @return true if the specified object is equal to this map + */ + public boolean equals(Object o) { + if (this == o) + return true; + if (o instanceof EnumMap) + return equals((EnumMap)o); + if (!(o instanceof Map)) + return false; + + Map m = (Map)o; + if (size != m.size()) + return false; + + for (int i = 0; i < keyUniverse.length; i++) { + if (null != vals[i]) { + K key = keyUniverse[i]; + V value = unmaskNull(vals[i]); + if (null == value) { + if (!((null == m.get(key)) && m.containsKey(key))) + return false; + } else { + if (!value.equals(m.get(key))) + return false; + } + } + } + + return true; + } + + private boolean equals(EnumMap em) { + if (em.keyType != keyType) + return size == 0 && em.size == 0; + + // Key types match, compare each value + for (int i = 0; i < keyUniverse.length; i++) { + Object ourValue = vals[i]; + Object hisValue = em.vals[i]; + if (hisValue != ourValue && + (hisValue == null || !hisValue.equals(ourValue))) + return false; + } + return true; + } + + /** + * Returns the hash code value for this map. The hash code of a map is + * defined to be the sum of the hash codes of each entry in the map. + */ + public int hashCode() { + int h = 0; + + for (int i = 0; i < keyUniverse.length; i++) { + if (null != vals[i]) { + h += entryHashCode(i); + } + } + + return h; + } + + private int entryHashCode(int index) { + return (keyUniverse[index].hashCode() ^ vals[index].hashCode()); + } + + /** + * Returns a shallow copy of this enum map. (The values themselves + * are not cloned. + * + * @return a shallow copy of this enum map + */ + public EnumMap clone() { + EnumMap result = null; + try { + result = (EnumMap) super.clone(); + } catch(CloneNotSupportedException e) { + throw new AssertionError(); + } + result.vals = result.vals.clone(); + return result; + } + + /** + * Throws an exception if e is not of the correct type for this enum set. + */ + private void typeCheck(K key) { + Class keyClass = key.getClass(); + if (keyClass != keyType && keyClass.getSuperclass() != keyType) + throw new ClassCastException(keyClass + " != " + keyType); + } + + /** + * Returns all of the values comprising K. + * The result is uncloned, cached, and shared by all callers. + */ + private static > K[] getKeyUniverse(Class keyType) { + return SharedSecrets.getJavaLangAccess() + .getEnumConstantsShared(keyType); + } + + private static final long serialVersionUID = 458661240069192865L; + + /** + * Save the state of the EnumMap instance to a stream (i.e., + * serialize it). + * + * @serialData The size of the enum map (the number of key-value + * mappings) is emitted (int), followed by the key (Object) + * and value (Object) for each key-value mapping represented + * by the enum map. + */ + private void writeObject(java.io.ObjectOutputStream s) + throws java.io.IOException + { + // Write out the key type and any hidden stuff + s.defaultWriteObject(); + + // Write out size (number of Mappings) + s.writeInt(size); + + // Write out keys and values (alternating) + int entriesToBeWritten = size; + for (int i = 0; entriesToBeWritten > 0; i++) { + if (null != vals[i]) { + s.writeObject(keyUniverse[i]); + s.writeObject(unmaskNull(vals[i])); + entriesToBeWritten--; + } + } + } + + /** + * Reconstitute the EnumMap instance from a stream (i.e., + * deserialize it). + */ + private void readObject(java.io.ObjectInputStream s) + throws java.io.IOException, ClassNotFoundException + { + // Read in the key type and any hidden stuff + s.defaultReadObject(); + + keyUniverse = getKeyUniverse(keyType); + vals = new Object[keyUniverse.length]; + + // Read in size (number of Mappings) + int size = s.readInt(); + + // Read the keys and values, and put the mappings in the HashMap + for (int i = 0; i < size; i++) { + K key = (K) s.readObject(); + V value = (V) s.readObject(); + put(key, value); + } + } +} diff -r c1e76ee31360 -r 9cf04876e4a5 emul/compact/src/main/java/java/util/EnumSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/EnumSet.java Sun Sep 22 21:49:42 2013 +0200 @@ -0,0 +1,443 @@ +/* + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util; + +import sun.misc.SharedSecrets; + +/** + * A specialized {@link Set} implementation for use with enum types. All of + * the elements in an enum set must come from a single enum type that is + * specified, explicitly or implicitly, when the set is created. Enum sets + * are represented internally as bit vectors. This representation is + * extremely compact and efficient. The space and time performance of this + * class should be good enough to allow its use as a high-quality, typesafe + * alternative to traditional int-based "bit flags." Even bulk + * operations (such as containsAll and retainAll) should + * run very quickly if their argument is also an enum set. + * + *

The iterator returned by the iterator method traverses the + * elements in their natural order (the order in which the enum + * constants are declared). The returned iterator is weakly + * consistent: it will never throw {@link ConcurrentModificationException} + * and it may or may not show the effects of any modifications to the set that + * occur while the iteration is in progress. + * + *

Null elements are not permitted. Attempts to insert a null element + * will throw {@link NullPointerException}. Attempts to test for the + * presence of a null element or to remove one will, however, function + * properly. + * + *

Like most collection implementations, EnumSet is not + * synchronized. If multiple threads access an enum set concurrently, and at + * least one of the threads modifies the set, it should be synchronized + * externally. This is typically accomplished by synchronizing on some + * object that naturally encapsulates the enum set. If no such object exists, + * the set should be "wrapped" using the {@link Collections#synchronizedSet} + * method. This is best done at creation time, to prevent accidental + * unsynchronized access: + * + *

+ * Set<MyEnum> s = Collections.synchronizedSet(EnumSet.noneOf(MyEnum.class));
+ * 
+ * + *

Implementation note: All basic operations execute in constant time. + * They are likely (though not guaranteed) to be much faster than their + * {@link HashSet} counterparts. Even bulk operations execute in + * constant time if their argument is also an enum set. + * + *

This class is a member of the + * + * Java Collections Framework. + * + * @author Josh Bloch + * @since 1.5 + * @see EnumMap + * @serial exclude + */ +public abstract class EnumSet> extends AbstractSet + implements Cloneable, java.io.Serializable +{ + /** + * The class of all the elements of this set. + */ + final Class elementType; + + /** + * All of the values comprising T. (Cached for performance.) + */ + final Enum[] universe; + + private static Enum[] ZERO_LENGTH_ENUM_ARRAY = new Enum[0]; + + EnumSet(ClasselementType, Enum[] universe) { + this.elementType = elementType; + this.universe = universe; + } + + /** + * Creates an empty enum set with the specified element type. + * + * @param elementType the class object of the element type for this enum + * set + * @throws NullPointerException if elementType is null + */ + public static > EnumSet noneOf(Class elementType) { + Enum[] universe = getUniverse(elementType); + if (universe == null) + throw new ClassCastException(elementType + " not an enum"); + + if (universe.length <= 64) + return new RegularEnumSet<>(elementType, universe); + else + return new JumboEnumSet<>(elementType, universe); + } + + /** + * Creates an enum set containing all of the elements in the specified + * element type. + * + * @param elementType the class object of the element type for this enum + * set + * @throws NullPointerException if elementType is null + */ + public static > EnumSet allOf(Class elementType) { + EnumSet result = noneOf(elementType); + result.addAll(); + return result; + } + + /** + * Adds all of the elements from the appropriate enum type to this enum + * set, which is empty prior to the call. + */ + abstract void addAll(); + + /** + * Creates an enum set with the same element type as the specified enum + * set, initially containing the same elements (if any). + * + * @param s the enum set from which to initialize this enum set + * @throws NullPointerException if s is null + */ + public static > EnumSet copyOf(EnumSet s) { + return s.clone(); + } + + /** + * Creates an enum set initialized from the specified collection. If + * the specified collection is an EnumSet instance, this static + * factory method behaves identically to {@link #copyOf(EnumSet)}. + * Otherwise, the specified collection must contain at least one element + * (in order to determine the new enum set's element type). + * + * @param c the collection from which to initialize this enum set + * @throws IllegalArgumentException if c is not an + * EnumSet instance and contains no elements + * @throws NullPointerException if c is null + */ + public static > EnumSet copyOf(Collection c) { + if (c instanceof EnumSet) { + return ((EnumSet)c).clone(); + } else { + if (c.isEmpty()) + throw new IllegalArgumentException("Collection is empty"); + Iterator i = c.iterator(); + E first = i.next(); + EnumSet result = EnumSet.of(first); + while (i.hasNext()) + result.add(i.next()); + return result; + } + } + + /** + * Creates an enum set with the same element type as the specified enum + * set, initially containing all the elements of this type that are + * not contained in the specified set. + * + * @param s the enum set from whose complement to initialize this enum set + * @throws NullPointerException if s is null + */ + public static > EnumSet complementOf(EnumSet s) { + EnumSet result = copyOf(s); + result.complement(); + return result; + } + + /** + * Creates an enum set initially containing the specified element. + * + * Overloadings of this method exist to initialize an enum set with + * one through five elements. A sixth overloading is provided that + * uses the varargs feature. This overloading may be used to create + * an enum set initially containing an arbitrary number of elements, but + * is likely to run slower than the overloadings that do not use varargs. + * + * @param e the element that this set is to contain initially + * @throws NullPointerException if e is null + * @return an enum set initially containing the specified element + */ + public static > EnumSet of(E e) { + EnumSet result = noneOf(e.getDeclaringClass()); + result.add(e); + return result; + } + + /** + * Creates an enum set initially containing the specified elements. + * + * Overloadings of this method exist to initialize an enum set with + * one through five elements. A sixth overloading is provided that + * uses the varargs feature. This overloading may be used to create + * an enum set initially containing an arbitrary number of elements, but + * is likely to run slower than the overloadings that do not use varargs. + * + * @param e1 an element that this set is to contain initially + * @param e2 another element that this set is to contain initially + * @throws NullPointerException if any parameters are null + * @return an enum set initially containing the specified elements + */ + public static > EnumSet of(E e1, E e2) { + EnumSet result = noneOf(e1.getDeclaringClass()); + result.add(e1); + result.add(e2); + return result; + } + + /** + * Creates an enum set initially containing the specified elements. + * + * Overloadings of this method exist to initialize an enum set with + * one through five elements. A sixth overloading is provided that + * uses the varargs feature. This overloading may be used to create + * an enum set initially containing an arbitrary number of elements, but + * is likely to run slower than the overloadings that do not use varargs. + * + * @param e1 an element that this set is to contain initially + * @param e2 another element that this set is to contain initially + * @param e3 another element that this set is to contain initially + * @throws NullPointerException if any parameters are null + * @return an enum set initially containing the specified elements + */ + public static > EnumSet of(E e1, E e2, E e3) { + EnumSet result = noneOf(e1.getDeclaringClass()); + result.add(e1); + result.add(e2); + result.add(e3); + return result; + } + + /** + * Creates an enum set initially containing the specified elements. + * + * Overloadings of this method exist to initialize an enum set with + * one through five elements. A sixth overloading is provided that + * uses the varargs feature. This overloading may be used to create + * an enum set initially containing an arbitrary number of elements, but + * is likely to run slower than the overloadings that do not use varargs. + * + * @param e1 an element that this set is to contain initially + * @param e2 another element that this set is to contain initially + * @param e3 another element that this set is to contain initially + * @param e4 another element that this set is to contain initially + * @throws NullPointerException if any parameters are null + * @return an enum set initially containing the specified elements + */ + public static > EnumSet of(E e1, E e2, E e3, E e4) { + EnumSet result = noneOf(e1.getDeclaringClass()); + result.add(e1); + result.add(e2); + result.add(e3); + result.add(e4); + return result; + } + + /** + * Creates an enum set initially containing the specified elements. + * + * Overloadings of this method exist to initialize an enum set with + * one through five elements. A sixth overloading is provided that + * uses the varargs feature. This overloading may be used to create + * an enum set initially containing an arbitrary number of elements, but + * is likely to run slower than the overloadings that do not use varargs. + * + * @param e1 an element that this set is to contain initially + * @param e2 another element that this set is to contain initially + * @param e3 another element that this set is to contain initially + * @param e4 another element that this set is to contain initially + * @param e5 another element that this set is to contain initially + * @throws NullPointerException if any parameters are null + * @return an enum set initially containing the specified elements + */ + public static > EnumSet of(E e1, E e2, E e3, E e4, + E e5) + { + EnumSet result = noneOf(e1.getDeclaringClass()); + result.add(e1); + result.add(e2); + result.add(e3); + result.add(e4); + result.add(e5); + return result; + } + + /** + * Creates an enum set initially containing the specified elements. + * This factory, whose parameter list uses the varargs feature, may + * be used to create an enum set initially containing an arbitrary + * number of elements, but it is likely to run slower than the overloadings + * that do not use varargs. + * + * @param first an element that the set is to contain initially + * @param rest the remaining elements the set is to contain initially + * @throws NullPointerException if any of the specified elements are null, + * or if rest is null + * @return an enum set initially containing the specified elements + */ + @SafeVarargs + public static > EnumSet of(E first, E... rest) { + EnumSet result = noneOf(first.getDeclaringClass()); + result.add(first); + for (E e : rest) + result.add(e); + return result; + } + + /** + * Creates an enum set initially containing all of the elements in the + * range defined by the two specified endpoints. The returned set will + * contain the endpoints themselves, which may be identical but must not + * be out of order. + * + * @param from the first element in the range + * @param to the last element in the range + * @throws NullPointerException if {@code from} or {@code to} are null + * @throws IllegalArgumentException if {@code from.compareTo(to) > 0} + * @return an enum set initially containing all of the elements in the + * range defined by the two specified endpoints + */ + public static > EnumSet range(E from, E to) { + if (from.compareTo(to) > 0) + throw new IllegalArgumentException(from + " > " + to); + EnumSet result = noneOf(from.getDeclaringClass()); + result.addRange(from, to); + return result; + } + + /** + * Adds the specified range to this enum set, which is empty prior + * to the call. + */ + abstract void addRange(E from, E to); + + /** + * Returns a copy of this set. + * + * @return a copy of this set + */ + public EnumSet clone() { + try { + return (EnumSet) super.clone(); + } catch(CloneNotSupportedException e) { + throw new AssertionError(e); + } + } + + /** + * Complements the contents of this enum set. + */ + abstract void complement(); + + /** + * Throws an exception if e is not of the correct type for this enum set. + */ + final void typeCheck(E e) { + Class eClass = e.getClass(); + if (eClass != elementType && eClass.getSuperclass() != elementType) + throw new ClassCastException(eClass + " != " + elementType); + } + + /** + * Returns all of the values comprising E. + * The result is uncloned, cached, and shared by all callers. + */ + private static > E[] getUniverse(Class elementType) { + return SharedSecrets.getJavaLangAccess() + .getEnumConstantsShared(elementType); + } + + /** + * This class is used to serialize all EnumSet instances, regardless of + * implementation type. It captures their "logical contents" and they + * are reconstructed using public static factories. This is necessary + * to ensure that the existence of a particular implementation type is + * an implementation detail. + * + * @serial include + */ + private static class SerializationProxy > + implements java.io.Serializable + { + /** + * The element type of this enum set. + * + * @serial + */ + private final Class elementType; + + /** + * The elements contained in this enum set. + * + * @serial + */ + private final Enum[] elements; + + SerializationProxy(EnumSet set) { + elementType = set.elementType; + elements = set.toArray(ZERO_LENGTH_ENUM_ARRAY); + } + + private Object readResolve() { + EnumSet result = EnumSet.noneOf(elementType); + for (Enum e : elements) + result.add((E)e); + return result; + } + + private static final long serialVersionUID = 362491234563181265L; + } + + Object writeReplace() { + return new SerializationProxy<>(this); + } + + // readObject method for the serialization proxy pattern + // See Effective Java, Second Ed., Item 78. + private void readObject(java.io.ObjectInputStream stream) + throws java.io.InvalidObjectException { + throw new java.io.InvalidObjectException("Proxy required"); + } +} diff -r c1e76ee31360 -r 9cf04876e4a5 emul/compact/src/main/java/java/util/JumboEnumSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/JumboEnumSet.java Sun Sep 22 21:49:42 2013 +0200 @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util; + +/** + * Private implementation class for EnumSet, for "jumbo" enum types + * (i.e., those with more than 64 elements). + * + * @author Josh Bloch + * @since 1.5 + * @serial exclude + */ +class JumboEnumSet> extends EnumSet { + private static final long serialVersionUID = 334349849919042784L; + + /** + * Bit vector representation of this set. The ith bit of the jth + * element of this array represents the presence of universe[64*j +i] + * in this set. + */ + private long elements[]; + + // Redundant - maintained for performance + private int size = 0; + + JumboEnumSet(ClasselementType, Enum[] universe) { + super(elementType, universe); + elements = new long[(universe.length + 63) >>> 6]; + } + + void addRange(E from, E to) { + int fromIndex = from.ordinal() >>> 6; + int toIndex = to.ordinal() >>> 6; + + if (fromIndex == toIndex) { + elements[fromIndex] = (-1L >>> (from.ordinal() - to.ordinal() - 1)) + << from.ordinal(); + } else { + elements[fromIndex] = (-1L << from.ordinal()); + for (int i = fromIndex + 1; i < toIndex; i++) + elements[i] = -1; + elements[toIndex] = -1L >>> (63 - to.ordinal()); + } + size = to.ordinal() - from.ordinal() + 1; + } + + void addAll() { + for (int i = 0; i < elements.length; i++) + elements[i] = -1; + elements[elements.length - 1] >>>= -universe.length; + size = universe.length; + } + + void complement() { + for (int i = 0; i < elements.length; i++) + elements[i] = ~elements[i]; + elements[elements.length - 1] &= (-1L >>> -universe.length); + size = universe.length - size; + } + + /** + * Returns an iterator over the elements contained in this set. The + * iterator traverses the elements in their natural order (which is + * the order in which the enum constants are declared). The returned + * Iterator is a "weakly consistent" iterator that will never throw {@link + * ConcurrentModificationException}. + * + * @return an iterator over the elements contained in this set + */ + public Iterator iterator() { + return new EnumSetIterator<>(); + } + + private class EnumSetIterator> implements Iterator { + /** + * A bit vector representing the elements in the current "word" + * of the set not yet returned by this iterator. + */ + long unseen; + + /** + * The index corresponding to unseen in the elements array. + */ + int unseenIndex = 0; + + /** + * The bit representing the last element returned by this iterator + * but not removed, or zero if no such element exists. + */ + long lastReturned = 0; + + /** + * The index corresponding to lastReturned in the elements array. + */ + int lastReturnedIndex = 0; + + EnumSetIterator() { + unseen = elements[0]; + } + + public boolean hasNext() { + while (unseen == 0 && unseenIndex < elements.length - 1) + unseen = elements[++unseenIndex]; + return unseen != 0; + } + + public E next() { + if (!hasNext()) + throw new NoSuchElementException(); + lastReturned = unseen & -unseen; + lastReturnedIndex = unseenIndex; + unseen -= lastReturned; + return (E) universe[(lastReturnedIndex << 6) + + Long.numberOfTrailingZeros(lastReturned)]; + } + + public void remove() { + if (lastReturned == 0) + throw new IllegalStateException(); + final long oldElements = elements[lastReturnedIndex]; + elements[lastReturnedIndex] &= ~lastReturned; + if (oldElements != elements[lastReturnedIndex]) { + size--; + } + lastReturned = 0; + } + } + + /** + * Returns the number of elements in this set. + * + * @return the number of elements in this set + */ + public int size() { + return size; + } + + /** + * Returns true if this set contains no elements. + * + * @return true if this set contains no elements + */ + public boolean isEmpty() { + return size == 0; + } + + /** + * Returns true if this set contains the specified element. + * + * @param e element to be checked for containment in this collection + * @return true if this set contains the specified element + */ + public boolean contains(Object e) { + if (e == null) + return false; + Class eClass = e.getClass(); + if (eClass != elementType && eClass.getSuperclass() != elementType) + return false; + + int eOrdinal = ((Enum)e).ordinal(); + return (elements[eOrdinal >>> 6] & (1L << eOrdinal)) != 0; + } + + // Modification Operations + + /** + * Adds the specified element to this set if it is not already present. + * + * @param e element to be added to this set + * @return true if the set changed as a result of the call + * + * @throws NullPointerException if e is null + */ + public boolean add(E e) { + typeCheck(e); + + int eOrdinal = e.ordinal(); + int eWordNum = eOrdinal >>> 6; + + long oldElements = elements[eWordNum]; + elements[eWordNum] |= (1L << eOrdinal); + boolean result = (elements[eWordNum] != oldElements); + if (result) + size++; + return result; + } + + /** + * Removes the specified element from this set if it is present. + * + * @param e element to be removed from this set, if present + * @return true if the set contained the specified element + */ + public boolean remove(Object e) { + if (e == null) + return false; + Class eClass = e.getClass(); + if (eClass != elementType && eClass.getSuperclass() != elementType) + return false; + int eOrdinal = ((Enum)e).ordinal(); + int eWordNum = eOrdinal >>> 6; + + long oldElements = elements[eWordNum]; + elements[eWordNum] &= ~(1L << eOrdinal); + boolean result = (elements[eWordNum] != oldElements); + if (result) + size--; + return result; + } + + // Bulk Operations + + /** + * Returns true if this set contains all of the elements + * in the specified collection. + * + * @param c collection to be checked for containment in this set + * @return true if this set contains all of the elements + * in the specified collection + * @throws NullPointerException if the specified collection is null + */ + public boolean containsAll(Collection c) { + if (!(c instanceof JumboEnumSet)) + return super.containsAll(c); + + JumboEnumSet es = (JumboEnumSet)c; + if (es.elementType != elementType) + return es.isEmpty(); + + for (int i = 0; i < elements.length; i++) + if ((es.elements[i] & ~elements[i]) != 0) + return false; + return true; + } + + /** + * Adds all of the elements in the specified collection to this set. + * + * @param c collection whose elements are to be added to this set + * @return true if this set changed as a result of the call + * @throws NullPointerException if the specified collection or any of + * its elements are null + */ + public boolean addAll(Collection c) { + if (!(c instanceof JumboEnumSet)) + return super.addAll(c); + + JumboEnumSet es = (JumboEnumSet)c; + if (es.elementType != elementType) { + if (es.isEmpty()) + return false; + else + throw new ClassCastException( + es.elementType + " != " + elementType); + } + + for (int i = 0; i < elements.length; i++) + elements[i] |= es.elements[i]; + return recalculateSize(); + } + + /** + * Removes from this set all of its elements that are contained in + * the specified collection. + * + * @param c elements to be removed from this set + * @return true if this set changed as a result of the call + * @throws NullPointerException if the specified collection is null + */ + public boolean removeAll(Collection c) { + if (!(c instanceof JumboEnumSet)) + return super.removeAll(c); + + JumboEnumSet es = (JumboEnumSet)c; + if (es.elementType != elementType) + return false; + + for (int i = 0; i < elements.length; i++) + elements[i] &= ~es.elements[i]; + return recalculateSize(); + } + + /** + * Retains only the elements in this set that are contained in the + * specified collection. + * + * @param c elements to be retained in this set + * @return true if this set changed as a result of the call + * @throws NullPointerException if the specified collection is null + */ + public boolean retainAll(Collection c) { + if (!(c instanceof JumboEnumSet)) + return super.retainAll(c); + + JumboEnumSet es = (JumboEnumSet)c; + if (es.elementType != elementType) { + boolean changed = (size != 0); + clear(); + return changed; + } + + for (int i = 0; i < elements.length; i++) + elements[i] &= es.elements[i]; + return recalculateSize(); + } + + /** + * Removes all of the elements from this set. + */ + public void clear() { + Arrays.fill(elements, 0); + size = 0; + } + + /** + * Compares the specified object with this set for equality. Returns + * true if the given object is also a set, the two sets have + * the same size, and every member of the given set is contained in + * this set. + * + * @param e object to be compared for equality with this set + * @return true if the specified object is equal to this set + */ + public boolean equals(Object o) { + if (!(o instanceof JumboEnumSet)) + return super.equals(o); + + JumboEnumSet es = (JumboEnumSet)o; + if (es.elementType != elementType) + return size == 0 && es.size == 0; + + return Arrays.equals(es.elements, elements); + } + + /** + * Recalculates the size of the set. Returns true if it's changed. + */ + private boolean recalculateSize() { + int oldSize = size; + size = 0; + for (long elt : elements) + size += Long.bitCount(elt); + + return size != oldSize; + } + + public EnumSet clone() { + JumboEnumSet result = (JumboEnumSet) super.clone(); + result.elements = result.elements.clone(); + return result; + } +} diff -r c1e76ee31360 -r 9cf04876e4a5 emul/compact/src/main/java/java/util/RegularEnumSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/compact/src/main/java/java/util/RegularEnumSet.java Sun Sep 22 21:49:42 2013 +0200 @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util; + +/** + * Private implementation class for EnumSet, for "regular sized" enum types + * (i.e., those with 64 or fewer enum constants). + * + * @author Josh Bloch + * @since 1.5 + * @serial exclude + */ +class RegularEnumSet> extends EnumSet { + private static final long serialVersionUID = 3411599620347842686L; + /** + * Bit vector representation of this set. The 2^k bit indicates the + * presence of universe[k] in this set. + */ + private long elements = 0L; + + RegularEnumSet(ClasselementType, Enum[] universe) { + super(elementType, universe); + } + + void addRange(E from, E to) { + elements = (-1L >>> (from.ordinal() - to.ordinal() - 1)) << from.ordinal(); + } + + void addAll() { + if (universe.length != 0) + elements = -1L >>> -universe.length; + } + + void complement() { + if (universe.length != 0) { + elements = ~elements; + elements &= -1L >>> -universe.length; // Mask unused bits + } + } + + /** + * Returns an iterator over the elements contained in this set. The + * iterator traverses the elements in their natural order (which is + * the order in which the enum constants are declared). The returned + * Iterator is a "snapshot" iterator that will never throw {@link + * ConcurrentModificationException}; the elements are traversed as they + * existed when this call was invoked. + * + * @return an iterator over the elements contained in this set + */ + public Iterator iterator() { + return new EnumSetIterator<>(); + } + + private class EnumSetIterator> implements Iterator { + /** + * A bit vector representing the elements in the set not yet + * returned by this iterator. + */ + long unseen; + + /** + * The bit representing the last element returned by this iterator + * but not removed, or zero if no such element exists. + */ + long lastReturned = 0; + + EnumSetIterator() { + unseen = elements; + } + + public boolean hasNext() { + return unseen != 0; + } + + public E next() { + if (unseen == 0) + throw new NoSuchElementException(); + lastReturned = unseen & -unseen; + unseen -= lastReturned; + return (E) universe[Long.numberOfTrailingZeros(lastReturned)]; + } + + public void remove() { + if (lastReturned == 0) + throw new IllegalStateException(); + elements &= ~lastReturned; + lastReturned = 0; + } + } + + /** + * Returns the number of elements in this set. + * + * @return the number of elements in this set + */ + public int size() { + return Long.bitCount(elements); + } + + /** + * Returns true if this set contains no elements. + * + * @return true if this set contains no elements + */ + public boolean isEmpty() { + return elements == 0; + } + + /** + * Returns true if this set contains the specified element. + * + * @param e element to be checked for containment in this collection + * @return true if this set contains the specified element + */ + public boolean contains(Object e) { + if (e == null) + return false; + Class eClass = e.getClass(); + if (eClass != elementType && eClass.getSuperclass() != elementType) + return false; + + return (elements & (1L << ((Enum)e).ordinal())) != 0; + } + + // Modification Operations + + /** + * Adds the specified element to this set if it is not already present. + * + * @param e element to be added to this set + * @return true if the set changed as a result of the call + * + * @throws NullPointerException if e is null + */ + public boolean add(E e) { + typeCheck(e); + + long oldElements = elements; + elements |= (1L << ((Enum)e).ordinal()); + return elements != oldElements; + } + + /** + * Removes the specified element from this set if it is present. + * + * @param e element to be removed from this set, if present + * @return true if the set contained the specified element + */ + public boolean remove(Object e) { + if (e == null) + return false; + Class eClass = e.getClass(); + if (eClass != elementType && eClass.getSuperclass() != elementType) + return false; + + long oldElements = elements; + elements &= ~(1L << ((Enum)e).ordinal()); + return elements != oldElements; + } + + // Bulk Operations + + /** + * Returns true if this set contains all of the elements + * in the specified collection. + * + * @param c collection to be checked for containment in this set + * @return true if this set contains all of the elements + * in the specified collection + * @throws NullPointerException if the specified collection is null + */ + public boolean containsAll(Collection c) { + if (!(c instanceof RegularEnumSet)) + return super.containsAll(c); + + RegularEnumSet es = (RegularEnumSet)c; + if (es.elementType != elementType) + return es.isEmpty(); + + return (es.elements & ~elements) == 0; + } + + /** + * Adds all of the elements in the specified collection to this set. + * + * @param c collection whose elements are to be added to this set + * @return true if this set changed as a result of the call + * @throws NullPointerException if the specified collection or any + * of its elements are null + */ + public boolean addAll(Collection c) { + if (!(c instanceof RegularEnumSet)) + return super.addAll(c); + + RegularEnumSet es = (RegularEnumSet)c; + if (es.elementType != elementType) { + if (es.isEmpty()) + return false; + else + throw new ClassCastException( + es.elementType + " != " + elementType); + } + + long oldElements = elements; + elements |= es.elements; + return elements != oldElements; + } + + /** + * Removes from this set all of its elements that are contained in + * the specified collection. + * + * @param c elements to be removed from this set + * @return true if this set changed as a result of the call + * @throws NullPointerException if the specified collection is null + */ + public boolean removeAll(Collection c) { + if (!(c instanceof RegularEnumSet)) + return super.removeAll(c); + + RegularEnumSet es = (RegularEnumSet)c; + if (es.elementType != elementType) + return false; + + long oldElements = elements; + elements &= ~es.elements; + return elements != oldElements; + } + + /** + * Retains only the elements in this set that are contained in the + * specified collection. + * + * @param c elements to be retained in this set + * @return true if this set changed as a result of the call + * @throws NullPointerException if the specified collection is null + */ + public boolean retainAll(Collection c) { + if (!(c instanceof RegularEnumSet)) + return super.retainAll(c); + + RegularEnumSet es = (RegularEnumSet)c; + if (es.elementType != elementType) { + boolean changed = (elements != 0); + elements = 0; + return changed; + } + + long oldElements = elements; + elements &= es.elements; + return elements != oldElements; + } + + /** + * Removes all of the elements from this set. + */ + public void clear() { + elements = 0; + } + + /** + * Compares the specified object with this set for equality. Returns + * true if the given object is also a set, the two sets have + * the same size, and every member of the given set is contained in + * this set. + * + * @param e object to be compared for equality with this set + * @return true if the specified object is equal to this set + */ + public boolean equals(Object o) { + if (!(o instanceof RegularEnumSet)) + return super.equals(o); + + RegularEnumSet es = (RegularEnumSet)o; + if (es.elementType != elementType) + return elements == 0 && es.elements == 0; + return es.elements == elements; + } +}