2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.5)
3 * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
20 import jalview.bin.Cache;
21 import jalview.datamodel.DBRefEntry;
22 import jalview.datamodel.SequenceGroup;
23 import jalview.datamodel.SequenceI;
24 import jalview.gui.AlignFrame;
25 import jalview.gui.Desktop;
26 import jalview.util.GroupUrlLink;
28 import java.awt.Component;
29 import java.awt.Cursor;
30 import java.awt.event.ActionEvent;
31 import java.awt.event.ActionListener;
32 import java.awt.event.ItemEvent;
33 import java.awt.event.ItemListener;
34 import java.io.BufferedReader;
35 import java.io.InputStreamReader;
37 import java.util.Hashtable;
38 import java.util.Vector;
40 import javax.swing.JMenu;
41 import javax.swing.JMenuItem;
42 import javax.swing.JOptionPane;
43 import javax.swing.event.MenuEvent;
44 import javax.swing.event.MenuListener;
45 import javax.xml.parsers.SAXParser;
46 import javax.xml.parsers.SAXParserFactory;
48 import org.xml.sax.Attributes;
49 import org.xml.sax.SAXException;
50 import org.xml.sax.helpers.DefaultHandler;
53 * Lightweight runnable to discover dynamic 'one way' group URL services
58 public class EnfinEnvision2OneWay extends DefaultHandler implements
59 Runnable, WSMenuEntryProviderI
61 private static EnfinEnvision2OneWay groupURLLinksGatherer = null;
63 public static EnfinEnvision2OneWay getInstance()
65 if (groupURLLinksGatherer == null)
67 groupURLLinksGatherer = new EnfinEnvision2OneWay();
69 return groupURLLinksGatherer;
72 private void waitForCompletion()
74 if (groupURLLinksGatherer.isRunning())
76 // wait around and show a visual delay indicator
77 Cursor oldCursor = Desktop.instance.getCursor();
78 Desktop.instance.setCursor(new Cursor(Cursor.WAIT_CURSOR));
79 while (groupURLLinksGatherer.isRunning())
84 } catch (InterruptedException e)
89 Desktop.instance.setCursor(oldCursor);
93 public Vector getEnvisionServiceGroupURLS()
102 private static String BACKGROUND = "BACKGROUNDPARAM";
105 * contains null strings or one of the above constants - indicate if this URL
108 private Vector additionalPar = new Vector();
111 * the enfin service URL
113 private String enfinService = null;
115 private String description = null;
117 private String wfname;
122 * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String,
123 * java.lang.String, java.lang.String)
125 public void endElement(String uri, String localName, String qName)
129 // System.err.println("End element: : '"+uri+" "+localName+" "+qName);
130 if (qName.equalsIgnoreCase("workflow") && description != null
131 && description.length() > 0)
133 // groupURLLinks.addElement("UNIPROT|EnVision2|http://www.ebi.ac.uk/enfin-srv/envision2/pages/linkin.jsf?tool=Jalview&workflow=Default&datasetName=JalviewIDs$DATASETID$&input=$SEQUENCEIDS$&inputType=0|,");
134 // groupURLLinks.addElement("Seqs|EnVision2|http://www.ebi.ac.uk/enfin-srv/envision2/pages/linkin.jsf?tool=Jalview&workflow=Default&datasetName=JalviewSeqs$DATASETID$&input=$SEQUENCES=/([A-Za-z]+)+/=$&inputType=1|,");
135 System.err.println("Adding entry for " + wfname + " " + description);
136 if (wfname.toLowerCase().indexOf("funcnet") == -1)
138 groupURLdescr.addElement(description);
139 groupURLdescr.addElement(description);
143 + "http://www.ebi.ac.uk/enfin-srv/envision2/pages/linkin.jsf?tool=Jalview&workflow="
145 + "&datasetName=JalviewSeqs$DATASETID$&input=$SEQUENCEIDS$&inputType=0|,"); // #"+description+"#");
149 + "http://www.ebi.ac.uk/enfin-srv/envision2/pages/linkin.jsf?tool=Jalview&workflow="
151 + "&datasetName=JalviewSeqs$DATASETID$&input=$SEQUENCES=/([A-Za-z]+)+/=$&inputType=1|,"); // #"+description+"#");
159 * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
161 public void characters(char[] ch, int start, int length)
164 if (description != null)
166 for (int i = start; i < start + length; i++)
168 description += ch[i];
176 * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
177 * java.lang.String, java.lang.String, org.xml.sax.Attributes)
179 public void startElement(String uri, String localName, String qName,
180 Attributes attributes) throws SAXException
182 if (qName.equalsIgnoreCase("workflow"))
185 wfname = attributes.getValue("name");
187 if (qName.equalsIgnoreCase("description"))
192 // System.err.println("Start element: : '"+uri+" "+localName+" "+qName+" attributes"+attributes);
193 // super.startElement(uri,localName,qname,attributes);
196 private boolean started = false;
198 private boolean running = false;
200 private Vector groupURLLinks = null;
202 private Vector groupURLdescr = null;
204 private static String[] allowedDb = new String[]
205 { "UNIPROT", "EMBL", "PDB" };
207 public EnfinEnvision2OneWay()
209 groupURLLinks = new Vector();
210 groupURLdescr = new Vector();
212 enfinService = Cache.getDefault("ENVISION2_WORKFLOWSERVICE",
213 "http://www.ebi.ac.uk/enfin-srv/envision2/pages/workflows.xml");
214 new Thread(this).start();
223 SAXParserFactory spf = SAXParserFactory.newInstance();
224 SAXParser sp = spf.newSAXParser();
225 sp.parse(new URL(enfinService).openStream(), this);
226 } catch (Exception e)
228 Cache.log.warn("Exception when discovering One Way services: ", e);
231 Cache.log.warn("Error when discovering One Way services: ", e);
234 Cache.log.debug("Finished running.");
238 * have we finished running yet ?
240 * @return false if we have been run.
242 public boolean isRunning()
245 // TODO Auto-generated method stub
246 return !started || running;
249 public static void main(String[] args)
252 EnfinEnvision2OneWay ow = new EnfinEnvision2OneWay();
253 while (ow.isRunning())
258 } catch (Exception e)
264 for (int i = 0; i < ow.groupURLLinks.size(); i++)
266 System.err.println("Description" + ow.groupURLdescr.elementAt(i)
267 + "Service URL: " + ow.groupURLLinks.elementAt(i));
271 // / Copied from jalview.gui.PopupMenu
273 * add a late bound URL service item to the given menu
277 * - menu label string
278 * @param urlgenerator
279 * GroupURLLink used to generate URL
281 * Object array returned from the makeUrlStubs function.
283 private void addshowLink(JMenu linkMenu, String label, String descr,
284 final GroupUrlLink urlgenerator, final Object[] urlstub)
286 Component[] jmi = linkMenu.getMenuComponents();
287 for (int i = 0; i < jmi.length; i++)
289 if (jmi[i] instanceof JMenuItem
290 && ((JMenuItem) jmi[i]).getText().equalsIgnoreCase(label))
292 // don't add this - its a repeat of an existing URL.
296 JMenuItem item = new JMenuItem(label);
297 item.setToolTipText("Submit ("
298 + urlgenerator.getNumberInvolved(urlstub)
299 + " seqs) to workflow: " + descr);
300 item.addActionListener(new java.awt.event.ActionListener()
302 public void actionPerformed(ActionEvent e)
304 new Thread(new Runnable()
309 showLink(urlgenerator.constructFrom(urlstub));
320 * open the given link in a new browser window
324 public void showLink(String url)
328 jalview.util.BrowserLauncher.openURL(url);
329 } catch (Exception ex)
332 .showInternalMessageDialog(
334 "Unixers: Couldn't find default web browser."
335 + "\nAdd the full path to your browser in Preferences.",
336 "Web browser not found", JOptionPane.WARNING_MESSAGE);
338 ex.printStackTrace();
343 * called by a web service menu instance when it is opened.
345 * @param enfinServiceMenu
348 private void buildGroupLinkMenu(JMenu enfinServiceMenu,
349 AlignFrame alignFrame)
351 SequenceI[] seqs = alignFrame.getViewport().getSelectionAsNewSequence();
352 SequenceGroup sg = alignFrame.getViewport().getSelectionGroup();
355 // consider visible regions here/
357 enfinServiceMenu.removeAll();
358 JMenu entries = buildGroupURLMenu(seqs, sg);
361 for (int i = 0, iSize = entries.getMenuComponentCount(); i < iSize; i++)
363 // transfer - menu component is removed from entries automatically
364 enfinServiceMenu.add(entries.getMenuComponent(0));
366 // entries.removeAll();
367 enfinServiceMenu.setEnabled(true);
371 enfinServiceMenu.setEnabled(false);
376 * construct a dynamic enfin services menu given a sequence selection
383 private JMenu buildGroupURLMenu(SequenceI[] seqs, SequenceGroup sg)
386 // TODO: usability: thread off the generation of group url content so root
388 // sequence only URLs
389 // ID/regex match URLs
390 JMenu groupLinksMenu = new JMenu("Group Link");
391 JMenu[] linkMenus = new JMenu[]
392 { null, new JMenu("IDS"), new JMenu("Sequences"),
393 new JMenu("IDS and Sequences") }; // three types of url that might be
395 String[][] idandseqs = GroupUrlLink.formStrings(seqs);
396 Hashtable commonDbrefs = new Hashtable();
397 for (int sq = 0; sq < seqs.length; sq++)
403 start = seqs[sq].findPosition(sg.getStartRes());
404 end = seqs[sq].findPosition(sg.getEndRes());
408 // get total width of alignment.
409 start = seqs[sq].getStart();
410 end = seqs[sq].findPosition(seqs[sq].getLength());
412 // we skip sequences which do not have any non-gaps in the region of
418 // just collect ids from dataset sequence
419 // TODO: check if IDs collected from selecton group intersects with the
420 // current selection, too
421 SequenceI sqi = seqs[sq];
422 while (sqi.getDatasetSequence() != null)
424 sqi = sqi.getDatasetSequence();
426 DBRefEntry[] dbr = sqi.getDBRef();
427 if (dbr != null && dbr.length > 0)
429 for (int d = 0; d < dbr.length; d++)
431 String src = dbr[d].getSource(); // jalview.util.DBRefUtils.getCanonicalName(dbr[d].getSource()).toUpperCase();
432 Object[] sarray = (Object[]) commonDbrefs.get(src);
435 sarray = new Object[2];
436 sarray[0] = new int[]
438 sarray[1] = new String[seqs.length];
440 commonDbrefs.put(src, sarray);
443 if (((String[]) sarray[1])[sq] == null)
446 || (dbr[d].getMap().locateMappedRange(start, end) != null))
448 ((String[]) sarray[1])[sq] = dbr[d].getAccessionId();
449 ((int[]) sarray[0])[0]++;
455 // now create group links for all distinct ID/sequence sets.
456 boolean addMenu = false; // indicates if there are any group links to give
458 for (int i = 0; i < groupURLLinks.size(); i++)
460 String link = groupURLLinks.elementAt(i).toString();
461 String descr = groupURLdescr.elementAt(i).toString();
462 // boolean specialCase =
463 // additionalPar.elementAt(i).toString().equals(BACKGROUND);
464 GroupUrlLink urlLink = null;
467 urlLink = new GroupUrlLink(link);
468 } catch (Exception foo)
470 jalview.bin.Cache.log.error("Exception for GroupURLLink '" + link
475 if (!urlLink.isValid())
477 jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
480 final String label = urlLink.getLabel();
481 boolean usingNames = false;
482 // Now see which parts of the group apply for this URL
484 String[] seqstr, ids; // input to makeUrl
485 for (int t = 0; t < allowedDb.length; t++)
487 ltarget = allowedDb[t]; // jalview.util.DBRefUtils.getCanonicalName(urlLink.getTarget());
488 Object[] idset = (Object[]) commonDbrefs.get(ltarget.toUpperCase());
491 int numinput = ((int[]) idset[0])[0];
492 String[] allids = ((String[]) idset[1]);
493 seqstr = new String[numinput];
494 ids = new String[numinput];
495 for (int sq = 0, idcount = 0; sq < seqs.length; sq++)
497 if (allids[sq] != null)
499 ids[idcount] = allids[sq];
500 seqstr[idcount++] = idandseqs[1][sq];
504 | createAndAddLinks(linkMenus, false, urlLink, label,
505 ltarget, descr, ids, seqstr);
508 // also do names only.
509 seqstr = idandseqs[1];
512 | createAndAddLinks(linkMenus, true, urlLink, label, "Names",
517 groupLinksMenu = new JMenu("Group Links");
518 for (int m = 0; m < linkMenus.length; m++)
520 if (linkMenus[m] != null
521 && linkMenus[m].getMenuComponentCount() > 0)
523 groupLinksMenu.add(linkMenus[m]);
527 return groupLinksMenu;
532 private boolean createAndAddLinks(JMenu[] linkMenus, boolean usingNames,
533 GroupUrlLink urlLink, String label, String ltarget, String descr,
534 String[] ids, String[] seqstr)
536 Object[] urlset = urlLink.makeUrlStubs(ids, seqstr, "FromJalview"
537 + System.currentTimeMillis(), false);
540 int type = urlLink.getGroupURLType() & 3;
541 // System.out.println(urlLink.getGroupURLType()
542 // +" "+((String[])urlset[3])[0]);
543 // first two bits ofurlLink type bitfield are sequenceids and sequences
544 // TODO: FUTURE: ensure the groupURL menu structure can be generalised
545 addshowLink(linkMenus[type], label
547 + (usingNames ? (((type & 1) == 1) ? "(Names)" : "") : ("("
548 + ltarget + ")")), descr, urlLink, urlset);
554 // / end of stuff copied from popupmenu
555 public void attachWSMenuEntry(final JMenu wsmenu,
556 final AlignFrame alignFrame)
558 final JMenu enfinServiceMenu = new JMenu("Envision 2");
559 wsmenu.add(enfinServiceMenu);
560 enfinServiceMenu.setEnabled(false);
561 wsmenu.addMenuListener(new MenuListener()
563 // this listener remembers when the menu was first selected, and
564 // doesn't rebuild the session list until it has been cleared and
566 boolean refresh = true;
568 public void menuCanceled(MenuEvent e)
573 public void menuDeselected(MenuEvent e)
578 public void menuSelected(MenuEvent e)
584 buildGroupLinkMenu(enfinServiceMenu, alignFrame);
585 } catch (OutOfMemoryError ex)
588 "Out of memory when calculating the Envision2 links.",
590 enfinServiceMenu.setEnabled(false);