javadoc
[vamsas.git] / src / uk / ac / vamsas / client / simpleclient / SimpleClient.java
index 739cf58..de2e00d 100644 (file)
@@ -77,11 +77,16 @@ public class SimpleClient implements IClient {
     this.user = user;
     this.client = client;
     //try {
+    log.debug("Creating new session for "+_session);
       session = new SessionUrn(_session);
-    /*} catch (MalformedURLException e) {
+      log.debug("Creating new Event Generator");
+      evgen = new EventGeneratorThread(_session, this, handlers);
+      /*} catch (MalformedURLException e) {
       log.error("Couldn't form a valid SessionUrn object!",e);
       throw new InvalidSessionUrnException(_session.toString());
     }*/
+      log.debug("SimpleClient constructed for session "+session.getSessionUrn());
+      
   }
   /**
    * construct new session by importing objects from an existing vamsas document
@@ -100,10 +105,12 @@ public class SimpleClient implements IClient {
       VamsasDocument doc = sdoc.getVamsasDocument(odoc);
       sessdoc.putVamsasDocument(doc, sdoc.vorba);
       sessdoc.closeArchive();
+      log.debug("Imported new vamsas data from "+importingArchive);
     } catch (Exception e) {
       sessdoc.cancelArchive();
-      // write a dummy archive
+      // write a dummy iohandler
       _session.slog.info("Exception when importing document data from "+importingArchive);
+      log.warn("While importing session data from existing archive in "+importingArchive, e);      
       throw new Exception("Failed to import data from "+importingArchive, e);
     }
   }
@@ -195,29 +202,48 @@ public class SimpleClient implements IClient {
    * @see uk.ac.vamsas.client.IClient#addDocumentUpdateHandler(java.util.EventListener)
    */
   public void addDocumentUpdateHandler(PropertyChangeListener evt) {
-    if (handlers.containsKey(Events.DOCUMENT_UPDATE)) {
-      Object handler;
-      ((PropertyChangeSupport) (handler = handlers.get(Events.DOCUMENT_UPDATE)))
-      .addPropertyChangeListener(evt);
-      listeners.add(handler);
-      listeners.add((Object) evt);
-    }
+    this.addVorbaEventHandler(Events.DOCUMENT_UPDATE, evt);
   }
   boolean finalized=false;
