package pt.ist.fenixframework.backend.jvstmojb.pstm; import java.lang.reflect.Field; import java.sql.SQLException; import jvstm.Transaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pt.ist.fenixframework.DomainFenixFrameworkRoot; import pt.ist.fenixframework.DomainMetaClass; import pt.ist.fenixframework.DomainMetaObject; import pt.ist.fenixframework.DomainObject; import pt.ist.fenixframework.NoDomainMetaObjects; import pt.ist.fenixframework.backend.jvstmojb.JvstmOJBConfig; import pt.ist.fenixframework.backend.jvstmojb.repository.ResultSetReader; import pt.ist.fenixframework.core.AbstractDomainObjectAdapter; import pt.ist.fenixframework.core.DomainObjectAllocator; import pt.ist.fenixframework.core.SharedIdentityMap; public abstract class AbstractDomainObject extends AbstractDomainObjectAdapter { private static final Logger logger = LoggerFactory.getLogger(AbstractDomainObject.class); private long oid; private VBox<DomainMetaObject> domainMetaObject; public class UnableToDetermineIdException extends RuntimeException { private static final long serialVersionUID = 3085208774911959073L; public UnableToDetermineIdException(Throwable cause) { super("Unable to determine id Exception", cause); } } protected AbstractDomainObject() { super(); TransactionSupport.storeNewObject(this); initMetaObject(false); if (JvstmOJBConfig.canCreateDomainMetaObjects() && !getClass().isAnnotationPresent(NoDomainMetaObjects.class)) { DomainMetaObject metaObject = new DomainMetaObject(); metaObject.setDomainObject(this); getDomainMetaClass().addExistingDomainMetaObject(getDomainMetaObject()); } } protected AbstractDomainObject(DomainObjectAllocator.OID oid) { super(oid); this.oid = ((Long) oid.oid).longValue(); initMetaObject(true); } private void initMetaObject(boolean allocateOnly) { domainMetaObject = VBox.makeNew(this, "domainMetaObject", allocateOnly, false); } @Deprecated public Long getOID() { return getOid(); } @Override protected void ensureOid() { try { // find successive ids until one is available while (true) { this.oid = DomainClassInfo.getNextOidFor(this.getClass()); Object cached = SharedIdentityMap.getCache().cache(this); if (cached == this) { // break the loop once we got this instance cached return; } } } catch (SQLException e) { throw new UnableToDetermineIdException(e); } } @Override public Long getOid() { return oid; } private long get$oid() { return oid; } VersionedSubject getSlotNamed(String attrName) { Class myClass = this.getClass(); while (myClass != Object.class) { try { Field f = myClass.getDeclaredField(attrName); f.setAccessible(true); return (VersionedSubject) f.get(this); } catch (NoSuchFieldException nsfe) { myClass = myClass.getSuperclass(); } catch (IllegalAccessException iae) { throw new Error("Couldn't find attribute " + attrName + ": " + iae); } catch (SecurityException se) { throw new Error("Couldn't find attribute " + attrName + ": " + se); } } return null; } Object getCurrentValueFor(String attrName) { return getSlotNamed(attrName).getCurrentValue(this, attrName); } jvstm.VBoxBody addNewVersion(String attrName, int txNumber) { VersionedSubject vs = getSlotNamed(attrName); if (vs != null) { return vs.addNewVersion(attrName, txNumber); } logger.warn("!!! WARNING !!!: addNewVersion couldn't find the appropriate slot"); return null; } public DomainMetaObject getDomainMetaObject() { return domainMetaObject.get(this, "domainMetaObject"); } public void justSetMetaObject(DomainMetaObject domainMetaObject) { this.domainMetaObject.put(this, "domainMetaObject", domainMetaObject); } private void setMetaObject(DomainMetaObject domainMetaObject) { domainMetaObject.setDomainObject(this); } /** * This should be invoked only when this DO is being deleted. */ private void deleteDomainMetaObject() { if (getDomainMetaObject() != null) { getDomainMetaObject().delete(); } } private Long get$oidDomainMetaObject() { DomainObject value = getDomainMetaObject(); return (value == null) ? null : Long.valueOf(value.getExternalId()); } public void readFromResultSet(java.sql.ResultSet rs) throws java.sql.SQLException { int txNumber = Transaction.current().getNumber(); readSlotsFromResultSet(rs, txNumber); readMetaObjectFromResultSet(rs, txNumber); } protected void readMetaObjectFromResultSet(java.sql.ResultSet rs, int txNumber) throws SQLException { DomainMetaObject metaObject = ResultSetReader.readDomainObject(rs, "OID_DOMAIN_META_OBJECT"); this.domainMetaObject.persistentLoad(metaObject, txNumber); } protected abstract void readSlotsFromResultSet(java.sql.ResultSet rs, int txNumber) throws java.sql.SQLException; protected void checkDisconnected() { } protected void handleAttemptToDeleteConnectedObject(String roleName) { throw new Error("Trying to delete a DomainObject that is still connected to other objects: " + this + " by role: " + roleName); } @Override protected void deleteDomainObject() { invokeDeletionListeners(); checkDisconnected(); deleteDomainMetaObject(); TransactionSupport.deleteObject(this); } private DomainMetaClass getDomainMetaClass() { return DomainFenixFrameworkRoot.getInstance().getDomainMetaClass(this.getClass()); } @Override public final String getExternalId() { return Long.toString(oid); } @Override public String toString() { return getClass().getName() + ":" + getExternalId(); } }