Merge branch 'features/JAL-1333' into Release_2_8_2_Branch
[jalview.git] / src / ext / edu / ucsf / rbvi / strucviz2 / port / ListenerThreads.java
diff --git a/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java b/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java
new file mode 100644 (file)
index 0000000..dee027b
--- /dev/null
@@ -0,0 +1,218 @@
+package ext.edu.ucsf.rbvi.strucviz2.port;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ext.edu.ucsf.rbvi.strucviz2.*;
+
+/***************************************************
+ *                 Thread Classes                  *
+ **************************************************/
+
+/**
+ * Reply listener thread
+ */
+public class ListenerThreads extends Thread {
+       private InputStream readChan = null;
+       private BufferedReader lineReader = null;
+       private Process chimera = null;
+       private Map<String, List<String>> replyLog = null;
+       private Logger logger;
+       private StructureManager structureManager = null;
+
+       /**
+        * Create a new listener thread to read the responses from Chimera
+        * 
+        * @param chimera
+        *            a handle to the Chimera Process
+        * @param log
+        *            a handle to a List to post the responses to
+        * @param chimeraObject
+        *            a handle to the Chimera Object
+        */
+       public ListenerThreads(Process chimera, StructureManager structureManager) {
+               this.chimera = chimera;
+               this.structureManager = structureManager;
+               replyLog = new HashMap<String, List<String>>();
+               // Get a line-oriented reader
+               readChan = chimera.getInputStream();
+               lineReader = new BufferedReader(new InputStreamReader(readChan));
+               logger = LoggerFactory.getLogger(ext.edu.ucsf.rbvi.strucviz2.port.ListenerThreads.class);
+       }
+
+       /**
+        * Start the thread running
+        */
+       public void run() {
+               // System.out.println("ReplyLogListener running");
+               while (true) {
+                       try {
+                               chimeraRead();
+                       } catch (IOException e) {
+                               logger.warn("UCSF Chimera has exited: " + e.getMessage());
+                               return;
+                       }
+               }
+       }
+
+       public List<String> getResponse(String command) {
+               List<String> reply;
+               // System.out.println("getResponse: "+command);
+               while (!replyLog.containsKey(command)) {
+                       try {
+                               Thread.currentThread().sleep(100);
+                       } catch (InterruptedException e) {
+                       }
+               }
+
+               synchronized (replyLog) {
+                       reply = replyLog.get(command);
+                       // System.out.println("getResponse ("+command+") = "+reply);
+                       replyLog.remove(command);
+               }
+               return reply;
+       }
+
+       public void clearResponse(String command) {
+               try {
+                       Thread.currentThread().sleep(100);
+               } catch (InterruptedException e) {
+               }
+               if (replyLog.containsKey(command))
+                       replyLog.remove(command);
+               return;
+       }
+
+       /**
+        * Read input from Chimera
+        * 
+        * @return a List containing the replies from Chimera
+        */
+       private void chimeraRead() throws IOException {
+               if (chimera == null)
+                       return;
+
+               String line = null;
+               while ((line = lineReader.readLine()) != null) {
+                       // System.out.println("From Chimera-->" + line);
+                       if (line.startsWith("CMD")) {
+                               chimeraCommandRead(line.substring(4));
+                       } else if (line.startsWith("ModelChanged: ")) {
+                               (new ModelUpdater()).start();
+                       } else if (line.startsWith("SelectionChanged: ")) {
+                               (new SelectionUpdater()).start();
+                       } else if (line.startsWith("Trajectory residue network info:")) {
+                               (new NetworkUpdater(line)).start();
+                       }
+               }
+               return;
+       }
+
+       private void chimeraCommandRead(String command) throws IOException {
+               // Generally -- looking for:
+               // CMD command
+               // ........
+               // END
+               // We return the text in between
+               List<String> reply = new ArrayList<String>();
+               boolean updateModels = false;
+               boolean updateSelection = false;
+               boolean importNetwork = false;
+               String line = null;
+
+               synchronized (replyLog) {
+                       while ((line = lineReader.readLine()) != null) {
+                               // System.out.println("From Chimera (" + command + ") -->" + line);
+                               if (line.startsWith("CMD")) {
+                                       logger.warn("Got unexpected command from Chimera: " + line);
+
+                               } else if (line.startsWith("END")) {
+                                       break;
+                               }
+                               if (line.startsWith("ModelChanged: ")) {
+                                       updateModels = true;
+                               } else if (line.startsWith("SelectionChanged: ")) {
+                                       updateSelection = true;
+                               } else if (line.length() == 0) {
+                                       continue;
+                               } else if (!line.startsWith("CMD")) {
+                                       reply.add(line);
+                               } else if (line.startsWith("Trajectory residue network info:")) {
+                                       importNetwork = true;
+                               }
+                       }
+                       replyLog.put(command, reply);
+               }
+               if (updateModels)
+                       (new ModelUpdater()).start();
+               if (updateSelection)
+                       (new SelectionUpdater()).start();
+               if (importNetwork) {
+                       (new NetworkUpdater(line)).start();
+               }
+               return;
+       }
+
+       /**
+        * Model updater thread
+        */
+       class ModelUpdater extends Thread {
+
+               public ModelUpdater() {
+               }
+
+               public void run() {
+                       structureManager.updateModels();
+                       structureManager.modelChanged();
+               }
+       }
+
+       /**
+        * Selection updater thread
+        */
+       class SelectionUpdater extends Thread {
+
+               public SelectionUpdater() {
+               }
+
+               public void run() {
+                       try {
+                         logger.info("Responding to chimera selection");
+                         structureManager.chimeraSelectionChanged();
+                       } catch (Exception e) {
+                               logger.warn("Could not update selection", e);
+                       }
+               }
+       }
+
+       /**
+        * Selection updater thread
+        */
+       class NetworkUpdater extends Thread {
+
+               private String line;
+
+               public NetworkUpdater(String line) {
+                       this.line = line;
+               }
+
+               public void run() {
+                       try {
+//                             ((TaskManager<?, ?>) structureManager.getService(TaskManager.class))
+//                                             .execute(new ImportTrajectoryRINTaskFactory(structureManager, line)
+//                                                             .createTaskIterator());
+                       } catch (Exception e) {
+                               logger.warn("Could not import trajectory network", e);
+                       }
+               }
+       }
+}