2b2ce48d742b94140227a65775a78174b303aa05
[jalview.git] / src / ext / edu / ucsf / rbvi / strucviz2 / port / ListenerThreads.java
1 package ext.edu.ucsf.rbvi.strucviz2.port;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.InputStreamReader;
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.List;
10 import java.util.Map;
11
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14
15 import ext.edu.ucsf.rbvi.strucviz2.StructureManager;
16
17 /***************************************************
18  *                 Thread Classes                  *
19  **************************************************/
20
21 /**
22  * Reply listener thread
23  */
24 public class ListenerThreads extends Thread
25 {
26   private BufferedReader lineReader = null;
27
28   private Process chimera = null;
29
30   private Map<String, List<String>> replyLog = null;
31
32   private Logger logger;
33
34   private StructureManager structureManager = null;
35
36   private boolean stopMe = false;
37
38   /**
39    * Create a new listener thread to read the responses from Chimera
40    * 
41    * @param chimera
42    *          a handle to the Chimera Process
43    * @param structureManager
44    *          a handle to the Chimera structure manager
45    */
46   public ListenerThreads(Process chimera, StructureManager structureManager)
47   {
48     this.chimera = chimera;
49     this.structureManager = structureManager;
50     replyLog = new HashMap<String, List<String>>();
51     // Get a line-oriented reader
52     InputStream readChan = chimera.getInputStream();
53     lineReader = new BufferedReader(new InputStreamReader(readChan));
54     logger = LoggerFactory
55             .getLogger(ext.edu.ucsf.rbvi.strucviz2.port.ListenerThreads.class);
56   }
57
58   /**
59    * Start the thread running
60    */
61   public void run()
62   {
63     // System.out.println("ReplyLogListener running");
64     while (!stopMe)
65     {
66       try
67       {
68         chimeraRead();
69       } catch (IOException e)
70       {
71         logger.warn("UCSF Chimera has exited: " + e.getMessage());
72         return;
73       } finally
74       {
75         if (lineReader != null)
76         {
77           try
78           {
79             lineReader.close();
80           } catch (IOException e)
81           {
82           }
83         }
84       }
85     }
86   }
87
88   public List<String> getResponse(String command)
89   {
90     List<String> reply;
91     // System.out.println("getResponse: "+command);
92     // TODO do we need a maximum wait time before aborting?
93     while (!replyLog.containsKey(command))
94     {
95       try
96       {
97         Thread.currentThread().sleep(100);
98       } catch (InterruptedException e)
99       {
100       }
101     }
102
103     synchronized (replyLog)
104     {
105       reply = replyLog.get(command);
106       // System.out.println("getResponse ("+command+") = "+reply);
107       replyLog.remove(command);
108     }
109     return reply;
110   }
111
112   public void clearResponse(String command)
113   {
114     try
115     {
116       Thread.currentThread().sleep(100);
117     } catch (InterruptedException e)
118     {
119     }
120     if (replyLog.containsKey(command))
121     {
122       replyLog.remove(command);
123     }
124     return;
125   }
126
127   /**
128    * Read input from Chimera
129    * 
130    * @return a List containing the replies from Chimera
131    */
132   private void chimeraRead() throws IOException
133   {
134     if (chimera == null)
135     {
136       return;
137     }
138
139     String line = null;
140     while ((line = lineReader.readLine()) != null)
141     {
142       // System.out.println("From Chimera-->" + line);
143       if (line.startsWith("CMD"))
144       {
145         chimeraCommandRead(line.substring(4));
146       }
147       else if (line.startsWith("ModelChanged: "))
148       {
149         (new ModelUpdater()).start();
150       }
151       else if (line.startsWith("SelectionChanged: "))
152       {
153         (new SelectionUpdater()).start();
154       }
155       else if (line.startsWith("Trajectory residue network info:"))
156       {
157         (new NetworkUpdater(line)).start();
158       }
159     }
160     return;
161   }
162
163   private void chimeraCommandRead(String command) throws IOException
164   {
165     // Generally -- looking for:
166     // CMD command
167     // ........
168     // END
169     // We return the text in between
170     List<String> reply = new ArrayList<String>();
171     boolean updateModels = false;
172     boolean updateSelection = false;
173     boolean importNetwork = false;
174     String line = null;
175
176     synchronized (replyLog)
177     {
178       while ((line = lineReader.readLine()) != null)
179       {
180         // System.out.println("From Chimera (" + command + ") -->" + line);
181         if (line.startsWith("CMD"))
182         {
183           logger.warn("Got unexpected command from Chimera: " + line);
184
185         }
186         else if (line.startsWith("END"))
187         {
188           break;
189         }
190         if (line.startsWith("ModelChanged: "))
191         {
192           updateModels = true;
193         }
194         else if (line.startsWith("SelectionChanged: "))
195         {
196           updateSelection = true;
197         }
198         else if (line.length() == 0)
199         {
200           continue;
201         }
202         else if (!line.startsWith("CMD"))
203         {
204           reply.add(line);
205         }
206         else if (line.startsWith("Trajectory residue network info:"))
207         {
208           importNetwork = true;
209         }
210       }
211       replyLog.put(command, reply);
212     }
213     if (updateModels)
214     {
215       (new ModelUpdater()).start();
216     }
217     if (updateSelection)
218     {
219       (new SelectionUpdater()).start();
220     }
221     if (importNetwork)
222     {
223       (new NetworkUpdater(line)).start();
224     }
225     return;
226   }
227
228   /**
229    * Model updater thread
230    */
231   class ModelUpdater extends Thread
232   {
233
234     public ModelUpdater()
235     {
236     }
237
238     public void run()
239     {
240       structureManager.updateModels();
241       structureManager.modelChanged();
242     }
243   }
244
245   /**
246    * Selection updater thread
247    */
248   class SelectionUpdater extends Thread
249   {
250
251     public SelectionUpdater()
252     {
253     }
254
255     public void run()
256     {
257       try
258       {
259         logger.info("Responding to chimera selection");
260         structureManager.chimeraSelectionChanged();
261       } catch (Exception e)
262       {
263         logger.warn("Could not update selection", e);
264       }
265     }
266   }
267
268   /**
269    * Selection updater thread
270    */
271   class NetworkUpdater extends Thread
272   {
273
274     private String line;
275
276     public NetworkUpdater(String line)
277     {
278       this.line = line;
279     }
280
281     public void run()
282     {
283       try
284       {
285         // ((TaskManager<?, ?>) structureManager.getService(TaskManager.class))
286         // .execute(new ImportTrajectoryRINTaskFactory(structureManager, line)
287         // .createTaskIterator());
288       } catch (Exception e)
289       {
290         logger.warn("Could not import trajectory network", e);
291       }
292     }
293   }
294
295   /**
296    * Set a flag that this thread should clean up and exit.
297    */
298   public void requestStop()
299   {
300     this.stopMe = true;
301   }
302 }