package com.webobjects.foundation; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Set; /** * <div class="en"> * NSSet reimplementation to support JDK 1.5 templates. Use with * </div> * * <div class="ja"> * JDK 1.5 テンプレートをサポートする為の再実装。使用は * </div> * * <pre>{@code * NSMutableSet<E> set = new NSMutableSet<E>(); * set.put(new E()) * * for (E t : set) * logger.debug(t); * }</pre> * * @param <E> - type of set contents */ public class NSMutableSet<E> extends NSSet<E> { static final long serialVersionUID = -6054074706096120227L; public NSMutableSet() { } public NSMutableSet(int capacity) { if (capacity < 0) { throw new IllegalArgumentException("Capacity cannot be less than 0"); } _ensureCapacity(capacity); } public NSMutableSet(Collection<? extends E> collection) { super(collection); } public NSMutableSet(E object) { super(object); } public NSMutableSet(E[] objects) { super(objects); } public NSMutableSet(E object, E... objects) { super(object, objects); } public NSMutableSet(NSArray<? extends E> objects) { super(objects); } public NSMutableSet(NSSet<? extends E> otherSet) { super(otherSet); } public NSMutableSet(Set<? extends E> set, boolean ignoreNull) { super(set, ignoreNull); } public void addObject(E object) { if (object == null) { throw new IllegalArgumentException("Attempt to insert null into an " + getClass().getName() + "."); } if (count() == capacity()) { _ensureCapacity(count() + 1); } if (_NSCollectionPrimitives.addValueToSet(object, _objects, _flags)) { _setCount(count() + 1); _objectsCache = null; } } public void addObjects(E... objects) { if (objects != null && objects.length > 0) { if (count() + objects.length > capacity()) { _ensureCapacity(count() + objects.length); } for (int i = 0; i < objects.length; i++) { if (objects[i] == null) throw new IllegalArgumentException("Attempt to insert null into an " + getClass().getName() + "."); if (_NSCollectionPrimitives.addValueToSet(objects[i], _objects, _flags)) { _setCount(count() + 1); _objectsCache = null; } } } } public E removeObject(Object object) { Object result = null; if (object != null && count() != 0) { result = _NSCollectionPrimitives.removeValueInHashTable(object, _objects, _objects, _flags); if (result != null) { _setCount(count() - 1); _deletionLimit--; if (count() == 0 || _deletionLimit == 0) { _clearDeletionsAndCollisions(); } _objectsCache = null; } } return (E) result; } public void removeAllObjects() { if (count() != 0) { _objects = new Object[_hashtableBuckets]; _flags = new byte[_hashtableBuckets]; _setCount(0); _objectsCache = null; _deletionLimit = _NSCollectionPrimitives.deletionLimitForTableBuckets(_hashtableBuckets); } } public void setSet(NSSet<? extends E> otherSet) { if (otherSet != this) { removeAllObjects(); if (otherSet != null) { E[] objects = (E[])otherSet.objectsNoCopy(); for (int i = 0; i < objects.length; i++) { addObject(objects[i]); } } } } public void addObjectsFromArray(NSArray<? extends E> array) { if (array != null) { E[] objects = (E[])array.objectsNoCopy(); for (int i = 0; i < objects.length; i++) { addObject(objects[i]); } } } public void intersectSet(NSSet<?> otherSet) { if (otherSet != this) { if (otherSet == null || otherSet.count() == 0) { removeAllObjects(); return; } E[] objects = (E[])objectsNoCopy(); for (int i = 0; i < objects.length; i++) { if (otherSet.member(objects[i]) == null) { removeObject(objects[i]); } } } } public void subtractSet(NSSet<?> otherSet) { if (otherSet == null || otherSet.count() == 0) { return; } if (otherSet == this) { removeAllObjects(); return; } Object[] objects = otherSet.objectsNoCopy(); for (int i = 0; i < objects.length; i++) { if (member(objects[i]) != null) { removeObject(objects[i]); } } } public void unionSet(NSSet<? extends E> otherSet) { if (otherSet == null || otherSet.count() == 0 || otherSet == this) { return; } E[] objects = (E[])otherSet.objectsNoCopy(); for (int i = 0; i < objects.length; i++) { addObject(objects[i]); } } @Override public Object clone() { return new NSMutableSet<E>(this); } @Override public NSSet<E> immutableClone() { return new NSSet<E>(this); } @Override public NSMutableSet<E> mutableClone() { return (NSMutableSet<E>) clone(); } public static final Class _CLASS = _NSUtilities._classWithFullySpecifiedName("com.webobjects.foundation.NSMutableSet"); @Override public boolean add(E o) { if (contains(o)) { return false; } addObject(o); return true; } @Override public boolean remove(Object o) { return removeObject(o) != null ? true : false; } @Override public boolean addAll(Collection<? extends E> c) { boolean updated = false; for (E t : c) { if (!contains(t)) { add(t); updated = true; } } return updated; } @Override public boolean retainAll(Collection<?> c) { NSMutableSet<Object> s = new NSMutableSet<>(); boolean updated = false; for (Object o : c) { s.add(o); if (!contains(o)) { updated = true; } } intersectSet(s); return updated; } @Override public boolean removeAll(Collection<?> c) { NSMutableSet<Object> s = new NSMutableSet<>(); boolean updated = false; for (Object o : c) { s.add(o); if (!contains(o)) { updated = true; } } subtractSet(s); return updated; } @Override public void clear() { removeAllObjects(); } @Override public Iterator<E> iterator() { return new Itr(); } private class Itr implements Iterator<E> { int cursor = 0; static final int NotFound = -1; int lastRet = NotFound; protected Itr() { } public boolean hasNext() { return cursor != size(); } public E next() { try { Object next = objectsNoCopy()[cursor]; lastRet = cursor++; return (E)next; } catch (IndexOutOfBoundsException e) { throw new NoSuchElementException(); } } public void remove() { if (lastRet == NotFound) { throw new IllegalStateException(); } try { removeObject(objectsNoCopy()[lastRet]); if (lastRet < cursor) { cursor--; } lastRet = NotFound; } catch (IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } } }