package pt.ist.fenixframework.pstm; import jvstm.VBoxBody; import pt.ist.fenixframework.DomainObject; public class VBox extends jvstm.VBox implements VersionedSubject,dml.runtime.FenixVBox { static final Object NOT_LOADED_VALUE = new Object(); public VBox() { super(); } public VBox(E initial) { super(initial); } protected VBox(VBoxBody body) { super(body); } public E get(Object obj, String attrName) { return Transaction.currentFenixTransaction().getBoxValue(this, obj, attrName); } public void put(Object obj, String attrName, E newValue) { // TODO: eventually remove this if (! (attrName.equals("idInternal") || attrName.equals("ackOptLock"))) { // the set of the idInternal or ackOptLock is performed by OJB and should not be logged Transaction.storeObject((DomainObject)obj, attrName); } put(newValue); } public boolean hasValue() { return Transaction.currentFenixTransaction().isBoxValueLoaded(this); } public void putNotLoadedValue() { this.put((E)NOT_LOADED_VALUE); } protected void persistentLoad(E value) { int txNumber = Transaction.current().getNumber(); persistentLoad(value, txNumber); } public void persistentLoad(Object value, int txNumber) { // find appropriate body VBoxBody body = this.body.getBody(txNumber); if (body.value == NOT_LOADED_VALUE) { body.value = (E)value; } } public VBoxBody addNewVersion(String attr, int txNumber) { if (body.version < txNumber) { return commit((E)NOT_LOADED_VALUE, txNumber); } else { // when adding a new version to a box it may happen that a // version with the same number exists already, if we are // processing the change logs in the same server that // committed those changelogs, between the time when the // changelog were written to the database and the commit // finishes setting the committed tx number // // so, do nothing and just return null //System.out.println("!!! WARNING !!!: adding older version for a box attr " + attr + " -> " + body.version + " not < " + txNumber); return null; } } public Object getCurrentValue(Object obj, String attrName) { return this.get(obj, attrName); } boolean reload(Object obj, String attr) { try { doReload(obj, attr); return true; } catch (Throwable e) { // what to do? System.err.println("Couldn't reload attribute '" + attr + "': " + e.getMessage()); //e.printStackTrace(); return false; } } protected void doReload(Object obj, String attr) { throw new Error("Can't reload a simple VBox. Use a PrimitiveBox or a ReferenceBox instead."); } public static VBox makeNew(boolean allocateOnly, boolean isReference) { if (isReference) { if (allocateOnly) { // when a box is allocated, it is safe // to say that the version number is 0 return new ReferenceBox(makeNewBody((T)NOT_LOADED_VALUE, 0, null)); } else { return new ReferenceBox(); } } else { if (allocateOnly) { // when a box is allocated, it is safe // to say that the version number is 0 return new PrimitiveBox(makeNewBody((T)NOT_LOADED_VALUE, 0, null)); } else { return new PrimitiveBox(); } } } public void setFromOJB(Object obj, String attr, E value) { persistentLoad(value); } }