/
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.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 implements LogicalObject {

	/**
	 * 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;

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

	public int getRoleClassId() {
		return ((DbOid) getDbClass().getOid()).getIndexId(); // using paindb low level internals!
	}

	public boolean sameObjectAs(LogicalObject obj) {
		if (obj == this) {
			return true;
		}
		if (obj.getClass() == Root.class) {
			return getRoot() == obj;
		}

		return getRoot() == ((Role) obj).getRoot();
	}

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

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

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

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

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

}