applied LGPLv3 and source code formatting.
[vamsas.git] / src / uk / ac / vamsas / client / Vobject.java
index 6603f1a..23cb8e0 100644 (file)
@@ -1,5 +1,23 @@
-/**
+/*
+ * This file is part of the Vamsas Client version 0.1. 
+ * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite, 
+ *  Andrew Waterhouse and Dominik Lindner.
+ * 
+ * Earlier versions have also been incorporated into Jalview version 2.4 
+ * since 2008, and TOPALi version 2 since 2007.
  * 
+ * The Vamsas Client is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *  
+ * The Vamsas Client is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the Vamsas Client.  If not, see <http://www.gnu.org/licenses/>.
  */
 package uk.ac.vamsas.client;
 
@@ -25,33 +43,44 @@ import uk.ac.vamsas.test.simpleclient.VamsasArchive;
  */
 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
+   * 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.
+   * 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;
+
   /**
-   * true if Vobject appeared in the document after the last access by this vamsas library instance
+   * 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 
+   * memory of the last doHash() value computed for the Vobject
+   * 
    * @see doHash()
    */
-  protected int __last_hash = 0; 
+  protected int __last_hash = 0;
+
   /**
    * set by testInstanceForIdField() if Vobject should have a VorbaId
    */
-  protected boolean registerable = false; 
+  protected boolean registerable = false;
+
   protected boolean __visited = false;
+
   /**
    * reference to containing object for this Vobject.
    */
-  protected Vobject V_parent=null;
+  protected Vobject V_parent = null;
+
   /**
    * unique id for all vamsas objects allows unambiguous referencing to any
    * Vobject in the vamsas document
@@ -62,14 +91,16 @@ public abstract class Vobject {
    * the source of unique VorbaIds.
    */
   protected IVorbaIdFactory __vorba = null;
-  
-  /* (non-Javadoc)
+
+  /*
+   * (non-Javadoc)
+   * 
    * @see java.lang.Object#finalize()
    */
   protected void finalize() throws Throwable {
-    V_parent=null;
-    __vorba=null;
-    vorbaId=null;
+    V_parent = null;
+    __vorba = null;
+    vorbaId = null;
     super.finalize();
   }
 
@@ -80,67 +111,86 @@ public abstract class Vobject {
     super();
     testInstanceForIdField();
   }
+
   /**
-   * Override Object.hashCode with base value for castor generated object hashcodes.
+   * 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
+
+  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.
+   * 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
+    // 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();
+
+    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;
+          ___id_field = fd;
           this.setRegisterable(true);
           break;
         }
       } catch (SecurityException e) {
-        log.error("Unexpected Security Exception whilst finding id fields to set!",e);
+        log
+            .error(
+                "Unexpected Security Exception whilst finding id fields to set!",
+                e);
       } catch (NoSuchFieldException e) {
-        thisclass=thisclass.getSuperclass();
+        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 && !__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);
+          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);
+          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?)");
+          log
+              .warn(this.getClass().toString()
+                  + " was erroneously marked as a Vorba Vobject class (Implementation error?)");
           this.setRegisterable(false);
         }
     } else {
@@ -148,35 +198,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 && !__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)
+          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 (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);
+          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?)");
+          log
+              .warn(this.getClass().toString()
+                  + " was erroneously marked as a Vorba Vobject class (Implementation error?)");
           this.setRegisterable(false);
         }
     } else {
@@ -185,8 +243,10 @@ public abstract class Vobject {
     }
     return null;
   }
+
   /**
    * calls the castor-generated hashCode() method
+   * 
    * @return
    */
   protected int __callHash() {
@@ -194,69 +254,83 @@ public abstract class Vobject {
       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) {
+        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 (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);
+      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);
+      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: 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)
+   * values. (isRegisterable is an immutable attribute property) 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;
+    __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;
+    __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;
+    __visited = false;
+    Vobject _V_parent = V_parent;
+    V_parent = null;
     VorbaId thisid = vorbaId;
     vorbaId = null;
     IVorbaIdFactory factory = __vorba;
     __vorba = null;
     java.lang.reflect.Field idfield = ___id_field;
