/
codebase/src/net/sourceforge/pain/admin/console/command/
codebase/src/net/sourceforge/pain/data/role/
codebase/src/net/sourceforge/pain/network/console/telnet/
codebase/src/net/sourceforge/pain/network/guitool/
codebase/src/net/sourceforge/pain/plugin/
codebase/src/net/sourceforge/pain/util/
db/src/net/sourceforge/pain/util/
gui/
gui/lib/
gui/src/net/sourceforge/pain/tools/guitool/dbbrowse/
gui/src/net/sourceforge/pain/tools/guitool/dialog/
gui/src/net/sourceforge/pain/tools/guitool/menu/
gui/src/net/sourceforge/pain/tools/guitool/resources/
gui/src/net/sourceforge/pain/tools/guitool/resources/images/
gui/src/net/sourceforge/pain/tools/guitool/resources/images/explorer/
mudlibs/tinylib/
mudlibs/tinylib/area/
mudlibs/tinylib/etc/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/data/affect/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/data/prototype/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/data/trigger/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/logic/affect/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/logic/event/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/logic/event/deploy/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/logic/event/guitool/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/logic/event/guitool/event/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/logic/fn/util/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/logic/trigger/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/logic/trigger/impl/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/plugin/command/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/plugin/reset/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/plugin/shutdown/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/plugin/social/
mudlibs/tinylib/src/net/sourceforge/pain/tinylib/util/
tests/
tests/src/
tests/src/net/sourceforge/pain/db/data/
package net.sourceforge.pain.db;

import java.util.*;

abstract class DbAbstractMap extends DbCollection {
    static final AMapEntry[] ZERO_DATA = new AMapEntry[0];
    final static float DEFAULT_LOAD_FACTOR = 0.9F;
    private final static float DEFAULT_EXTENTION_FACTOR = 1.3F;

    static final UniversalKey ukey = new UniversalKey();

    int nElements;
    AMapEntry[] data;
    private int modCount = 0;

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

// ---- PAiN DB internal usage methods --- /// 
    final int _size() {
        return nElements;
    }

    final void _clear() {
        if (nElements == 0) {
            return;
        }
        final int len = data.length;
        for (int i = 0; i < len; i++) {
            for (AMapEntry e = data[i]; e != null; e = e.next) {
                e.unlinkFromMap();
            }
        }
        modCount++;
        nElements = 0;
    }

    AMapEntry[] _getData() {
        return data;
    }


    final void restoreFromBackup(final Object o) {
        _clear();
        restoreFromImage(o);
    }

// --  internal private helpers --
    private DbObject p_checkObject(final Object o) {
        final DbObject obj = (DbObject) o;
        obj.ensureReal();
        owner.ensureDb(obj);
        return obj;
    }

    private DbObject p_remove(final AMapEntry e) {
        final DbObject result = e.obj;
//		check();
        e.unlinkFromMap();
        nElements--;
        modCount++;
//		check();
        return result;
    }

    private void p_checkRehash(final int n) {
        final int newNElements = nElements + n;
        if (newNElements > data.length * DEFAULT_LOAD_FACTOR) {
            p_rehash(newNElements);
        }
    }

    private void p_rehash(final int minCapacity) {
        modCount++;
        int newCapacity = (int) (data.length * DEFAULT_EXTENTION_FACTOR);
        if (newCapacity < minCapacity) {
            newCapacity = (int) (minCapacity * DEFAULT_EXTENTION_FACTOR);
            if (newCapacity < 4) {
                newCapacity = 4;
            }
        }
        final AMapEntry[] oldData = data;
        data = new AMapEntry[newCapacity];
        final int oldLen = oldData.length;
        for (int i = 0; i < oldLen; i++) {
            for (AMapEntry e = oldData[i]; e != null;) {
                final AMapEntry next = e.next;
                e.rehash();
                e = next;
            }
        }
//		check();
    }
	
// -------- ////
	

// --- MAP --//
// Map interface analog. We should not expose public Map interface from this class
// since one of it's subclasses has Set interface	
	
