2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
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
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import static jalview.util.UrlConstants.DB_ACCESSION;
24 import static jalview.util.UrlConstants.SEQUENCE_ID;
25 import static org.testng.AssertJUnit.assertEquals;
26 import static org.testng.AssertJUnit.assertFalse;
27 import static org.testng.AssertJUnit.assertTrue;
29 import jalview.datamodel.AlignmentAnnotation;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.Annotation;
32 import jalview.datamodel.DBRefEntry;
33 import jalview.datamodel.DBRefSource;
34 import jalview.datamodel.Sequence;
35 import jalview.datamodel.SequenceI;
36 import jalview.io.DataSourceType;
37 import jalview.io.FileFormat;
38 import jalview.io.FormatAdapter;
39 import jalview.util.MessageManager;
41 import java.awt.Component;
42 import java.io.IOException;
43 import java.util.ArrayList;
44 import java.util.List;
46 import javax.swing.JMenu;
47 import javax.swing.JMenuItem;
48 import javax.swing.JPopupMenu;
49 import javax.swing.JSeparator;
51 import org.testng.annotations.BeforeMethod;
52 import org.testng.annotations.Test;
54 public class PopupMenuTest
56 // 4 sequences x 13 positions
57 final static String TEST_DATA = ">FER_CAPAA Ferredoxin\n"
59 + ">FER_CAPAN Ferredoxin, chloroplast precursor\n"
61 + ">FER1_SOLLC Ferredoxin-1, chloroplast precursor\n"
62 + "TIETHKEEELTA-\n" + ">Q93XJ9_SOLTU Ferredoxin I precursor\n"
67 AlignmentPanel parentPanel;
69 PopupMenu testee = null;
71 @BeforeMethod(alwaysRun = true)
72 public void setUp() throws IOException
74 alignment = new FormatAdapter().readFile(TEST_DATA,
75 DataSourceType.PASTE, FileFormat.Fasta);
76 AlignFrame af = new AlignFrame(alignment, 700, 500);
77 parentPanel = new AlignmentPanel(af, af.getViewport());
78 testee = new PopupMenu(parentPanel, null, null);
80 for (SequenceI seq : alignment.getSequences())
82 final AlignmentAnnotation annotation = new AlignmentAnnotation(
83 "label" + i, "desc" + i, i);
84 annotation.setCalcId("calcId" + i);
85 seq.addAlignmentAnnotation(annotation);
86 annotation.setSequenceRef(seq);
90 @Test(groups = { "Functional" })
91 public void testConfigureReferenceAnnotationsMenu_noSequenceSelected()
93 JMenuItem menu = new JMenuItem();
94 List<SequenceI> seqs = new ArrayList<SequenceI>();
95 testee.configureReferenceAnnotationsMenu(menu, seqs);
96 assertFalse(menu.isEnabled());
98 menu.setEnabled(true);
99 testee.configureReferenceAnnotationsMenu(menu, null);
100 assertFalse(menu.isEnabled());
104 * Test building the 'add reference annotations' menu for the case where there
105 * are no reference annotations to add to the alignment. The menu item should
108 @Test(groups = { "Functional" })
109 public void testConfigureReferenceAnnotationsMenu_noReferenceAnnotations()
111 JMenuItem menu = new JMenuItem();
114 * Initial state is that sequences have annotations, and have dataset
115 * sequences, but the dataset sequences have no annotations. Hence nothing
118 List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
120 testee.configureReferenceAnnotationsMenu(menu, seqs);
121 assertFalse(menu.isEnabled());
125 * Test building the 'add reference annotations' menu for the case where all
126 * reference annotations are already on the alignment. The menu item should be
129 @Test(groups = { "Functional" })
130 public void testConfigureReferenceAnnotationsMenu_alreadyAdded()
132 JMenuItem menu = new JMenuItem();
133 List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
135 // make up new annotations and add to dataset sequences, sequences and
137 attachReferenceAnnotations(seqs, true, true);
139 testee.configureReferenceAnnotationsMenu(menu, seqs);
140 assertFalse(menu.isEnabled());
144 * Test building the 'add reference annotations' menu for the case where
145 * several reference annotations are on the dataset but not on the sequences.
146 * The menu item should be enabled, and acquire a tooltip which lists the
147 * annotation sources (calcIds) and type (labels).
149 @Test(groups = { "Functional" })
150 public void testConfigureReferenceAnnotationsMenu()
152 JMenuItem menu = new JMenuItem();
153 List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
155 // make up new annotations and add to dataset sequences
156 attachReferenceAnnotations(seqs, false, false);
158 testee.configureReferenceAnnotationsMenu(menu, seqs);
159 assertTrue(menu.isEnabled());
160 String s = MessageManager.getString("label.add_annotations_for");
161 String expected = "<html><style> p.ttip {width: 350; text-align: justify; word-wrap: break-word;}</style><p class=\"ttip\">"
162 + s + "<br/>Jmol/secondary structure<br/>PDB/Temp</p></html>";
163 assertEquals(expected, menu.getToolTipText());
167 * Test building the 'add reference annotations' menu for the case where
168 * several reference annotations are on the dataset and the sequences but not
169 * on the alignment. The menu item should be enabled, and acquire a tooltip
170 * which lists the annotation sources (calcIds) and type (labels).
172 @Test(groups = { "Functional" })
173 public void testConfigureReferenceAnnotationsMenu_notOnAlignment()
175 JMenuItem menu = new JMenuItem();
176 List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
178 // make up new annotations and add to dataset sequences and sequences
179 attachReferenceAnnotations(seqs, true, false);
181 testee.configureReferenceAnnotationsMenu(menu, seqs);
182 assertTrue(menu.isEnabled());
183 String s = MessageManager.getString("label.add_annotations_for");
184 String expected = "<html><style> p.ttip {width: 350; text-align: justify; word-wrap: break-word;}</style><p class=\"ttip\">"
185 + s + "<br/>Jmol/secondary structure<br/>PDB/Temp</p></html>";
186 assertEquals(expected, menu.getToolTipText());
190 * Generate annotations and add to dataset sequences and (optionally)
191 * sequences and/or alignment
194 * @param addToSequence
195 * @param addToAlignment
197 private void attachReferenceAnnotations(List<SequenceI> seqs,
198 boolean addToSequence, boolean addToAlignment)
200 // PDB.secondary structure on Sequence0
201 AlignmentAnnotation annotation = new AlignmentAnnotation(
202 "secondary structure", "", 0);
203 annotation.setCalcId("PDB");
204 seqs.get(0).getDatasetSequence().addAlignmentAnnotation(annotation);
207 seqs.get(0).addAlignmentAnnotation(annotation);
211 this.alignment.addAnnotation(annotation);
214 // PDB.Temp on Sequence1
215 annotation = new AlignmentAnnotation("Temp", "", 0);
216 annotation.setCalcId("PDB");
217 seqs.get(1).getDatasetSequence().addAlignmentAnnotation(annotation);
220 seqs.get(1).addAlignmentAnnotation(annotation);
224 this.alignment.addAnnotation(annotation);
227 // JMOL.secondary structure on Sequence0
228 annotation = new AlignmentAnnotation("secondary structure", "", 0);
229 annotation.setCalcId("Jmol");
230 seqs.get(0).getDatasetSequence().addAlignmentAnnotation(annotation);
233 seqs.get(0).addAlignmentAnnotation(annotation);
237 this.alignment.addAnnotation(annotation);
242 * Test building the 'add reference annotations' menu for the case where there
243 * are two alignment views:
245 * <li>in one view, reference annotations have been added (are on the
246 * datasets, sequences and alignment)</li>
247 * <li>in the current view, reference annotations are on the dataset and
248 * sequence, but not the alignment</li>
250 * The menu item should be enabled, and acquire a tooltip which lists the
251 * annotation sources (calcIds) and type (labels).
253 @Test(groups = { "Functional" })
254 public void testConfigureReferenceAnnotationsMenu_twoViews()
259 * Test for building menu options including 'show' and 'hide' annotation
262 @Test(groups = { "Functional" })
263 public void testBuildAnnotationTypesMenus()
265 JMenu showMenu = new JMenu();
266 JMenu hideMenu = new JMenu();
267 List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
269 // make up new annotations and add to sequences and to the alignment
271 // PDB.secondary structure on Sequence0
272 AlignmentAnnotation annotation = new AlignmentAnnotation(
273 "secondary structure", "", new Annotation[] {});
274 annotation.setCalcId("PDB");
275 annotation.visible = true;
276 seqs.get(0).addAlignmentAnnotation(annotation);
277 parentPanel.getAlignment().addAnnotation(annotation);
279 // JMOL.secondary structure on Sequence0 - hidden
280 annotation = new AlignmentAnnotation("secondary structure", "",
281 new Annotation[] {});
282 annotation.setCalcId("JMOL");
283 annotation.visible = false;
284 seqs.get(0).addAlignmentAnnotation(annotation);
285 parentPanel.getAlignment().addAnnotation(annotation);
287 // Jpred.SSP on Sequence0 - hidden
288 annotation = new AlignmentAnnotation("SSP", "", new Annotation[] {});
289 annotation.setCalcId("JPred");
290 annotation.visible = false;
291 seqs.get(0).addAlignmentAnnotation(annotation);
292 parentPanel.getAlignment().addAnnotation(annotation);
294 // PDB.Temp on Sequence1
295 annotation = new AlignmentAnnotation("Temp", "", new Annotation[] {});
296 annotation.setCalcId("PDB");
297 annotation.visible = true;
298 seqs.get(1).addAlignmentAnnotation(annotation);
299 parentPanel.getAlignment().addAnnotation(annotation);
302 * Expect menu options to show "secondary structure" and "SSP", and to hide
303 * "secondary structure" and "Temp". Tooltip should be calcId.
305 testee.buildAnnotationTypesMenus(showMenu, hideMenu, seqs);
307 assertTrue(showMenu.isEnabled());
308 assertTrue(hideMenu.isEnabled());
310 Component[] showOptions = showMenu.getMenuComponents();
311 Component[] hideOptions = hideMenu.getMenuComponents();
313 assertEquals(4, showOptions.length); // includes 'All' and separator
314 assertEquals(4, hideOptions.length);
315 assertEquals("All", ((JMenuItem) showOptions[0]).getText());
316 assertTrue(showOptions[1] instanceof JPopupMenu.Separator);
317 assertEquals(JSeparator.HORIZONTAL,
318 ((JSeparator) showOptions[1]).getOrientation());
319 assertEquals("secondary structure",
320 ((JMenuItem) showOptions[2]).getText());
321 assertEquals("JMOL", ((JMenuItem) showOptions[2]).getToolTipText());
322 assertEquals("SSP", ((JMenuItem) showOptions[3]).getText());
323 assertEquals("JPred", ((JMenuItem) showOptions[3]).getToolTipText());
325 assertEquals("All", ((JMenuItem) hideOptions[0]).getText());
326 assertTrue(hideOptions[1] instanceof JPopupMenu.Separator);
327 assertEquals(JSeparator.HORIZONTAL,
328 ((JSeparator) hideOptions[1]).getOrientation());
329 assertEquals("secondary structure",
330 ((JMenuItem) hideOptions[2]).getText());
331 assertEquals("PDB", ((JMenuItem) hideOptions[2]).getToolTipText());
332 assertEquals("Temp", ((JMenuItem) hideOptions[3]).getText());
333 assertEquals("PDB", ((JMenuItem) hideOptions[3]).getToolTipText());
337 * Test for building menu options with only 'hide' annotation types enabled.
339 @Test(groups = { "Functional" })
340 public void testBuildAnnotationTypesMenus_showDisabled()
342 JMenu showMenu = new JMenu();
343 JMenu hideMenu = new JMenu();
344 List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
346 // make up new annotations and add to sequences and to the alignment
348 // PDB.secondary structure on Sequence0
349 AlignmentAnnotation annotation = new AlignmentAnnotation(
350 "secondary structure", "", new Annotation[] {});
351 annotation.setCalcId("PDB");
352 annotation.visible = true;
353 seqs.get(0).addAlignmentAnnotation(annotation);
354 parentPanel.getAlignment().addAnnotation(annotation);
356 // PDB.Temp on Sequence1
357 annotation = new AlignmentAnnotation("Temp", "", new Annotation[] {});
358 annotation.setCalcId("PDB");
359 annotation.visible = true;
360 seqs.get(1).addAlignmentAnnotation(annotation);
361 parentPanel.getAlignment().addAnnotation(annotation);
364 * Expect menu options to hide "secondary structure" and "Temp". Tooltip
365 * should be calcId. 'Show' menu should be disabled.
367 testee.buildAnnotationTypesMenus(showMenu, hideMenu, seqs);
369 assertFalse(showMenu.isEnabled());
370 assertTrue(hideMenu.isEnabled());
372 Component[] showOptions = showMenu.getMenuComponents();
373 Component[] hideOptions = hideMenu.getMenuComponents();
375 assertEquals(2, showOptions.length); // includes 'All' and separator
376 assertEquals(4, hideOptions.length);
377 assertEquals("All", ((JMenuItem) showOptions[0]).getText());
378 assertTrue(showOptions[1] instanceof JPopupMenu.Separator);
379 assertEquals(JSeparator.HORIZONTAL,
380 ((JSeparator) showOptions[1]).getOrientation());
382 assertEquals("All", ((JMenuItem) hideOptions[0]).getText());
383 assertTrue(hideOptions[1] instanceof JPopupMenu.Separator);
384 assertEquals(JSeparator.HORIZONTAL,
385 ((JSeparator) hideOptions[1]).getOrientation());
386 assertEquals("secondary structure",
387 ((JMenuItem) hideOptions[2]).getText());
388 assertEquals("PDB", ((JMenuItem) hideOptions[2]).getToolTipText());
389 assertEquals("Temp", ((JMenuItem) hideOptions[3]).getText());
390 assertEquals("PDB", ((JMenuItem) hideOptions[3]).getToolTipText());
394 * Test for building menu options with only 'show' annotation types enabled.
396 @Test(groups = { "Functional" })
397 public void testBuildAnnotationTypesMenus_hideDisabled()
399 JMenu showMenu = new JMenu();
400 JMenu hideMenu = new JMenu();
401 List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
403 // make up new annotations and add to sequences and to the alignment
405 // PDB.secondary structure on Sequence0
406 AlignmentAnnotation annotation = new AlignmentAnnotation(
407 "secondary structure", "", new Annotation[] {});
408 annotation.setCalcId("PDB");
409 annotation.visible = false;
410 seqs.get(0).addAlignmentAnnotation(annotation);
411 parentPanel.getAlignment().addAnnotation(annotation);
413 // PDB.Temp on Sequence1
414 annotation = new AlignmentAnnotation("Temp", "", new Annotation[] {});
415 annotation.setCalcId("PDB2");
416 annotation.visible = false;
417 seqs.get(1).addAlignmentAnnotation(annotation);
418 parentPanel.getAlignment().addAnnotation(annotation);
421 * Expect menu options to show "secondary structure" and "Temp". Tooltip
422 * should be calcId. 'hide' menu should be disabled.
424 testee.buildAnnotationTypesMenus(showMenu, hideMenu, seqs);
426 assertTrue(showMenu.isEnabled());
427 assertFalse(hideMenu.isEnabled());
429 Component[] showOptions = showMenu.getMenuComponents();
430 Component[] hideOptions = hideMenu.getMenuComponents();
432 assertEquals(4, showOptions.length); // includes 'All' and separator
433 assertEquals(2, hideOptions.length);
434 assertEquals("All", ((JMenuItem) showOptions[0]).getText());
435 assertTrue(showOptions[1] instanceof JPopupMenu.Separator);
436 assertEquals(JSeparator.HORIZONTAL,
437 ((JSeparator) showOptions[1]).getOrientation());
438 assertEquals("secondary structure",
439 ((JMenuItem) showOptions[2]).getText());
440 assertEquals("PDB", ((JMenuItem) showOptions[2]).getToolTipText());
441 assertEquals("Temp", ((JMenuItem) showOptions[3]).getText());
442 assertEquals("PDB2", ((JMenuItem) showOptions[3]).getToolTipText());
444 assertEquals("All", ((JMenuItem) hideOptions[0]).getText());
445 assertTrue(hideOptions[1] instanceof JPopupMenu.Separator);
446 assertEquals(JSeparator.HORIZONTAL,
447 ((JSeparator) hideOptions[1]).getOrientation());
451 * Test for adding feature links
453 @Test(groups = { "Functional" })
454 public void testAddFeatureLinks()
456 // sequences from the alignment
457 List<SequenceI> seqs = parentPanel.getAlignment().getSequences();
459 // create list of links and list of DBRefs
460 List<String> links = new ArrayList<String>();
461 List<DBRefEntry> refs = new ArrayList<DBRefEntry>();
463 // links as might be added into Preferences | Connections dialog
464 links.add("EMBL-EBI Search | http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$"
465 + SEQUENCE_ID + "$");
466 links.add("UNIPROT | http://www.uniprot.org/uniprot/$" + DB_ACCESSION
468 links.add("INTERPRO | http://www.ebi.ac.uk/interpro/entry/$"
469 + DB_ACCESSION + "$");
470 // Gene3D entry tests for case (in)sensitivity
471 links.add("Gene3D | http://gene3d.biochem.ucl.ac.uk/Gene3D/search?sterm=$"
472 + DB_ACCESSION + "$&mode=protein");
475 refs.add(new DBRefEntry(DBRefSource.UNIPROT, "1", "P83527"));
476 refs.add(new DBRefEntry("INTERPRO", "1", "IPR001041"));
477 refs.add(new DBRefEntry("INTERPRO", "1", "IPR006058"));
478 refs.add(new DBRefEntry("INTERPRO", "1", "IPR012675"));
481 refs.add(new DBRefEntry(DBRefSource.UNIPROT, "1", "Q9ZTS2"));
482 refs.add(new DBRefEntry("GENE3D", "1", "3.10.20.30"));
484 // add all the dbrefs to the sequences: Uniprot 1 each, Interpro all 3 to
485 // seq0, Gene3D to seq1
486 seqs.get(0).addDBRef(refs.get(0));
488 seqs.get(0).addDBRef(refs.get(1));
489 seqs.get(0).addDBRef(refs.get(2));
490 seqs.get(0).addDBRef(refs.get(3));
492 seqs.get(1).addDBRef(refs.get(4));
493 seqs.get(1).addDBRef(refs.get(5));
495 // get the Popup Menu for first sequence
496 testee = new PopupMenu(parentPanel, (Sequence) seqs.get(0), links);
497 Component[] seqItems = testee.sequenceMenu.getMenuComponents();
498 JMenu linkMenu = (JMenu) seqItems[6];
499 Component[] linkItems = linkMenu.getMenuComponents();
501 // check the number of links are the expected number
502 assertEquals(5, linkItems.length);
504 // first entry is EMBL-EBI which just uses sequence id not accession id?
505 assertEquals("EMBL-EBI Search", ((JMenuItem) linkItems[0]).getText());
507 // sequence id for each link should match corresponding DB accession id
508 for (int i = 1; i < 4; i++)
510 assertEquals(refs.get(i - 1).getSource(), ((JMenuItem) linkItems[i])
511 .getText().split("\\|")[0]);
512 assertEquals(refs.get(i - 1).getAccessionId(),
513 ((JMenuItem) linkItems[i])
514 .getText().split("\\|")[1]);
517 // get the Popup Menu for second sequence
518 testee = new PopupMenu(parentPanel, (Sequence) seqs.get(1), links);
519 seqItems = testee.sequenceMenu.getMenuComponents();
520 linkMenu = (JMenu) seqItems[6];
521 linkItems = linkMenu.getMenuComponents();
523 // check the number of links are the expected number
524 assertEquals(3, linkItems.length);
526 // first entry is EMBL-EBI which just uses sequence id not accession id?
527 assertEquals("EMBL-EBI Search", ((JMenuItem) linkItems[0]).getText());
529 // sequence id for each link should match corresponding DB accession id
530 for (int i = 1; i < 3; i++)
532 assertEquals(refs.get(i + 3).getSource(), ((JMenuItem) linkItems[i])
533 .getText().split("\\|")[0].toUpperCase());
534 assertEquals(refs.get(i + 3).getAccessionId(),
535 ((JMenuItem) linkItems[i]).getText().split("\\|")[1]);
538 // if there are no valid links the Links submenu is disabled
539 List<String> nomatchlinks = new ArrayList<String>();
540 nomatchlinks.add("NOMATCH | http://www.uniprot.org/uniprot/$"
541 + DB_ACCESSION + "$");
543 testee = new PopupMenu(parentPanel, (Sequence) seqs.get(0),
545 seqItems = testee.sequenceMenu.getMenuComponents();
546 linkMenu = (JMenu) seqItems[6];
547 assertFalse(linkMenu.isEnabled());