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