    final Object x_get(UniversalKey key) {
        owner.ensureReal();
        if (nElements == 0) {
            return null;
        }
        final int index = a_getIndex(key);
        for (AMapEntry e = data[index]; e != null; e = e.next) {
            if (e.hasSameKey(ukey)) {
                return e.obj;
            }
        }
        return null;
    }

    final DbObject x_remove(final UniversalKey ukey) {
        owner.ensureReal();
        if (nElements == 0) {
            return null;
        }
        final int index = a_getIndex(ukey);
        for (AMapEntry e = data[index]; e != null; e = e.next) {
            if (e.hasSameKey(ukey)) {
                owner.onCollectionChange(this);
                return p_remove(e);
            }
        }
        return null;
    }

    final DbObject x_removeAll(final UniversalKey ukey) {
        owner.ensureReal();
        if (nElements == 0) {
            return null;
        }
        final int index = a_getIndex(ukey);
        for (AMapEntry e = data[index]; e != null; e = e.next) {
            if (e.hasSameKey(ukey)) {
                owner.onCollectionChange(this);
                return p_remove(e);
            }
        }
        return null;
    }


    final int x_size() {
        owner.ensureReal();
        return nElements;
    }

    final boolean x_isEmpty() {
        return x_size() == 0;
    }


    final boolean x_containsKey(final UniversalKey key) {
        return x_get(key) != null;
    }


    final boolean x_containsValue(final Object o) {
        owner.ensureReal();
        if (o == null) {
            return false;
        }
        final DbObject obj = p_checkObject(o);
        final int len = data.length;
        for (int i = 0; i < len; i++) {
            for (AMapEntry e = data[i]; e != null; e = e.next) {
                if (e.obj == obj) {
                    return true;
                }
            }
        }
        return false;
    }


    final void x_putAll(final Map t) {
        throw new UnsupportedOperationException();
    }

    final void x_clear() {
        owner.ensureReal();
        owner.onCollectionChange(this);
        _clear();
    }

    final Set x_keySet() {
        owner.ensureReal();
        return new Keys();
    }

    final Iterator x_keysIterator() {
        owner.ensureReal();
        return new MapIterator(MapIterator.KEYS);
    }

    final Collection x_values() {
        owner.ensureReal();
        return new Values();
    }

    final Iterator x_valuesIterator() {
        owner.ensureReal();
        return new MapIterator(MapIterator.VALUES);
    }

    final Set x_entrySet() {
        owner.ensureReal();
        return new EntrySet();
    }


    final Object x_put(UniversalKey ukey, Object o) {
        owner.ensureReal();
        if (o == null) {
            throw new NullPointerException();
        }
        final DbObject obj = p_checkObject(o);
        owner.onCollectionChange(this);
        p_checkRehash(1);
        final int index = a_getIndex(ukey);
        DbObject result = null;
        for (AMapEntry e = data[index]; e != null; e = e.next) {
            if (e.hasSameKey(ukey)) {
                result = e.obj;
                p_remove(e);
                break;
            }
        }
        modCount++;
        a_addNewEntry(ukey, obj);
        nElements++;
//		check();
        return result;
    }


// -- abstracts  --- //
    abstract int a_getIndex(final UniversalKey key);

    abstract Object a_get(Object key);

    abstract void restoreFromImage(Object image);

    abstract Object createBackupImage();

    abstract void a_addNewEntry(UniversalKey key, DbObject value);	
	
//----------------- inners -----------------------//

    abstract class AMapEntry extends DbInverseRef implements Map.Entry {
        AMapEntry next;
        private AMapEntry prev;

        AMapEntry(final DbObject obj) {
            super(obj);
        }

        final void linkToMap() { // called by subclass at the end of constructor when all fields are set
            final int index = getIndex();
            next = data[index];
            data[index] = this;
            if (next != null) {
                next.prev = this;
            }
        }

        abstract int getIndex();

        public abstract Object getKey();

        final void rehash() {
            final int index = getIndex();
            prev = null;
            next = data[index];
            data[index] = this;
            if (next != null) {
                next.prev = this;
            }
        }

        final void _onTargetDelete() {
//			check();
            owner.onCollectionChange(DbAbstractMap.this);
            p_remove(this);
        }

        final public Object getValue() {
            return obj;
        }

