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.util.Collection;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* <div class="en">
* NSDictionary reimplementation to support JDK 1.5 templates. Use with
* </div>
*
* <div class="ja">
* JDK 1.5 テンプレートをサポートする為の再実装。使用は
* </div>
*
* <pre>{@code
* NSDictionary<String, String> env = new NSDictionary<String, String>(System.getenv(), true);
*
* for (String key : env)
* logger.debug(env.valueForKey(key));
* }</pre>
*
* @param <K>
* type of key contents
* @param <V>
* type of value contents
*/
public class NSDictionary<K, V> implements Cloneable, Serializable, NSCoding, NSKeyValueCoding, NSKeyValueCodingAdditions, _NSFoundationCollection, Map<K, V> {
static final long serialVersionUID = 2886170486405617806L;
public class _JavaNSDictionaryMapEntry<P, Q> implements java.util.Map.Entry<P, Q> {
public P getKey() {
return _entryKey;
}
public Q getValue() {
return _entryValue;
}
public Q setValue(Q value) {
return (Q)NSDictionary.this.put((K)getKey(), (V)value);
}
@Override
public boolean equals(Object o) {
return _entryKey == null && ((Map.Entry<P, Q>) o).getKey() == null && getKey().equals(((Map.Entry<P, Q>) o).getKey()) && getValue().equals(((Map.Entry<P, Q>) o).getValue());
}
@Override
public int hashCode() {
return _entryKey == null ? System.identityHashCode(this) : _entryKey.hashCode();
}
Q _entryValue;
P _entryKey;
public _JavaNSDictionaryMapEntry(P key, Q value) {
super();
_entryKey = key;
_entryValue = value;
}
}
private void _copyImmutableDictionary(NSDictionary<? extends K, ? extends V> otherDictionary) {
_capacity = otherDictionary._capacity;
_count = otherDictionary._count;
_hashtableBuckets = otherDictionary._hashtableBuckets;
_hashCache = otherDictionary._hashCache;
_objects = otherDictionary._objects;
_objectsCache = otherDictionary._objectsCache;
_entrySetCache = null;
_flags = otherDictionary._flags;
_keys = otherDictionary._keys;
_keysCache = otherDictionary._keysCache;
_deletionLimit = otherDictionary._deletionLimit;
}
void _copyMutableDictionary(NSDictionary<? extends K, ? extends V> otherDictionary) {
if (otherDictionary.getClass() == NSMutableDictionary._CLASS || otherDictionary.getClass() == NSDictionary._CLASS) {
this._capacity = otherDictionary._capacity;
this._count = otherDictionary._count;
this._hashtableBuckets = otherDictionary._hashtableBuckets;
this._hashCache = otherDictionary._hashCache;
this._objects = _NSCollectionPrimitives.copyArray(otherDictionary._objects);
this._objectsCache = null;
this._entrySetCache = null;
this._flags = _NSCollectionPrimitives.copyArray(otherDictionary._flags);
this._keys = _NSCollectionPrimitives.copyArray(otherDictionary._keys);
this._keysCache = null;
this._keySetCache = null;
this._deletionLimit = otherDictionary._deletionLimit;
}
else {
_initializeDictionary();
_ensureCapacity(otherDictionary.count());
Enumeration<? extends K> keyEnum = otherDictionary.keyEnumerator();
while (keyEnum.hasMoreElements()) {
K key = keyEnum.nextElement();
V object = otherDictionary.objectForKey(key);
if (_NSCollectionPrimitives.addValueInHashTable(key, object, this._keys, this._objects, this._flags)) {
this._count++;
}
}
}
}
protected void _initializeDictionary() {
_capacity = _count = 0;
_objects = _objectsCache = null;
_entrySetCache = null;
_flags = null;
_keys = _keysCache = null;
_hashtableBuckets = _NSCollectionPrimitives.hashTableBucketsForCapacity(_capacity);
_deletionLimit = _NSCollectionPrimitives.deletionLimitForTableBuckets(_hashtableBuckets);
_keySetCache = null;
_entrySetCache = null;
}
protected void _ensureCapacity(int capacity) {
int currentCapacity = _capacity;
if (capacity > currentCapacity) {
int newCapacity = _NSCollectionPrimitives.hashTableCapacityForCapacity(capacity);
if (newCapacity != currentCapacity) {
int oldSize = _hashtableBuckets;
int newSize = _NSCollectionPrimitives.hashTableBucketsForCapacity(newCapacity);
_hashtableBuckets = newSize;
if (newSize == 0) {
_objects = null;
_keys = null;
_flags = null;
}
else {
Object[] oldObjects = _objects;
Object[] oldKeys = _keys;
byte[] oldFlags = _flags;
Object[] newObjects = new Object[newSize];
Object[] newKeys = new Object[newSize];
byte[] newFlags = new byte[newSize];
for (int i = 0; i < oldSize; i++) {
if ((oldFlags[i] & 0xffffffc0) == -128) {
_NSCollectionPrimitives.addValueInHashTable(oldKeys[i], oldObjects[i], newKeys, newObjects, newFlags);
}
}
_objects = newObjects;
_keys = newKeys;
_flags = newFlags;
}
_deletionLimit = _NSCollectionPrimitives.deletionLimitForTableBuckets(newSize);
_capacity = newCapacity;
}
}
}
protected void _clearDeletionsAndCollisions() {
int size = _hashtableBuckets;
if (_count == 0) {
_flags = new byte[size];
}
else {
Object[] oldObjects = _objects;
Object[] oldKeys = _keys;
byte[] oldFlags = _flags;
Object[] newObjects = new Object[size];
Object[] newKeys = new Object[size];
byte[] newFlags = new byte[size];
for (int i = 0; i < size; i++) {
if ((oldFlags[i] & 0xffffffc0) == -128) {
_NSCollectionPrimitives.addValueInHashTable(oldKeys[i], oldObjects[i], newKeys, newObjects, newFlags);
}
}
}
_deletionLimit = _NSCollectionPrimitives.deletionLimitForTableBuckets(size);
}
public NSDictionary() {
_initializeDictionary();
}
public NSDictionary(V object, K key) {
if (object == null) {
throw new IllegalArgumentException("Attempt to insert null object into an " + getClass().getName() + ".");
}
if (key == null) {
throw new IllegalArgumentException("Attempt to insert null key into an " + getClass().getName() + ".");
}
_initializeDictionary();
_ensureCapacity(1);
if (_NSCollectionPrimitives.addValueInHashTable(key, object, _keys, _objects, _flags)) {
_count++;
}
}
private void initFromKeyValues(Object[] objects, Object[] keys, boolean checkForNull) {
if (objects != null && keys != null) {
if (objects.length != keys.length) {
throw new IllegalArgumentException("Attempt to create an " + getClass().getName() + " with a different number of objects and keys.");
}
if (checkForNull) {
for (int i = 0; i < objects.length; i++) {
if (objects[i] == null) {
throw new IllegalArgumentException("Attempt to insert null object into an " + getClass().getName() + ".");
}
if (keys[i] == null) {
throw new IllegalArgumentException("Attempt to insert null key into an " + getClass().getName() + ".");
}
}
}
_initializeDictionary();
_ensureCapacity(objects.length);
for (int i = 0; i < objects.length; i++) {
if (_NSCollectionPrimitives.addValueInHashTable(keys[i], objects[i], _keys, _objects, _flags)) {
_count++;
}
}
} else if (objects == null && keys == null) {
_initializeDictionary();
} else {
throw new IllegalArgumentException("Either objects and keys cannot be null");
}
}
private NSDictionary(V[] objects, K[] keys, boolean checkForNull) {
initFromKeyValues(objects, keys, checkForNull);
}
public NSDictionary(V[] objects, K[] keys) {
this(objects, keys, CheckForNull);
}
public NSDictionary(NSArray<? extends V> objects, NSArray<? extends K> keys) {
this(objects == null ? null : (V[])objects.objectsNoCopy(), keys == null ? null : (K[])keys.objectsNoCopy(), false);
}
public NSDictionary(NSDictionary<? extends K, ? extends V> otherDictionary) {
if (otherDictionary.getClass() == _CLASS) {
_copyImmutableDictionary(otherDictionary);
} else {
_copyMutableDictionary(otherDictionary);
}
}
public NSDictionary(Map<? extends K, ? extends V> map) {
this(map, false);
}
public NSDictionary(Map<? extends K, ? extends V> map, boolean ignoreNull) {
_initializeDictionary();
if (map != null) {
_ensureCapacity(map.size());
Set<? extends K> keySet = map.keySet();
Iterator<? extends K> it = keySet.iterator();
do {
if (!it.hasNext()) {
break;
}
Object key = it.next();
Object object = map.get(key);
if (key == null) {
if (!ignoreNull) {
throw new IllegalArgumentException("Attempt to insert null key into an " + getClass().getName() + ".");
}
}
else if (object == null) {
if (!ignoreNull) {
throw new IllegalArgumentException("Attempt to insert null value into an " + getClass().getName() + ".");
}
}
else if (_NSCollectionPrimitives.addValueInHashTable(key, object, _keys, _objects, _flags)) {
_count++;
}
}
while (true);
} else {
throw new NullPointerException("map cannot be null");
}
}
public NSDictionary(Dictionary<? extends K, ? extends V> dictionary, boolean ignoreNull) {
_initializeDictionary();
if (dictionary != null) {
_ensureCapacity(dictionary.size());
Enumeration<? extends K> enumeration = dictionary.keys();
do {
if (!enumeration.hasMoreElements()) {
break;
}
Object key = enumeration.nextElement();
Object object = dictionary.get(key);
if (key == null) {
if (!ignoreNull) {
throw new IllegalArgumentException("Attempt to insert null key into an " + getClass().getName() + ".");
}
}
else if (object == null) {
if (!ignoreNull) {
throw new IllegalArgumentException("Attempt to insert null value into an " + getClass().getName() + ".");
}
}
else if (_NSCollectionPrimitives.addValueInHashTable(key, object, _keys, _objects, _flags)) {
_count++;
}
}
while (true);
}
}
protected Object[] keysNoCopy() {
if (_keysCache == null) {
_keysCache = _count != 0 ? _NSCollectionPrimitives.keysInHashTable(_keys, _objects, _flags, _capacity, _hashtableBuckets) : _NSCollectionPrimitives.EmptyArray;
}
return _keysCache;
}
protected Object[] objectsNoCopy() {
if (_objectsCache == null) {
_objectsCache = _count != 0 ? _NSCollectionPrimitives.valuesInHashTable(_keys, _objects, _flags, _capacity, _hashtableBuckets) : _NSCollectionPrimitives.EmptyArray;
_entrySetCache = null;
}
return _objectsCache;
}
public int count() {
return _count;
}
public V objectForKey(Object key) {
return _count != 0 && key != null ? (V) _NSCollectionPrimitives.findValueInHashTable(key, _keys, _objects, _flags) : null;
}
public Hashtable<K, V> hashtable() {
Object[] keys = keysNoCopy();
int c = keys.length;
Hashtable<K, V> hashtable = new Hashtable<K, V>(c <= 0 ? 1 : c);
for (int i = 0; i < c; i++) {
hashtable.put((K)keys[i], objectForKey(keys[i]));
}
return hashtable;
}
public HashMap<K, V> hashMap() {
Object[] keys = keysNoCopy();
int c = keys.length;
HashMap<K, V> map = new HashMap<K, V>(c <= 0 ? 1 : c);
for (int i = 0; i < c; i++) {
map.put((K)keys[i], objectForKey(keys[i]));
}
return map;
}
public NSArray<K> allKeysForObject(Object object) {
if (object != null) {
Object[] keys = keysNoCopy();
NSMutableArray<K> array = new NSMutableArray<K>(keys.length);
for (int i = 0; i < keys.length; i++) {
Object compareObject = objectForKey(keys[i]);
if (object == compareObject || object.equals(compareObject)) {
array.addObject((K) keys[i]);
}
}
return array;
}
return NSArray.EmptyArray;
}
public NSArray<V> objectsForKeys(NSArray<? extends K> keys, V notFoundMarker) {
if (keys != null) {
Object[] keysArray = keys.objectsNoCopy();
NSMutableArray<V> array = new NSMutableArray<V>(keysArray.length);
for (int i = 0; i < keysArray.length; i++) {
V object = objectForKey(keysArray[i]);
if (object != null) {
array.addObject(object);
continue;
}
if (notFoundMarker != null) {
array.addObject(notFoundMarker);
}
}
return array;
}
return NSArray.EmptyArray;
}
private boolean _equalsDictionary(NSDictionary<?, ?> otherDictionary) {
int count = count();
if (count != otherDictionary.count()) {
return false;
}
Object[] keys = keysNoCopy();
for (int i = 0; i < count; i++) {
Object value = objectForKey(keys[i]);
Object otherValue = otherDictionary.objectForKey(keys[i]);
if (otherValue == null || !value.equals(otherValue)) {
return false;
}
}
return true;
}
public boolean isEqualToDictionary(NSDictionary<?, ?> otherDictionary) {
if (otherDictionary == null) {
return false;
}
if (otherDictionary == this) {
return true;
}
return _equalsDictionary(otherDictionary);
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof NSDictionary) {
return _equalsDictionary((NSDictionary<K,V>) object);
}
return false;
}
@SuppressWarnings("unchecked")
public NSArray<K> allKeys() {
return new NSArray(keysNoCopy());
}
@SuppressWarnings("unchecked")
public NSArray<V> allValues() {
return new NSArray(objectsNoCopy());
}
@SuppressWarnings("unchecked")
public Enumeration<K> keyEnumerator() {
return new _NSCollectionEnumerator(_keys, _flags, _count);
}
@SuppressWarnings("unchecked")
public Enumeration<V> objectEnumerator() {
return new _NSCollectionEnumerator(_objects, _flags, _count);
}
public Object valueForKey(String key) {
Object value = objectForKey(key);
if (value == null && key != null) {
if (key.equals("allValues")) {
return allValues();
}
if (key.equals("allKeys")) {
return allKeys();
}
if (key.equals("count")) {
return _NSUtilities.IntegerForInt(count());
}
}
return value;
}
public void takeValueForKey(Object value, String key) {
throw new IllegalStateException(getClass().getName() + " is immutable.");
}
public Object valueForKeyPath(String keyPath) {
Object flattenedKeyPresent = objectForKey(keyPath);
if (flattenedKeyPresent != null) {
return flattenedKeyPresent;
}
return NSKeyValueCodingAdditions.DefaultImplementation.valueForKeyPath(this, keyPath);
}
public void takeValueForKeyPath(Object value, String keyPath) {
NSKeyValueCodingAdditions.DefaultImplementation.takeValueForKeyPath(this, value, keyPath);
}
public Class classForCoder() {
return _CLASS;
}
public static final <K, V> NSDictionary<K, V> emptyDictionary() {
return NSDictionary.EmptyDictionary;
}
public static Object decodeObject(NSCoder coder) {
int count = coder.decodeInt();
Object[] keys = new Object[count];
Object[] objects = new Object[count];
for (int i = 0; i < count; i++) {
keys[i] = coder.decodeObject();
objects[i] = coder.decodeObject();
}
return new NSDictionary<Object, Object>(objects, keys);
}
public void encodeWithCoder(NSCoder coder) {
int count = count();
coder.encodeInt(count);
if (count > 0) {
Object[] keys = keysNoCopy();
for (int i = 0; i < keys.length; i++) {
coder.encodeObject(keys[i]);
coder.encodeObject(objectForKey(keys[i]));
}
}
}
public int _shallowHashCode() {
return _NSDictionaryClassHashCode;
}
@Override
public int hashCode() {
return _NSDictionaryClassHashCode ^ count();
}
@Override
public Object clone() {
return this;
}
public NSDictionary<K, V> immutableClone() {
return this;
}
public NSMutableDictionary<K, V> mutableClone() {
return new NSMutableDictionary<K, V>(this);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append('{');
Object[] keys = keysNoCopy();
for (int i = 0; i < keys.length; i++) {
Object key = keys[i];
Object object = objectForKey(key);
sb.append(key.toString());
sb.append(" = ");
if (object instanceof String) {
sb.append('"');
sb.append((String) object);
sb.append('"');
}
else if (object instanceof Boolean) {
sb.append(((Boolean) object).toString());
}
else {
sb.append(object);
}
sb.append("; ");
}
sb.append('}');
return sb.toString();
}
private void writeObject(ObjectOutputStream s) throws IOException {
java.io.ObjectOutputStream.PutField fields = s.putFields();
Object[] keys = keysNoCopy();
int c = keys.length;
Object[] values = new Object[c];
for (int i = 0; i < c; i++) {
values[i] = objectForKey(keys[i]);
}
fields.put(SerializationKeysFieldKey, ((keys)));
fields.put(SerializationValuesFieldKey, ((values)));
s.writeFields();
}
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
java.io.ObjectInputStream.GetField fields = null;
fields = s.readFields();
Object[] keys = (Object[]) fields.get(SerializationKeysFieldKey, ((_NSUtilities._NoObjectArray)));
Object[] values = (Object[]) fields.get(SerializationValuesFieldKey, ((_NSUtilities._NoObjectArray)));
keys = keys != null ? keys : _NSUtilities._NoObjectArray;
values = values != null ? values : _NSUtilities._NoObjectArray;
initFromKeyValues(values, keys, CheckForNull);
}
private Object readResolve() throws ObjectStreamException {
if (getClass() == _CLASS && count() == 0) {
return EmptyDictionary;
}
return this;
}
public int size() {
return count();
}
public boolean isEmpty() {
return count() <= 0;
}
public boolean containsKey(Object key) {
return objectForKey(key) != null;
}
public boolean containsValue(Object value) {
return allValues().containsObject(value);
}
public V get(Object key) {
return objectForKey(key);
}
public V put(K key, V value) {
throw new UnsupportedOperationException("put is not a supported operation in com.webobjects.foundation.NSDictionary");
}
public V remove(Object key) {
throw new UnsupportedOperationException("remove is not a supported operation in com.webobjects.foundation.NSDictionary");
}
public void putAll(Map<? extends K, ? extends V> t) {
throw new UnsupportedOperationException("putAll is not a supported operation in com.webobjects.foundation.NSDictionary");
}
public void clear() {
throw new UnsupportedOperationException("putAll is not a supported operation in com.webobjects.foundation.NSDictionary");
}
public Set<K> keySet() {
if (_keySetCache == null) {
Object[] currKeys = keysNoCopy();
if (currKeys != null && currKeys.length > 0) {
_keySetCache = new NSSet<K>((K[]) currKeys);
}
else {
_keySetCache = NSSet.EmptySet;
}
}
return _keySetCache;
}
public Collection<V> values() {
return allValues();
}
public Set<Map.Entry<K, V>> entrySet() {
if (_entrySetCache == null) {
_entrySetCache = _initMapEntrySet();
}
return _entrySetCache;
}
private Set<Map.Entry<K, V>> _initMapEntrySet() {
Object[] keys = keysNoCopy();
int length = keys.length;
_JavaNSDictionaryMapEntry<K, V>[] set = new _JavaNSDictionaryMapEntry[length];
for (int i = 0; i < length; i++) {
K key = (K) keys[i];
V object = objectForKey(key);
_JavaNSDictionaryMapEntry<K, V> current = new _JavaNSDictionaryMapEntry<K, V>(key, object);
set[i] = current;
}
return new NSSet<Map.Entry<K, V>>(set);
}
public static final Class _CLASS = _NSUtilitiesExtra._classWithFullySpecifiedNamePrime("com.webobjects.foundation.NSDictionary");
public static final Class _MAP_ENTRY_CLASS = _NSUtilitiesExtra._classWithFullySpecifiedNamePrime("com.webobjects.foundation.NSDictionary$_JavaNSDictionaryMapEntry");
public static final NSDictionary EmptyDictionary = new NSDictionary();
private static final String SerializationKeysFieldKey = "keys";
private static final String SerializationValuesFieldKey = "objects";
private static final Class<?> _objectArrayClass = ((Object) (new Object[0])).getClass();
protected transient int _capacity;
protected transient int _hashtableBuckets;
protected transient int _count;
protected Object[] _objects;
protected transient Object[] _objectsCache;
protected transient byte[] _flags;
protected Object[] _keys;
protected transient Object[] _keysCache;
protected transient int _hashCache;
protected transient int _deletionLimit;
protected static int _NSDictionaryClassHashCode = _CLASS.hashCode();
protected static int _NSDictionaryMapEntryHashCode = _MAP_ENTRY_CLASS.hashCode();
protected Set<K> _keySetCache;
protected Set<Map.Entry<K, V>> _entrySetCache;
public static final boolean CheckForNull = true;
public static final boolean IgnoreNull = true;
private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(SerializationKeysFieldKey, _objectArrayClass), new ObjectStreamField(SerializationValuesFieldKey, _objectArrayClass) };
}