half implemented the SimpleClientAppdata interface.
authorjprocter <jprocter@compbio.dundee.ac.uk>
Mon, 20 Mar 2006 17:11:43 +0000 (17:11 +0000)
committerjprocter <jprocter@compbio.dundee.ac.uk>
Mon, 20 Mar 2006 17:11:43 +0000 (17:11 +0000)
git-svn-id: https://svn.lifesci.dundee.ac.uk/svn/repository/trunk@192 be28352e-c001-0410-b1a7-c7978e42abec

src/org/vamsas/client/simpleclient/ClientDocument.java
src/org/vamsas/client/simpleclient/SimpleClientAppdata.java

index e6ef1f5..de197e7 100644 (file)
@@ -197,4 +197,20 @@ public class ClientDocument extends org.vamsas.client.ClientDocument implements
     
     super.finalize();
   }
+  /**
+   * access the vamsas document
+   * @return the session's vamsas document
+   */
+  protected VamsasDocument getVamsasDocument() {
+    // TODO: IMPLEMENT
+    return null;
+  }
+  /**
+   * returns the read-only IO interface for the vamsas document Jar file
+   * @return
+   */
+  protected VamsasArchiveReader getVamsasArchiveReader() {
+    // TODO: IMPLEMENT getVamsasArchiveReader
+    return null;
+  }
 }
index 9f6b27f..d488782 100644 (file)
@@ -3,9 +3,14 @@
  */
 package org.vamsas.client.simpleclient;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.DataInput;
+import java.io.DataInputStream;
 import java.io.DataOutput;
+import java.io.InputStream;
 import java.util.Vector;
+import java.util.jar.JarInputStream;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -19,10 +24,23 @@ import org.vamsas.objects.utils.AppDataReference;
  * @author jimp
  * Access interface to data chunks read from a VamsasArchiveReader stream 
  * (or byte buffer input stream) or written to a VamsasArchive stream.
