/
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.data;

import net.sourceforge.pain.db.*;

import java.util.*;

/**
 * role can be considered as type of object, every object could have only one role of the specified class
 */
public abstract class Role extends DbObject  {

    /**
     * used for default getSuperroles method impl
     */
    private static final Class[] emptySuper = new Class[0];

    /**
     * every LogicalObject may have as many Roles as it want to have
     * All it's roles linked with one Root object.
     * This field is a reference to the LogicalObject root
     */
    private static final int ROOT = 0;

    /**
     * Number of subrroles of this Role in LogicalObject.
     * Subrroles is Dynamic SubClasses of this Role.
     */
    private static final int NSUBROLES = 1;

    protected static final int LAST_BASE_FIELD_INDEX = 1;

    /**
     * used by db during startup
     */
    public Role() {
    }

    protected Role(PainDB db) {
        super(db);
    }


    final void init(Root root) {
        setReference(ROOT, root);
    }

    /**
     * Every Role subclass MUST call provideSuperSchema();
     */
    protected final int fillSuperSchema(byte[] types, String[] names) {
        types[ROOT] = DbType.REFERENCE;
        names[ROOT] = "root";

        types[NSUBROLES] = DbType.INT;
        names[NSUBROLES] = "nsubroles";

        return 1;
    }

    /**
     * PAiN has dynamic inheritance model,
     * every type(role) should know own superroles with deep=1
     * this method could be overriden by impl
     * returns array of Role classes
     */
    protected Class[] getSuperroles() {
        return emptySuper;
    }

    void incNSubroles() {
        setInt(NSUBROLES, getInt(NSUBROLES) + 1);
    }

    public final boolean hasSubroles() {
        return getInt(NSUBROLES) > 0;
    }

    void decNSubroles() {
        setInt(NSUBROLES, getInt(NSUBROLES) - 1);
    }


    /**
     * helpers:
     * Used to avoid explicit owner extraction before cast to another type
     */
    public final Role getRole(Class typeClass) {
        if (typeClass == getClass()) {
            return this;
        }
        return getRoot().getRole(typeClass);
    }

    public final boolean is(Class typeClass) {
        if (typeClass == getClass()) {
            return true;
        }
        return getRoot().is(typeClass);
    }

    public final Role addRole(Class typeClass) throws Exception {
        return getRoot().addRole(typeClass);
    }

    public final void removeRole(Class typeClass) throws Exception {
        getRoot().removeRole(typeClass);
    }

//    public final void detach() {
//        getRoot().removeRole(this);
//    }

    final int getRoleClassId() {
        return getDbClass().pain_getIndexId(); // using paindb low level internals!
    }

    public boolean sameObjectAs(Role obj) {
        if (obj == this) {
            return true;
        }
        
        return getRoot() == ((Role) obj).getRoot();
    }

    public final Iterator rolesIterator() {
        return getRoot().rolesIterator();
    }

    Root getRoot() {
        return (Root) getReference(ROOT);
    }

    void _nullRoot() {
        setReference(ROOT, null);
    }

    final void _delete() {
        super.delete();
    }

    /**
     * will delete whole object with all roles
     */
    public void delete() {
        getRoot().delete();
    }

    /**
     * remove method for this iterator will delete trigger as dbobject
     */
    public final Iterator getTriggersByEventType(int eventType) {
        return getRoot().getTriggersByEventType(eventType);
    }

    /**
     * remove method for this iterator will delete trigger as dbobject
     */
    public final Iterator getRoleTriggers() {
        return getRoot().getRoleTriggers(this);
    }

    public final Iterator getAffects() {
        return getRoot().getAffects();
    }

    public final boolean isAffected(int affectType) {
        return getRoot().isAffected(affectType);
    }

    public final AffectData getAffectData(int affectType) {
        return getRoot().getAffectImage(affectType);
    }

    /**
     * dynamic role properties are properties used by clients, but not typical for the role by itself
     * Example: room coords on area editor grid
     * properties assignet to the role but not to the object and removed when role is removed from object
     */
    public final String getRoleClientProperty(String propertyName) {
        return getRoot().getRoleClientProperty(this, propertyName);
    }

    /**
     * dynamic role properties are properties used by clients, but not typical for the role by itself
     * Example: room coords on area editor grid
     * properties assignet to the role but not to the object and removed when role is removed from object
     */
    public final void setRoleClientProperty(String propertyName, String value) {
        getRoot().setRoleClientProperty(this, propertyName, value);
    }
}