2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3 * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 import jalview.bin.Cache;
22 import jalview.datamodel.SequenceI;
23 import jalview.io.VamsasAppDatastore;
24 import jalview.structure.StructureSelectionManager;
25 import jalview.structure.VamsasListener;
27 import java.beans.PropertyChangeEvent;
28 import java.beans.PropertyChangeListener;
30 import java.io.IOException;
31 import java.util.Hashtable;
32 import java.util.IdentityHashMap;
34 import javax.swing.JInternalFrame;
35 import javax.swing.JOptionPane;
37 import uk.ac.vamsas.client.ClientHandle;
38 import uk.ac.vamsas.client.IClient;
39 import uk.ac.vamsas.client.IClientDocument;
40 import uk.ac.vamsas.client.InvalidSessionDocumentException;
41 import uk.ac.vamsas.client.NoDefaultSessionException;
42 import uk.ac.vamsas.client.UserHandle;
43 import uk.ac.vamsas.client.VorbaId;
44 import uk.ac.vamsas.client.picking.IMessageHandler;
45 import uk.ac.vamsas.client.picking.IPickManager;
46 import uk.ac.vamsas.client.picking.Message;
47 import uk.ac.vamsas.client.picking.MouseOverMessage;
48 import uk.ac.vamsas.client.picking.SelectionMessage;
49 import uk.ac.vamsas.objects.core.Entry;
55 public class VamsasApplication
57 IClient vclient = null;
59 ClientHandle app = null;
61 UserHandle user = null;
63 Desktop jdesktop = null; // our jalview desktop reference
65 // Cache.preferences for vamsas client session arena
66 // preferences for check for default session at startup.
67 // user and organisation stuff.
68 public VamsasApplication(Desktop jdesktop, File sessionPath)
71 // we should create a session URI from the sessionPath and pass it to
72 // the clientFactory - but the vamsas api doesn't cope with that yet.
73 this.jdesktop = jdesktop;
74 initClientSession(null, sessionPath);
77 private static uk.ac.vamsas.client.IClientFactory getClientFactory()
80 return new uk.ac.vamsas.client.simpleclient.SimpleClientFactory();
84 * Start a new vamsas session
88 public VamsasApplication(Desktop jdesktop)
90 this.jdesktop = jdesktop;
91 initClientSession(null, null);
95 * init a connection to the session at the given url
100 public VamsasApplication(Desktop jdesktop, String sessionUrl)
102 this.jdesktop = jdesktop;
103 initClientSession(sessionUrl, null);
107 * @throws IOException
108 * or other if clientfactory instantiation failed.
109 * @return list of current sessions or null if no session exists.
111 public static String[] getSessionList() throws Exception
113 return getClientFactory().getCurrentSessions();
117 * initialise, possibly with either a valid session url or a file for a new
121 * null or a valid session url
122 * @param vamsasDocument
123 * null or a valid vamsas document file
124 * @return false if no vamsas connection was made
126 private boolean initClientSession(String sess, File vamsasDocument)
130 // Only need to tell the library what the application is here
131 app = getJalviewHandle();
132 uk.ac.vamsas.client.IClientFactory clientfactory = getClientFactory();
133 if (vamsasDocument != null)
138 "Implementation Error - cannot import existing vamsas document into an existing session, Yet!");
142 vclient = clientfactory.openAsNewSessionIClient(app,
144 } catch (InvalidSessionDocumentException e)
147 .showInternalMessageDialog(
150 "VAMSAS Document could not be opened as a new session - please choose another",
151 "VAMSAS Document Import Failed",
152 JOptionPane.ERROR_MESSAGE);
158 // join existing or create a new session
161 vclient = clientfactory.getNewSessionIClient(app);
165 vclient = clientfactory.getIClient(app, sess);
168 // set some properties for our VAMSAS interaction
170 user = vclient.getUserHandle();
172 } catch (Exception e)
174 jalview.bin.Cache.log
175 .error("Couldn't instantiate vamsas client !", e);
181 private void setVclientConfig()
189 if (vclient instanceof uk.ac.vamsas.client.simpleclient.SimpleClient)
191 uk.ac.vamsas.client.simpleclient.SimpleClientConfig cfg = ((uk.ac.vamsas.client.simpleclient.SimpleClient) vclient)
192 .getSimpleClientConfig();
193 cfg._validatemergedroots = false;
194 cfg._validateupdatedroots = true; // we may write rubbish otherwise.
200 "Probable SERIOUS VAMSAS client incompatibility - carrying on regardless",
202 } catch (Exception e)
206 "Probable VAMSAS client incompatibility - carrying on regardless",
212 * make the appHandle for Jalview
216 private ClientHandle getJalviewHandle()
218 return new ClientHandle("jalview.bin.Jalview", jalview.bin.Cache
219 .getProperty("VERSION"));
224 * @return true if we are registered in a vamsas session
226 public boolean inSession()
228 return (vclient != null);
232 * called to connect to session inits handlers, does an initial document
235 public void initial_update()
240 "Impementation error! Vamsas Operations when client not initialised and connected.");
242 addDocumentUpdateHandler();
243 addStoreDocumentHandler();
246 .debug("Jalview loading the Vamsas Session for the first time.");
247 dealWithDocumentUpdate(false); // we don't push an update out to the
249 Cache.log.debug("... finished update for the first time.");
253 * Update all windows after a vamsas datamodel change. this could go on the
257 protected void updateJalviewGui()
259 JInternalFrame[] frames = jdesktop.getAllFrames();
269 for (int i = frames.length - 1; i > -1; i--)
271 if (frames[i] instanceof AlignFrame)
273 AlignFrame af = (AlignFrame) frames[i];
274 af.alignPanel.alignmentChanged();
277 } catch (Exception e)
281 "Exception whilst refreshing jalview windows after a vamsas document update.",
286 public void push_update()
288 Thread udthread = new Thread(new Runnable()
293 Cache.log.info("Jalview updating to the Vamsas Session.");
295 dealWithDocumentUpdate(true);
297 * IClientDocument cdoc=null; try { cdoc = vclient.getClientDocument(); }
298 * catch (Exception e) { Cache.log.error("Failed to get client document
299 * for update."); // RAISE A WARNING DIALOG disableGui(false); return; }
300 * updateVamsasDocument(cdoc); updateJalviewGui();
301 * cdoc.setVamsasRoots(cdoc.getVamsasRoots()); // propagate update flags
302 * back vclient.updateDocument(cdoc);
304 Cache.log.info("Jalview finished updating to the Vamsas Session.");
305 // TODO Auto-generated method stub
312 public void end_session()
315 throw new Error("Jalview not connected to Vamsas session.");
316 Cache.log.info("Jalview disconnecting from the Vamsas Session.");
321 vclient.finalizeClient();
322 Cache.log.info("Jalview has left the session.");
327 .warn("JV Client leaving a session that's its not joined yet.");
329 joinedSession = false;
335 } catch (Exception e)
337 Cache.log.error("Vamsas Session finalization threw exceptions!", e);
341 public void updateJalview(IClientDocument cdoc)
343 Cache.log.debug("Jalview updating from sesion document ..");
345 VamsasAppDatastore vds = new VamsasAppDatastore(cdoc, vobj2jv, jv2vobj,
346 baseProvEntry(), alRedoState);
347 vds.updateToJalview();
348 Cache.log.debug(".. finished updating from sesion document.");
352 private void ensureJvVamsas()
356 jv2vobj = new IdentityHashMap();
357 vobj2jv = new Hashtable();
358 alRedoState = new Hashtable();
363 * jalview object binding to VorbaIds
365 IdentityHashMap jv2vobj = null;
367 Hashtable vobj2jv = null;
369 Hashtable alRedoState = null;
371 public void updateVamsasDocument(IClientDocument doc)
374 VamsasAppDatastore vds = new VamsasAppDatastore(doc, vobj2jv, jv2vobj,
375 baseProvEntry(), alRedoState);
376 // wander through frames
377 JInternalFrame[] frames = Desktop.desktop.getAllFrames();
387 for (int i = frames.length - 1; i > -1; i--)
389 if (frames[i] instanceof AlignFrame)
391 AlignFrame af = (AlignFrame) frames[i];
393 // update alignment and root from frame.
394 vds.storeVAMSAS(af.getViewport(), af.getTitle());
398 for (int i = frames.length - 1; i > -1; i--)
400 if (frames[i] instanceof AlignFrame)
402 AlignFrame af = (AlignFrame) frames[i];
404 // add any AlignedCodonFrame mappings on this alignment to any other.
405 vds.storeSequenceMappings(af.getViewport(), af.getTitle());
408 } catch (Exception e)
410 Cache.log.error("Vamsas Document store exception", e);
414 private Entry baseProvEntry()
416 uk.ac.vamsas.objects.core.Entry pentry = new uk.ac.vamsas.objects.core.Entry();
417 pentry.setUser(user.getFullName());
418 pentry.setApp(app.getClientUrn());
419 pentry.setDate(new java.util.Date());
420 pentry.setAction("created");
425 * do a vamsas document update or update jalview from the vamsas document
428 * true to update from jalview to the vamsas document
430 protected void dealWithDocumentUpdate(boolean fromJalview)
432 // called by update handler for document update.
433 Cache.log.debug("Updating jalview from changed vamsas document.");
437 long time = System.currentTimeMillis();
438 IClientDocument cdoc = vclient.getClientDocument();
439 if (Cache.log.isDebugEnabled())
441 Cache.log.debug("Time taken to get ClientDocument = "
442 + (System.currentTimeMillis() - time));
443 time = System.currentTimeMillis();
447 this.updateVamsasDocument(cdoc);
448 if (Cache.log.isDebugEnabled())
451 .debug("Time taken to update Vamsas Document from jalview\t= "
452 + (System.currentTimeMillis() - time));
453 time = System.currentTimeMillis();
455 cdoc.setVamsasRoots(cdoc.getVamsasRoots());
456 if (Cache.log.isDebugEnabled())
458 Cache.log.debug("Time taken to set Document Roots\t\t= "
459 + (System.currentTimeMillis() - time));
460 time = System.currentTimeMillis();
466 if (Cache.log.isDebugEnabled())
469 .debug("Time taken to update Jalview from vamsas document Roots\t= "
470 + (System.currentTimeMillis() - time));
471 time = System.currentTimeMillis();
475 vclient.updateDocument(cdoc);
476 if (Cache.log.isDebugEnabled())
478 Cache.log.debug("Time taken to update Session Document\t= "
479 + (System.currentTimeMillis() - time));
480 time = System.currentTimeMillis();
483 } catch (Exception ee)
485 System.err.println("Exception whilst updating :");
486 ee.printStackTrace(System.err);
488 Cache.log.debug("Finished updating from document change.");
492 private void addDocumentUpdateHandler()
494 final VamsasApplication client = this;
495 vclient.addDocumentUpdateHandler(new PropertyChangeListener()
497 public void propertyChange(PropertyChangeEvent evt)
499 Cache.log.debug("Dealing with document update event.");
500 client.dealWithDocumentUpdate(false);
501 Cache.log.debug("finished dealing with event.");
504 Cache.log.debug("Added Jalview handler for vamsas document updates.");
507 private void addStoreDocumentHandler()
509 final VamsasApplication client = this;
510 vclient.addVorbaEventHandler(
511 uk.ac.vamsas.client.Events.DOCUMENT_REQUESTTOCLOSE,
512 new PropertyChangeListener()
514 public void propertyChange(PropertyChangeEvent evt)
517 .debug("Asking user if the vamsas session should be stored.");
518 int reply = JOptionPane
519 .showInternalConfirmDialog(
521 "The current VAMSAS session has unsaved data - do you want to save it ?",
522 "VAMSAS Session Shutdown",
523 JOptionPane.YES_NO_OPTION,
524 JOptionPane.QUESTION_MESSAGE);
526 if (reply == JOptionPane.YES_OPTION)
528 Cache.log.debug("Prompting for vamsas store filename.");
529 Desktop.instance.vamsasSave_actionPerformed(null);
530 Cache.log.debug("Finished attempt at storing document.");
533 .debug("finished dealing with REQUESTTOCLOSE event.");
536 Cache.log.debug("Added Jalview handler for vamsas document updates.");
539 public void disableGui(boolean b)
541 Desktop.instance.setVamsasUpdate(b);
544 private boolean joinedSession = false;
546 private VamsasListener picker = null;
548 private void startSession()
554 vclient.joinSession();
555 joinedSession = true;
556 } catch (Exception e)
559 Cache.log.error("Failed to join vamsas session.", e);
564 final IPickManager pm = vclient.getPickManager();
565 final StructureSelectionManager ssm = StructureSelectionManager
566 .getStructureSelectionManager();
567 pm.registerMessageHandler(new IMessageHandler()
571 public void handleMessage(Message message)
575 // we are not in a session yet.
578 if (message instanceof MouseOverMessage)
580 MouseOverMessage mm = (MouseOverMessage) message;
581 String mstring = mm.getVorbaID() + " " + mm.getPosition();
582 if (last != null && mstring.equals(last))
586 // if (Cache.log.isDebugEnabled())
588 // Cache.log.debug("Received MouseOverMessage "+mm.getVorbaID()+"
589 // "+mm.getPosition());
591 Object jvobj = vobj2jv.get(mm.getVorbaID());
592 if (jvobj != null && jvobj instanceof SequenceI)
595 // Cache.log.debug("Handling Mouse over "+mm.getVorbaID()+"
596 // bound to "+jvobj+" at "+mm.getPosition());
597 // position is character position in aligned sequence
598 ssm.mouseOverVamsasSequence((SequenceI) jvobj, mm
602 if (message instanceof uk.ac.vamsas.client.picking.SelectionMessage)
604 // we only care about AlignmentSequence selections
605 SelectionMessage sm = (SelectionMessage) message;
607 Object[] jvobjs = new Object[sm.getVorbaIDs().length];
609 for (int o=0;o<jvobjs.length; o++)
611 jvobjs[o] = vobj2jv.get(sm.getVorbaIDs()[o]);
614 // can't cope with selections for unmapped objects
617 if (type==null){ type = jvobjs[o].getClass(); };
618 if (type != jvobjs[o].getClass())
620 // discard - can't cope with selections over mixed objects
624 if (type == jalview.datamodel.Alignment.class)
626 if (jvobjs.length==1) {
627 // othewise discard - can't cope with multiple alignment selections (at the moment) ?
630 // send a message to select the specified columns over the given alignment
632 if (type == jalview.datamodel.Sequence.class)
634 boolean aligned = ((jalview.datamodel.Sequence)jvobjs[0]).getDatasetSequence()==null;
635 for (int c=0; jvobjs.length>1 && c<jvobjs.length; c++)
637 if (((jalview.datamodel.Sequence) jvobjs[c]).getDatasetSequence()==null)
645 // if cardinality is greater than one then verify all sequences are alignment sequences.
646 if (jvobjs.length==1)
648 // find all instances of this dataset sequence in the displayed alignments containing the associated range and select them.
651 // locate the alignment containing the given sequences and select the associated ranges on them.
655 for (int c=0;c<jvobjs.length;c++) { jvobjs[c] = null;};
661 picker = new VamsasListener()
663 SequenceI last = null;
667 public void mouseOver(SequenceI seq, int index)
671 if (seq != last || i != index)
673 VorbaId v = (VorbaId) jv2vobj.get(seq);
676 //Cache.log.debug("Mouse over " + v.getId() + " bound to "
677 // + seq + " at " + index);
680 MouseOverMessage message = new MouseOverMessage(v.getId(),
682 pm.sendMessage(message);
687 ssm.addStructureViewerListener(picker); // better method here
688 } catch (Exception e)
690 Cache.log.error("Failed to init Vamsas Picking", e);