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