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); } }; }