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