package com.webobjects.foundation;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.ObjectStreamField;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Vector;
import er.extensions.eof.ERXKey;
import er.extensions.foundation.ERXArrayUtilities;
/**
* <div class="en">
* NSArray re-implementation to support JDK 1.5 templates. Use with
* </div>
*
* <div class="ja">
* JDK 1.5 テンプレートをサポートする為の再実装。使用は
* </div>
*
* <pre><code>
* NSArray<Bug> bugs = ds.fetchObjects();
*
* for(Bug : bugs) {
* ...
* }</code></pre>
*
* @param <E> - type of array contents
*/
public class NSArray<E> implements Cloneable, Serializable, NSCoding, NSKeyValueCoding, NSKeyValueCodingAdditions, _NSFoundationCollection, List<E> {
static final long serialVersionUID = -3789592578296478260L;
public static class _AvgNumberOperator extends _Operator implements Operator {
public Object compute(NSArray<?> values, String keyPath) {
int count = values.count();
if (count != 0) {
BigDecimal sum = _sum(values, keyPath);
return sum.divide(BigDecimal.valueOf(count), sum.scale() + 4, 6);
}
return null;
}
}
public static class _SumNumberOperator extends _Operator implements Operator {
public Object compute(NSArray<?> values, String keyPath) {
return _sum(values, keyPath);
}
}
public static class _MinOperator extends _Operator implements Operator {
public Object compute(NSArray<?> values, String keyPath) {
Object min = null;
Object[] objects = values.objectsNoCopy();
for (int i = 0; i < objects.length; i++) {
min = _minOrMaxValue(min, _operationValue(objects[i], keyPath), false);
}
return min;
}
}
public static class _MaxOperator extends _Operator implements Operator {
public Object compute(NSArray<?> values, String keyPath) {
Object max = null;
Object[] objects = values.objectsNoCopy();
for (int i = 0; i < objects.length; i++) {
max = _minOrMaxValue(max, _operationValue(objects[i], keyPath), true);
}
return max;
}
}
public static class _Operator {
protected Object _operationValue(Object object, String keyPath) {
return keyPath == null || keyPath.length() <= 0 ? object : NSKeyValueCodingAdditions.Utility.valueForKeyPath(object, keyPath);
}
private BigDecimal _bigDecimalForValue(Object object) {
if (object != null) {
if (_NSUtilities._isClassANumberOrABoolean(object.getClass())) {
return (BigDecimal) _NSUtilities.convertNumberOrBooleanIntoCompatibleValue(object, _NSUtilities._BigDecimalClass);
}
if (object instanceof String) {
return new BigDecimal((String) object);
}
throw new IllegalStateException("Can't convert " + object + " (class " + object.getClass().getName() + ") into number");
}
return null;
}
BigDecimal _sum(NSArray<?> values, String keyPath) {
BigDecimal sum = BigDecimal.valueOf(0L);
Object[] objects = values.objectsNoCopy();
for (int i = 0; i < objects.length; i++) {
BigDecimal value = _bigDecimalForValue(_operationValue(objects[i], keyPath));
if (value != null) {
sum = sum.add(value);
}
}
return sum;
}
Object _minOrMaxValue(Object referenceValue, Object compareValue, boolean trueForMaxAndFalseForMin) {
if (referenceValue == null) {
return compareValue;
}
if (compareValue == null) {
return referenceValue;
}
int comparison;
if (_NSUtilities._isClassANumberOrABoolean(referenceValue.getClass())) {
comparison = _NSUtilities.compareNumbersOrBooleans(referenceValue, compareValue);
}
else if (referenceValue instanceof NSTimestamp) {
comparison = ((NSTimestamp) referenceValue).compare((NSTimestamp) compareValue);
}
else if (referenceValue instanceof Comparable) {
comparison = ((Comparable<Object>) referenceValue).compareTo(compareValue);
}
else {
throw new IllegalStateException("Cannot compare values " + referenceValue + " and " + compareValue + " (they are not instance of Comparable");
}
if (trueForMaxAndFalseForMin) {
if (comparison >= 0) {
return referenceValue;
}
}
else if (comparison <= 0) {
return referenceValue;
}
return compareValue;
}
}
public static class _CountOperator implements Operator {
public Object compute(NSArray<?> values, String keyPath) {
return _NSUtilities.IntegerForInt(values.count());
}
}
public static abstract interface Operator {
public abstract Object compute(NSArray<?> nsarray, String s);
}
public static final Class _CLASS = _NSUtilitiesExtra._classWithFullySpecifiedNamePrime("com.webobjects.foundation.NSArray");
public static final int NotFound = -1;
public static final NSArray EmptyArray = new NSArray<Object>();
private static final char _OperatorIndicatorChar = '@';
public static final String CountOperatorName = "count";
public static final String MaximumOperatorName = "max";
public static final String MinimumOperatorName = "min";
public static final String SumOperatorName = "sum";
public static final String AverageOperatorName = "avg";
private static final String SerializationValuesFieldKey = "objects";
private static NSMutableDictionary<String, Operator> _operators = new NSMutableDictionary<>(8);
protected static final int _NSArrayClassHashCode = _CLASS.hashCode();
protected Object[] _objects;
protected transient int _hashCache;
private transient boolean _recomputeHashCode = true;
public static final boolean CheckForNull = true;
public static final boolean IgnoreNull = true;
private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(SerializationValuesFieldKey, ((Object) (new Object[0])).getClass()) };
public static NSArray<String> operatorNames() {
NSArray<String> operatorNames;
synchronized (_operators) {
operatorNames = _operators.allKeys();
}
return operatorNames;
}
public static void setOperatorForKey(String operatorName, Operator arrayOperator) {
if (operatorName == null) {
throw new IllegalArgumentException("Operator key cannot be null");
}
if (arrayOperator == null) {
throw new IllegalArgumentException("Operator cannot be null for " + operatorName);
}
synchronized (_operators) {
_operators.setObjectForKey(arrayOperator, operatorName);
}
}
public static Operator operatorForKey(String operatorName) {
Operator arrayOperator;
synchronized (_operators) {
arrayOperator = _operators.objectForKey(operatorName);
}
return arrayOperator;
}
public static void removeOperatorForKey(String operatorName) {
if (operatorName != null) {
synchronized (_operators) {
_operators.removeObjectForKey(operatorName);
}
}
}
protected void _initializeWithCapacity(int capacity) {
_setObjects(capacity <= 0 ? null : new Object[capacity]);
_setCount(0);
_setMustRecomputeHash(true);
}
public NSArray() {
this(null, 0, 0, false, false);
}
public NSArray(E object) {
if (object == null) {
throw new IllegalArgumentException("Attempt to insert null into an NSArray");
}
_initializeWithCapacity(1);
_objects()[0] = object;
_setCount(1);
}
private void initFromObjects(Object[] objects, int rangeLocation, int rangeLength, boolean checkForNull, boolean ignoreNull) {
initFromObjects(objects, rangeLocation, rangeLength, 0, checkForNull, ignoreNull);
}
private void initFromObjects(Object[] objects, int rangeLocation, int rangeLength, int offset, boolean checkForNull, boolean ignoreNull) {
if (checkForNull) {
int maxRange = rangeLocation + rangeLength;
int validCount = 0;
Object[] validObjects = new Object[maxRange];
for (int i = rangeLocation; i < maxRange; i++) {
Object o = objects[i];
if (o != null) {
validObjects[validCount++] = o;
continue;
}
if (!ignoreNull)
throw new IllegalArgumentException("Attempt to insert null into an " + getClass().getName() + ".");
}
_initializeWithCapacity(validCount + offset);
if (validCount > 0) {
System.arraycopy(validObjects, 0, _objects(), offset, validCount);
}
_setCount(validCount + offset);
} else {
_initializeWithCapacity(rangeLength + offset);
if (rangeLength > 0) {
System.arraycopy(objects, rangeLocation, _objects(), offset, rangeLength);
}
_setCount(rangeLength + offset);
}
}
private void initFromList(List<? extends E> list, int rangeLocation, int rangeLength, int offset, boolean checkForNull, boolean ignoreNull) {
int maxRange = rangeLocation + rangeLength;
if (checkForNull) {
int validCount = 0;
Object[] validObjects = new Object[maxRange];
for (int i = rangeLocation; i < maxRange; i++) {
Object o = list.get(i);
if (o != null) {
validObjects[validCount++] = o;
continue;
}
if (!ignoreNull)
throw new IllegalArgumentException("Attempt to insert null into an " + getClass().getName() + ".");
}
_initializeWithCapacity(validCount + offset);
if (validCount > 0) {
System.arraycopy(validObjects, 0, _objects(), offset, validCount);
}
_setCount(validCount + offset);
} else {
_initializeWithCapacity(rangeLength + offset);
System.arraycopy(list.toArray(), rangeLocation, _objects(), offset, rangeLength);
_setCount(rangeLength + offset);
}
}
protected NSArray(Object[] objects, int rangeLocation, int rangeLength, boolean checkForNull, boolean ignoreNull) {
initFromObjects(objects, rangeLocation, rangeLength, checkForNull, ignoreNull);
}
public NSArray(E[] objects) {
this(objects, 0, objects == null ? 0 : objects.length, true, true);
}
public NSArray(E object, E... objects) {
if (object == null) {
initFromObjects(objects, 0, objects == null ? 0 : objects.length, 0, true, true);
} else {
initFromObjects(objects, 0, objects == null ? 0 : objects.length, 1, true, true);
_objects()[0] = object;
}
}
public NSArray(E[] objects, NSRange range) {
this(objects, range == null ? 0 : range.location(), range == null ? 0 : range.length(), true, true);
}
public NSArray(NSArray<? extends E> otherArray) {
this(otherArray == null ? null : (E[])otherArray.objectsNoCopy(), 0, otherArray == null ? 0 : otherArray.count(), false, false);
}
public NSArray(List<? extends E> list, boolean checkForNull) {
if (list == null) {
initFromObjects(null, 0, 0, false, false);
} else {
initFromList(list, 0, list.size(), 0, checkForNull, false);
}
}
public NSArray(Collection<? extends E> collection, boolean checkForNull) {
initFromObjects(collection == null ? null : collection.toArray(), 0, collection == null ? 0 : collection.size(), checkForNull, false);
}
public NSArray(Collection<? extends E> collection) {
this(collection, true);
}
public NSArray(List<? extends E> list, NSRange range, boolean ignoreNull) {
if (list == null) {
throw new IllegalArgumentException("List cannot be null");
}
initFromList(list, range != null ? range.location() : 0, range != null ? range.length() : 0, 0, true, ignoreNull);
}
public NSArray(Vector<? extends E> vector, NSRange range, boolean ignoreNull) {
this((List<E>)vector, range, ignoreNull);
}
protected void _setCount(int count) {
// if(count != count() && count != 0) {
// throw new IllegalStateException();
// }
}
protected Object[] _objects() {
return _objects;
}
protected void _setObjects(Object[] objects) {
_objects = objects;
}
protected Object[] objectsNoCopy() {
Object[] objs = _objects();
return objs != null ? objs : _NSCollectionPrimitives.EmptyArray;
}
public int count() {
return _objects != null ? _objects.length : 0;
}
public E objectAtIndex(int index) {
int count = count();
if (index >= 0 && index < count) {
return (E)_objects()[index];
}
if (count == 0) {
throw new IllegalArgumentException("Array is empty");
}
throw new IllegalArgumentException("Index (" + index + ") out of bounds [0, " + (count() - 1) + "]");
}
public NSArray<E> arrayByAddingObject(E object) {
if (object == null) {
throw new IllegalArgumentException("Attempt to insert null into an " + getClass().getName() + ".");
}
int count = count();
Object[] objects = new Object[count + 1];
System.arraycopy(objectsNoCopy(), 0, objects, 0, count);
objects[count] = object;
return new NSArray<E>(objects, 0, count + 1, false, false);
}
public NSArray<E> arrayByAddingObjectsFromArray(NSArray<? extends E> otherArray) {
if (otherArray != null) {
int count = count();
int otherCount = otherArray.count();
if (count == 0) {
return (NSArray<E>) otherArray.immutableClone();
}
if (otherCount == 0) {
return immutableClone();
}
Object[] objects = new Object[count + otherCount];
System.arraycopy(objectsNoCopy(), 0, objects, 0, count);
System.arraycopy(otherArray.objectsNoCopy(), 0, objects, count, otherCount);
return new NSArray<E>(objects, 0, count + otherCount, false, false);
}
return immutableClone();
}
public Object[] objects() {
int count = count();
Object[] objects = new Object[count];
if (count > 0) {
System.arraycopy(objectsNoCopy(), 0, objects, 0, count);
}
return objects;
}
public Object[] objects(NSRange range) {
if (range == null) {
return _NSCollectionPrimitives.EmptyArray;
}
int rangeLength = range.length();
Object[] objects = new Object[rangeLength];
System.arraycopy(objectsNoCopy(), range.location(), objects, 0, rangeLength);
return objects;
}
public Vector<E> vector() {
Vector<E> vector = new Vector<E>();
E[] objects = (E[])objectsNoCopy();
for (int i = 0; i < objects.length; i++) {
vector.addElement(objects[i]);
}
return vector;
}
public ArrayList<E> arrayList() {
E[] objects = (E[])objectsNoCopy();
ArrayList<E> list = new ArrayList<E>(objects.length);
for (int i = 0; i < objects.length; i++) {
list.add(objects[i]);
}
return list;
}
public boolean containsObject(Object object) {
if (object == null) {
return false;
}
return _findObjectInArray(0, count(), object, false) != NotFound;
}
public E firstObjectCommonWithArray(NSArray<?> otherArray) {
if (otherArray == null) {
return null;
}
int otherCount = otherArray.count();
if (otherCount > 0) {
Object[] objects = objectsNoCopy();
for (int i = 0; i < objects.length; i++) {
if (otherArray.containsObject(objects[i])) {
return (E)objects[i];
}
}
}
return null;
}
/**
* @deprecated use {@link #objects()} or {@link #objectsNoCopy()}
*/
@Deprecated
public void getObjects(Object[] objects) {
if (objects == null) {
throw new IllegalArgumentException("Object buffer cannot be null");
}
System.arraycopy(objectsNoCopy(), 0, objects, 0, count());
}
/**
* @deprecated use {@link #objects(NSRange)}
*/
@Deprecated
public void getObjects(Object[] objects, NSRange range) {
if (objects == null) {
throw new IllegalArgumentException("Object buffer cannot be null");
}
if (range == null) {
throw new IllegalArgumentException("Range cannot be null");
}
System.arraycopy(objectsNoCopy(), range.location(), objects, 0, range.length());
}
private final int _findObjectInArray(int index, int length, Object object, boolean identical) {
if (count() > 0) {
Object[] objects = objectsNoCopy();
int maxIndex = (index + length) - 1;
for (int i = index; i <= maxIndex; i++) {
if (objects[i] == object) {
return i;
}
if (!identical && object.equals(objects[i])) {
return i;
}
}
}
return NotFound;
}
public int indexOfObject(Object object) {
if (object == null) {
return NotFound;
}
return _findObjectInArray(0, count(), object, false);
}
public int indexOfObject(Object object, NSRange range) {
if (object == null || range == null) {
return NotFound;
}
int count = count();
int rangeLocation = range.location();
int rangeLength = range.length();
if (rangeLocation + rangeLength > count || rangeLocation >= count) {
throw new IllegalArgumentException("Range [" + rangeLocation + "; " + rangeLength + "] out of bounds [0, " + (count() - 1) + "]");
}
return _findObjectInArray(rangeLocation, rangeLength, object, false);
}
public int indexOfIdenticalObject(Object object) {
if (object == null) {
return NotFound;
}
return _findObjectInArray(0, count(), object, true);
}
public int indexOfIdenticalObject(Object object, NSRange range) {
if (object == null || range == null) {
return NotFound;
}
int count = count();
int rangeLocation = range.location();
int rangeLength = range.length();
if (rangeLocation + rangeLength > count || rangeLocation >= count) {
throw new IllegalArgumentException("Range [" + rangeLocation + "; " + rangeLength + "] out of bounds [0, " + (count() - 1) + "]");
}
return _findObjectInArray(rangeLocation, rangeLength, object, true);
}
public NSArray<E> subarrayWithRange(NSRange range) {
if (range == null) {
return EmptyArray;
}
return new NSArray<E>(objectsNoCopy(), range.location(), range.length(), false, false);
}
public E lastObject() {
int count = count();
return count != 0 ? objectAtIndex(count - 1) : null;
}
private boolean _equalsArray(NSArray<?> otherArray) {
int count = count();
if (count != otherArray.count()) {
return false;
}
if (!_mustRecomputeHash() && !otherArray._mustRecomputeHash() && hashCode() != otherArray.hashCode()) {
return false;
}
Object[] objects = objectsNoCopy();
Object[] otherObjects = otherArray.objectsNoCopy();
for (int i = 0; i < count; i++) {
if (!objects[i].equals(otherObjects[i])) {
return false;
}
}
return true;
}
public boolean isEqualToArray(NSArray<?> otherArray) {
if (otherArray == this) {
return true;
}
if (otherArray == null) {
return false;
}
return _equalsArray(otherArray);
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof NSArray) {
return _equalsArray((NSArray<?>) object);
}
return false;
}
@SuppressWarnings("unchecked")
public Enumeration<E> objectEnumerator() {
return new _NSJavaArrayEnumerator(objectsNoCopy(), count(), false);
}
@SuppressWarnings("unchecked")
public Enumeration<E> reverseObjectEnumerator() {
return new _NSJavaArrayEnumerator(objectsNoCopy(), count(), true);
}
/**
* @deprecated Method sortedArrayUsingSelector is deprecated
*/
@Deprecated
@SuppressWarnings("unchecked")
public NSArray sortedArrayUsingSelector(NSSelector selector) throws NSComparator.ComparisonException {
NSMutableArray array = new NSMutableArray(this);
NSComparator comparator = new NSComparator._NSSelectorComparator(selector);
array.sortUsingComparator(comparator);
return array;
}
public NSArray<E> sortedArrayUsingComparator(NSComparator comparator) throws NSComparator.ComparisonException {
NSMutableArray<E> array = new NSMutableArray<E>(this);
array.sortUsingComparator(comparator);
return array;
}
public String componentsJoinedByString(String separator) {
Object[] objects = objectsNoCopy();
StringBuilder buffer = new StringBuilder(objects.length * 32);
for (int i = 0; i < objects.length; i++) {
if (i > 0 && separator != null) {
buffer.append(separator);
}
buffer.append(objects[i].toString());
}
return buffer.toString();
}
public static NSArray<String> componentsSeparatedByString(String string, String separator) {
NSMutableArray<String> objects;
if ((string == null) || (string.length() == 0)) {
return emptyArray();
}
int stringLength = string.length();
if ((separator == null) || (separator.length() == 0)) {
return new NSArray<>(string);
}
int separatorLength = separator.length();
int start = 0; int index = 0; int count = 0;
if ((separatorLength == 1) && (stringLength < 256)) {
char[] parseData = string.toCharArray();
char charSeparator = separator.charAt(0);
for (int i = 0; i < stringLength; ++i) {
if (parseData[i] == charSeparator) {
++count;
}
}
if (count == 0) {
return new NSArray<>(string);
}
objects = new NSMutableArray<>(count + 1);
int end = stringLength - 1;
for (index = 0; index <= end; ++index) {
if (parseData[index] == charSeparator) {
if (start == index) {
objects.addObject("");
} else {
objects.addObject(string.substring(start, index));
}
start = index + 1;
}
}
if (parseData[end] == charSeparator) {
objects.addObject("");
} else {
objects.addObject(string.substring(start, stringLength));
}
} else {
objects = new NSMutableArray<>(4);
int end = stringLength - separatorLength;
while (true) {
if (start >= stringLength) {
return objects;
}
index = string.indexOf(separator, start);
if (index < 0) {
index = stringLength;
}
if (index == end) {
break;
}
objects.addObject(string.substring(start, index));
start = index + separatorLength;
}
if (start <= index) {
objects.addObject(string.substring(start, index));
}
objects.addObject("");
}
return objects;
}
public static NSMutableArray<String> _mutableComponentsSeparatedByString(String string, String separator) {
return componentsSeparatedByString(string, separator).mutableClone();
}
private Object _valueForKeyPathWithOperator(String keyPath) {
int index = keyPath.indexOf('.');
String operatorName;
String operatorPath;
if (index < 0) {
operatorName = keyPath.substring(1);
operatorPath = "";
} else {
operatorName = keyPath.substring(1, index);
operatorPath = index >= keyPath.length() - 1 ? "" : keyPath.substring(index + 1);
}
Operator arrayOperator = operatorForKey(operatorName);
if (arrayOperator != null) {
return arrayOperator.compute(this, operatorPath);
}
throw new IllegalArgumentException("No key operator available to compute aggregate " + keyPath);
}
public Object valueForKey(String key) {
if (key != null) {
if (key.charAt(0) == _OperatorIndicatorChar) {
return _valueForKeyPathWithOperator(key);
}
if (key.equals(CountOperatorName)) {
return _NSUtilities.IntegerForInt(count());
}
}
Object[] objects = objectsNoCopy();
NSMutableArray<Object> values = new NSMutableArray<>(objects.length);
for (int i = 0; i < objects.length; i++) {
Object value = NSKeyValueCodingAdditions.Utility.valueForKeyPath(objects[i], key);
values.addObject(value == null ? ((Object) (NSKeyValueCoding.NullValue)) : value);
}
return values;
}
public void takeValueForKey(Object value, String key) {
Object[] objects = objectsNoCopy();
for (int i = 0; i < objects.length; i++) {
NSKeyValueCodingAdditions.Utility.takeValueForKeyPath(objects[i], value, key);
}
}
public Object valueForKeyPath(String keyPath) {
if (keyPath != null && keyPath.charAt(0) == _OperatorIndicatorChar) {
return _valueForKeyPathWithOperator(keyPath);
}
return NSKeyValueCodingAdditions.DefaultImplementation.valueForKeyPath(this, keyPath);
}
public void takeValueForKeyPath(Object value, String keyPath) {
NSKeyValueCodingAdditions.DefaultImplementation.takeValueForKeyPath(this, value, keyPath);
}
@SuppressWarnings("unchecked")
public Class classForCoder() {
return _CLASS;
}
public static Object decodeObject(NSCoder coder) {
return new NSArray<Object>(coder.decodeObjects());
}
public void encodeWithCoder(NSCoder coder) {
coder.encodeObjects(objectsNoCopy());
}
public void makeObjectsPerformSelector(NSSelector selector, Object... parameters) {
if (selector == null) {
throw new IllegalArgumentException("Selector cannot be null");
}
Object[] objects = objectsNoCopy();
for (int i = 0; i < objects.length; i++) {
NSSelector._safeInvokeSelector(selector, objects[i], parameters);
}
}
public int _shallowHashCode() {
return _NSArrayClassHashCode;
}
@Override
public int hashCode() {
if (_mustRecomputeHash()) {
int hash = 0;
int max = count() <= 16 ? count() : 16;
for (int i = 0; i < max; i++) {
Object element = objectAtIndex(i);
if (element instanceof _NSFoundationCollection) {
hash ^= ((_NSFoundationCollection) element)._shallowHashCode();
} else {
hash ^= element.hashCode();
}
}
_hashCache = hash;
_setMustRecomputeHash(false);
}
return _hashCache;
}
@Override
public Object clone() {
return this;
}
public NSArray<E> immutableClone() {
return this;
}
public NSMutableArray<E> mutableClone() {
return new NSMutableArray<E>(this);
}
@Override
public String toString() {
if(count() == 0) {
return "()";
}
StringBuilder buffer = new StringBuilder(128);
buffer.append('(');
Object[] objects = objectsNoCopy();
for (int i = 0; i < objects.length; i++) {
Object object = objects[i];
if (i > 0) {
buffer.append(", ");
}
if (object instanceof String) {
buffer.append('"');
buffer.append((String) object);
buffer.append('"');
continue;
}
if (object instanceof Boolean) {
buffer.append(((Boolean) object).booleanValue() ? "true" : "false");
} else {
buffer.append(object == this ? "THIS" : object.toString());
}
}
buffer.append(')');
return buffer.toString();
}
protected boolean _mustRecomputeHash() {
return _recomputeHashCode;
}
protected void _setMustRecomputeHash(boolean change) {
_recomputeHashCode = change;
}
private void writeObject(ObjectOutputStream s) throws IOException {
java.io.ObjectOutputStream.PutField fields = s.putFields();
fields.put(SerializationValuesFieldKey, objects());
s.writeFields();
}
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
java.io.ObjectInputStream.GetField fields = null;
fields = s.readFields();
Object[] values = (Object[]) fields.get(SerializationValuesFieldKey, _NSUtilities._NoObjectArray);
values = values != null ? values : _NSUtilities._NoObjectArray;
initFromObjects(values, 0, values.length, true, false);
}
private Object readResolve() throws ObjectStreamException {
if (getClass() == _CLASS && count() == 0) {
return EmptyArray;
}
return this;
}
public void add(int index, E element) {
throw new UnsupportedOperationException("add is not a supported operation in com.webobjects.foundation.NSArray");
}
public boolean add(E element) {
throw new UnsupportedOperationException("add is not a supported operation in com.webobjects.foundation.NSArray");
}
public boolean addAll(Collection<? extends E> collection) {
throw new UnsupportedOperationException("addAll is not a supported operation in com.webobjects.foundation.NSArray");
}
public boolean addAll(int index, Collection<? extends E> collection) {
throw new UnsupportedOperationException("addAll is not a supported operation in com.webobjects.foundation.NSArray");
}
public boolean contains(Object element) {
if (element == null) {
throw new NullPointerException("NSArray does not support null values");
}
return containsObject(element);
}
@SuppressWarnings("unchecked")
public Iterator<E> iterator() {
return new _NSJavaArrayListIterator(objectsNoCopy(), count());
}
public Object[] toArray() {
return objects();
}
public <T> T[] toArray(T[] objects) {
if (objects == null) {
throw new NullPointerException("List.toArray() cannot have a null parameter");
}
int count = count();
if (count <= 0) {
return objects;
}
Object[] objs = objectsNoCopy();
if (objects.length < objs.length) {
objects = (T[])java.lang.reflect.Array.newInstance(objects.getClass().getComponentType(), objs.length);
}
System.arraycopy(objs, 0, objects, 0, objs.length);
return objects;
}
public boolean containsAll(Collection<?> c) {
Object[] objects = c.toArray();
if (objects.length > 0) {
for (int i = 0; i < objects.length; i++) {
if (objects[i] == null) {
return false;
}
if (_findObjectInArray(0, count(), objects[i], false) == NotFound) {
return false;
}
}
}
return true;
}
@SuppressWarnings("unchecked")
public ListIterator<E> listIterator() {
Object[] objs = objectsNoCopy();
return new _NSJavaArrayListIterator(objs, count());
}
@SuppressWarnings("unchecked")
public ListIterator<E> listIterator(int index) {
Object[] objs = objectsNoCopy();
return new _NSJavaArrayListIterator(objs, count(), index);
}
public E get(int index) {
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException("Index " + index + " is out of bounds");
}
return objectAtIndex(index);
}
public E set(int index, E element) {
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException("Index " + index + " is out of bounds");
}
throw new UnsupportedOperationException("Set is not a support operation in com.webobjects.foundation.NSArray");
}
public int indexOf(Object element) {
if (element == null) {
throw new NullPointerException("com.webobjects.foundation.NSArray does not support null values");
}
return indexOfObject(element);
}
public int lastIndexOf(Object element) {
int lastIndex = NotFound;
if (element == null) {
throw new NullPointerException("com.webobjects.foundation.NSArray does not support null values");
}
for (int i = 0; i < count(); i++) {
if (objectAtIndex(i).equals(element)) {
lastIndex = i;
}
}
return lastIndex;
}
public boolean isEmpty() {
return count() == 0;
}
public int size() {
return count();
}
public E remove(int index) {
throw new UnsupportedOperationException("Remove is not a support operation in com.webobjects.foundation.NSArray");
}
public boolean remove(Object object) {
throw new UnsupportedOperationException("Remove is not a support operation in com.webobjects.foundation.NSArray");
}
public void clear() {
throw new UnsupportedOperationException("Clear is not a supported operation in com.webobjects.foundation.NSArray");
}
public boolean retainAll(Collection<?> collection) {
throw new UnsupportedOperationException("RetainAll is not a supported operation in com.webobjects.foundation.NSArray");
}
public boolean removeAll(Collection<?> collection) {
throw new UnsupportedOperationException("RemoveAll is not a supported operation in com.webobjects.foundation.NSArray");
}
public List<E> subList(int fromIndex, int toIndex) {
if (fromIndex < 0 || toIndex > count() || fromIndex > toIndex) {
throw new IndexOutOfBoundsException("Illegal index value (fromIndex < 0 || toIndex > size || fromIndex > toIndex)");
}
return subarrayWithRange(new NSRange(fromIndex, (toIndex - fromIndex)));
}
public static final <T> NSArray<T> emptyArray() {
return EmptyArray;
}
static {
try {
setOperatorForKey(CountOperatorName, new _CountOperator());
setOperatorForKey(MaximumOperatorName, new _MaxOperator());
setOperatorForKey(MinimumOperatorName, new _MinOperator());
setOperatorForKey(SumOperatorName, new _SumNumberOperator());
setOperatorForKey(AverageOperatorName, new _AvgNumberOperator());
}
catch (Throwable e) {
NSLog.err.appendln("Exception occurred in initializer");
if (NSLog.debugLoggingAllowedForLevel(1)) {
NSLog.debug.appendln(e);
}
throw NSForwardException._runtimeExceptionForThrowable(e);
}
}
/**
* A type-safe wrapper for {@link #valueForKeyPath(String)} that simply
* calls {@code valueForKeyPath(erxKey.key())} and attempts to cast the
* result to {@code NSArray<T>}. If the value returned cannot be cast it
* will throw a {@link ClassCastException}.
*
* @param <T>
* the Type of elements in the returned {@code NSArray}
* @param erxKey
* @return an {@code NSArray} of {@code T} objects.
* @author David Avendasora
*/
public <T> NSArray<T> valueForKeyPath(ERXKey<T> erxKey) {
return (NSArray<T>) valueForKeyPath(erxKey.key());
}
/**
* A type-safe wrapper for {@link #valueForKey(String)} that automatically
* does the following (in order) to the resulting array prior to returning
* it:
* <ol>
* <li>{@link ERXArrayUtilities#removeNullValues(NSArray) remove}
* {@code NSKeyValueCoding.Null} elements</li>
* <li>{@link ERXArrayUtilities#flatten(NSArray) flatten} all elements that
* are arrays (<em>Only</em> if {@link ERXKey#isToManyRelationship()}
* returns <code>true</code>, which can only possibly happen if
* {@link ERXKey#type()} has been set.)</li>
* <li>{@link ERXArrayUtilities#distinct(Collection) remove} all duplicate
* objects</li>
* </ol>
*
* @param <T>
* the Type of elements in the returned {@code NSArray}
* @param erxKey
*
* @return an {@code NSArray} of {@code T} objects.
*
* @author David Avendasora
*/
public <T> NSArray<T> valueForKey(ERXKey<T> erxKey) {
return valueForKey(erxKey, true, true, true);
}
/**
* A type-safe wrapper for {@link #valueForKeyPath(String)} that calls
* {@code valueForKeyPath(erxKey.key())} and attempts to cast the result to
* {@code NSArray<T>}.
* <p>
* Then, depending upon the parameters,
* <ol>
* <li>{@link ERXArrayUtilities#removeNullValues(NSArray) remove}
* {@code NSKeyValueCoding.Null} elements</li>
* <li>{@link ERXArrayUtilities#flatten(NSArray) flatten} all elements that
* are arrays (<em>Only</em> if {@link ERXKey#isToManyRelationship()}
* returns <code>true</code>, which can only possibly happen if
* {@link ERXKey#type()} has been set.)</li>
* <li>{@link ERXArrayUtilities#distinct(Collection) remove} all duplicate
* objects</li>
* </ol>
* <p>
* <b>If the value cannot be cast it will throw a {@link ClassCastException}
* .</b>
*
* @param <T>
* the Type of elements in the returned {@code NSArray}
* @param erxKey
* @param removeNulls
* if {@code true} all {@link NSKeyValueCoding.Null} elements
* will be {@link ERXArrayUtilities#removeNullValues(NSArray)
* removed}
* @param distinct
* if {@code true} all duplicate elements will be
* {@link ERXArrayUtilities#distinct(NSArray) removed}
* @param flatten
* if {@code true} all {@link NSArray} elements will be
* {@link ERXArrayUtilities#flatten(NSArray) flattened}
*
* @return an {@code NSArray} of {@code T} objects.
*
* @author David Avendasora
*/
public <T> NSArray<T> valueForKey(ERXKey<T> erxKey, boolean removeNulls, boolean distinct, boolean flatten) {
if (erxKey.type() == ERXKey.Type.Operator) {
final String message = "You cannot use an Operator (@sum, @max, etc.) ERXKey with valueForKey(ERXKey) "
+ "because the value returned by valueForKey(opperator) cannot be cast to NSArray. "
+ "Call valueForKey(MY_OPPERATOR_ERXKEY.key()) instead.";
throw new IllegalArgumentException(message);
}
NSArray<T> values = (NSArray<T>) valueForKeyPath(erxKey.key());
if (removeNulls) {
values = ERXArrayUtilities.removeNullValues(values);
}
if (flatten && erxKey.isToManyRelationship()) {
values = ERXArrayUtilities.flatten(values);
}
if (distinct) {
values = ERXArrayUtilities.distinct(values);
}
return values;
}
}