+  private void haltPickmanager() {
+    if (pickmanager!=null) {
+      final SimpleClient dying=this; 
+      new Thread() {
+        public void run() {
+          SimpleClient.log.debug("Stopping pickManager..");
+          dying.pickmanager.shutdown();
+          SimpleClient.log.debug("pickManager halted.");
+        }
+      }.start();
+    }
+  }
   /*
    * (non-Javadoc)
    * 
    * @see uk.ac.vamsas.client.IClient#finalizeClient()
    */
   public void finalizeClient() {
+    if (finalized)
+      throw new Error("VAMSAS Client Implementation Error: Finalized called twice for same client instance.");
+
+    // mark this instance as finalized
+    finalized=true;
+    
     // TODO: determine if this is last client in session
-    // TODO: raise events like : ((lst_client && document.request.to.close), (client_finalization), (
     
+    // TODO: raise events like : ((lst_client && document.request.to.close), (client_finalization), (
+    evgen._raise(Events.CLIENT_FINALIZATION, null, this,null);
     // if (handlers.containsKey(Events.))
     // if (handlers.containsKey(Events.CLIENT_FINALIZATION))
     // deregister listeners.
-    // mark this instance as finalized
-    this._session.removeClient(this);
+    log.debug("Stopping pickManager");
+    haltPickmanager();
+    log.debug("Stopping EventGenerator..");
+    evgen.stopWatching();
+    SimpleClient.log.debug("EventGenerator halted.");
+    log.debug("Deregistering Client");
+    _session.removeClient(this);
+    log.debug("finalization Complete.");
   }
   
   /*
@@ -226,10 +252,12 @@ public class SimpleClient implements IClient {
    * @see uk.ac.vamsas.client.IClient#getClientDocument()
    */
   public IClientDocument getClientDocument() throws IOException {
+    log.debug("getClientDocument");
     if (cdocument!=null) {
       // cdocument is non-nill if the ClientDocument.finalise() method hasn't been called.
       return cdocument;
     }
+    evgen.disableDocumentWatch();
     VamsasArchive va = null;
     try {
       // LATER: bail out if it takes too long to get the lock ?
@@ -240,16 +268,16 @@ public class SimpleClient implements IClient {
     }
     VamsasDocument doc=null;
     IdFactory vorba = null;
-    // TODO: reduce size of vorba ids generated from these parameters to IdFactory (mainly sessionHandle rationalization ?)
+    // TODO: LATER: reduce size of vorba ids generated from these parameters to IdFactory (mainly sessionHandle rationalization ?)
     try {
       va.setVorba(vorba=makeVorbaIdFactory());
       // if session currently holds data - read it in - or get a dummy
-      _session.slog.debug("Accessing document");
+      log.debug("Accessing document");
       doc = 
         va.getVamsasDocument(getProvenanceUser(),
             "created new session document.", null);
       if (doc!=null)
-        _session.slog.debug("Successfully retrieved document.");
+        log.debug("Successfully retrieved document.");
       else
         log.error("Unexpectedly retrieved null document!");
     }
@@ -259,8 +287,8 @@ public class SimpleClient implements IClient {
     }
     // Construct the IClientDocument instance
     
-    ClientDocument cdoc = new ClientDocument(doc, va, vorba, this);
-    return cdoc;
+    cdocument = new ClientDocument(doc, va, vorba, this);
+    return cdocument;
   }
   
   /*
@@ -269,23 +297,32 @@ public class SimpleClient implements IClient {
    * @see uk.ac.vamsas.client.IClient#updateDocument(uk.ac.vamsas.client.IClientDocument)
    */
   public void updateDocument(IClientDocument newdoc) {
+    log.debug("updateDocument:");
+    // Check validity of simpleclient instance and that it holds a lock on the session's document
     if (!(newdoc instanceof ClientDocument)) {
-      throw new Error("Invalid IClientDocument instance for SimpleClient.");
+      throw new Error("Invalid IClientDocument passsed to SimpleClient.");
     }
     if (cdocument==null)
-      throw new Error("Client Error - updateDocument() called before getClientDocument().");
+      throw new Error("Client Error - updateDocument() called before getClientDocument() on this SimpleClient instance.");
     if (newdoc!=cdocument)
       throw new Error("Client Error - SimpleClient.updateDocument() can only take the IClientDocument instance returned from SimpleClient.getClientDocument()");
+
+    if (evgen.isDocumentWatchEnabled())
+      throw new Error("Client Error - or Library Bug : Document watcher still enabled whilst ClientDocument instance exists.");
+    
     if (!cdocument.isModified()) {
+      // client document is silently got rid of, with no session update events.
       if (log.isDebugEnabled())
-        log.debug("updateDocument for "+session.getSessionUrn()+" with unmodified IClientDocument.");
+        log.debug("updateDocument for "+session.getSessionUrn()+" with unmodified IClientDocument (skipping the write)");
     } else {
       try {
         if (!cdocument.updateSessionDocument()) {
           log.warn("Session document did not update properly for session directory "+_session.sessionDir);
-          // cdocument.archive.cancelArchive(); // LATER: could be done - would need to prevent updateSessionDocument closing the archive.
+          // cdocument.archive.cancelArchive(); // LATER: could be done - would need to prevent updateSessionDocument closing the iohandler.
           _session.slog.warn("Session Document updated but may not be valid (false return from org.vamsas.simpleclient.ClientDocument.updateSessionDocument()");
         }
+        log.debug("Document update successful.");
+        _session.setUnsavedFlag();
       }
       catch (IOException e) {
         log.warn("IO Problems when updating document!",e);
@@ -294,12 +331,20 @@ public class SimpleClient implements IClient {
     }
     // garbage collect the ClientDocument instance.
     try {
+      log.debug("Finalizing ClientDocument instance.");
       cdocument.finalize();
-
     } catch (Throwable e) {
       log.error("Exception when trying to garbage collect ClientDocument for "+session.getSessionUrn(), e);
     }
     cdocument = null; // this is probably done by finalize
+
+    try {
+      _session.unlockVamsasDocument();
+      evgen.enableDocumentWatch();
+    } catch (IOException e) {
+      log.warn("IO Problems when releasing lock on session document!",e);
+      _session.slog.error("IO problems when attempting to release lock on session document.");
+    }
   }
   
   /*
@@ -308,7 +353,9 @@ public class SimpleClient implements IClient {
    * @see uk.ac.vamsas.client.IClient#storeDocument(java.io.File)
    */
   public void storeDocument(File location) {
-    
+    if (location==null)
+      throw new Error("Vamsas Client API Usage Error: storeDocument called with null location.");
+    log.debug("StoreDocument to "+location);
     // write storeDocument file to inform other clients that they should raise
     Lock vamlock = evgen.want_to_store();
     // Events.DOCUMENT_FINALIZEAPPDATA
@@ -330,6 +377,7 @@ public class SimpleClient implements IClient {
    */
   public void addVorbaEventHandler(String EventChain, PropertyChangeListener evt) {
     if (handlers.containsKey(EventChain)) {
+      log.debug("Adding new handler for "+EventChain);
       Object handler;
       ((PropertyChangeSupport) (handler = handlers.get(EventChain)))
       .addPropertyChangeListener(evt);
@@ -342,13 +390,13 @@ public class SimpleClient implements IClient {
    * @see uk.ac.vamsas.client.IClient#pollUpdate()
    */
   public void pollUpdate() {
-    
+    log.debug("pollUpdate");
     if (evgen==null) {
       log.warn("pollUpdate called on incomplete SimpleClient object.");
       return;
     }
     
-    if (!evgen.isAlive()) {
+    if (!evgen.isWatcherAlive()) {
       log.warn("pollUpdate called before joinSession() - trying to do this.");
       try {
         joinSession();
@@ -359,7 +407,7 @@ public class SimpleClient implements IClient {
     
     //TODO ensure event generator robustly handles these interrupts.
     log.debug("interrrupting event generator.");
-    evgen.interrupt();
+    evgen.interruptWatching();
     log.debug("interrrupted event generator.");
   }
   
@@ -367,24 +415,26 @@ public class SimpleClient implements IClient {
    * @see uk.ac.vamsas.client.IClient#joinSession()
    */
   public void joinSession() throws Exception {
+    log.debug("Joining Session.");
     // start the EventGenerator thread.
     if (evgen==null) {
       log.warn("joinSession called on incomplete SimpleClient object.");
       return;
     }
-    if (evgen.isAlive())
+    if (evgen.isWatcherAlive())
       throw new Error("Join session called twice for the same SimpleClient (IClient instance).");
-    evgen.start();
-    if (evgen.isAlive())
+    evgen.startWatching();
+    if (evgen.isWatcherAlive())
       log.debug("Started EventGenerator thread.");
     else {
       log.warn("Failed to start EventGenerator thread.");
       throw new Exception("Failed to start event generator thread - client cannot be instantiated.");
     }
     if (evgen.countHandlersFor(Events.DOCUMENT_CREATE)>0) {
-      //TODO: is this application connecting to a newly created session document ?
+      //TODO: LATER: is this application connecting to a newly created session document ?
       //evgen.raise(Events.DOCUMENT_CREATE);
     }
+    
   }
   
   
@@ -424,12 +474,20 @@ public class SimpleClient implements IClient {
   protected VamsasSession get_session() {
     return this._session;
   }
-
+  SimplePickManager pickmanager=null;
   /* (non-Javadoc)
    * @see uk.ac.vamsas.client.IClient#getPickManager()
    */
   public IPickManager getPickManager() {
-    // TODO Auto-generated method stub
-    return null;
+    createPickManager();
+    return pickmanager;
+  }
+
+  private void createPickManager() {
+    if (pickmanager==null){
+      // TODO: Construct PickManager for session using details from sessionURN!
+      log.debug("Creating PickManager (not from sessionURN yet)");
+      pickmanager = new SimplePickManager(new uk.ac.vamsas.client.picking.SocketManager());
+    }
   }
 }