JAL-2933 gui and applet Finder hold a FinderI per viewport
[jalview.git] / test / jalview / analysis / FinderTest.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
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.
11  *  
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.
16  * 
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.
20  */
21 package jalview.analysis;
22
23 import static org.testng.Assert.assertEquals;
24 import static org.testng.Assert.assertSame;
25 import static org.testng.Assert.assertTrue;
26
27 import jalview.api.FinderI;
28 import jalview.bin.Cache;
29 import jalview.datamodel.Alignment;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.ColumnSelection;
32 import jalview.datamodel.HiddenColumns;
33 import jalview.datamodel.SearchResultMatchI;
34 import jalview.datamodel.SearchResultsI;
35 import jalview.datamodel.Sequence;
36 import jalview.datamodel.SequenceGroup;
37 import jalview.gui.AlignFrame;
38 import jalview.gui.JvOptionPane;
39 import jalview.io.DataSourceType;
40 import jalview.io.FileLoader;
41
42 import java.util.List;
43
44 import org.testng.annotations.BeforeClass;
45 import org.testng.annotations.Test;
46
47 import junit.extensions.PA;
48
49 public class FinderTest
50 {
51   @BeforeClass(alwaysRun = true)
52   public void setUpJvOptionPane()
53   {
54     JvOptionPane.setInteractiveMode(false);
55     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
56   }
57
58   private AlignFrame af;
59
60   private AlignmentI al;
61
62   @BeforeClass(groups = "Functional")
63   public void setUp()
64   {
65     Cache.loadProperties("test/jalview/io/testProps.jvprops");
66     Cache.applicationProperties.setProperty("PAD_GAPS",
67             Boolean.FALSE.toString());
68
69     String seqData = "seq1seq1/8-18 ABCD--EF-GHIJI\n" + "seq2 A--BCDefHI\n"
70             + "seq3 --bcdEFH\n" + "seq4 aa---aMMMMMaaa\n";
71     af = new FileLoader().LoadFileWaitTillLoaded(seqData,
72             DataSourceType.PASTE);
73     al = af.getViewport().getAlignment();
74   }
75
76   /**
77    * Test for find matches of a regular expression
78    */
79   @Test(groups = "Functional")
80   public void testFind_regex()
81   {
82     /*
83      * find next match only
84      */
85     Finder f = new Finder(al);
86     f.findNext("E.H", null, false, false); // 'E, any character, H'
87     // should match seq2 efH only
88     SearchResultsI sr = f.getSearchResults();
89     assertEquals(sr.getSize(), 1);
90     List<SearchResultMatchI> matches = sr.getResults();
91     assertSame(matches.get(0).getSequence(), al.getSequenceAt(1));
92     assertEquals(matches.get(0).getStart(), 5);
93     assertEquals(matches.get(0).getEnd(), 7);
94
95     f = new Finder(al);
96     f.findAll("E.H", null, false, false); // 'E, any character, H'
97     // should match seq2 efH and seq3 EFH
98     sr = f.getSearchResults();
99     assertEquals(sr.getSize(), 2);
100     matches = sr.getResults();
101     assertSame(matches.get(0).getSequence(), al.getSequenceAt(1));
102     assertSame(matches.get(1).getSequence(), al.getSequenceAt(2));
103     assertEquals(matches.get(0).getStart(), 5);
104     assertEquals(matches.get(0).getEnd(), 7);
105     assertEquals(matches.get(1).getStart(), 4);
106     assertEquals(matches.get(1).getEnd(), 6);
107   }
108
109   /**
110    * Test for (undocumented) find residue by position
111    */
112   @Test(groups = "Functional")
113   public void testFind_residueNumber()
114   {
115     Finder f = new Finder(al);
116
117     /*
118      * find first match should return seq1 residue 9
119      */
120     f.findNext("9", null, false, false);
121     SearchResultsI sr = f.getSearchResults();
122     assertEquals(sr.getSize(), 1);
123     List<SearchResultMatchI> matches = sr.getResults();
124     assertSame(matches.get(0).getSequence(), al.getSequenceAt(0));
125     assertEquals(matches.get(0).getStart(), 9);
126     assertEquals(matches.get(0).getEnd(), 9);
127
128     /*
129      * find all matches should return seq1 and seq4 (others are too short)
130      */
131     f = new Finder(al);
132     f.findAll("9", null, false, false);
133     sr = f.getSearchResults();
134     assertEquals(sr.getSize(), 2);
135     matches = sr.getResults();
136     assertSame(matches.get(0).getSequence(), al.getSequenceAt(0));
137     assertSame(matches.get(1).getSequence(), al.getSequenceAt(3));
138     assertEquals(matches.get(0).getStart(), 9);
139     assertEquals(matches.get(0).getEnd(), 9);
140     assertEquals(matches.get(1).getStart(), 9);
141     assertEquals(matches.get(1).getEnd(), 9);
142
143     /*
144      * parsing of search string as integer is strict
145      */
146     f = new Finder(al);
147     f.findNext(" 9", null, false, false);
148     assertTrue(f.getSearchResults().isEmpty());
149   }
150
151   /**
152    * Test for find next action
153    */
154   @Test(groups = "Functional")
155   public void testFindNext()
156   {
157     /*
158      * start at second sequence; colIndex of -1
159      * means sequence id / description is searched
160      */
161     Finder f = new Finder(al);
162     PA.setValue(f, "sequenceIndex", 1);
163     PA.setValue(f, "columnIndex", -1);
164     f.findNext("e", null, false, false); // matches id
165
166     assertTrue(f.getSearchResults().isEmpty());
167     assertEquals(f.getIdMatches().size(), 1);
168     assertSame(f.getIdMatches().get(0), al.getSequenceAt(1));
169
170     // colIndex is now 0 - for use in next find next
171     // searching A--BCDefHI
172     assertEquals(PA.getValue(f, "columnIndex"), 0);
173     f = new Finder(al);
174     PA.setValue(f, "sequenceIndex", 1);
175     PA.setValue(f, "columnIndex", 0);
176     f.findNext("e", null, false, false); // matches in sequence
177     assertTrue(f.getIdMatches().isEmpty());
178     assertEquals(f.getSearchResults().getSize(), 1);
179     List<SearchResultMatchI> matches = f.getSearchResults().getResults();
180     assertEquals(matches.get(0).getStart(), 5);
181     assertEquals(matches.get(0).getEnd(), 5);
182     assertSame(matches.get(0).getSequence(), al.getSequenceAt(1));
183     // still in the second sequence
184     assertEquals(PA.getValue(f, "sequenceIndex"), 1);
185     // next column position to search from is 7
186     assertEquals(PA.getValue(f, "columnIndex"), 7);
187
188     // find next from end of sequence - finds next sequence id
189     f = new Finder(al);
190     PA.setValue(f, "sequenceIndex", 1);
191     PA.setValue(f, "columnIndex", 7);
192     f.findNext("e", null, false, false);
193     assertEquals(f.getIdMatches().size(), 1);
194     assertSame(f.getIdMatches().get(0), al.getSequenceAt(2));
195     assertTrue(f.getSearchResults().isEmpty());
196   }
197
198   /**
199    * Test for matching within sequence descriptions
200    */
201   @Test(groups = "Functional")
202   public void testFind_inDescription()
203   {
204     AlignmentI al2 = new Alignment(al);
205     al2.getSequenceAt(0).setDescription("BRAF");
206     al2.getSequenceAt(1).setDescription("braf");
207
208     /*
209      * find first match only
210      */
211     Finder f = new Finder(al2);
212     f.findNext("rAF", null, false, true);
213     assertEquals(f.getIdMatches().size(), 1);
214     assertSame(f.getIdMatches().get(0), al2.getSequenceAt(0));
215     assertTrue(f.getSearchResults().isEmpty());
216
217     /*
218      * find all matches
219      */
220     f = new Finder(al2);
221     f.findAll("rAF", null, false, true);
222     assertEquals(f.getIdMatches().size(), 2);
223     assertSame(f.getIdMatches().get(0), al2.getSequenceAt(0));
224     assertSame(f.getIdMatches().get(1), al2.getSequenceAt(1));
225     assertTrue(f.getSearchResults().isEmpty());
226
227     /*
228      * case sensitive
229      */
230     f = new Finder(al2);
231     f.findAll("RAF", null, true, true);
232     assertEquals(f.getIdMatches().size(), 1);
233     assertSame(f.getIdMatches().get(0), al2.getSequenceAt(0));
234     assertTrue(f.getSearchResults().isEmpty());
235
236     /*
237      * match sequence id, description and sequence!
238      */
239     al2.getSequenceAt(0).setDescription("the efh sequence");
240     al2.getSequenceAt(0).setName("mouseEFHkinase");
241     al2.getSequenceAt(1).setName("humanEFHkinase");
242     f = new Finder(al2);
243
244     /*
245      * sequence matches should have no duplicates
246      */
247     f.findAll("EFH", null, false, true);
248     assertEquals(f.getIdMatches().size(), 2);
249     assertSame(f.getIdMatches().get(0), al2.getSequenceAt(0));
250     assertSame(f.getIdMatches().get(1), al2.getSequenceAt(1));
251
252     assertEquals(f.getSearchResults().getSize(), 2);
253     SearchResultMatchI match = f.getSearchResults().getResults().get(0);
254     assertSame(match.getSequence(), al2.getSequenceAt(1));
255     assertEquals(match.getStart(), 5);
256     assertEquals(match.getEnd(), 7);
257     match = f.getSearchResults().getResults().get(1);
258     assertSame(match.getSequence(), al2.getSequenceAt(2));
259     assertEquals(match.getStart(), 4);
260     assertEquals(match.getEnd(), 6);
261   }
262
263   /**
264    * Test for matching within sequence ids
265    */
266   @Test(groups = "Functional")
267   public void testFindAll_sequenceIds()
268   {
269     Finder f = new Finder(al);
270
271     /*
272      * case insensitive; seq1 occurs twice in sequence id but
273      * only one match should be returned
274      */
275     f.findAll("SEQ1", null, false, false);
276     assertEquals(f.getIdMatches().size(), 1);
277     assertSame(f.getIdMatches().get(0), al.getSequenceAt(0));
278     SearchResultsI searchResults = f.getSearchResults();
279     assertTrue(searchResults.isEmpty());
280
281     /*
282      * case sensitive
283      */
284     f = new Finder(al);
285     f.findAll("SEQ1", null, true, false);
286     searchResults = f.getSearchResults();
287     assertTrue(searchResults.isEmpty());
288
289     /*
290      * match both sequence id and sequence
291      */
292     AlignmentI al2 = new Alignment(al);
293     al2.addSequence(new Sequence("aBz", "xyzabZpqrAbZ"));
294     f = new Finder(al2);
295     f.findAll("ABZ", null, false, false);
296     assertEquals(f.getIdMatches().size(), 1);
297     assertSame(f.getIdMatches().get(0), al2.getSequenceAt(4));
298     searchResults = f.getSearchResults();
299     assertEquals(searchResults.getSize(), 2);
300     SearchResultMatchI match = searchResults.getResults().get(0);
301     assertSame(match.getSequence(), al2.getSequenceAt(4));
302     assertEquals(match.getStart(), 4);
303     assertEquals(match.getEnd(), 6);
304     match = searchResults.getResults().get(1);
305     assertSame(match.getSequence(), al2.getSequenceAt(4));
306     assertEquals(match.getStart(), 10);
307     assertEquals(match.getEnd(), 12);
308   }
309
310   /**
311    * Test finding next match of a sequence pattern in an alignment
312    */
313   @Test(groups = "Functional")
314   public void testFind_findNext()
315   {
316     /*
317      * efh should be matched in seq2 only
318      */
319     FinderI f = new Finder(al);
320     f.findNext("EfH", null, false, false);
321     SearchResultsI searchResults = f.getSearchResults();
322     assertEquals(searchResults.getSize(), 1);
323     SearchResultMatchI match = searchResults.getResults().get(0);
324     assertSame(match.getSequence(), al.getSequenceAt(1));
325     assertEquals(match.getStart(), 5);
326     assertEquals(match.getEnd(), 7);
327
328     /*
329      * I should be found in seq1 (twice) and seq2 (once)
330      */
331     f = new Finder(al);
332     f.findNext("I", null, false, false); // find next: seq1/16
333     searchResults = f.getSearchResults();
334     assertEquals(searchResults.getSize(), 1);
335     match = searchResults.getResults().get(0);
336     assertSame(match.getSequence(), al.getSequenceAt(0));
337     assertEquals(match.getStart(), 16);
338     assertEquals(match.getEnd(), 16);
339
340     f.findNext("I", null, false, false); // find next: seq1/18
341     searchResults = f.getSearchResults();
342     assertEquals(searchResults.getSize(), 1);
343     match = searchResults.getResults().get(0);
344     assertSame(match.getSequence(), al.getSequenceAt(0));
345     assertEquals(match.getStart(), 18);
346     assertEquals(match.getEnd(), 18);
347
348     f.findNext("I", null, false, false); // find next: seq2/8
349     searchResults = f.getSearchResults();
350     assertEquals(searchResults.getSize(), 1);
351     match = searchResults.getResults().get(0);
352     assertSame(match.getSequence(), al.getSequenceAt(1));
353     assertEquals(match.getStart(), 8);
354     assertEquals(match.getEnd(), 8);
355
356     f.findNext("I", null, false, false);
357     assertTrue(f.getSearchResults().isEmpty());
358
359     /*
360      * find should reset to start of alignment after a failed search
361      */
362     f.findNext("I", null, false, false); // find next: seq1/16
363     searchResults = f.getSearchResults();
364     assertEquals(searchResults.getSize(), 1);
365     match = searchResults.getResults().get(0);
366     assertSame(match.getSequence(), al.getSequenceAt(0));
367     assertEquals(match.getStart(), 16);
368     assertEquals(match.getEnd(), 16);
369   }
370
371   /**
372    * Test for JAL-2302 to verify that sub-matches are not included in a find all
373    * result
374    */
375   @Test(groups = "Functional")
376   public void testFind_maximalResultOnly()
377   {
378     Finder f = new Finder(al);
379     f.findAll("M+", null, false, false);
380     SearchResultsI searchResults = f.getSearchResults();
381     assertEquals(searchResults.getSize(), 1);
382     SearchResultMatchI match = searchResults.getResults().get(0);
383     assertSame(match.getSequence(), al.getSequenceAt(3));
384     assertEquals(match.getStart(), 4); // dataset sequence positions
385     assertEquals(match.getEnd(), 8); // base 1
386   }
387
388   /**
389    * Test finding all matches of a sequence pattern in an alignment
390    */
391   @Test(groups = "Functional")
392   public void testFind_findAll()
393   {
394     Finder f = new Finder(al);
395     f.findAll("EfH", null, false, false);
396     SearchResultsI searchResults = f.getSearchResults();
397     assertEquals(searchResults.getSize(), 2);
398     SearchResultMatchI match = searchResults.getResults().get(0);
399     assertSame(match.getSequence(), al.getSequenceAt(1));
400     assertEquals(match.getStart(), 5);
401     assertEquals(match.getEnd(), 7);
402     match = searchResults.getResults().get(1);
403     assertSame(match.getSequence(), al.getSequenceAt(2));
404     assertEquals(match.getStart(), 4);
405     assertEquals(match.getEnd(), 6);
406
407     /*
408      * find all I should find 2 positions in seq1, 1 in seq2
409      */
410     f.findAll("I", null, false, false);
411     searchResults = f.getSearchResults();
412     assertEquals(searchResults.getSize(), 3);
413     match = searchResults.getResults().get(0);
414     assertSame(match.getSequence(), al.getSequenceAt(0));
415     assertEquals(match.getStart(), 16);
416     assertEquals(match.getEnd(), 16);
417     match = searchResults.getResults().get(1);
418     assertSame(match.getSequence(), al.getSequenceAt(0));
419     assertEquals(match.getStart(), 18);
420     assertEquals(match.getEnd(), 18);
421     match = searchResults.getResults().get(2);
422     assertSame(match.getSequence(), al.getSequenceAt(1));
423     assertEquals(match.getStart(), 8);
424     assertEquals(match.getEnd(), 8);
425   }
426
427   /**
428    * Test finding all matches, case-sensitive
429    */
430   @Test(groups = "Functional")
431   public void testFind_findAllCaseSensitive()
432   {
433     Finder f = new Finder(al);
434
435     /*
436      * BC should match seq1/9-10 and seq2/2-3
437      */
438     f.findAll("BC", null, true, false);
439     SearchResultsI searchResults = f.getSearchResults();
440     assertEquals(searchResults.getSize(), 2);
441     SearchResultMatchI match = searchResults.getResults().get(0);
442     assertSame(match.getSequence(), al.getSequenceAt(0));
443     assertEquals(match.getStart(), 9);
444     assertEquals(match.getEnd(), 10);
445     match = searchResults.getResults().get(1);
446     assertSame(match.getSequence(), al.getSequenceAt(1));
447     assertEquals(match.getStart(), 2);
448     assertEquals(match.getEnd(), 3);
449
450     /*
451      * bc should match seq3/1-2
452      */
453     f = new Finder(al);
454     f.findAll("bc", null, true, false);
455     searchResults = f.getSearchResults();
456     assertEquals(searchResults.getSize(), 1);
457     match = searchResults.getResults().get(0);
458     assertSame(match.getSequence(), al.getSequenceAt(2));
459     assertEquals(match.getStart(), 1);
460     assertEquals(match.getEnd(), 2);
461
462     f.findAll("bC", null, true, false);
463     assertTrue(f.getSearchResults().isEmpty());
464   }
465
466   /**
467    * Test finding next match of a sequence pattern in a selection group
468    */
469   @Test(groups = "Functional")
470   public void testFind_inSelection()
471   {
472     /*
473      * select sequences 2 and 3, columns 4-6 which contains
474      * BCD
475      * cdE
476      */
477     SequenceGroup sg = new SequenceGroup();
478     sg.setStartRes(3);
479     sg.setEndRes(5);
480     sg.addSequence(al.getSequenceAt(1), false);
481     sg.addSequence(al.getSequenceAt(2), false);
482
483     FinderI f = new Finder(al);
484     f.findNext("b", sg, false, false);
485     assertTrue(f.getIdMatches().isEmpty());
486     SearchResultsI searchResults = f.getSearchResults();
487     assertEquals(searchResults.getSize(), 1);
488     SearchResultMatchI match = searchResults.getResults().get(0);
489     assertSame(match.getSequence(), al.getSequenceAt(1));
490     assertEquals(match.getStart(), 2);
491     assertEquals(match.getEnd(), 2);
492
493     /*
494      * a second Find should not return the 'b' in seq3 as outside the selection
495      */
496     f.findNext("b", sg, false, false);
497     assertTrue(f.getSearchResults().isEmpty());
498     assertTrue(f.getIdMatches().isEmpty());
499
500     f = new Finder(al);
501     f.findNext("d", sg, false, false);
502     assertTrue(f.getIdMatches().isEmpty());
503     searchResults = f.getSearchResults();
504     assertEquals(searchResults.getSize(), 1);
505     match = searchResults.getResults().get(0);
506     assertSame(match.getSequence(), al.getSequenceAt(1));
507     assertEquals(match.getStart(), 4);
508     assertEquals(match.getEnd(), 4);
509     f.findNext("d", sg, false, false);
510     assertTrue(f.getIdMatches().isEmpty());
511     searchResults = f.getSearchResults();
512     assertEquals(searchResults.getSize(), 1);
513     match = searchResults.getResults().get(0);
514     assertSame(match.getSequence(), al.getSequenceAt(2));
515     assertEquals(match.getStart(), 3);
516     assertEquals(match.getEnd(), 3);
517   }
518
519   /**
520    * Test finding all matches of a search pattern in a selection group
521    */
522   @Test(groups = "Functional")
523   public void testFind_findAllInSelection()
524   {
525     /*
526      * select sequences 2 and 3, columns 4-6 which contains
527      * BCD
528      * cdE
529      */
530     SequenceGroup sg = new SequenceGroup();
531     sg.setStartRes(3);
532     sg.setEndRes(5);
533     sg.addSequence(al.getSequenceAt(1), false);
534     sg.addSequence(al.getSequenceAt(2), false);
535   
536     /*
537      * search for 'e' should match two sequence ids and one residue
538      */
539     Finder f = new Finder(al);
540     f.findAll("e", sg, false, false);
541     assertEquals(f.getIdMatches().size(), 2);
542     assertSame(f.getIdMatches().get(0), al.getSequenceAt(1));
543     assertSame(f.getIdMatches().get(1), al.getSequenceAt(2));
544     SearchResultsI searchResults = f.getSearchResults();
545     assertEquals(searchResults.getSize(), 1);
546     SearchResultMatchI match = searchResults.getResults().get(0);
547     assertSame(match.getSequence(), al.getSequenceAt(2));
548     assertEquals(match.getStart(), 4);
549     assertEquals(match.getEnd(), 4);
550
551     /*
552      * search for 'Q' should match two sequence ids only
553      */
554     f = new Finder(al);
555     f.findAll("Q", sg, false, false);
556     assertEquals(f.getIdMatches().size(), 2);
557     assertSame(f.getIdMatches().get(0), al.getSequenceAt(1));
558     assertSame(f.getIdMatches().get(1), al.getSequenceAt(2));
559     assertTrue(f.getSearchResults().isEmpty());
560   }
561
562   /**
563    * Test finding in selection with a sequence too short to reach it
564    */
565   @Test(groups = "Functional")
566   public void testFind_findAllInSelectionWithShortSequence()
567   {
568     /*
569      * select all sequences, columns 10-12
570      * BCD
571      * cdE
572      */
573     SequenceGroup sg = new SequenceGroup();
574     sg.setStartRes(9);
575     sg.setEndRes(11);
576     sg.addSequence(al.getSequenceAt(0), false);
577     sg.addSequence(al.getSequenceAt(1), false);
578     sg.addSequence(al.getSequenceAt(2), false);
579     sg.addSequence(al.getSequenceAt(3), false);
580   
581     /*
582      * search for 'I' should match two sequence positions
583      */
584     Finder f = new Finder(al);
585     f.findAll("I", sg, false, false);
586     assertTrue(f.getIdMatches().isEmpty());
587     SearchResultsI searchResults = f.getSearchResults();
588     assertEquals(searchResults.getSize(), 2);
589     SearchResultMatchI match = searchResults.getResults().get(0);
590     assertSame(match.getSequence(), al.getSequenceAt(0));
591     assertEquals(match.getStart(), 16);
592     assertEquals(match.getEnd(), 16);
593     match = searchResults.getResults().get(1);
594     assertSame(match.getSequence(), al.getSequenceAt(1));
595     assertEquals(match.getStart(), 8);
596     assertEquals(match.getEnd(), 8);
597   }
598
599   /**
600    * Test that find does not report hidden positions
601    */
602   @Test(groups = "Functional")
603   public void testFind_withHiddenColumns()
604   {
605     /*
606      * 0    5   9
607      * ABCD--EF-GHI
608      * A--BCDefHI
609      * --bcdEFH
610      * aa---aMMMMMaaa
611      */
612
613     /*
614      * hide 2-4 (CD- -BC bcd ---)
615      */
616     HiddenColumns hc = new HiddenColumns();
617     hc.hideColumns(2, 4);
618     al.setHiddenColumns(hc);
619
620     /*
621      * find all search for D should ignore hidden positions in seq1 and seq3,
622      * find the visible D in seq2
623      */
624     Finder f = new Finder(al);
625     f.findAll("D", null, false, false);
626     SearchResultsI searchResults = f.getSearchResults();
627     assertEquals(searchResults.getSize(), 1);
628     SearchResultMatchI match = searchResults.getResults().get(0);
629     assertSame(match.getSequence(), al.getSequenceAt(1));
630     assertEquals(match.getStart(), 4);
631     assertEquals(match.getEnd(), 4);
632
633     /*
634      * hide columns 2-5:
635      * find all 'aaa' should find end of seq4 only
636      */
637     hc.hideColumns(2, 5);
638     f = new Finder(al);
639     f.findAll("aaa", null, false, false);
640     searchResults = f.getSearchResults();
641     assertEquals(searchResults.getSize(), 1);
642     match = searchResults.getResults().get(0);
643     assertSame(match.getSequence(), al.getSequenceAt(3));
644     assertEquals(match.getStart(), 9);
645     assertEquals(match.getEnd(), 11);
646
647     /*
648      * find all 'BE' should not match across hidden columns in seq1
649      */
650     f.findAll("BE", null, false, false);
651     assertTrue(f.getSearchResults().isEmpty());
652
653     /*
654      * boundary case: hide columns at end of alignment
655      * search for H should match seq3/6 only
656      */
657     hc.revealAllHiddenColumns(new ColumnSelection());
658     hc.hideColumns(8, 13);
659     f = new Finder(al);
660     f.findNext("H", null, false, false);
661     searchResults = f.getSearchResults();
662     assertEquals(searchResults.getSize(), 1);
663     match = searchResults.getResults().get(0);
664     assertSame(match.getSequence(), al.getSequenceAt(2));
665     assertEquals(match.getStart(), 6);
666     assertEquals(match.getEnd(), 6);
667   }
668
669   @Test(groups = "Functional")
670   public void testFind_withHiddenColumnsAndSelection()
671   {
672     /*
673      * 0    5   9
674      * ABCD--EF-GHI
675      * A--BCDefHI
676      * --bcdEFH
677      * aa---aMMMMMaaa
678      */
679   
680     /*
681      * hide columns 2-4 and 6-7
682      */
683     HiddenColumns hc = new HiddenColumns();
684     hc.hideColumns(2, 4);
685     hc.hideColumns(6, 7);
686     al.setHiddenColumns(hc);
687   
688     /*
689      * select rows 2-3
690      */
691     SequenceGroup sg = new SequenceGroup();
692     sg.addSequence(al.getSequenceAt(1), false);
693     sg.addSequence(al.getSequenceAt(2), false);
694     sg.setStartRes(0);
695     sg.setEndRes(13);
696
697     /*
698      * find all search for A or H
699      * should match seq2/1, seq2/7, not seq3/6
700      */
701     Finder f = new Finder(al);
702     f.findAll("[AH]", sg, false, false);
703     SearchResultsI searchResults = f.getSearchResults();
704     assertEquals(searchResults.getSize(), 2);
705     SearchResultMatchI match = searchResults.getResults().get(0);
706     assertSame(match.getSequence(), al.getSequenceAt(1));
707     assertEquals(match.getStart(), 1);
708     assertEquals(match.getEnd(), 1);
709     match = searchResults.getResults().get(1);
710     assertSame(match.getSequence(), al.getSequenceAt(1));
711     assertEquals(match.getStart(), 7);
712     assertEquals(match.getEnd(), 7);
713   }
714 }