choose a particular vamsas session, load, or create a new session and export the...
[jalview.git] / src / jalview / gui / VamsasApplication.java
1 /**
2  *
3  */
4 package jalview.gui;
5
6 import jalview.bin.Cache;
7 import jalview.datamodel.SequenceI;
8 import jalview.io.VamsasAppDatastore;
9 import jalview.structure.StructureSelectionManager;
10 import jalview.structure.VamsasListener;
11
12 import java.beans.PropertyChangeEvent;
13 import java.beans.PropertyChangeListener;
14 import java.io.File;
15 import java.io.IOException;
16 import java.util.Hashtable;
17 import java.util.IdentityHashMap;
18
19 import javax.swing.JInternalFrame;
20
21 import uk.ac.vamsas.client.ClientHandle;
22 import uk.ac.vamsas.client.IClient;
23 import uk.ac.vamsas.client.IClientDocument;
24 import uk.ac.vamsas.client.NoDefaultSessionException;
25 import uk.ac.vamsas.client.UserHandle;
26 import uk.ac.vamsas.client.VorbaId;
27 import uk.ac.vamsas.client.picking.IMessageHandler;
28 import uk.ac.vamsas.client.picking.IPickManager;
29 import uk.ac.vamsas.client.picking.Message;
30 import uk.ac.vamsas.client.picking.MouseOverMessage;
31 import uk.ac.vamsas.objects.core.Entry;
32 /**
33  * @author jimp
34  *
35  */
36 public class VamsasApplication
37 {
38   IClient vclient=null;
39   ClientHandle app=null;
40   UserHandle user=null;
41   
42   Desktop jdesktop = null; // our jalview desktop reference
43   
44   // Cache.preferences for vamsas client session arena
45   // preferences for check for default session at startup.
46   // user and organisation stuff.
47   public VamsasApplication(Desktop jdesktop,
48                       File sessionPath)
49   {
50     // JBPNote:
51     // we should create a session URI from the sessionPath and pass it to
52     // the clientFactory - but the vamsas api doesn't cope with that yet.
53     this(jdesktop);
54     throw new Error("Sorry - can't start from session file yet."); // make this a warning
55   }
56   private static uk.ac.vamsas.client.IClientFactory getClientFactory() throws IOException {
57     return new uk.ac.vamsas.client.simpleclient.SimpleClientFactory();
58   }
59   /**
60    * Start a new vamsas session
61    * @param jdesktop
62    */
63   public VamsasApplication(Desktop jdesktop)
64   {
65     this.jdesktop = jdesktop; 
66     initClientSession(null);
67   }
68   /**
69    * init a connection to the session at the given url
70    * @param jdesktop
71    * @param sessionUrl
72    */
73   public VamsasApplication(Desktop jdesktop, String sessionUrl)
74   {
75     this.jdesktop = jdesktop; 
76     initClientSession(sessionUrl);
77   }
78   /**
79    * @throws IOException or other if clientfactory instantiation failed.
80    * @return list of current sessions or null if no session exists.
81    */
82   public static String[] getSessionList() throws Exception {
83     return getClientFactory().getCurrentSessions();
84   }
85   /**
86    * initialise, possibly with e valid session url
87    * @param sess
88    * @return
89    */
90   private boolean initClientSession(String sess) {
91     try {
92       // Only need to tell the library what the application is here
93       app = new ClientHandle("jalview.bin.Jalview", jalview.bin.Cache.getProperty("VERSION"));
94       uk.ac.vamsas.client.IClientFactory clientfactory = getClientFactory();
95       if (sess==null)
96       {
97         vclient = clientfactory.getNewSessionIClient(app);
98       }
99       else
100       {
101         vclient = clientfactory.getIClient(app,sess);
102       }
103       
104       user = vclient.getUserHandle();
105       
106     } 
107     catch (Exception e)
108     {
109       jalview.bin.Cache.log.error("Couldn't instantiate vamsas client !",e);
110       return false;
111     }
112     return true;
113   }
114   /**
115    * 
116    * @return true if we are registered in a vamsas session
117    */
118   public boolean inSession()
119   {
120     return (vclient!=null);
121   }
122   /**
123    * called to connect to session
124    * inits handlers, does an initial document update.
125    */
126   public void initial_update()
127   {
128     if (!inSession())
129     {
130       throw new Error("Impementation error! Vamsas Operations when client not initialised and connected.");
131     }
132     addDocumentUpdateHandler();
133     startSession();
134     Cache.log.debug("Jalview loading the Vamsas Session for the first time.");
135     dealWithDocumentUpdate(false); // we don't push an update out to the document yet.
136     Cache.log.debug("... finished update for the first time.");
137   }
138   /**
139    * Update all windows after a vamsas datamodel change.
140    * this could go on the desktop object!
141    * 
142    */
143   protected void updateJalviewGui() 
144   {
145     JInternalFrame[] frames = jdesktop.getAllFrames();
146
147     if (frames == null)
148     {
149       return;
150     }
151
152     try
153     {
154       //REVERSE ORDER
155       for (int i = frames.length - 1; i > -1; i--)
156       {
157         if (frames[i] instanceof AlignFrame)
158         {
159           AlignFrame af = (AlignFrame) frames[i];
160           af.alignPanel.alignmentChanged();
161         }
162       }
163     }
164     catch (Exception e)
165     {
166       Cache.log.warn(
167           "Exception whilst refreshing jalview windows after a vamsas document update.",
168           e);
169     }
170   }
171   public void push_update()
172   {
173     Cache.log.info("Jalview updating to the Vamsas Session.");
174     dealWithDocumentUpdate(true);
175     /*
176     IClientDocument cdoc=null;
177     try
178     {
179       cdoc = vclient.getClientDocument();
180     }
181     catch (Exception e)
182     {
183       Cache.log.error("Failed to get client document for update.");
184       // RAISE A WARNING DIALOG
185       disableGui(false);
186       return;
187     }
188     updateVamsasDocument(cdoc);
189     updateJalviewGui();
190     cdoc.setVamsasRoots(cdoc.getVamsasRoots()); // propagate update flags back
191     vclient.updateDocument(cdoc);
192     */
193     Cache.log.info("Jalview finished updating to the Vamsas Session.");
194   }
195
196   public void end_session()
197   {
198     if (!inSession())
199       throw new Error("Jalview not connected to Vamsas session.");
200     Cache.log.info("Jalview disconnecting from the Vamsas Session.");
201     try
202     {
203       if (joinedSession) {
204         vclient.finalizeClient();
205         Cache.log.info("Jalview has left the session.");
206       } else {
207         Cache.log.warn("JV Client leaving a session that's its not joined yet.");
208       }
209       joinedSession=false;
210       vclient = null;
211       app=null; user = null;
212       jv2vobj = null;
213       vobj2jv = null;
214     }
215     catch (Exception e)
216     {
217       Cache.log.error("Vamsas Session finalization threw exceptions!",e);
218     }
219   }
220
221   public void updateJalview(IClientDocument cdoc)
222   {
223     Cache.log.debug("Jalview updating from sesion document ..");
224     ensureJvVamsas();
225     VamsasAppDatastore vds = new VamsasAppDatastore(cdoc, vobj2jv, jv2vobj,
226                                               baseProvEntry());
227     vds.updateToJalview();
228     Cache.log.debug(".. finished updating from sesion document.");
229     
230   }
231   private void ensureJvVamsas()
232   {
233     if (jv2vobj == null)
234     {
235       jv2vobj = new IdentityHashMap();
236       vobj2jv = new Hashtable();
237     }
238   }
239
240   /**
241    * jalview object binding to VorbaIds
242    */
243   IdentityHashMap jv2vobj = null;
244   Hashtable vobj2jv = null;
245   public void updateVamsasDocument(IClientDocument doc)
246   {
247     ensureJvVamsas();
248     VamsasAppDatastore vds = new VamsasAppDatastore(doc, vobj2jv, jv2vobj,
249                                               baseProvEntry());
250     // wander through frames
251     JInternalFrame[] frames = Desktop.desktop.getAllFrames();
252
253     if (frames == null)
254     {
255       return;
256     }
257
258     try
259     {
260       //REVERSE ORDER
261       for (int i = frames.length - 1; i > -1; i--)
262       {
263         if (frames[i] instanceof AlignFrame)
264         {
265           AlignFrame af = (AlignFrame) frames[i];
266
267           // update alignment and root from frame.
268           vds.storeVAMSAS(af.getViewport(), af.getTitle());
269         }
270       }
271       //REVERSE ORDER
272       for (int i = frames.length - 1; i > -1; i--)
273       {
274         if (frames[i] instanceof AlignFrame)
275         {
276           AlignFrame af = (AlignFrame) frames[i];
277
278           // add any AlignedCodonFrame mappings on this alignment to any other.
279           vds.storeSequenceMappings(af.getViewport(), af.getTitle());
280         }
281       }
282     }
283     catch (Exception e)
284     {
285       Cache.log.error("Vamsas Document store exception", e);
286     }
287   }
288
289   private Entry baseProvEntry()
290   {
291     uk.ac.vamsas.objects.core.Entry pentry = new uk.ac.vamsas.objects.core.Entry();
292     pentry.setUser(user.getFullName());
293     pentry.setApp(app.getClientUrn());
294     pentry.setDate(new java.util.Date());
295     pentry.setAction("created");
296     return pentry;
297   }
298   /**
299    * do a vamsas document update or update jalview from the vamsas document
300    * @param fromJalview true to update from jalview to the vamsas document
301    */
302   protected void dealWithDocumentUpdate(boolean fromJalview)
303   {
304     // called by update handler for document update.
305     Cache.log.debug("Updating jalview from changed vamsas document.");
306     disableGui(true);
307     try {
308       long time = System.currentTimeMillis();
309       IClientDocument cdoc = vclient.getClientDocument();
310       if (Cache.log.isDebugEnabled())
311       {
312         Cache.log.debug("Time taken to get ClientDocument = "+(System.currentTimeMillis()-time));
313         time = System.currentTimeMillis();
314       }
315       if (fromJalview)
316       {
317         this.updateVamsasDocument(cdoc);
318         if (Cache.log.isDebugEnabled())
319         {
320           Cache.log.debug("Time taken to update Vamsas Document from jalview\t= "+(System.currentTimeMillis()-time));
321           time = System.currentTimeMillis();
322         }
323         cdoc.setVamsasRoots(cdoc.getVamsasRoots());
324         if (Cache.log.isDebugEnabled())
325         {
326           Cache.log.debug("Time taken to set Document Roots\t\t= "+(System.currentTimeMillis()-time));
327           time = System.currentTimeMillis();
328         }
329       } else
330       {
331         updateJalview(cdoc);
332         if (Cache.log.isDebugEnabled())
333         {
334           Cache.log.debug("Time taken to update Jalview from vamsas document Roots\t= "+(System.currentTimeMillis()-time));
335           time = System.currentTimeMillis();
336         }
337
338       }
339       vclient.updateDocument(cdoc);
340       if (Cache.log.isDebugEnabled())
341       {
342         Cache.log.debug("Time taken to update Session Document\t= "+(System.currentTimeMillis()-time));
343         time = System.currentTimeMillis();
344       }
345       cdoc=null;
346     } catch (Exception ee) {
347       System.err.println("Exception whilst updating :");
348       ee.printStackTrace(System.err);
349     }
350     Cache.log.debug("Finished updating from document change.");
351     disableGui(false);
352   }
353   private void addDocumentUpdateHandler()
354   {
355     final VamsasApplication client = this;
356     vclient.addDocumentUpdateHandler(new PropertyChangeListener() {
357       public void propertyChange(PropertyChangeEvent evt)
358       {
359         Cache.log.debug("Dealing with document update event.");
360         client.dealWithDocumentUpdate(false);
361         Cache.log.debug("finished dealing with event.");
362       }
363     });
364     Cache.log.debug("Added Jalview handler for vamsas document updates.");
365   }
366   public void disableGui(boolean b)
367   {
368     Desktop.instance.setVamsasUpdate(b);
369   }
370   private boolean joinedSession=false;
371   private VamsasListener picker=null;
372   private void startSession()
373   {
374     if (inSession())
375     {
376       try {
377         vclient.joinSession();
378         joinedSession=true;
379       }
380       catch (Exception e)
381       {
382         // Complain to GUI
383         Cache.log.error("Failed to join vamsas session.",e);
384         vclient=null;
385       }
386       try {
387         final IPickManager pm = vclient.getPickManager();
388         final StructureSelectionManager ssm = StructureSelectionManager.getStructureSelectionManager();
389         pm.registerMessageHandler(new IMessageHandler() {
390           String last=null;
391           public void handleMessage(Message message)
392           {
393             if (message instanceof MouseOverMessage && vobj2jv!=null)
394             {
395               MouseOverMessage mm = (MouseOverMessage) message;
396               String mstring = mm.getVorbaID()+" "+mm.getPosition();
397               if (last!=null && mstring.equals(last))
398               {
399                 return;
400               }
401               //if (Cache.log.isDebugEnabled())
402               //{
403               //  Cache.log.debug("Received MouseOverMessage "+mm.getVorbaID()+" "+mm.getPosition());
404               //}
405               Object jvobj = vobj2jv.get(mm.getVorbaID());
406               if (jvobj != null && jvobj instanceof SequenceI)
407               {
408                 last = mstring;
409                 // Cache.log.debug("Handling Mouse over "+mm.getVorbaID()+" bound to "+jvobj+" at "+mm.getPosition());
410                 // position is in sequence or in aligned sequence ???????
411                 ssm.mouseOverVamsasSequence((SequenceI) jvobj, mm.getPosition());
412               }
413             }
414           }
415         });
416         picker = new VamsasListener() {
417           SequenceI last=null;
418           int i=-1;
419           public void mouseOver(SequenceI seq, int index)
420           {
421             if (jv2vobj==null)
422               return;
423             if (seq!=last || i!=index)
424             {
425               VorbaId v = (VorbaId) jv2vobj.get(seq);
426               if (v!=null)
427               {
428                 Cache.log.debug("Mouse over "+v.getId()+" bound to "+seq+" at "+index);
429                 last = seq;
430                 i=index;
431                 MouseOverMessage message = new MouseOverMessage(v.getId(), index);
432                 pm.sendMessage(message);
433               }
434             }
435           }
436         };
437         ssm.addStructureViewerListener(picker); // better method here
438       } catch (Exception e)
439       {
440         Cache.log.error("Failed to init Vamsas Picking",e);
441       }
442     }
443   }
444 }