X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fuk%2Fac%2Fvamsas%2Fclient%2FVobject.java;h=6603f1a8756ef829d5ed867cb2b0b63e7d317a7f;hb=261406f42435f46617fb9efe7c5472b5f670ff42;hp=c5f26977060fc1ac5759659e688f695f801ef2b1;hpb=c4904945c33259fb1fb171700a8072657e6672e0;p=vamsas.git diff --git a/src/uk/ac/vamsas/client/Vobject.java b/src/uk/ac/vamsas/client/Vobject.java index c5f2697..6603f1a 100644 --- a/src/uk/ac/vamsas/client/Vobject.java +++ b/src/uk/ac/vamsas/client/Vobject.java @@ -35,6 +35,10 @@ public abstract class Vobject { */ 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() */ @@ -76,6 +80,12 @@ public abstract class Vobject { 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 @@ -175,31 +185,66 @@ public abstract class Vobject { } 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; @@ -208,7 +253,10 @@ public abstract class Vobject { __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); } /** @@ -275,16 +323,24 @@ public abstract class Vobject { /** * @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()); } /** @@ -297,6 +353,18 @@ public abstract class Vobject { */ 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()); } /** @@ -306,7 +374,7 @@ public abstract class Vobject { * * @return Returns the __last_hash. */ - public int get__last_hash() { + public long get__last_hash() { return __last_hash; } @@ -351,13 +419,16 @@ public abstract class Vobject { 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 " @@ -462,4 +533,29 @@ public abstract class Vobject { 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; + } }