        public final Object setValue(final Object value) {
            throw new UnsupportedOperationException();
        }


        private void unlinkFromMap() {
            if (prev == null) {
                final int index = getIndex();
                assert(data[index] == this);
                data[index] = next;
            } else {
                prev.next = next;
            }
            if (next != null) {
                next.prev = prev;
            }
            onReferenceDestroy();
        }

        abstract boolean hasSameKey(UniversalKey ukey);
    };

    final class Values implements Collection {

        public Values() {
        }

        public int size() {
            owner.ensureReal();
            return nElements;
        }

        public boolean isEmpty() {
            owner.ensureReal();
            return nElements == 0;
        }

        public boolean contains(final Object o) {
            owner.ensureReal();
            if (o == null) {
                return false;
            }
            final DbObject obj = p_checkObject(o);
            final int len = data.length;
            for (int i = 0; i < len; i++) {
                for (AMapEntry e = data[i]; e != null; e = e.next) {
                    if (e.obj == obj) {
                        return true;
                    }
                }
            }
            return false;

        }

        public Iterator iterator() {
            owner.ensureReal();
            return new MapIterator(MapIterator.VALUES);
        }

        public Object[] toArray() {
            owner.ensureReal();
            final DbObject[] arr = new DbObject[nElements];
            int j = 0;
            final int len = data.length;
            for (int i = 0; i < len; i++) {
                for (AMapEntry e = data[i]; e != null; e = e.next) {
                    arr[j] = e.obj;
                    j++;
                }
            }
            return arr;
        }


        public Object[] toArray(Object a[]) {
            owner.ensureReal();
            if (a.length < nElements) {
                a = (Object[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), nElements);
            }
            int j = 0;
            final int len = data.length;
            for (int i = 0; i < len; i++) {
                for (AMapEntry e = data[i]; e != null; e = e.next) {
                    a[j] = e.obj;
                    j++;
                }
            }
            if (a.length > nElements) {
                a[nElements] = null;
            }
            return a;
        }

        public boolean add(final Object o) {
            throw new UnsupportedOperationException();
        }

        public boolean remove(final Object o) {
            throw new UnsupportedOperationException();
        }

        public boolean containsAll(final Collection c) {
            owner.ensureReal();
            for (Iterator it = c.iterator(); it.hasNext();) {
                if (!x_containsValue(it.next())) {
                    return false;
                }
            }
            return true;
        }

        public boolean addAll(final Collection c) {
            throw new UnsupportedOperationException();
        }

        public boolean removeAll(final Collection c) {
            throw new UnsupportedOperationException();
        }

        public boolean retainAll(final Collection c) {
            throw new UnsupportedOperationException();
        }

        public void clear() {
            owner.ensureReal();
            _clear();
        }
    };

    final class Keys implements Set {
        Keys() {
        }

        public int size() {
            owner.ensureReal();
            return nElements;
        }

        public boolean isEmpty() {
            owner.ensureReal();
            return nElements == 0;
        }

        public boolean contains(final Object o) {
            return a_get(o) != null;
        }

        public Iterator iterator() {
            owner.ensureReal();
            return new MapIterator(MapIterator.KEYS);
        }

        public Object[] toArray() {
            owner.ensureReal();
            final Object[] arr = new Object[nElements];
            int j = 0;
            final int len = data.length;
            for (int i = 0; i < len; i++) {
                for (AMapEntry e = data[i]; e != null; e = e.next) {
                    arr[j] = e.getKey();
                    j++;
                }

            }
            return arr;
        }

        public Object[] toArray(Object a[]) {
            owner.ensureReal();
            if (a.length < nElements) {
                a = (Object[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), nElements);
            }
            int j = 0;
            final int len = data.length;
            for (int i = 0; i < len; i++) {
                for (AMapEntry e = data[i]; e != null; e = e.next) {
                    a[j] = e.getKey();
                    j++;
                }

            }
            if (a.length > nElements) {
                a[nElements] = null;
            }
            return a;
        }

        public boolean add(final Object o) {
            throw new UnsupportedOperationException();
        }

        public boolean remove(final Object o) {
            throw new UnsupportedOperationException();
        }

