-/**
- *
- */
-package org.vamsas.client;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Iterator;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-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;
-
-/**
- * Base class for all Vamsas objects extracted from an IClientDocument. An
- * Vobject maybe registered or unregistered.
- *
- * @author jimp
- *
- */
-public abstract class Vobject {
- static Log log = LogFactory.getLog(Vobject.class);
-
- /**
- * true if Vobject was stored in a vamsas Document or has been retrieved from it
- */
- protected boolean __stored_in_document = false;
- /**
- * true if Vobject was updated since the vamsas library last read a Vobj with the same VorbaId from a document.
- */
- protected boolean __updated_since_last_read = false;
- /**
- * memory of the last doHash() value computed for the Vobject
- * @see doHash()
- */
- protected int __last_hash = 0;
- /**
- * set by testInstanceForIdField() if Vobject should have a VorbaId
- */
- protected boolean registerable = false;
- protected boolean __visited = false;
- /**
- * reference to containing object for this Vobject.
- */
- protected Vobject V_parent=null;
- /**
- * unique id for all vamsas objects allows unambiguous referencing to any
- * Vobject in the vamsas document
- */
- protected VorbaId vorbaId = null;
-
- /**
- * the source of unique VorbaIds.
- */
- protected IVorbaIdFactory __vorba = null;
-
- /* (non-Javadoc)
- * @see java.lang.Object#finalize()
- */
- protected void finalize() throws Throwable {
- V_parent=null;
- __vorba=null;
- vorbaId=null;
- super.finalize();
- }
-
- /**
- *
- */
- protected Vobject() {
- super();
- testInstanceForIdField();
- }
- 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
- * the reflected class instance.
- */
- private void testInstanceForIdField() {
- // TODO: decide if 'id' is an appropriate reserved attribute name for the VorbaId
- // look for the id field in all castor classes (should be an NCName string)
-
- Class thisclass=this.getClass();
- setRegisterable(false);
- while (!thisclass.equals(Vobject.class)) {
- try {
- java.lang.reflect.Field fd = thisclass.getDeclaredField("_id");
- if (String.class.isAssignableFrom(fd.getType())) {
- ___id_field=fd;
- this.setRegisterable(true);
- break;
- }
- } catch (SecurityException e) {
- log.error("Unexpected Security Exception whilst finding id fields to set!",e);
- } catch (NoSuchFieldException e) {
- thisclass=thisclass.getSuperclass();
- }
- }
- }
- // boolean __testedInstance=false;
- /**
- * update the Vobject instance's _id field, based on the contents of the
- * VorbaId. Only call this if you mean to do it!
- */
- protected void setInstanceIdField() {
- /*if (!registerable && !__testedInstance) {
- testInstanceForIdField();
- __testedInstance=true;
- }*/
- if (registerable) {
- if (__vorba != null)
- try {
- Method fd = this.getClass().getMethod("setId", new Class[] { String.class });
- fd.invoke((Object) this, new Object[] {new String(this.getVorbaId().id)});
- log.debug(this.getClass().getName()+" called setInstanceIdField!");
- } catch (InvocationTargetException e) {
- log.error("SourceGeneration of "
- + this.getClass().toString()
- + "\n has resulted in an inaccessible 'setId' method!\nCannot set ID from the vorbaId Vobject.", e);
- }
- catch (IllegalAccessException e) {
- log.error("SourceGeneration of "
- + this.getClass().toString()
- + "\n has resulted in an inaccessible 'setId' method!\nCannot set ID from the vorbaId Vobject.", e);
- } catch (SecurityException e) {
- log.error("Security access violation for "+this.getClass().toString(),e);
- } catch (NoSuchMethodException e) {
- log.warn(this.getClass().toString()+" was erroneously marked as a Vorba Vobject class (Implementation error?)");
- this.setRegisterable(false);
- }
- } else {
- System.err.println("Client error. Trying to setInstanceIdField on a "
- + this.getClass().toString() + " (which cannot be given a vorbaId)");
- }
- }
-
- protected String __getInstanceIdField() {
- /*if (!registerable && !__testedInstance) {
- testInstanceForIdField();
- __testedInstance=true;
- }*/
- if (registerable) {
- if (__vorba != null)
- try {
- Method fd = this.getClass().getMethod("getId", (Class[]) null);
- Object idstring = fd.invoke((Object) this, (Object[]) null);
- log.debug(this.getClass().getName()+" called getInstanceIdField!");
- if (idstring!=null && idstring instanceof String) {
- if (((String) idstring).length()>0)
- return (String) idstring;
- }
- } catch (InvocationTargetException e) {
- log.error("SourceGeneration of "
- + this.getClass().toString()
- + "\n has resulted in an inaccessible 'getId' method!\nCannot set ID from the vorbaId Vobject.", e);
- }
- catch (IllegalAccessException e) {
- log.error("SourceGeneration of "
- + this.getClass().toString()
- + "\n has resulted in an inaccessible 'getId' method!\nCannot set ID from the vorbaId Vobject.", e);
- } catch (SecurityException e) {
- log.error("Security access violation for "+this.getClass().toString(),e);
- } catch (NoSuchMethodException e) {
- log.warn(this.getClass().toString()+" was erroneously marked as a Vorba Vobject class (Implementation error?)");
- this.setRegisterable(false);
- }
- } else {
- System.err.println("Client error. Trying to getInstanceIdField on a "
- + this.getClass().toString() + " (which cannot be given a vorbaId)");
- }
- return null;
- }
-
- /**
- * 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
- */
- synchronized protected boolean doHash() {
- long __old_hash = __last_hash;
- __last_hash = 0;
- Vobject _V_parent=V_parent;
- V_parent=null;
- VorbaId thisid = vorbaId;
- IVorbaIdFactory factory = __vorba;
- boolean stored = __stored_in_document;
- boolean updated = __updated_since_last_read;
- boolean visited = __visited;
- java.lang.reflect.Field idfield = ___id_field;
- ___id_field=null;
- __updated_since_last_read=false;
- vorbaId = null;
- __vorba = null;
- __visited=false;
- // compute hash
- __last_hash = this.hashCode();
- // reset houseskeeping variables
- ___id_field=idfield;
- vorbaId = thisid;
- __vorba = factory;
- __stored_in_document = stored;
- __updated_since_last_read=updated;
- V_parent=_V_parent;
- __visited=visited;
- return (__old_hash==0) || (__old_hash == __last_hash);
- }
-
- /**
- * TODO: combine two versions of the same collection Vobject to resolve
- * asynchronous updates to the same vamsas Vobject Merges two vamsas objects,
- * one of which is a later version of the earlier (ie they have the same
- * vorbaId but one is a later version recently read from the vamsasDocument
- * collection.
- *
- * @return
- */
- protected boolean merge(Vobject laterCopy) {
- log.warn(this.getClass().getName()+".merge() not implemented.");
- return true;
- }
-
- /**
- *
- * @return true if Vobject is registered
- */
- public boolean isRegistered() {
- return (registerable) ? (vorbaId != null) : false;
- }
-
- /**
- * Method to get fixed reference for the Vobject in the vamsas document.
- *
- * @returns null if Vobject is neither registered or not associated with a
- * properly instantiated VorbaIdFactory.
- */
- public VorbaId getVorbaId() {
- if (registerable && vorbaId == null) {
- if (this.__stored_in_document) {
- if (__vorba!=null)
- vorbaId=org.vamsas.client.VorbaId.newId(this.__getInstanceIdField());
- }
- // Try to use the associated factory.
- if (__vorba != null)
- if ((vorbaId = __vorba.makeVorbaId(this)) == null)
- return null; // Factory not valid.
- else {
- this.setInstanceIdField();
- return vorbaId;
- }
- }
- return vorbaId;
- }
-
- /**
- * used by the IClient implementation to generate unique Id based on client
- * applications current namespace.
- */
- protected void setVorbaId(VorbaId newid) {
- vorbaId = newid;
- }
-
- /**
- * @return true if Vobject is present in Vamsas Document.
- */
- public boolean is__stored_in_document() {
- return __stored_in_document;
- }
-
- /**
- * @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() {
- return __updated_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;
- }
-
- /**
- * for use by Vorba agent to reflect state of vamsas Vobject to client
- * application.
- * Setting stored_in_document on a registerable Vobject without a
- * vorbaId will mean is will *never* get a vorbaId and
- * horrible things will happen.
- * @param __stored_in_document true if Vobject has been marshalled into current document.
- */
- protected void set__stored_in_document(boolean __stored_in_document) {
- this.__stored_in_document = __stored_in_document;
- }
-
- /**
- * __last_hash is the hash value computed when the Vobject was last checked
- * against a IClientDocument generated by the Vobject's parent IClient
- * instance.
- *
- * @return Returns the __last_hash.
- */
- public int get__last_hash() {
- return __last_hash;
- }
-
- /**
- * @return true if Vobject can have a vorbaId
- */
- public boolean isRegisterable() {
- return registerable;
- }
-
- /**
- * Called by __testInstanceForidField and the post-unmarshalling handler
- * to indicate if Vobject will have a vorbaId.
- * @param registerable
- */
- protected void setRegisterable(boolean registerable) {
- this.registerable = registerable;
- }
- /**
- * ensure's internal id field corresponds to vorbaId and
- * cascade through all fields referring to an instance of Vobject
- * calling the same method on them.
- * TODO: LATER: properly apply castors own field mechanisms to get at accessors
- * TODO: FIX CYCLIC __ensure+instance_ids
- * Implementation note for the todo:
- * this works like a depth-first search over all vamsas objects in an vamsasDocument.
- * __visited is the visited flag, any Vobj who's flag is of a different parity
- * to the visited argument will be recursed on.
- * note - the doHash() function used to be used as the 'visited' flag -
- * this *is not* a valid heuristic, although it will work "most of the time".
- * TODO: LATER? Add another method for setDefaultProvenanceField (in the spirit of setInstanceIdField) using the info from the __vorba.getClient/User/Session methods
- */
- protected void __ensure_instance_ids() {
- __ensure_instance_ids(!__visited);
- }
- protected void __ensure_instance_ids(boolean visited) {
- if (__vorba==null)
- throw new Error("Improperly intialised org.vamsas.client.Vobject - no VorbaFactory given.");
- log.debug("doing "+this.getClass()+".__ensure_instance_ids()");
- if (!__stored_in_document && registerable)
- setInstanceIdField();
- if (__visited==visited)
- return;
- __visited=visited;
- __vorba.updateHashValue(this);
-
- Class descriptor = null;
- XMLClassDescriptorImpl descimpl = null;
- try {
- // castor descriptor resolver magic
- descriptor = this.getClass().getClassLoader().loadClass(this.getClass().getName()+"Descriptor");
- descimpl = (XMLClassDescriptorImpl) descriptor.getConstructor((Class[])null).newInstance((Object[])null);
- } catch (Exception e) {
- log.fatal("Source Generation Error!: Couldn't resolve descriptor for "
- +this.getClass().getName()
- +" was 'generate descriptors' set for castorbuilder.properties?");
- return;
- }
- FieldDescriptor fields[] = descimpl.getFields();
- for (int i=0,j=fields.length; i<j; i++) {
- Class type= fields[i].getFieldType();
- if (type.isArray()) {
- if (Vobject[].class.isAssignableFrom(type)) {
- try {
- Object val = fields[i].getHandler().getValue(this);
- if (val!=null) {
- Vobject vals[] = (Vobject[]) val;
- for (int k=0, l=vals.length; k<l; k++) {
- if (vals[k].__vorba==null)
- vals[k].__vorba = __vorba; // propagate IVorbaIdFactory
- if (vals[k].V_parent==null)
- vals[k].V_parent=this; // propagate parent reference to this element.
- vals[k].__ensure_instance_ids(visited);
- }
- }
- }
- catch (Exception e) {
- log.error("Client error - could not access array "+type.getName()+" in "+this.getClass().getName(), e);
- }
- }
- } else
- if (Vobject.class.isAssignableFrom(type)) {
- try {
- FieldHandler fh = fields[i].getHandler();
- Vobject rf = null;
- if (fh != null) {
- Object fval = fh.getValue(this);
- if (fval!=null) {
- if (fval.getClass().isArray()) {
- //if (Vobject[].class.isAssignableFrom(type)) {
- try {
- Vobject vals[] = (Vobject[]) fval;
- for (int k=0, l=vals.length; k<l; k++) {
- if (vals[k].__vorba==null)
- vals[k].__vorba = __vorba; // propagate IVorbaIdFactory
- if (vals[k].V_parent==null)
- vals[k].V_parent=this; // propagate parent reference to this field object
- vals[k].__ensure_instance_ids(visited);
- }
- }
- catch (Exception e) {
- log.error("Client error - could not access (fhval)array "+type.getName()+" in "+this.getClass().getName(), e);
- }
- //}
- } else {
- rf = (Vobject) fval;
- log.debug("Got value for "+fields[i].getFieldName());
- }
- }
- } else {
- // castor's mechanism doesn't work for this object... so...*/
- // fuck around, fuck around, jump up jump up and get down! */
- Object o = fields[i].getClassDescriptor();
- if (o!=null) {
- // XMLClassDescriptorImpl fclasdes = (XMLClassDescriptorImpl) o;
- String methname = "get"+fields[i].getFieldName();
- Method fgetmeth = this.getClass().getMethod(methname,(Class[])null);
- if (fgetmeth!=null) {
- Object fval = fgetmeth.invoke(this,(Object[])null);
- if (fval!=null)
- rf = (Vobject) fval;
- } else {
- log.warn("Couldn't find "+this.getClass().getName()+"."+methname);
- }
- }
- }
- if (rf!=null) {
- if (rf.__vorba==null)
- rf.__vorba = __vorba; // propagate IVorbaIdFactory
- if (rf.V_parent==null)
- rf.V_parent=this; // propagate parent reference
- rf.__ensure_instance_ids(visited);
- }
- }
- catch (Exception e) {
- log.error("Client error - could not access "+type.getName()+" in "+this.getClass().getName(), e);
- }
- }
- }
-
- }
-
- /**
- * @return the __parent
- */
- public Vobject getV_parent() {
- return V_parent;
- }
-
- /**
- * @param __parent the __parent to set
- */
- protected void setV_parent(Vobject V_parent) {
- this.V_parent = V_parent;
- }
-}