import org.exolab.castor.mapping.FieldDescriptor;
import org.exolab.castor.mapping.FieldHandler;
import org.exolab.castor.xml.util.XMLClassDescriptorImpl;
-import org.vamsas.test.simpleclient.VamsasArchive;
+
+import uk.ac.vamsas.test.simpleclient.VamsasArchive;
/**
* Base class for all Vamsas objects extracted from an IClientDocument. An
*/
protected boolean __updated_since_last_read = false;
/**
+ * true if Vobject appeared in the document after the last access by this vamsas library instance
+ */
+ protected boolean __added_since_last_read = false;
+ /**
* memory of the last doHash() value computed for the Vobject
* @see doHash()
*/
super();
testInstanceForIdField();
}
+ /**
+ * Override Object.hashCode with base value for castor generated object hashcodes.
+ */
+ public int hashCode() {
+ return 17;
+ }
java.lang.reflect.Field ___id_field=null; // set to ease pain of reflection
/**
* set the isRegisterable flag based on the presence of a 'private String _id' field in
}
return null;
}
-
+ /**
+ * calls the castor-generated hashCode() method
+ * @return
+ */
+ protected int __callHash() {
+ try {
+ Method fd = this.getClass().getMethod("hashCode", (Class[]) null);
+ Object hashvalue = fd.invoke((Object) this, (Object[]) null);
+ if (log.isDebugEnabled())
+ log.debug(this.getClass().getName()+" called hashCode()!");
+ if (hashvalue!=null && hashvalue instanceof Integer) {
+ return ((Integer) hashvalue).intValue();
+ }
+ } catch (InvocationTargetException e) {
+ log.error("SourceGeneration of "
+ + this.getClass().toString()
+ + "\n has resulted in an inaccessible 'hashCode' method!\nHave you set org.exolab.castor.builder.equalsmethod=true in castorbuilder.properties ?.", e);
+ }
+ catch (IllegalAccessException e) {
+ log.error("SourceGeneration of "
+ + this.getClass().toString()
+ + "\n has resulted in an inaccessible 'hashCode' method!\nHave you set org.exolab.castor.builder.equalsmethod=true in castorbuilder.properties ?.", e);
+ } catch (SecurityException e) {
+ log.error("Security access violation for "+this.getClass().toString(),e);
+ } catch (NoSuchMethodException e) {
+ log.warn(this.getClass().toString()+" was erroneously extending from a Vorba Vobject class (Implementation error? no hashCode() method)" +
+ "\nHave you set org.exolab.castor.builder.equalsmethod=true in castorbuilder.properties ?.", e);
+ }
+ return 0;
+ }
/**
* calculate a hash for the Vobject with all housekeeping fields at standard
* values. (isRegisterable is an immutable attribute property)
- * TODO: decide if __stored_in_document should be included in the hash or not.
- * @return true if new hash different to last hash
+ * TODO: LATER: make this hash function compute a hash that truly reflects changes in Vobject attributes for benefit of update mechanism
+ * @return true if new hash different to last hash (or first time its been computed)
*/
synchronized protected boolean doHash() {
+ boolean stored = __stored_in_document;
+ __stored_in_document=false;
+ boolean updated = __updated_since_last_read;
+ __updated_since_last_read=false;
+ boolean added_since=__added_since_last_read;
+ __added_since_last_read=false;
long __old_hash = __last_hash;
__last_hash = 0;
+ // leave registerable - doesn't change
+ boolean visited = __visited;
+ __visited=false;
Vobject _V_parent=V_parent;
V_parent=null;
VorbaId thisid = vorbaId;
+ vorbaId = null;
IVorbaIdFactory factory = __vorba;
- boolean stored = __stored_in_document;
- boolean updated = __updated_since_last_read;
- boolean visited = __visited;
+ __vorba = null;
java.lang.reflect.Field idfield = ___id_field;
___id_field=null;
- __updated_since_last_read=false;
- vorbaId = null;
- __vorba = null;
- __visited=false;
+ long l_hash = __l_hash;
+ __l_hash = 0;
// compute hash
- __last_hash = this.hashCode();
+ __last_hash = __callHash();
// reset houseskeeping variables
___id_field=idfield;
vorbaId = thisid;
__updated_since_last_read=updated;
V_parent=_V_parent;
__visited=visited;
- return (__old_hash==0) || (__old_hash == __last_hash);
+ __added_since_last_read=added_since;
+ __l_hash = l_hash;
+ // return true if first time hash was computed or if hash has changed
+ return (__old_hash==0) || (__old_hash != __last_hash);
}
/**
/**
* @return true if this object has been updated in the currently stored document since the last time a Vobject with the same ID was read from a Vamsas Document
*/
- public boolean is__updated_since_last_read() {
+ public boolean isUpdated() {
return __updated_since_last_read;
}
-
+ /**
+ *
+ * @return true if this object was added to the document after the last time the vamsas library acessed the session document
+ */
+ public boolean isNewInDocument() {
+ return __added_since_last_read;
+ }
/**
* Set internal flag to indicate this object was updated since the last document read
* @param __updated_since_last_read the __updated_since_last_read to set
*/
protected void set__updated_since_last_read(boolean __updated_since_last_read) {
this.__updated_since_last_read = __updated_since_last_read;
+ if(__updated_since_last_read && log.isDebugEnabled())
+ log.debug("Registered update for "+this.getVorbaId());
}
/**
*/
protected void set__stored_in_document(boolean __stored_in_document) {
this.__stored_in_document = __stored_in_document;
+ if(__stored_in_document && log.isDebugEnabled())
+ log.debug("Retrieved document object: "+this.getVorbaId());
+ }
+
+ /**
+ * @param __added_since_last_read the __added_since_last_read to set
+ */
+ protected void set__added_since_last_read(boolean __added_since_last_read) {
+ this.__added_since_last_read = __added_since_last_read;
+
+ if(__added_since_last_read && log.isDebugEnabled())
+ log.debug("New object in document: "+this.getVorbaId());
}
/**
*
* @return Returns the __last_hash.
*/
- public int get__last_hash() {
+ public long get__last_hash() {
return __last_hash;
}
if (__visited==visited)
return;
__visited=visited;
- __vorba.updateHashValue(this);
+ //__vorba.updateHashValue(this);
Class descriptor = null;
XMLClassDescriptorImpl descimpl = null;
try {
// castor descriptor resolver magic
- descriptor = this.getClass().getClassLoader().loadClass(this.getClass().getName()+"Descriptor");
+ StringBuffer desname = new StringBuffer(this.getClass().getName());
+ desname.insert(desname.lastIndexOf("."), ".descriptors");
+ desname.append("Descriptor");
+ descriptor = this.getClass().getClassLoader().loadClass(desname.toString());
descimpl = (XMLClassDescriptorImpl) descriptor.getConstructor((Class[])null).newInstance((Object[])null);
} catch (Exception e) {
log.fatal("Source Generation Error!: Couldn't resolve descriptor for "
protected void setV_parent(Vobject V_parent) {
this.V_parent = V_parent;
}
+ /**
+ * LhashValue - used for change detection between document updates.
+ */
+ private long __l_hash=0;
+ /**
+ * set the base LhashValue for this object
+ * @param checksum
+ */
+ protected void __setInitHash(long checksum) {
+ __l_hash = checksum;
+ }
+ /**
+ * compute the final LhashValue as a difference between checksum and the current base
+ * @param checksum
+ */
+ protected void __setFinalHash(long checksum) {
+ __l_hash = checksum - __l_hash;
+ }
+ /**
+ * get the LhashValue for this object
+ * @return the difference in values passed to __setFinalHash less __setInitHash
+ */
+ protected long __getLHash() {
+ return __l_hash;
+ }
}