X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FVamsasApplication.java;h=c48c86f460191618f91640d95bab082ae32c2410;hb=153dd62dc91da13ae732600e6ea55ddbe15eab39;hp=b3f3f6ce0be25b434298b3ca8e0104ae8044cb13;hpb=0ed26e745344cf4c4e5b18ff2ba25c65c5a95327;p=jalview.git diff --git a/src/jalview/gui/VamsasApplication.java b/src/jalview/gui/VamsasApplication.java index b3f3f6c..c48c86f 100644 --- a/src/jalview/gui/VamsasApplication.java +++ b/src/jalview/gui/VamsasApplication.java @@ -1,156 +1,290 @@ -/** - * +/* + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.6) + * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Jalview. If not, see . */ package jalview.gui; +import jalview.bin.Cache; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.ColumnSelection; +import jalview.datamodel.SequenceGroup; +import jalview.datamodel.SequenceI; +import jalview.io.VamsasAppDatastore; +import jalview.structure.SelectionListener; +import jalview.structure.SelectionSource; +import jalview.structure.StructureSelectionManager; +import jalview.structure.VamsasListener; + import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; +import java.util.Enumeration; import java.util.Hashtable; import java.util.IdentityHashMap; -import java.util.Vector; -import java.util.jar.JarOutputStream; +import java.util.Iterator; import javax.swing.JInternalFrame; +import javax.swing.JOptionPane; -import jalview.bin.Cache; -import jalview.io.VamsasAppDatastore; -import jalview.io.VamsasDatastore; - -import uk.ac.vamsas.client.*; -import uk.ac.vamsas.*; -import uk.ac.vamsas.objects.*; +import uk.ac.vamsas.client.ClientHandle; +import uk.ac.vamsas.client.IClient; +import uk.ac.vamsas.client.IClientDocument; +import uk.ac.vamsas.client.InvalidSessionDocumentException; +import uk.ac.vamsas.client.NoDefaultSessionException; +import uk.ac.vamsas.client.UserHandle; +import uk.ac.vamsas.client.VorbaId; +import uk.ac.vamsas.client.picking.IMessageHandler; +import uk.ac.vamsas.client.picking.IPickManager; +import uk.ac.vamsas.client.picking.Message; +import uk.ac.vamsas.client.picking.MouseOverMessage; +import uk.ac.vamsas.client.picking.SelectionMessage; import uk.ac.vamsas.objects.core.Entry; +import uk.ac.vamsas.objects.core.Input; +import uk.ac.vamsas.objects.core.Pos; +import uk.ac.vamsas.objects.core.Seg; + /** * @author jimp - * + * */ -public class VamsasApplication +public class VamsasApplication implements SelectionSource { - IClient vclient=null; - ClientHandle app=null; - UserHandle user=null; - + IClient vclient = null; + + ClientHandle app = null; + + UserHandle user = null; + Desktop jdesktop = null; // our jalview desktop reference - + + private boolean inInitialUpdate = true; + // Cache.preferences for vamsas client session arena // preferences for check for default session at startup. // user and organisation stuff. - public VamsasApplication(Desktop jdesktop, - File sessionPath) + public VamsasApplication(Desktop jdesktop, File sessionPath, + String sessionName) { // JBPNote: // we should create a session URI from the sessionPath and pass it to // the clientFactory - but the vamsas api doesn't cope with that yet. - this(jdesktop); - throw new Error("Sorry - can't start from session file yet."); // make this a warning + this.jdesktop = jdesktop; + initClientSession(null, sessionPath, sessionName); } - private static uk.ac.vamsas.client.IClientFactory getClientFactory() throws IOException { + + private static uk.ac.vamsas.client.IClientFactory getClientFactory() + throws IOException + { return new uk.ac.vamsas.client.simpleclient.SimpleClientFactory(); } + + /** + * Start a new vamsas session + * + * @param jdesktop + */ public VamsasApplication(Desktop jdesktop) { - this.jdesktop = jdesktop; - initClientSession(null); + this.jdesktop = jdesktop; + initClientSession(null, null); + } + + /** + * init a connection to the session at the given url + * + * @param jdesktop + * @param sessionUrl + */ + public VamsasApplication(Desktop jdesktop, String sessionUrl) + { + this.jdesktop = jdesktop; + initClientSession(sessionUrl, null); } + /** - * @throws IOException or other if clientfactory instantiation failed. + * @throws IOException + * or other if clientfactory instantiation failed. * @return list of current sessions or null if no session exists. */ - public static String[] getSessionList() throws Exception { - uk.ac.vamsas.client.IClientFactory clientfactory = null; - clientfactory = getClientFactory(); - return clientfactory.getCurrentSessions(); + public static String[] getSessionList() throws Exception + { + return getClientFactory().getCurrentSessions(); } + /** - * initialise, possibly with e valid session url + * initialise, possibly with either a valid session url or a file for a new + * session + * * @param sess - * @return + * null or a valid session url + * @param vamsasDocument + * null or a valid vamsas document file + * @return false if no vamsas connection was made */ - private boolean initClientSession(String sess) { - try { + private void initClientSession(String sess, File vamsasDocument) + { + initClientSession(sess, vamsasDocument, null); + } + + private boolean initClientSession(String sess, File vamsasDocument, + String newDocSessionName) + { + try + { // Only need to tell the library what the application is here - app = new ClientHandle("jalview.bin.Jalview", jalview.bin.Cache.getProperty("VERSION")); + app = getJalviewHandle(); uk.ac.vamsas.client.IClientFactory clientfactory = getClientFactory(); - if (sess==null) + if (vamsasDocument != null) { - vclient = clientfactory.getIClient(app); + if (sess != null) + { + throw new Error( + "Implementation Error - cannot import existing vamsas document into an existing session, Yet!"); + } + try + { + if (newDocSessionName != null) + { + vclient = clientfactory.openAsNewSessionIClient(app, + vamsasDocument, newDocSessionName); + } + else + { + vclient = clientfactory.openAsNewSessionIClient(app, + vamsasDocument); + } + } catch (InvalidSessionDocumentException e) + { + JOptionPane + .showInternalMessageDialog( + Desktop.desktop, + + "VAMSAS Document could not be opened as a new session - please choose another", + "VAMSAS Document Import Failed", + JOptionPane.ERROR_MESSAGE); + + } } else { - vclient = clientfactory.getIClient(app,sess); + // join existing or create a new session + if (sess == null) + { + vclient = clientfactory.getNewSessionIClient(app); + } + else + { + vclient = clientfactory.getIClient(app, sess); + } } - + // set some properties for our VAMSAS interaction + setVclientConfig(); user = vclient.getUserHandle(); - - } catch (NoDefaultSessionException e) + + } catch (Exception e) { + jalview.bin.Cache.log + .error("Couldn't instantiate vamsas client !", e); return false; } - catch (Exception e) + return true; + } + + private void setVclientConfig() + { + if (vclient == null) { - jalview.bin.Cache.log.error("Couldn't instantiate vamsas client !",e); - return false; + return; + } + try + { + if (vclient instanceof uk.ac.vamsas.client.simpleclient.SimpleClient) + { + uk.ac.vamsas.client.simpleclient.SimpleClientConfig cfg = ((uk.ac.vamsas.client.simpleclient.SimpleClient) vclient) + .getSimpleClientConfig(); + cfg._validatemergedroots = false; + cfg._validateupdatedroots = true; // we may write rubbish otherwise. + } + } catch (Error e) + { + Cache.log + .warn( + "Probable SERIOUS VAMSAS client incompatibility - carrying on regardless", + e); + } catch (Exception e) + { + Cache.log + .warn( + "Probable VAMSAS client incompatibility - carrying on regardless", + e); } - return true; } + + /** + * make the appHandle for Jalview + * + * @return + */ + private ClientHandle getJalviewHandle() + { + return new ClientHandle("jalview.bin.Jalview", jalview.bin.Cache + .getProperty("VERSION")); + } + /** * * @return true if we are registered in a vamsas session */ public boolean inSession() { - return (vclient!=null); + return (vclient != null); } + /** - * called to connect to session - * inits handlers, does an initial document update. + * called to connect to session inits handlers, does an initial document + * update. */ public void initial_update() { if (!inSession()) { - throw new Error("Impementation error! Vamsas Operations when client not initialised and connected."); - } - this.addDocumentUpdateHandler(); - this.startSession(); - Cache.log.info("Jalview loading the Vamsas Session."); - // load in the vamsas archive for the first time - IClientDocument cdoc=null; - try - { - cdoc = vclient.getClientDocument(); + throw new Error( + "Impementation error! Vamsas Operations when client not initialised and connected."); } - catch (IOException e) - { - Cache.log.error("Serious: Exception whilst getting vamsas document",e); - return; - } - updateJalview(cdoc); - updateJalviewGui(); - cdoc.setVamsasRoots(cdoc.getVamsasRoots()); // propagate update flags back - - try{ - vclient.updateDocument(cdoc); - } - catch (Exception e) - { - Cache.log.error("Serious: Exception whilst updating vamsas document.",e); - return; - } - cdoc=null; + addDocumentUpdateHandler(); + addStoreDocumentHandler(); + startSession(); + inInitialUpdate = true; + Cache.log + .debug("Jalview loading the Vamsas Session for the first time."); + dealWithDocumentUpdate(false); // we don't push an update out to the + inInitialUpdate = false; + // document yet. + Cache.log.debug("... finished update for the first time."); } + /** - * Update all windows after a vamsas datamodel change. - * this could go on the desktop object! + * Update all windows after a vamsas datamodel change. this could go on the + * desktop object! * */ - protected void updateJalviewGui() + protected void updateJalviewGui() { - JInternalFrame[] frames = Desktop.desktop.getAllFrames(); + JInternalFrame[] frames = jdesktop.getAllFrames(); if (frames == null) { @@ -159,7 +293,7 @@ public class VamsasApplication try { - //REVERSE ORDER + // REVERSE ORDER for (int i = frames.length - 1; i > -1; i--) { if (frames[i] instanceof AlignFrame) @@ -168,103 +302,121 @@ public class VamsasApplication af.alignPanel.alignmentChanged(); } } - } - catch (Exception e) + } catch (Exception e) { - Cache.log.warn( - "Exception whilst refreshing jalview windows after a vamsas document update.", - e); + Cache.log + .warn( + "Exception whilst refreshing jalview windows after a vamsas document update.", + e); } } - /** - * this will close all windows currently in Jalview. - * - protected void closeWindows() { - JInternalFrame[] frames = Desktop.desktop.getAllFrames(); + public void push_update() + { + Thread udthread = new Thread(new Runnable() + { - if (frames == null) - { - return; - } + public void run() + { + Cache.log.info("Jalview updating to the Vamsas Session."); - try - { - for (int i = frames.length - 1; i > -1; i--) { - frames[i].dispose(); - } - } catch (Exception e) { - Cache.log.error("Whilst closing windows",e); - } + dealWithDocumentUpdate(true); + Cache.log.info("Jalview finished updating to the Vamsas Session."); + } - } + }); + udthread.start(); + } - public void get_update(VamsasArchive doc) { - // Close windows - load update. - Cache.log.info("Jalview updating from Vamsas Session."); - } + /** + * leave a session, prompting the user to save if necessary */ - public void push_update() + public void end_session() { - disableGui(true); - Cache.log.info("Jalview updating the Vamsas Session."); - IClientDocument cdoc=null; - try - { - cdoc = vclient.getClientDocument(); - } - catch (Exception e) - { - Cache.log.error("Failed to get client document for update."); - // RAISE A WARNING DIALOG - disableGui(false); - return; - } - updateVamsasDocument(cdoc); - updateJalviewGui(); - cdoc.setVamsasRoots(cdoc.getVamsasRoots()); // propagate update flags back - vclient.updateDocument(cdoc); - disableGui(false); - cdoc = null; + end_session(true); } - public void end_session() + private boolean promptUser = true; + + /** + * leave a session, optionally prompting the user to save if necessary + * + * @param promptUser + * when true enable prompting by this application + */ + + public void end_session(boolean promptUser) { if (!inSession()) throw new Error("Jalview not connected to Vamsas session."); Cache.log.info("Jalview disconnecting from the Vamsas Session."); try { - if (joinedSession) { + if (joinedSession) + { + boolean ourprompt = this.promptUser; + this.promptUser = promptUser; vclient.finalizeClient(); Cache.log.info("Jalview has left the session."); - } else { - Cache.log.warn("JV Client leaving a session that's its not joined yet."); + this.promptUser = ourprompt; // restore default value } + else + { + Cache.log + .warn("JV Client leaving a session that's its not joined yet."); + } + joinedSession = false; vclient = null; - app=null; user = null; + app = null; + user = null; jv2vobj = null; vobj2jv = null; - } - catch (Exception e) + } catch (Exception e) { - Cache.log.error("Vamsas Session finalization threw exceptions!",e); + Cache.log.error("Vamsas Session finalization threw exceptions!", e); } } public void updateJalview(IClientDocument cdoc) { + Cache.log.debug("Jalview updating from sesion document .."); ensureJvVamsas(); VamsasAppDatastore vds = new VamsasAppDatastore(cdoc, vobj2jv, jv2vobj, - baseProvEntry()); - vds.updateToJalview(); + baseProvEntry(), alRedoState); + try + { + vds.updateToJalview(); + } catch (Exception e) + { + Cache.log.error("Failed to update Jalview from vamsas document.", e); + } + try + { + if (firstUpdate) + { + vds.updateJalviewFromAppdata(); + // Comment this out to repeatedly read in data from JalviewAppData + // firstUpdate=false; + } + } catch (Exception e) + { + Cache.log.error( + "Exception when updating Jalview settings from Appdata.", e); + } + Cache.log.debug(".. finished updating from sesion document."); + } + + boolean firstUpdate = false; + private void ensureJvVamsas() { if (jv2vobj == null) { jv2vobj = new IdentityHashMap(); vobj2jv = new Hashtable(); + alRedoState = new Hashtable(); + firstUpdate = true; } } @@ -272,38 +424,120 @@ public class VamsasApplication * jalview object binding to VorbaIds */ IdentityHashMap jv2vobj = null; + Hashtable vobj2jv = null; - public void updateVamsasDocument(IClientDocument doc) + + Hashtable alRedoState = null; + + boolean errorsDuringUpdate = false; + + boolean errorsDuringAppUpdate = false; + + /** + * update the document accessed through doc. A backup of the current object + * bindings is made. + * + * @param doc + * @return number of views stored in document (updated and new views) + */ + public int updateVamsasDocument(IClientDocument doc) { + int storedviews = 0; ensureJvVamsas(); + errorsDuringUpdate = false; + errorsDuringAppUpdate = false; + backup_objectMapping(); VamsasAppDatastore vds = new VamsasAppDatastore(doc, vobj2jv, jv2vobj, - baseProvEntry()); + baseProvEntry(), alRedoState); // wander through frames JInternalFrame[] frames = Desktop.desktop.getAllFrames(); if (frames == null) { - return; + return 0; } + Hashtable skipList = new Hashtable(); + Hashtable viewset = new Hashtable(); try { - //REVERSE ORDER + // REVERSE ORDER for (int i = frames.length - 1; i > -1; i--) { if (frames[i] instanceof AlignFrame) { AlignFrame af = (AlignFrame) frames[i]; - - // update alignment and root from frame. - vds.storeVAMSAS(af.getViewport(), af.getTitle()); + if (!viewset.containsKey(af.getViewport().getSequenceSetId())) + { + // update alignment and root from frame. + boolean stored = false; + try + { + stored = vds.storeVAMSAS(af.getViewport(), af.getTitle()); + } catch (Exception e) + { + errorsDuringUpdate = true; + Cache.log.error("Exception synchronizing " + + af.getTitle() + + " " + + (af.getViewport().viewName == null ? "" : " view " + + af.getViewport().viewName) + + " to document.", e); + stored = false; + } + if (!stored) + { // record skip in skipList + skipList.put(af.getViewport().getSequenceSetId(), af); + } + else + { + storedviews++; + // could try to eliminate sequenceSetId from skiplist .. + // (skipList.containsKey(af.getViewport().getSequenceSetId())) + // remember sequenceSetId so we can skip all the other views on + // same alignment + viewset.put(af.getViewport().getSequenceSetId(), af); + } + } } } + // REVERSE ORDER + // for (int i = frames.length - 1; i > -1; i--) + // { + // if (frames[i] instanceof AlignFrame) + // { + // AlignFrame af = (AlignFrame) frames[i]; + Iterator aframes = viewset.values().iterator(); + while (aframes.hasNext()) + { + AlignFrame af = (AlignFrame) aframes.next(); + // add any AlignedCodonFrame mappings on this alignment to any other. + vds.storeSequenceMappings(af.getViewport(), af.getTitle()); + } + } catch (Exception e) + { + Cache.log.error("Exception synchronizing Views to Document :", e); + errorsDuringUpdate = true; } - catch (Exception e) + + try + { + if (viewset.size() > 0) + { + // Alignment views were synchronized, so store their state in the + // appData, too. + // The skipList ensures we don't write out any alignments not actually + // in the document. + vds.setSkipList(skipList); + vds.updateJalviewClientAppdata(); + } + } catch (Exception e) { - Cache.log.error("Vamsas Document store exception", e); + Cache.log.error("Client Appdata Write exception", e); + errorsDuringAppUpdate = true; } + vds.clearSkipList(); + return storedviews; } private Entry baseProvEntry() @@ -311,55 +545,572 @@ public class VamsasApplication uk.ac.vamsas.objects.core.Entry pentry = new uk.ac.vamsas.objects.core.Entry(); pentry.setUser(user.getFullName()); pentry.setApp(app.getClientUrn()); - pentry.setDate(new org.exolab.castor.types.Date(new java.util.Date())); + pentry.setDate(new java.util.Date()); pentry.setAction("created"); return pentry; } + /** + * do a vamsas document update or update jalview from the vamsas document + * + * @param fromJalview + * true to update from jalview to the vamsas document + * @return total number of stored alignments in the document after the update + */ + protected int dealWithDocumentUpdate(boolean fromJalview) + { + int storedviews = 0; + // called by update handler for document update. + Cache.log.debug("Updating jalview from changed vamsas document."); + disableGui(true); + try + { + long time = System.currentTimeMillis(); + IClientDocument cdoc = vclient.getClientDocument(); + if (Cache.log.isDebugEnabled()) + { + Cache.log.debug("Time taken to get ClientDocument = " + + (System.currentTimeMillis() - time)); + time = System.currentTimeMillis(); + } + if (fromJalview) + { + storedviews += updateVamsasDocument(cdoc); + if (Cache.log.isDebugEnabled()) + { + Cache.log + .debug("Time taken to update Vamsas Document from jalview\t= " + + (System.currentTimeMillis() - time)); + time = System.currentTimeMillis(); + } + cdoc.setVamsasRoots(cdoc.getVamsasRoots()); + if (Cache.log.isDebugEnabled()) + { + Cache.log.debug("Time taken to set Document Roots\t\t= " + + (System.currentTimeMillis() - time)); + time = System.currentTimeMillis(); + } + } + else + { + updateJalview(cdoc); + if (Cache.log.isDebugEnabled()) + { + Cache.log + .debug("Time taken to update Jalview from vamsas document Roots\t= " + + (System.currentTimeMillis() - time)); + time = System.currentTimeMillis(); + } + + } + vclient.updateDocument(cdoc); + if (Cache.log.isDebugEnabled()) + { + Cache.log.debug("Time taken to update Session Document\t= " + + (System.currentTimeMillis() - time)); + time = System.currentTimeMillis(); + } + cdoc = null; + } catch (Exception ee) + { + System.err.println("Exception whilst updating :"); + ee.printStackTrace(System.err); + // recover object map backup, since its probably corrupted with references + // to Vobjects that don't exist anymore. + recover_objectMappingBackup(); + storedviews = 0; + } + Cache.log.debug("Finished updating from document change."); + disableGui(false); + return storedviews; + } + private void addDocumentUpdateHandler() { - final IClient vorbaclient = vclient; final VamsasApplication client = this; - vorbaclient.addDocumentUpdateHandler(new PropertyChangeListener() { + vclient.addDocumentUpdateHandler(new PropertyChangeListener() + { public void propertyChange(PropertyChangeEvent evt) { - // update handler for document update. - Cache.log.debug("Updating jalview from changed vamsas document."); - client.disableGui(true); - try { - IClientDocument cdoc = vorbaclient.getClientDocument(); - client.updateJalview(cdoc); - // cdoc.setVamsasRoots(cdoc.getVamsasRoots()); - vorbaclient.updateDocument(cdoc); - cdoc=null; - } catch (Exception ee) { - System.err.println("Exception whilst updating :"); - ee.printStackTrace(System.err); - } - Cache.log.debug("Finished updating from document change."); - client.disableGui(false); + Cache.log.debug("Dealing with document update event."); + client.dealWithDocumentUpdate(false); + Cache.log.debug("finished dealing with event."); } }); + Cache.log.debug("Added Jalview handler for vamsas document updates."); + } + + private void addStoreDocumentHandler() + { + final VamsasApplication client = this; + vclient.addVorbaEventHandler( + uk.ac.vamsas.client.Events.DOCUMENT_REQUESTTOCLOSE, + new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent evt) + { + if (client.promptUser) + { + Cache.log + .debug("Asking user if the vamsas session should be stored."); + int reply = JOptionPane + .showInternalConfirmDialog( + Desktop.desktop, + "The current VAMSAS session has unsaved data - do you want to save it ?", + "VAMSAS Session Shutdown", + JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE); + + if (reply == JOptionPane.YES_OPTION) + { + Cache.log.debug("Prompting for vamsas store filename."); + Desktop.instance.vamsasSave_actionPerformed(null); + Cache.log + .debug("Finished attempt at storing document."); + } + Cache.log + .debug("finished dealing with REQUESTTOCLOSE event."); + } + else + { + Cache.log + .debug("Ignoring store document request (promptUser==false)"); + } + } + }); + Cache.log.debug("Added Jalview handler for vamsas document updates."); } + public void disableGui(boolean b) { Desktop.instance.setVamsasUpdate(b); } - private boolean joinedSession=false; + + Hashtable _backup_vobj2jv; + + IdentityHashMap _backup_jv2vobj; + + /** + * make a backup of the object mappings (vobj2jv and jv2vobj) + */ + public void backup_objectMapping() + { + _backup_vobj2jv = new Hashtable(vobj2jv); + _backup_jv2vobj = new IdentityHashMap(jv2vobj); + } + + /** + * recover original object mappings from the object mapping backup if document + * IO failed + * + * @throws Error + * if backup_objectMapping was not called. + */ + public void recover_objectMappingBackup() + { + if (_backup_vobj2jv == null) + { + if (inInitialUpdate) + { + // nothing to recover so just + return; + } + + throw new Error( + "IMPLEMENTATION ERROR: Cannot recover vamsas object mappings - no backup was made."); + } + jv2vobj.clear(); + Iterator el = _backup_jv2vobj.entrySet().iterator(); + while (el.hasNext()) + { + java.util.Map.Entry mp = (java.util.Map.Entry) el.next(); + jv2vobj.put(mp.getKey(), mp.getValue()); + } + el = _backup_vobj2jv.entrySet().iterator(); + while (el.hasNext()) + { + java.util.Map.Entry mp = (java.util.Map.Entry) el.next(); + vobj2jv.put(mp.getKey(), mp.getValue()); + } + } + + private boolean joinedSession = false; + + private VamsasListener picker = null; + + private SelectionListener selecter; + private void startSession() { if (inSession()) { - try { + try + { vclient.joinSession(); - joinedSession=true; - } - catch (Exception e) + joinedSession = true; + } catch (Exception e) { // Complain to GUI - Cache.log.error("Failed to join vamsas session.",e); - vclient=null; + Cache.log.error("Failed to join vamsas session.", e); + vclient = null; } + try + { + final IPickManager pm = vclient.getPickManager(); + final StructureSelectionManager ssm = StructureSelectionManager + .getStructureSelectionManager(); + final SelectionSource me = this; + pm.registerMessageHandler(new IMessageHandler() + { + String last = null; + + public void handleMessage(Message message) + { + if (vobj2jv == null) + { + // we are not in a session yet. + return; + } + if (message instanceof MouseOverMessage) + { + MouseOverMessage mm = (MouseOverMessage) message; + String mstring = mm.getVorbaID() + " " + mm.getPosition(); + if (last != null && mstring.equals(last)) + { + return; + } + // if (Cache.log.isDebugEnabled()) + // { + // Cache.log.debug("Received MouseOverMessage "+mm.getVorbaID()+" + // "+mm.getPosition()); + // } + Object jvobj = vobj2jv.get(mm.getVorbaID()); + if (jvobj != null && jvobj instanceof SequenceI) + { + last = mstring; + // Cache.log.debug("Handling Mouse over "+mm.getVorbaID()+" + // bound to "+jvobj+" at "+mm.getPosition()); + // position is character position in aligned sequence + ssm.mouseOverVamsasSequence((SequenceI) jvobj, mm + .getPosition()); + } + } + if (message instanceof uk.ac.vamsas.client.picking.SelectionMessage) + { + // we only care about AlignmentSequence selections + SelectionMessage sm = (SelectionMessage) message; + sm.validate(); + System.err.println("Received\n" + sm.getRawMessage()); + Object[] jvobjs = sm.getVorbaIDs() == null ? null + : new Object[sm.getVorbaIDs().length]; + if (jvobjs == null) + { + // TODO: rationalise : can only clear a selection over a + // referred to object + ssm.sendSelection(null, null, me); + return; + } + Class type = null; + boolean send = true; + for (int o = 0; o < jvobjs.length; o++) + { + jvobjs[o] = vobj2jv.get(sm.getVorbaIDs()[o]); + if (jvobjs[o] == null) + { + // can't cope with selections for unmapped objects + continue; + } + if (type == null) + { + type = jvobjs[o].getClass(); + } + ; + if (type != jvobjs[o].getClass()) + { + send = false; + // discard - can't cope with selections over mixed objects + // continue; + } + } + SequenceGroup jselection = null; + ColumnSelection colsel = null; + if (type == jalview.datamodel.Alignment.class) + { + if (jvobjs.length == 1) + { + // TODO if (sm.isNone())// send a message to select the + // specified columns over the + // given + // alignment + + send = true; + } + } + if (type == jalview.datamodel.Sequence.class) + { + + SequenceI seq; + boolean aligned = ((jalview.datamodel.Sequence) jvobjs[0]) + .getDatasetSequence() != null; + int maxWidth = 0; + if (aligned) + { + jselection = new SequenceGroup(); + jselection.addSequence( + seq = (jalview.datamodel.Sequence) jvobjs[0], + false); + maxWidth = seq.getLength(); + } + for (int c = 1; aligned && jvobjs.length > 1 + && c < jvobjs.length; c++) + { + if (((jalview.datamodel.Sequence) jvobjs[c]) + .getDatasetSequence() == null) + { + aligned = false; + continue; + } + else + { + jselection.addSequence( + seq = (jalview.datamodel.Sequence) jvobjs[c], + false); + if (maxWidth < seq.getLength()) + { + maxWidth = seq.getLength(); + } + + } + } + if (!aligned) + { + jselection = null; + // if cardinality is greater than one then verify all + // sequences are alignment sequences. + if (jvobjs.length == 1) + { + // find all instances of this dataset sequence in the + // displayed alignments containing the associated range and + // select them. + } + } + else + { + jselection.setStartRes(0); + jselection.setEndRes(maxWidth); + // locate the alignment containing the given sequences and + // select the associated ranges on them. + if (sm.getRanges() != null) + { + int[] prange = uk.ac.vamsas.objects.utils.Range + .getBounds(sm.getRanges()); + jselection.setStartRes(prange[0] - 1); + jselection.setEndRes(prange[1] - 1); + prange = uk.ac.vamsas.objects.utils.Range + .getIntervals(sm.getRanges()); + colsel = new ColumnSelection(); + for (int p = 0; p < prange.length; p += 2) + { + int d = (prange[p] <= prange[p + 1]) ? 1 : -1; + // try to join up adjacent columns to make a larger + // selection + // lower and upper bounds + int l = (d < 0) ? 1 : 0; + int u = (d > 0) ? 1 : 0; + + if (jselection.getStartRes() > 0 + && prange[p + l] == jselection.getStartRes()) + { + jselection.setStartRes(prange[p + l] - 1); + } + if (jselection.getEndRes() <= maxWidth + && prange[p + u] == (jselection.getEndRes() + 2)) + { + jselection.setEndRes(prange[p + u] - 1); + } + // mark all the columns in the range. + for (int sr = prange[p], er = prange[p + 1], de = er + + d; sr != de; sr += d) + { + colsel.addElement(sr - 1); + } + } + } + send = true; + } + } + if (send) + { + ssm.sendSelection(jselection, colsel, me); + } + // discard message. + for (int c = 0; c < jvobjs.length; c++) + { + jvobjs[c] = null; + } + ; + jvobjs = null; + return; + } + } + }); + picker = new VamsasListener() + { + SequenceI last = null; + + int i = -1; + + public void mouseOver(SequenceI seq, int index) + { + if (jv2vobj == null) + return; + if (seq != last || i != index) + { + VorbaId v = (VorbaId) jv2vobj.get(seq); + if (v != null) + { + // this should really be a trace message. + // Cache.log.debug("Mouse over " + v.getId() + " bound to " + // + seq + " at " + index); + last = seq; + i = index; + MouseOverMessage message = new MouseOverMessage(v.getId(), + index); + pm.sendMessage(message); + } + } + } + }; + selecter = new SelectionListener() + { + + public void selection(SequenceGroup seqsel, + ColumnSelection colsel, SelectionSource source) + { + if (vobj2jv == null) + { + Cache.log + .warn("Selection listener still active for dead session."); + // not in a session. + return; + } + if (source != me) + { + AlignmentI visal = null; + if (source instanceof AlignViewport) + { + visal = ((AlignViewport) source).getAlignment(); + } + SelectionMessage sm = null; + if ((seqsel == null || seqsel.getSize() == 0) + && (colsel == null || colsel.getSelected() == null || colsel + .getSelected().size() == 0)) + { + if (source instanceof AlignViewport) + { + // the empty selection. + sm = new SelectionMessage("jalview", new String[] + { ((AlignViewport) source).getSequenceSetId() }, null, + true); + } + else + { + // the empty selection. + sm = new SelectionMessage("jalview", null, null, true); + } + } + else + { + String[] vobj = new String[seqsel.getSize()]; + int o = 0; + Enumeration sels = seqsel.getSequences(null).elements(); + while (sels.hasMoreElements()) + { + SequenceI sel = (SequenceI) sels.nextElement(); + VorbaId v = (VorbaId) jv2vobj.get(sel); + if (v != null) + { + vobj[o++] = v.toString(); + } + } + if (o < vobj.length) + { + String t[] = vobj; + vobj = new String[o]; + System.arraycopy(t, 0, vobj, 0, o); + t = null; + } + Input range = null; + if (seqsel != null && colsel != null) + { + // deparse the colsel into positions on the vamsas alignment + // sequences + range = new Input(); + if (colsel.getSelected() != null + && colsel.getSelected().size() > 0 + && visal != null + && seqsel.getSize() == visal.getHeight()) + { + // gather selected columns outwith the sequence positions + // too + Enumeration cols = colsel.getSelected().elements(); + while (cols.hasMoreElements()) + { + int ival = ((Integer) cols.nextElement()).intValue(); + Pos p = new Pos(); + p.setI(ival + 1); + range.addPos(p); + } + } + else + { + int[] intervals = colsel.getVisibleContigs(seqsel + .getStartRes(), seqsel.getEndRes() + 1); + for (int iv = 0; iv < intervals.length; iv += 2) + { + Seg s = new Seg(); + s.setStart(intervals[iv] + 1); // vamsas indices begin at + // 1, not zero. + s.setEnd(intervals[iv + 1] + 1); + s.setInclusive(true); + range.addSeg(s); + } + } + } + if (vobj.length > 0) + { + sm = new SelectionMessage("jalview", vobj, range); + } + else + { + sm = null; + } + } + if (sm != null) + { + sm.validate(); // debug + Cache.log.debug("Selection Message\n" + sm.getRawMessage()); + pm.sendMessage(sm); + } + } + } + + }; + ssm.addStructureViewerListener(picker); // better method here + ssm.addSelectionListener(selecter); + } catch (Exception e) + { + Cache.log.error("Failed to init Vamsas Picking", e); + } + } + } + + public String getCurrentSession() + { + if (vclient != null) + { + return (vclient.getSessionUrn()); } + return null; } }