package ns.foundation;
import java.io.Serializable;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class NSSet<E> extends AbstractSet<E> implements Set<E>, _NSFoundationCollection, Cloneable, Serializable {
private static final long serialVersionUID = -2249197480070093501L;
public static final boolean CheckForNull = true;
@SuppressWarnings("rawtypes")
public static final NSSet EmptySet = new NSSet();
public static final boolean IgnoreNull = true;
protected static final String NULL_NOT_ALLOWED = "Attempt to insert null into an NSSet.";
private Set<E> _backingStore;
public NSSet() {
_initializeWithCapacity(0);
}
protected NSSet(int capacity) {
_initializeWithCapacity(capacity);
}
public NSSet(Collection<? extends E> collection) {
if (collection == null)
throw new IllegalArgumentException("objects may not be null");
_initializeWithCollection(collection, NullHandling.CheckAndFail);
}
public NSSet(E object) {
if (object == null)
throw new IllegalArgumentException("object may not be null");
_initializeWithCapacity(1).add(object);
}
public NSSet(E... objects) {
if (objects == null)
throw new IllegalArgumentException("objects may not be null");
_initializeWithObjects(objects, NullHandling.CheckAndFail);
}
public NSSet(NSArray<? extends E> objects) {
if (objects == null)
throw new IllegalArgumentException("objects may not be null");
_initializeWithCollection(objects, NullHandling.CheckAndFail);
}
public NSSet(NSSet<? extends E> otherSet) {
this(otherSet, false);
}
public NSSet(Set<? extends E> set, boolean ignoreNull) {
if (set == null)
throw new IllegalArgumentException("set may not be null");
_initializeWithCollection(set, ignoreNull ? NullHandling.CheckAndSkip : NullHandling.CheckAndFail);
}
protected Set<E> setNoCopy() {
return _backingStore;
}
protected Set<E> _setSet(Set<E> set) {
return _backingStore = set;
}
protected Set<E> _initializeWithCapacity(int capacity) {
Set<E> set = new HashSet<E>(capacity);
_setSet(Collections.unmodifiableSet(set));
return set;
}
protected void _initializeWithObjects(E[] objects, NullHandling nullHandling) {
Set<E> store = _initializeWithCapacity(objects.length);
if (nullHandling == NullHandling.NoCheck) {
store.addAll(Arrays.asList(objects));
return;
}
for (E e : objects) {
if (e == null) {
if (nullHandling == NullHandling.CheckAndFail)
throw new IllegalArgumentException(NULL_NOT_ALLOWED);
} else {
store.add(e);
}
}
}
protected void _initializeWithCollection(Collection<? extends E> collection, NullHandling nullHandling) {
if (collection == null) {
_initializeWithCapacity(0);
return;
}
Set<E> store = _initializeWithCapacity(collection.size());
if (nullHandling == NullHandling.NoCheck || collection instanceof _NSFoundationCollection) {
store.addAll(collection);
return;
}
for (E e : collection) {
if (e == null) {
if (nullHandling == NullHandling.CheckAndFail)
throw new IllegalArgumentException(NULL_NOT_ALLOWED);
continue;
}
store.add(e);
}
}
public static <E> NSSet<E> asSet(Set<E> set) {
return asSet(set, NullHandling.CheckAndFail);
}
public static <E> NSSet<E> asSet(Set<E> set, NullHandling nullHandling) {
if (set == null || set.size() == 0)
return emptySet();
if (set.getClass() == NSSet.class)
return (NSSet<E>)set;
return _initializeNSSetWithSet(new NSSet<E>(), Collections.unmodifiableSet(set), nullHandling);
}
public static <E> NSMutableSet<E> asMutableSet(Set<E> set) {
return asMutableSet(set, NullHandling.CheckAndFail);
}
public static <E> NSMutableSet<E> asMutableSet(Set<E> set, NullHandling nullHandling) {
if (set == null)
return new NSMutableSet<E>();
if (set.getClass() == NSMutableSet.class)
return (NSMutableSet<E>)set;
return _initializeNSSetWithSet(new NSMutableSet<E>(), set, nullHandling);
}
protected static <E, T extends NSSet<E>> T _initializeNSSetWithSet(T nsset, Set<E> set, NullHandling nullHandling) {
if (set == null)
throw new IllegalArgumentException("set may not be null");
if (nullHandling != NullHandling.NoCheck && set.size() > 0) {
try {
if (set.contains(null)) {
if (nullHandling == NullHandling.CheckAndFail)
throw new IllegalArgumentException(NULL_NOT_ALLOWED);
nsset._initializeWithCollection(set, nullHandling);
return nsset;
}
} catch (NullPointerException e) {
// Must not support nulls either
}
}
nsset._setSet((Set<E>)set);
return nsset;
}
public NSArray<E> allObjects() {
return new NSArray<E>(this);
}
public E anyObject() {
if (isEmpty())
return null;
int index = 0;
return (E) allObjects().get(index);
}
public int count() {
return size();
}
public boolean containsObject(Object object) {
return contains(object);
}
@Override
public NSSet<E> clone() {
return this;
}
@SuppressWarnings("unchecked")
public static <T> NSSet<T> emptySet() {
return EmptySet;
}
@Override
public int _shallowHashCode() {
return NSSet.class.hashCode();
}
@Override
public int hashCode() {
return _shallowHashCode() ^ count();
}
@Override
public boolean equals(Object obj) {
if (obj == this || obj == setNoCopy())
return true;
if (obj instanceof NSSet<?> && setNoCopy() == ((NSSet<?>)obj).setNoCopy())
return true;
return super.equals(obj);
}
public HashSet<E> hashSet() {
return new HashSet<E>(this);
}
public NSSet<E> immutableClone() {
return this;
}
public boolean intersectsSet(NSSet<?> otherSet) {
for (Object o : otherSet) {
if (containsObject(o)) {
return true;
}
}
return false;
}
public boolean isEqualToSet(NSSet<?> otherSet) {
return equals(otherSet);
}
public boolean isSubsetOfSet(NSSet<?> otherSet) {
for (Object o : this) {
if (!otherSet.containsObject(o)) {
return false;
}
}
return true;
}
public Object member(Object object) {
if (!contains(object))
return null;
for(Object element : this) {
if (element.equals(object))
return element;
}
return null;
}
public NSMutableSet<E> mutableClone() {
return new NSMutableSet<E>(this);
}
@Override
public Iterator<E> iterator() {
return setNoCopy().iterator();
}
@Override
public int size() {
return setNoCopy().size();
}
public NSSet<E> setByIntersectingSet(NSSet<?> otherSet) {
NSMutableSet<E> result = new NSMutableSet<E>();
for (E e : this) {
if (otherSet.contains(e)) {
result.add(e);
}
}
return result;
}
public NSSet<E> setBySubtractingSet(NSSet<?> otherSet) {
NSSet<E> result = mutableClone();
result.removeAll(otherSet);
return result;
}
public NSSet<E> setByUnioningSet(NSSet<? extends E> otherSet) {
NSSet<E> result = mutableClone();
result.addAll(otherSet);
return result;
}
}