+ * // TODO: get VamsasArchiveReader from sclient
  */
 public class SimpleClientAppdata implements IClientAppdata {
   private static Log log = LogFactory.getLog(SimpleClientAppdata.class);
-
+  /**
+   * has the session's document been accessed to get the AppData entrys?
+   */
+  protected boolean accessedDocument = false;
+  /**
+   * has the user datablock been modified ?
+   */
+  protected boolean modifiedUserData = false;
+  /**
+   * has the apps global datablock been modified ?
+   */
+  protected boolean modifiedAppData = false;
+  
   ClientDocument clientdoc;
   /**
    * state flags
@@ -46,70 +64,247 @@ public class SimpleClientAppdata implements IClientAppdata {
     this.clientdoc = clientdoc;
   }
   /**
+   * set by extractAppData
+   */
+  protected ApplicationData appsGlobal = null;
+  /**
+   * set by extractAppData
+   */
+  protected User usersData = null;
+  /**
    * gets appropriate app data for the application, if it exists in this dataset
-   * 
+   * Called by every accessor to ensure data has been retrieved from document.
    */
-  private void extractAppData() {
-    org.vamsas.objects.core.VamsasDocument doc = null;
+  private void extractAppData(org.vamsas.objects.core.VamsasDocument doc) {
+    if (doc==null) {
+      log.debug("extractAppData called for null document object");
+      return;
+    }
+    if (accessedDocument) {
+      return;
+    }
     Vector apldataset = AppDataReference.getUserandApplicationsData(
         doc, clientdoc.sclient.getUserHandle(), clientdoc.sclient.getClientHandle());
-    ApplicationData appsglobal=null;
-    User usersdata = null;
+    accessedDocument = true;
     if (apldataset!=null) {
       if (apldataset.size()>0) {
         AppData clientdat = (AppData) apldataset.get(0);
         if (clientdat instanceof ApplicationData) {
-          appsglobal = (ApplicationData) clientdat;
+          appsGlobal = (ApplicationData) clientdat;
+          modifiedAppData = false;
           if (apldataset.size()>1) {
             clientdat = (AppData) apldataset.get(1);
-            if (clientdat instanceof User)
-              usersdata = (User) clientdat;
+            if (clientdat instanceof User) {
+              usersData = (User) clientdat;
+              modifiedUserData = false;
+            }
             if (apldataset.size()>2)
               log.info("Ignoring additional ("+(apldataset.size()-2)+") AppDatas returned by document appdata query.");
           } 
         } else {
           log.warn("Unexpected entry in AppDataReference query: id="+clientdat.getVorbaId()+" type="+clientdat.getClass().getName());
         }
+        apldataset.removeAllElements(); // destroy references.
       }
     }
   }
-
-  /* (non-Javadoc)
-   * @see org.vamsas.client.IClientAppdata#getClientAppdata()
+  /**
+   * LATER: generalize this for different low-level session implementations (it may not always be a Jar)
+   * @param appdata
+   * @param docreader
+   * @return
    */
-  public byte[] getClientAppdata() {
-    // TODO Auto-generated method stub
+  private JarInputStream getAppDataStream(AppData appdata, VamsasArchiveReader docreader) {
+    String entryRef = appdata.getDataReference();
+    if (entryRef!=null) {
+      log.debug("Resolving appData reference +"+entryRef);
+      InputStream entry = docreader.getAppdataStream(entryRef);
+      if (entry!=null) {
+        if (entry instanceof JarInputStream) {
+          return (JarInputStream) entry;
+        }
+        log.warn("Implementation problem - docreader didn't return a JarInputStream entry.");
+      }
+    } else {
+      log.debug("GetAppDataStream called for an AppData without a data reference.");
+    }
     return null;
   }
+  /**
+   * yuk - size of buffer used for slurping appData JarEntry into a byte array.
+   */
+  private final int _TRANSFER_BUFFER=4096*4;
 
-  /* (non-Javadoc)
-   * @see org.vamsas.client.IClientAppdata#getClientInputStream()
+  /**
+   * Resolve AppData object to a byte array.
+   * @param appdata
+   * @param archiveReader
+   * @return null or the application data as a byte array
    */
-  public DataInput getClientInputStream() {
-    // TODO Auto-generated method stub
+  private byte[] getAppDataAsByteArray(AppData appdata, VamsasArchiveReader docreader) {
+    if (appdata.getData()==null) {
+      // resolve and load data
+      JarInputStream entry = getAppDataStream(appdata, docreader); 
+      ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+      try {
+        byte buff[] = new byte[_TRANSFER_BUFFER];
+        int olen=0;
+        while (entry.available()>0) {
+          int len = entry.read(buff, olen, _TRANSFER_BUFFER);
+          bytes.write(buff, 0, len);
+          olen+=len;
+        }
+        buff=null;
+      } catch (Exception e) {
+        log.warn("Unexpected exception - probable truncation when accessing VamsasDocument entry "+appdata.getDataReference(), e);
+      }
+      if (bytes.size()>0) {
+        // LATER: deal with probable OutOfMemoryErrors here
+        log.debug("Got "+bytes.size()+" bytes from AppDataReference "+appdata.getDataReference());
+        byte data[] = bytes.toByteArray();
+        bytes = null;
+        return data;
+      }
+      return null;
+    } else {
+      log.debug("Returning inline AppData block for "+appdata.getVorbaId());
+      return appdata.getData();
+    }
+  }
+  /**
+   * internal method for getting a DataInputStream from an AppData object.
+   * @param appdata
+   * @param docreader
+   * @return data in object or null if no data is accessible
+   */
+  private DataInput getAppDataAsDataInputStream(AppData appdata, VamsasArchiveReader docreader) {
+    if (appdata!=null) {
+      String entryRef = appdata.getDataReference();
+      if (entryRef!=null) {
+        log.debug("Resolving AppData reference for "+entryRef);
+        InputStream jstrm = docreader.getAppdataStream(entryRef);
+        if (jstrm!=null)
+          return new AppDataInputStream(jstrm);
+        else {
+          log.debug("Returning null input stream for unresolved reference ("+entryRef+") id="+appdata.getVorbaId());
+          return null;
+        }
+      } else {
+        // return a byteArray input stream
+        byte[] data=appdata.getData();
+        if (data.length>0) {
+          ByteArrayInputStream stream = new ByteArrayInputStream(data);
+          return new DataInputStream(stream);
+        } else {
+          log.debug("Returning null input stream for empty Appdata data block in id="+appdata.getVorbaId());
+          return null;
+        }
+      }
+    } else {
+      log.debug("Returning null DataInputStream for appdata entry:"+appdata.getVorbaId());
+    }
     return null;
   }
 
-  /* (non-Javadoc)
-   * @see org.vamsas.client.IClientAppdata#getClientOutputStream()
+  /**
+   * internal method for getting ByteArray from AppData object
+   * @param clientOrUser - true for returning userData, otherwise return Client AppData.
+   * @return null or byte array
    */
-  public DataOutput getClientOutputStream() {
-    // TODO Auto-generated method stub
+  private byte[] _getappdataByteArray(boolean clientOrUser) {
+    if (clientdoc==null)
+      throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
+    byte[] data=null;
+    String appdName;
+    if (!clientOrUser) {
+      appdName = "Client's Appdata";
+    } else {
+      appdName = "User's Appdata";
+    }    
+    log.debug("getting "+appdName+" as a byte array");
+    extractAppData(clientdoc.getVamsasDocument());// TODO: get VamsasArchiveReader from sclient
+    AppData object;
+    if (!clientOrUser) {
+      object = appsGlobal;
+    } else {
+      object = usersData;
+    }
+    if (object!=null) {
+      log.debug("Trying to resolve "+appdName+" object to byte array.");
+      data = getAppDataAsByteArray(object, clientdoc.getVamsasArchiveReader());
+    }
+    if (data == null)
+      log.debug("Returning null for "+appdName+"ClientAppdata byte[] array");
+    return data;
+    
+  }
+  
+  /**
+   * common method for Client and User AppData->InputStream accessor
+   * @param clientOrUser - the appData to resolve - false for client, true for user appdata.
+   * @return null or the DataInputStream desired.
+   */
+  private DataInput _getappdataInputStream(boolean clientOrUser) {
+    if (clientdoc==null)
+      throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
+    String appdName;
+    if (!clientOrUser) {
+      appdName = "Client's Appdata";
+    } else {
+      appdName = "User's Appdata";
+    }
+    if (log.isDebugEnabled())
+      log.debug("getting "+appdName+" as an input stream.");
+    extractAppData(clientdoc.getVamsasDocument());
+    AppData object;
+    if (!clientOrUser) {
+      object = appsGlobal;
+    } else {
+      object = usersData;
+    }
+    if (object!=null) {
+      log.debug("Trying to resolve ClientAppdata object to an input stream.");
+      return getAppDataAsDataInputStream(object, clientdoc.getVamsasArchiveReader());
+    }
+    log.debug("getClientInputStream returning null.");
     return null;
   }
+  /* (non-Javadoc)
+   * @see org.vamsas.client.IClientAppdata#getClientAppdata()
+   */
+  public byte[] getClientAppdata() {
+    return _getappdataByteArray(false);
+  }
+  /* (non-Javadoc)
+   * @see org.vamsas.client.IClientAppdata#getClientInputStream()
+   */
+  public DataInput getClientInputStream() {
+    return _getappdataInputStream(false);
+  }
 
   /* (non-Javadoc)
    * @see org.vamsas.client.IClientAppdata#getUserAppdata()
    */
   public byte[] getUserAppdata() {
-    // TODO Auto-generated method stub
-    return null;
+    return _getappdataByteArray(true);
   }
 
   /* (non-Javadoc)
    * @see org.vamsas.client.IClientAppdata#getUserInputStream()
    */
   public DataInput getUserInputStream() {
+    return _getappdataInputStream(true);
+  }
+  /**
+   * methods for writing new AppData entries.
+   */
+  
+  /* (non-Javadoc)
+   * @see org.vamsas.client.IClientAppdata#getClientOutputStream()
+   */
+  public DataOutput getClientOutputStream() {
+    if (clientdoc==null)
+      throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
     // TODO Auto-generated method stub
     return null;
   }
@@ -118,6 +313,8 @@ public class SimpleClientAppdata implements IClientAppdata {
    * @see org.vamsas.client.IClientAppdata#getUserOutputStream()
    */
   public DataOutput getUserOutputStream() {
+    if (clientdoc==null)
+      throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
     // TODO Auto-generated method stub
     return null;
   }
@@ -126,6 +323,8 @@ public class SimpleClientAppdata implements IClientAppdata {
    * @see org.vamsas.client.IClientAppdata#hasClientAppdata()
    */
   public boolean hasClientAppdata() {
+    if (clientdoc==null)
+      throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
     // TODO Auto-generated method stub
     return false;
   }
@@ -134,6 +333,8 @@ public class SimpleClientAppdata implements IClientAppdata {
    * @see org.vamsas.client.IClientAppdata#hasUserAppdata()
    */
   public boolean hasUserAppdata() {
+    if (clientdoc==null)
+      throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
     // TODO Auto-generated method stub
     return false;
   }
@@ -142,6 +343,8 @@ public class SimpleClientAppdata implements IClientAppdata {
    * @see org.vamsas.client.IClientAppdata#setClientAppdata(byte[])
    */
   public void setClientAppdata(byte[] data) {
+    if (clientdoc==null)
+      throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
     // TODO Auto-generated method stub
     
   }
@@ -150,6 +353,8 @@ public class SimpleClientAppdata implements IClientAppdata {
    * @see org.vamsas.client.IClientAppdata#setUserAppdata(byte[])
    */
   public void setUserAppdata(byte[] data) {
+    if (clientdoc==null)
+      throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
     // TODO Auto-generated method stub
     
   }