/* Copyright (c) 2008-2014, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. There is NO WARRANTY for this software. See license.txt for details. */ package java.util; public class EnumSet> extends AbstractSet { private BitSet bitset; private Class elementType; private EnumSet(int size, Class type) { bitset = new BitSet(size); elementType = type; } @Override public boolean add(T element) { int index = element.ordinal(); boolean contains = bitset.get(index); if (!contains) { bitset.set(index); } return !contains; } @Override public boolean remove(Object toRemove) { T element = tryToCast(toRemove); int index = element.ordinal(); boolean contains = bitset.get(index); if (contains) { bitset.clear(index); } return contains; } @Override public boolean contains(Object toCheck) { T element = tryToCast(toCheck); int index = element.ordinal(); return bitset.get(index); } @Override public int size() { return bitset.cardinality(); } @Override public Iterator iterator() { return new EnumSetIterator(); } public static >EnumSet allOf(Class elementType) { EnumSet enumSet = createEmptyEnumSet(elementType); enumSet.bitset.set(0, elementType.getEnumConstants().length); return enumSet; } public static >EnumSet noneOf(Class elementType) { return createEmptyEnumSet(elementType); } public static >EnumSet of(T first, T ... rest) { EnumSet enumSet = createEmptyEnumSet(first.getDeclaringClass()); enumSet.add(first); addAllElementsToSet(Arrays.asList(rest), enumSet); return enumSet; } public static >EnumSet complementOf(EnumSet s) { EnumSet enumSet = copyOf(s); enumSet.bitset.flip(0, s.elementType.getEnumConstants().length); return enumSet; } public static >EnumSet copyOf(EnumSet s) { EnumSet enumSet = createEmptyEnumSet(s.elementType); enumSet.bitset.or(s.bitset); return enumSet; } private static >EnumSet createEmptyEnumSet(Class elementType) { T[] constants = elementType.getEnumConstants(); EnumSet enumSet = new EnumSet(constants.length, elementType); return enumSet; } private static > void addAllElementsToSet(Iterable elements, EnumSet enumSet) { for (T element : elements) { enumSet.add(element); } } @SuppressWarnings("unchecked") private T tryToCast(Object object) throws ClassCastException { //We want the class cast exception if we can't convert. return (T) object; } private class EnumSetIterator implements Iterator { private int currentIndex = 0; private boolean removeAllowed = false; public T next() { if (!hasNext()) { throw new NoSuchElementException("EnumSet has no more elements"); } int indexOfNextValue = nextIndex(); T element = elementType.getEnumConstants()[indexOfNextValue]; currentIndex = indexOfNextValue + 1; removeAllowed = true; return element; } public boolean hasNext() { int indexOfNextValue = nextIndex(); if (indexOfNextValue >= 0) { return true; } else { return false; } } public void remove() { if (!removeAllowed) { throw new IllegalStateException("Cannot remove from this iterator in this state"); } bitset.clear(currentIndex - 1); removeAllowed = false; } private int nextIndex() { return bitset.nextSetBit(currentIndex); } } }