        public boolean containsAll(final Collection c) {
            owner.ensureReal();
            for (Iterator it = c.iterator(); it.hasNext();) {
                if (a_get(it.next()) == null) {
                    return false;
                }
            }
            return true;
        }

        public boolean addAll(final Collection c) {
            throw new UnsupportedOperationException();
        }

        public boolean retainAll(final Collection c) {
            throw new UnsupportedOperationException();
        }

        public boolean removeAll(final Collection c) {
            throw new UnsupportedOperationException();
        }

        public void clear() {
            owner.ensureReal();
            _clear();
        }
    };

    final class EntrySet implements Set {
        EntrySet() {
        }

        public int size() {
            owner.ensureReal();
            return nElements;
        }

        public boolean isEmpty() {
            owner.ensureReal();
            return nElements == 0;
        }

        public boolean contains(final Object o) {
            owner.ensureReal();
            final AMapEntry f = (AMapEntry) o;
            final int len = data.length;
            for (int i = 0; i < len; i++) {
                for (AMapEntry e = data[i]; e != null; e = e.next) {
                    if (e == f) {
                        return true;
                    }
                }
            }
            return false;
        }

        public Iterator iterator() {
            owner.ensureReal();
            return new MapIterator(MapIterator.ENTRIES);

        }

        public Object[] toArray() {
            throw new UnsupportedOperationException();
        }

        public Object[] toArray(final Object[] a) {
            throw new UnsupportedOperationException();
        }

        public boolean add(final Object o) {
            throw new UnsupportedOperationException();
        }

        public boolean remove(final Object o) {
            throw new UnsupportedOperationException();
        }

        public boolean containsAll(final Collection c) {
            throw new UnsupportedOperationException();
        }

        public boolean addAll(final Collection c) {
            throw new UnsupportedOperationException();
        }

        public boolean retainAll(final Collection c) {
            throw new UnsupportedOperationException();
        }

        public boolean removeAll(final Collection c) {
            throw new UnsupportedOperationException();
        }

        public void clear() {
            owner.ensureReal();
            _clear();
        }
    };

    final class MapIterator implements Iterator {
        final static int VALUES = 1;
        final static int KEYS = 2;
        final static int ENTRIES = 3;

        private int expectedModCount;
        private final int type;
        private AMapEntry e = null;
        private int index = -1;
        private int nPassed = 0;

        public MapIterator(final int type) {
            this.type = type;
            expectedModCount = modCount;
        }

        public boolean hasNext() {
            checkState();
            return nPassed < nElements;
        }

        public Object next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            e = (e == null || e.next == null) ? findWithNextIndex() : e.next;
            nPassed++;
            return (type == KEYS) ? e.getKey() : type == VALUES ? (Object) e.obj : (Object) e;
        }

        private AMapEntry findWithNextIndex() {
            final int len = data.length;
            while (++index < len) {
                final AMapEntry e = data[index];
                if (e != null) {
                    return e;
                }
            }
            return null;
        }

        private AMapEntry findWithPrevIndex() {
            while (--index >= 0) {
                AMapEntry e = data[index];
                if (e != null) {
                    while (e.next != null) {
                        e = e.next;
                    }
                    return e;
                }
            }
            return null;
        }


        public void remove() {
            checkState();
            if (e == null) {
                throw new IllegalStateException();
            }
            final AMapEntry re = e;
            e = (e.prev == null) ? findWithPrevIndex() : e.prev;
            owner.onCollectionChange(DbAbstractMap.this);
            p_remove(re);
            expectedModCount++;
            nPassed--;
        }

        private void checkState() {
            owner.ensureReal();
            checkForComodifications();
        }

        private void checkForComodifications() {
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
        }
    };

    final static class UniversalKey {
        int intKey;
        String strKey;
    }


//	public void check() {
//		for (int i = 0; i < data.length; i++) {
//			AMapEntry e = data[i];
//			if (e == null) {
//				continue;
//			}
//			assert e.prev == null;
//			while (e != null) {
//				assert e.getIndex() == i;
//				AMapEntry prev = e;
//				e = e.next;
//				if (e != null) {
//					assert e.prev == prev;
//				}
//			}
//			;
//		}
//	}
}