-    ___id_field=null;
+    ___id_field = null;
     long l_hash = __l_hash;
     __l_hash = 0;
     // compute hash
     __last_hash = __callHash();
     // reset houseskeeping variables
-    ___id_field=idfield;
+    ___id_field = idfield;
     vorbaId = thisid;
     __vorba = factory;
     __stored_in_document = stored;
-    __updated_since_last_read=updated;
-    V_parent=_V_parent;
-    __visited=visited;
-    __added_since_last_read=added_since;
+    __updated_since_last_read = updated;
+    V_parent = _V_parent;
+    __visited = visited;
+    __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 (__old_hash == 0) || (__old_hash != __last_hash);
   }
 
   /**
@@ -269,7 +343,7 @@ public abstract class Vobject {
    * @return
    */
   protected boolean merge(Vobject laterCopy) {
-    log.warn(this.getClass().getName()+".merge() not implemented.");
+    log.warn(this.getClass().getName() + ".merge() not implemented.");
     return true;
   }
 
@@ -290,8 +364,9 @@ public abstract class Vobject {
   public VorbaId getVorbaId() {
     if (registerable && vorbaId == null) {
       if (this.__stored_in_document) {
-        if (__vorba!=null)
-          vorbaId=uk.ac.vamsas.client.VorbaId.newId(this.__getInstanceIdField());
+        if (__vorba != null)
+          vorbaId = uk.ac.vamsas.client.VorbaId.newId(this
+              .__getInstanceIdField());
       }
       // Try to use the associated factory.
       if (__vorba != null)
@@ -321,50 +396,60 @@ 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
+   * @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 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
+   * @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
+   * 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());
+    if (__updated_since_last_read && log.isDebugEnabled())
+      log.debug("Registered update for " + this.getVorbaId());
   }
 
   /**
    * 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.
+   * 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;
-    if(__stored_in_document && log.isDebugEnabled())
-      log.debug("Retrieved document object: "+this.getVorbaId());
+    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
+   * @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());
+    if (__added_since_last_read && log.isDebugEnabled())
+      log.debug("New object in document: " + this.getVorbaId());
   }
 
   /**
@@ -386,41 +471,45 @@ public abstract class Vobject {
   }
 
   /**
-   * Called by __testInstanceForidField and the post-unmarshalling handler
-   * to indicate if Vobject will have a vorbaId.
-   * @param 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 
+   * 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 uk.ac.vamsas.client.Vobject - no VorbaFactory given.");
-    log.debug("doing "+this.getClass()+".__ensure_instance_ids()");
+    if (__vorba == null)
+      throw new Error(
+          "Improperly intialised uk.ac.vamsas.client.Vobject - no VorbaFactory given.");
+    log.debug("doing " + this.getClass() + ".__ensure_instance_ids()");
     if (!__stored_in_document && registerable)
       setInstanceIdField();
-    if (__visited==visited)
+    if (__visited == visited)
       return;
-    __visited=visited;
-    //__vorba.updateHashValue(this);
-    
+    __visited = visited;
+    // __vorba.updateHashValue(this);
+
     Class descriptor = null;
     XMLClassDescriptorImpl descimpl = null;
     try {
@@ -428,96 +517,101 @@ public abstract class Vobject {
       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);
+      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 "
-          +this.getClass().getName()
-          +" was 'generate descriptors' set for castorbuilder.properties?");
+          + 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();
+    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)
+            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.
+                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);
+          } 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);
+      } 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());
               }
             }
-            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);
+          } 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);
+              }
             }
           }
-          catch (Exception e) {
-            log.error("Client error - could not access "+type.getName()+" in "+this.getClass().getName(), e);
+          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);
         }
+      }
     }
-    
+
   }
 
   /**
@@ -528,32 +622,42 @@ public abstract class Vobject {
   }
 
   /**
-   * @param __parent the __parent to set
+   * @param __parent
+   *          the __parent to set
    */
   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;
+  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
+   * 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
+   * 
+   * @return the difference in values passed to __setFinalHash less
+   *         __setInitHash
    */
   protected long __getLHash() {
     return __l_hash;