/
area/
classes/net/sourceforge/pain/logic/
classes/net/sourceforge/pain/logic/event/
classes/net/sourceforge/pain/logic/fn/util/
classes/net/sourceforge/pain/network/console/
classes/net/sourceforge/pain/plugin/
classes/net/sourceforge/pain/plugin/reset/
classes/net/sourceforge/pain/plugin/shutdown/
classes/net/sourceforge/pain/plugin/social/
classest/net/sourceforge/pain/db/data/
doc/
doc/paindb/resources/
src/net/sourceforge/pain/logic/
src/net/sourceforge/pain/logic/event/
src/net/sourceforge/pain/logic/fn/util/
src/net/sourceforge/pain/network/console/
src/net/sourceforge/pain/network/console/telnet/
src/net/sourceforge/pain/plugin/
src/net/sourceforge/pain/plugin/command/
src/net/sourceforge/pain/plugin/reset/
src/net/sourceforge/pain/plugin/shutdown/
src/net/sourceforge/pain/plugin/social/
src/net/sourceforge/pain/util/
tests/
tests/net/sourceforge/pain/db/data/
package net.sourceforge.pain.db;

import java.util.*;

/**
 * Hash table based persistent implementation of the <tt>Map</tt> interface.<br>
 * This map allows only String objects instances as keys and {@link DbObject} as values.
 */
public final class DbStringKeyMap extends DbAbstractMap implements Map {

	private static final Object[] ZERO_STRING_KEY_MAP_IMAGE = new Object[]{new String[0], DbConstants.ZERO_INT_ARRAY};//keys, values

	DbStringKeyMap(final DbObject owner, final String keys[], final int[] image, final int fid) { //load from image during startup
		super(owner, fid);
		restoreFromImage(keys, image);
	}

	DbStringKeyMap(final DbObject owner, final int fid) { // new object during runtime
		super(owner, fid);
		nElements = 0;
		data = ZERO_DATA;
	}

	void restoreFromImage(Object image) {
		final Object[] raw = (Object[]) image;
		restoreFromImage((String[]) raw[0], (int[]) raw[1]);
	}

	private void restoreFromImage(String[] keys, final int[] image) {
		final PainDB db = owner._getDB();
		final int len = image.length;
		nElements = len;
		if (data == null || data.length < nElements || data.length > nElements * 2) {
			data = nElements == 0 ? ZERO_DATA : new AMapEntry[(int) (nElements / DEFAULT_LOAD_FACTOR)];
		}
		for (int i = 0; i < len; i++) {
			final int indexId = image[i];
			final String key = keys[i];
			assert(key != null);
			new StringKeyMapEntry(key, indexId == -1 ? null : db.getObjectByIndexId(indexId));//key, value
		}
	}

	Object createBackupImage() {
		if (nElements == 0) {
			return ZERO_STRING_KEY_MAP_IMAGE;
		}
		final int[] image = new int[nElements];
		final String[] keys = new String[nElements];
		int pos = 0;
		final int nItems = nElements;
		for (int i = 0; pos < nItems; i++) {
			for (AMapEntry e = data[i]; e != null; e = e.next) {
				final DbObject obj = e.obj;
				keys[pos] = ((StringKeyMapEntry) e).key;
				image[pos] = obj.indexId;
				pos++;
			}
		}
		return new Object[]{keys, image};
	}


// ---- DbAbstrat Map impls ---- ///

	int a_getIndex(DbAbstractMap.UniversalKey key) {
		return _getIndex(key.strKey);
	}

	private int _getIndex(final String key) {
		return (key.hashCode() & 0x7FFFFFFF) % data.length;
	}


	Object a_get(Object key) {
		return get(key);
	}

	void a_addNewEntry(DbAbstractMap.UniversalKey key, DbObject value) {
		new StringKeyMapEntry(key.strKey, value);
	}

// --- map interface ------//

	public Object get(final Object key) {
		ukey.strKey = (String) key;
		final Object result = x_get(ukey);
		ukey.strKey = null; // release reference
		return result;
	}


	public Object put(final Object key, final Object o) {
		ukey.strKey = (String) key;
		final Object result = x_put(ukey, o);
		ukey.strKey = null;
		return result;
	}

	public Object remove(final Object key) {
		ukey.strKey = (String) key;
		final Object result = x_remove(ukey);
		ukey.strKey = null;
		return result;

	}


	public int size() {
		return x_size();
	}

	public void clear() {
		x_clear();
	}

	public boolean isEmpty() {
		return x_isEmpty();
	}

	public boolean containsKey(Object key) {
		ukey.strKey = (String) key;
		final boolean result = x_containsKey(ukey);
		ukey.strKey = null;
		return result;
	}


	public boolean containsValue(Object value) {
		return x_containsValue(value);
	}

	public Collection values() {
		return x_values();
	}

	public void putAll(Map m) {
		x_putAll(m);
	}

	public Set entrySet() {
		return x_entrySet();
	}

	public Set keySet() {
		return x_keySet();
	}


//----------------- inners -----------------------//

	final class StringKeyMapEntry extends AMapEntry implements Map.Entry {
		final String key;

		StringKeyMapEntry(final String key, final DbObject obj) {
			super(obj);
			this.key = key;
			linkToMap();
		}


		public Object getKey() {
			return new Integer(key);
		}

		int getIndex() {
			return _getIndex(key);
		}

		boolean hasSameKey(UniversalKey ukey) {
			return ukey.strKey == key || ukey.strKey.equals(key);
		}
	};
}