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.StructureManager; /*************************************************** * Thread Classes * **************************************************/ /** * Reply listener thread */ public class ListenerThreads extends Thread { private InputStream readChan = null; private BufferedReader lineReader = null; private Process chimera = null; private Map> 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>(); // 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 getResponse(String command) { List reply; // System.out.println("getResponse: "+command); // TODO do we need a maximum wait time before aborting? 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 reply = new ArrayList(); 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); } } } }