Picking code updated with full basic implementation of message sending and server...
[vamsas.git] / src / org / vamsas / client / Vobject.java
index cb2738f..589b7ff 100644 (file)
@@ -39,7 +39,10 @@ public abstract class Vobject {
    */
   protected boolean registerable = 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
@@ -50,6 +53,16 @@ public abstract class Vobject {
    * 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();
+  }
 
   /**
    * 
@@ -58,31 +71,42 @@ public abstract class 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() {
-    // look for the id field (should be an NCName string)
     // TODO: decide if 'id' is an appropriate reserved attribute name for the VorbaId
-    try {
-      java.lang.reflect.Field fd = this.getClass().getDeclaredField("_id");
-      if (String.class.isAssignableFrom(fd.getType())) {
-        this.setRegisterable(true);
+    // 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();
       }
-    } catch (SecurityException e) {
-      e.printStackTrace();
-    } catch (NoSuchFieldException e) {
-      this.setRegisterable(false);
     }
   }
-
+  // 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 {
@@ -109,6 +133,43 @@ public abstract class Vobject {
           + 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
@@ -119,6 +180,8 @@ public abstract class Vobject {
   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;
@@ -128,6 +191,7 @@ public abstract class Vobject {
     vorbaId = thisid;
     __vorba = factory;
     __stored_in_document = stored;
+    V_parent=_V_parent;
     return (__old_hash==0) || (__old_hash == __last_hash);
   }
 
@@ -161,6 +225,10 @@ public abstract class Vobject {
    */
   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)
@@ -251,7 +319,7 @@ public abstract class Vobject {
     try {
       // castor descriptor resolver magic
       descriptor = this.getClass().getClassLoader().loadClass(this.getClass().getName()+"Descriptor");
-      descimpl = (XMLClassDescriptorImpl) descriptor.getConstructor(null).newInstance(null);
+      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()
@@ -270,6 +338,8 @@ public abstract class Vobject {
               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();
               }
             }
@@ -293,6 +363,8 @@ public abstract class Vobject {
                       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();
                       }
                     }
@@ -306,14 +378,15 @@ public abstract class Vobject {
                 }
               }
             } 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,null);
+                Method fgetmeth = this.getClass().getMethod(methname,(Class[])null);
                 if (fgetmeth!=null) {
-                  Object fval = fgetmeth.invoke(this,null);
+                  Object fval = fgetmeth.invoke(this,(Object[])null);
                   if (fval!=null)
                     rf = (Vobject) fval;
                 } else {
@@ -324,7 +397,9 @@ public abstract class Vobject {
             if (rf!=null) {
               if (rf.__vorba==null)
                 rf.__vorba = __vorba; // propagate IVorbaIdFactory
-              rf.__ensure_instance_ids();
+              if (rf.V_parent==null)
+                rf.V_parent=this; // propagate parent reference
+             rf.__ensure_instance_ids();
             }
           }
           catch (Exception e) {
@@ -334,4 +409,18 @@ public abstract class Vobject {
     }
     
   }
+
+  /**
+   * @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;
+  }
 }