JAL-2759 Convert reveal to use cursor
[jalview.git] / test / jalview / datamodel / HiddenColumnsTest.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.datamodel;
22
23 import static org.testng.Assert.assertNull;
24 import static org.testng.AssertJUnit.assertEquals;
25 import static org.testng.AssertJUnit.assertFalse;
26 import static org.testng.AssertJUnit.assertTrue;
27
28 import jalview.analysis.AlignmentGenerator;
29 import jalview.gui.JvOptionPane;
30 import jalview.util.Comparison;
31
32 import java.util.Arrays;
33 import java.util.BitSet;
34 import java.util.Iterator;
35 import java.util.Random;
36
37 import org.testng.annotations.BeforeClass;
38 import org.testng.annotations.Test;
39
40 public class HiddenColumnsTest
41 {
42
43   @BeforeClass(alwaysRun = true)
44   public void setUpJvOptionPane()
45   {
46     JvOptionPane.setInteractiveMode(false);
47     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
48   }
49
50   /**
51    * Test the method which counts the number of hidden columns
52    */
53   @Test(groups = { "Functional" })
54   public void testGetSize()
55   {
56     HiddenColumns hidden = new HiddenColumns();
57     assertEquals(0, hidden.getSize());
58
59     hidden.hideColumns(3, 5);
60     assertEquals(3, hidden.getSize());
61
62     hidden.hideColumns(8, 8);
63     assertEquals(4, hidden.getSize());
64
65     hidden.hideColumns(9, 14);
66     assertEquals(10, hidden.getSize());
67
68     ColumnSelection cs = new ColumnSelection();
69     hidden.revealAllHiddenColumns(cs);
70     assertEquals(0, hidden.getSize());
71   }
72
73   /**
74    * Test the method that finds the visible column position of an alignment
75    * column, allowing for hidden columns.
76    */
77   @Test(groups = { "Functional" })
78   public void testFindColumnPosition()
79   {
80     HiddenColumns cs = new HiddenColumns();
81     assertEquals(5, cs.findColumnPosition(5));
82
83     // hiding column 6 makes no difference
84     cs.hideColumns(6, 6);
85     assertEquals(5, cs.findColumnPosition(5));
86
87     // hiding column 4 moves column 5 to column 4
88     cs.hideColumns(4, 4);
89     assertEquals(4, cs.findColumnPosition(5));
90
91     // hiding column 4 moves column 4 to position 3
92     assertEquals(3, cs.findColumnPosition(4));
93
94     // hiding columns 1 and 2 moves column 5 to column 2
95     cs.hideColumns(1, 2);
96     assertEquals(2, cs.findColumnPosition(5));
97
98     // check with > 1 hidden column regions
99     // where some columns are in the hidden regions
100     HiddenColumns cs2 = new HiddenColumns();
101     cs2.hideColumns(5, 10);
102     cs2.hideColumns(20, 27);
103     cs2.hideColumns(40, 44);
104
105     // hiding columns 5-10 and 20-27 moves column 8 to column 4
106     assertEquals(4, cs2.findColumnPosition(8));
107
108     // and moves column 24 to 13
109     assertEquals(13, cs2.findColumnPosition(24));
110
111     // and moves column 28 to 14
112     assertEquals(14, cs2.findColumnPosition(28));
113
114     // and moves column 40 to 25
115     assertEquals(25, cs2.findColumnPosition(40));
116
117     // check when hidden columns start at 0 that the visible column
118     // is returned as 0
119     HiddenColumns cs3 = new HiddenColumns();
120     cs3.hideColumns(0, 4);
121     assertEquals(0, cs3.findColumnPosition(2));
122
123     // check that column after the last hidden region doesn't crash
124     assertEquals(46, cs2.findColumnPosition(65));
125   }
126
127   @Test(groups = { "Functional" })
128   public void testVisibleContigsIterator()
129   {
130     HiddenColumns cs = new HiddenColumns();
131
132     Iterator<int[]> visible = cs.getVisContigsIterator(3, 10);
133     int[] region = visible.next();
134     assertEquals("[3, 9]", Arrays.toString(region));
135     assertFalse(visible.hasNext());
136
137     cs.hideColumns(3, 6);
138     cs.hideColumns(8, 9);
139     cs.hideColumns(12, 12);
140
141     // Test both ends visible region
142
143     // start position is inclusive, end position exclusive
144     visible = cs.getVisContigsIterator(1, 13);
145     region = visible.next();
146     assertEquals("[1, 2]", Arrays.toString(region));
147     region = visible.next();
148     assertEquals("[7, 7]", Arrays.toString(region));
149     region = visible.next();
150     assertEquals("[10, 11]", Arrays.toString(region));
151     assertFalse(visible.hasNext());
152
153     // Test start hidden, end visible
154     visible = cs.getVisContigsIterator(4, 14);
155     region = visible.next();
156     assertEquals("[7, 7]", Arrays.toString(region));
157     region = visible.next();
158     assertEquals("[10, 11]", Arrays.toString(region));
159     region = visible.next();
160     assertEquals("[13, 13]", Arrays.toString(region));
161     assertFalse(visible.hasNext());
162
163     // Test start hidden, end hidden
164     visible = cs.getVisContigsIterator(3, 10);
165     region = visible.next();
166     assertEquals("[7, 7]", Arrays.toString(region));
167     assertFalse(visible.hasNext());
168
169     // Test start visible, end hidden
170     visible = cs.getVisContigsIterator(0, 13);
171     region = visible.next();
172     assertEquals("[0, 2]", Arrays.toString(region));
173     region = visible.next();
174     assertEquals("[7, 7]", Arrays.toString(region));
175     region = visible.next();
176     assertEquals("[10, 11]", Arrays.toString(region));
177     assertFalse(visible.hasNext());
178
179     // Test empty result
180     visible = cs.getVisContigsIterator(4, 6);
181     assertFalse(visible.hasNext());
182   }
183
184   @Test(groups = { "Functional" })
185   public void testEquals()
186   {
187     HiddenColumns cs = new HiddenColumns();
188     cs.hideColumns(5, 9);
189
190     // a different set of hidden columns
191     HiddenColumns cs2 = new HiddenColumns();
192
193     // with no hidden columns
194     assertFalse(cs.equals(cs2));
195     assertFalse(cs2.equals(cs));
196
197     // with hidden columns added in a different order
198     cs2.hideColumns(6, 9);
199     cs2.hideColumns(5, 8);
200
201     assertTrue(cs.equals(cs2));
202     assertTrue(cs.equals(cs));
203     assertTrue(cs2.equals(cs));
204     assertTrue(cs2.equals(cs2));
205   }
206
207   @Test(groups = "Functional")
208   public void testCopyConstructor()
209   {
210     HiddenColumns cs = new HiddenColumns();
211     cs.hideColumns(10, 11);
212     cs.hideColumns(5, 7);
213     Iterator<int[]> regions = cs.iterator();
214     assertEquals("[5, 7]",
215             Arrays.toString(regions.next()));
216
217     HiddenColumns cs2 = new HiddenColumns(cs);
218     regions = cs2.iterator();
219     assertTrue(cs2.hasHiddenColumns());
220     assertEquals(2, cs2.getNumberOfRegions());
221     // hidden columns are held in column order
222     assertEquals("[5, 7]",
223             Arrays.toString(regions.next()));
224     assertEquals("[10, 11]",
225             Arrays.toString(regions.next()));
226   }
227
228   @Test(groups = "Functional")
229   public void testCopyConstructor2()
230   {
231     HiddenColumns cs = new HiddenColumns();
232     cs.hideColumns(10, 11);
233     cs.hideColumns(5, 7);
234
235     HiddenColumns cs2 = new HiddenColumns(cs, 3, 9, 1);
236     assertTrue(cs2.hasHiddenColumns());
237     Iterator<int[]> regions = cs2.iterator();
238
239     // only [5,7] returned, offset by 1
240     assertEquals("[4, 6]",
241             Arrays.toString(regions.next()));
242     assertEquals(3, cs2.getSize());
243
244     cs2 = new HiddenColumns(cs, 8, 15, 4);
245     regions = cs2.iterator();
246     assertTrue(cs2.hasHiddenColumns());
247
248     // only [10,11] returned, offset by 4
249     assertEquals("[6, 7]",
250             Arrays.toString(regions.next()));
251     assertEquals(2, cs2.getSize());
252
253     cs2 = new HiddenColumns(cs, 6, 10, 4);
254     assertFalse(cs2.hasHiddenColumns());
255   }
256
257   /**
258    * Test the code used to locate the reference sequence ruler origin
259    */
260   @Test(groups = { "Functional" })
261   public void testLocateVisibleBoundsofSequence()
262   {
263     // create random alignment
264     AlignmentGenerator gen = new AlignmentGenerator(false);
265     AlignmentI al = gen.generate(50, 20, 123, 5, 5);
266
267     HiddenColumns cs = al.getHiddenColumns();
268     ColumnSelection colsel = new ColumnSelection();
269
270     SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
271     assertEquals(2, seq.findIndex(seq.getStart()));
272
273     // no hidden columns
274     assertEquals(seq.findIndex(seq.getStart()) - 1, cs.locateVisibleStartOfSequence(seq));
275
276     // hidden column on gap after end of sequence - should not affect bounds
277     colsel.hideSelectedColumns(13, al.getHiddenColumns());
278     assertEquals(seq.findIndex(seq.getStart()) - 1,cs.locateVisibleStartOfSequence(seq));
279
280     cs.revealAllHiddenColumns(colsel);
281     // hidden column on gap before beginning of sequence - should vis bounds by
282     // one
283     colsel.hideSelectedColumns(0, al.getHiddenColumns());
284     assertEquals(seq.findIndex(seq.getStart()) - 2,cs.locateVisibleStartOfSequence(seq));
285
286     cs.revealAllHiddenColumns(colsel);
287     // hide columns around most of sequence - leave one residue remaining
288     cs.hideColumns(1, 3);
289     cs.hideColumns(6, 11);
290     assertEquals("-D",
291             cs.getVisibleSequenceStrings(0, 5, new SequenceI[]
292     { seq })[0]);
293
294     assertEquals(1, cs.locateVisibleStartOfSequence(seq));
295     cs.revealAllHiddenColumns(colsel);
296
297     // hide whole sequence - should just get location of hidden region
298     // containing sequence
299     cs.hideColumns(1, 11);
300     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
301
302     cs.revealAllHiddenColumns(colsel);
303     cs.hideColumns(0, 15);
304     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
305
306     SequenceI seq2 = new Sequence("RefSeq2", "-------A-SD-ASD--E---");
307
308     cs.revealAllHiddenColumns(colsel);
309     cs.hideColumns(7, 17);
310     assertEquals(0,cs.locateVisibleStartOfSequence(seq2));
311
312     cs.revealAllHiddenColumns(colsel);
313     cs.hideColumns(3, 17);
314     assertEquals(0,cs.locateVisibleStartOfSequence(seq2));
315
316     cs.revealAllHiddenColumns(colsel);
317     cs.hideColumns(3, 19);
318     assertEquals(0,cs.locateVisibleStartOfSequence(seq2));
319
320     cs.revealAllHiddenColumns(colsel);
321     cs.hideColumns(0, 0);
322     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
323
324     cs.revealAllHiddenColumns(colsel);
325     cs.hideColumns(0, 1);
326     assertEquals(1,cs.locateVisibleStartOfSequence(seq));
327
328     cs.revealAllHiddenColumns(colsel);
329     cs.hideColumns(0, 2);
330     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
331
332     cs.revealAllHiddenColumns(colsel);
333     cs.hideColumns(1, 1);
334     assertEquals(2,cs.locateVisibleStartOfSequence(seq));
335
336     cs.revealAllHiddenColumns(colsel);
337     cs.hideColumns(1, 2);
338     assertEquals(1,cs.locateVisibleStartOfSequence(seq));
339
340     cs.revealAllHiddenColumns(colsel);
341     cs.hideColumns(1, 3);
342     assertEquals(1,cs.locateVisibleStartOfSequence(seq));
343
344     cs.revealAllHiddenColumns(colsel);
345     cs.hideColumns(0, 2);
346     cs.hideColumns(5, 6);
347     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
348
349     cs.revealAllHiddenColumns(colsel);
350     cs.hideColumns(0, 2);
351     cs.hideColumns(5, 6);
352     cs.hideColumns(9, 10);
353     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
354
355     cs.revealAllHiddenColumns(colsel);
356     cs.hideColumns(0, 2);
357     cs.hideColumns(7, 11);
358     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
359
360     cs.revealAllHiddenColumns(colsel);
361     cs.hideColumns(2, 4);
362     cs.hideColumns(7, 11);
363     assertEquals(1,cs.locateVisibleStartOfSequence(seq));
364
365     cs.revealAllHiddenColumns(colsel);
366     cs.hideColumns(2, 4);
367     cs.hideColumns(7, 12);
368     assertEquals(1,cs.locateVisibleStartOfSequence(seq));
369
370     cs.revealAllHiddenColumns(colsel);
371     cs.hideColumns(1, 11);
372     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
373
374     cs.revealAllHiddenColumns(colsel);
375     cs.hideColumns(0, 12);
376     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
377
378     cs.revealAllHiddenColumns(colsel);
379     cs.hideColumns(0, 4);
380     cs.hideColumns(6, 12);
381     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
382
383     cs.revealAllHiddenColumns(colsel);
384     cs.hideColumns(0, 1);
385     cs.hideColumns(3, 12);
386     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
387
388     cs.revealAllHiddenColumns(colsel);
389     cs.hideColumns(3, 14);
390     cs.hideColumns(17, 19);
391     assertEquals(3,cs.locateVisibleStartOfSequence(seq2));
392
393     cs.revealAllHiddenColumns(colsel);
394     cs.hideColumns(3, 7);
395     cs.hideColumns(9, 14);
396     cs.hideColumns(17, 19);
397     assertEquals(9,cs.locateVisibleStartOfSequence(seq2));
398
399     cs.revealAllHiddenColumns(colsel);
400     cs.hideColumns(0, 1);
401     cs.hideColumns(3, 4);
402     cs.hideColumns(6, 8);
403     cs.hideColumns(10, 12);
404     assertEquals(6, cs.locateVisibleStartOfSequence(seq));
405
406   }
407
408   @Test(groups = { "Functional" })
409   public void testLocateVisibleBoundsPathologicals()
410   {
411     // test some pathological cases we missed
412     AlignmentI al = new Alignment(
413             new SequenceI[]
414     { new Sequence("refseqGaptest", "KTDVTI----------NFI-----G----L") });
415     HiddenColumns cs = new HiddenColumns();
416     cs.hideInsertionsFor(al.getSequenceAt(0));
417     assertEquals("G", ""
418             + al.getSequenceAt(0).getCharAt(cs.adjustForHiddenColumns(9)));
419   }
420
421   @Test(groups = { "Functional" })
422   public void testHideColumns()
423   {
424     // create random alignment
425     AlignmentGenerator gen = new AlignmentGenerator(false);
426     AlignmentI al = gen.generate(50, 20, 123, 5, 5);
427
428     ColumnSelection colsel = new ColumnSelection();
429     HiddenColumns cs = al.getHiddenColumns();
430     colsel.hideSelectedColumns(5, al.getHiddenColumns());
431     Iterator<int[]> regions = cs.iterator();
432     assertEquals(1, cs.getNumberOfRegions());
433     assertEquals("[5, 5]", Arrays.toString(regions.next()));
434
435     colsel.hideSelectedColumns(3, al.getHiddenColumns());
436     regions = cs.iterator();
437     assertEquals(2, cs.getNumberOfRegions());
438     // two hidden ranges, in order:
439     assertEquals("[3, 3]", Arrays.toString(regions.next()));
440     assertEquals("[5, 5]", Arrays.toString(regions.next()));
441
442     // hiding column 4 expands [3, 3] to [3, 4]
443     // and merges to [5, 5] to make [3, 5]
444     colsel.hideSelectedColumns(4, al.getHiddenColumns());
445     regions = cs.iterator();
446     assertEquals(1, cs.getNumberOfRegions());
447     assertEquals("[3, 5]", Arrays.toString(regions.next()));
448
449     // clear hidden columns (note they are added to selected)
450     cs.revealAllHiddenColumns(colsel);
451     // it is now actually null but getter returns an empty list
452     assertEquals(0, cs.getNumberOfRegions());
453
454     cs.hideColumns(3, 6);
455     regions = cs.iterator();
456     int[] firstHiddenRange = regions.next();
457     assertEquals("[3, 6]", Arrays.toString(firstHiddenRange));
458
459     // adding a subrange of already hidden should do nothing
460     cs.hideColumns(4, 5);
461     regions = cs.iterator();
462     assertEquals(1, cs.getNumberOfRegions());
463     assertEquals("[3, 6]",
464             Arrays.toString(regions.next()));
465     cs.hideColumns(3, 5);
466     regions = cs.iterator();
467     assertEquals(1, cs.getNumberOfRegions());
468     assertEquals("[3, 6]",
469             Arrays.toString(regions.next()));
470     cs.hideColumns(4, 6);
471     regions = cs.iterator();
472     assertEquals(1, cs.getNumberOfRegions());
473     assertEquals("[3, 6]",
474             Arrays.toString(regions.next()));
475     cs.hideColumns(3, 6);
476     regions = cs.iterator();
477     assertEquals(1, cs.getNumberOfRegions());
478     assertEquals("[3, 6]",
479             Arrays.toString(regions.next()));
480
481     cs.revealAllHiddenColumns(colsel);
482     cs.hideColumns(2, 4);
483     regions = cs.iterator();
484     assertEquals(1, cs.getNumberOfRegions());
485     assertEquals("[2, 4]", Arrays.toString(regions.next()));
486
487     // extend contiguous with 2 positions overlap
488     cs.hideColumns(3, 5);
489     regions = cs.iterator();
490     assertEquals(1, cs.getNumberOfRegions());
491     assertEquals("[2, 5]", Arrays.toString(regions.next()));
492
493     // extend contiguous with 1 position overlap
494     cs.hideColumns(5, 6);
495     regions = cs.iterator();
496     assertEquals(1, cs.getNumberOfRegions());
497     assertEquals("[2, 6]", Arrays.toString(regions.next()));
498
499     // extend contiguous with overlap both ends:
500     cs.hideColumns(1, 7);
501     regions = cs.iterator();
502     assertEquals(1, cs.getNumberOfRegions());
503     assertEquals("[1, 7]", Arrays.toString(regions.next()));
504   }
505
506   /**
507    * Test the method that reveals a range of hidden columns given the start
508    * column of the range
509    */
510   @Test(groups = { "Functional" })
511   public void testRevealHiddenColumns()
512   {
513     ColumnSelection colsel = new ColumnSelection();
514     HiddenColumns cs = new HiddenColumns();
515     cs.hideColumns(5, 8);
516     colsel.addElement(10);
517     cs.revealHiddenColumns(5, colsel);
518
519     // hiddenColumns now empty
520     assertEquals(0, cs.getSize());
521
522     // revealed columns are marked as selected (added to selection):
523     assertEquals("[10, 5, 6, 7, 8]", colsel.getSelected().toString());
524
525     // calling with a column other than the range start does nothing:
526     colsel = new ColumnSelection();
527     cs = new HiddenColumns();
528     cs.hideColumns(5, 8);
529
530     int prevSize = cs.getSize();
531     cs.revealHiddenColumns(6, colsel);
532     assertEquals(prevSize, cs.getSize());
533     assertTrue(colsel.getSelected().isEmpty());
534   }
535
536   @Test(groups = { "Functional" })
537   public void testRevealAllHiddenColumns()
538   {
539     HiddenColumns hidden = new HiddenColumns();
540     ColumnSelection colsel = new ColumnSelection();
541     hidden.hideColumns(5, 8);
542     hidden.hideColumns(2, 3);
543     colsel.addElement(11);
544     colsel.addElement(1);
545     hidden.revealAllHiddenColumns(colsel);
546
547     /*
548      * revealing hidden columns adds them (in order) to the (unordered)
549      * selection list
550      */
551
552     // hiddenColumns now empty
553     assertEquals(0, hidden.getSize());
554
555     assertEquals("[11, 1, 2, 3, 5, 6, 7, 8]",
556             colsel.getSelected().toString());
557   }
558
559   @Test(groups = { "Functional" })
560   public void testIsVisible()
561   {
562     HiddenColumns cs = new HiddenColumns();
563     cs.hideColumns(2, 4);
564     cs.hideColumns(6, 7);
565     assertTrue(cs.isVisible(0));
566     assertTrue(cs.isVisible(-99));
567     assertTrue(cs.isVisible(1));
568     assertFalse(cs.isVisible(2));
569     assertFalse(cs.isVisible(3));
570     assertFalse(cs.isVisible(4));
571     assertTrue(cs.isVisible(5));
572     assertFalse(cs.isVisible(6));
573     assertFalse(cs.isVisible(7));
574   }
575
576   /**
577    * Test for the case when a hidden range encloses more one already hidden
578    * range
579    */
580   @Test(groups = { "Functional" })
581   public void testHideColumns_subsumingHidden()
582   {
583     /*
584      * JAL-2370 bug scenario:
585      * two hidden ranges subsumed by a third
586      */
587     HiddenColumns cs = new HiddenColumns();
588     cs.hideColumns(49, 59);
589     cs.hideColumns(69, 79);
590     Iterator<int[]> regions = cs.iterator();
591     assertEquals(2, cs.getNumberOfRegions());
592     assertEquals("[49, 59]", Arrays.toString(regions.next()));
593     assertEquals("[69, 79]", Arrays.toString(regions.next()));
594
595     cs.hideColumns(48, 80);
596     regions = cs.iterator();
597     assertEquals(1, cs.getNumberOfRegions());
598     assertEquals("[48, 80]", Arrays.toString(regions.next()));
599
600     /*
601      * another...joining hidden ranges
602      */
603     cs = new HiddenColumns();
604     cs.hideColumns(10, 20);
605     cs.hideColumns(30, 40);
606     cs.hideColumns(50, 60);
607     // hiding 21-49 should merge to one range
608     cs.hideColumns(21, 49);
609     regions = cs.iterator();
610     assertEquals(1, cs.getNumberOfRegions());
611     assertEquals("[10, 60]", Arrays.toString(regions.next()));
612
613     /*
614      * another...left overlap, subsumption, right overlap,
615      * no overlap of existing hidden ranges
616      */
617     cs = new HiddenColumns();
618     cs.hideColumns(10, 20);
619     cs.hideColumns(10, 20);
620     cs.hideColumns(30, 35);
621     cs.hideColumns(40, 50);
622     cs.hideColumns(60, 70);
623
624     cs.hideColumns(15, 45);
625     regions = cs.iterator();
626     assertEquals(2, cs.getNumberOfRegions());
627     assertEquals("[10, 50]", Arrays.toString(regions.next()));
628     assertEquals("[60, 70]", Arrays.toString(regions.next()));
629   }
630
631   @Test(groups = { "Functional" })
632   public void testHideBitset()
633   {
634     HiddenColumns cs;
635
636     BitSet one = new BitSet();
637
638     // one hidden range
639     one.set(1);
640     cs = new HiddenColumns();
641     cs.hideMarkedBits(one);
642     assertEquals(1, cs.getNumberOfRegions());
643
644     one.set(2);
645     cs = new HiddenColumns();
646     cs.hideMarkedBits(one);
647     assertEquals(1, cs.getNumberOfRegions());
648
649     one.set(3);
650     cs = new HiddenColumns();
651     cs.hideMarkedBits(one);
652     assertEquals(1, cs.getNumberOfRegions());
653
654     // split
655     one.clear(2);
656     cs = new HiddenColumns();
657     cs.hideMarkedBits(one);
658     assertEquals(2, cs.getNumberOfRegions());
659
660     assertEquals(0, cs.adjustForHiddenColumns(0));
661     assertEquals(2, cs.adjustForHiddenColumns(1));
662     assertEquals(4, cs.adjustForHiddenColumns(2));
663
664     // one again
665     one.clear(1);
666     cs = new HiddenColumns();
667     cs.hideMarkedBits(one);
668
669     assertEquals(1, cs.getNumberOfRegions());
670
671     assertEquals(0, cs.adjustForHiddenColumns(0));
672     assertEquals(1, cs.adjustForHiddenColumns(1));
673     assertEquals(2, cs.adjustForHiddenColumns(2));
674     assertEquals(4, cs.adjustForHiddenColumns(3));
675   }
676
677   @Test(groups = { "Functional" })
678   public void testMarkHiddenRegions()
679   {
680     BitSet toMark, fromMark;
681     long seed = -3241532;
682     Random number = new Random(seed);
683     for (int n = 0; n < 1000; n++)
684     {
685       // create a random bitfield
686       toMark = BitSet
687               .valueOf(new long[]
688       { number.nextLong(), number.nextLong(), number.nextLong() });
689       toMark.set(n * number.nextInt(10), n * (25 + number.nextInt(25)));
690       HiddenColumns hc = new HiddenColumns();
691       hc.hideMarkedBits(toMark);
692
693       // see if we can recover bitfield
694       hc.markHiddenRegions(fromMark = new BitSet());
695       assertEquals(toMark, fromMark);
696     }
697   }
698
699   @Test(groups = { "Functional" })
700   public void testRegionsToString()
701   {
702     HiddenColumns hc = new HiddenColumns();
703
704     String result = hc.regionsToString(",", "--");
705     assertEquals("", result);
706
707     hc.hideColumns(3, 7);
708     hc.hideColumns(10, 10);
709     hc.hideColumns(14, 15);
710
711     result = hc.regionsToString(",", "--");
712     assertEquals("3--7,10--10,14--15", result);
713   }
714
715   @Test(groups = "Functional")
716   public void testGetVisibleStartAndEndIndexTest()
717   {
718     Sequence seq = new Sequence("testSeq", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
719     AlignmentI align = new Alignment(new SequenceI[] { seq });
720     HiddenColumns hc = new HiddenColumns();
721
722     int[] startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
723     assertEquals(0, startEnd[0]);
724     assertEquals(25, startEnd[1]);
725
726     hc.hideColumns(0, 0);
727     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
728     assertEquals(1, startEnd[0]);
729     assertEquals(25, startEnd[1]);
730
731     hc.hideColumns(6, 9);
732     hc.hideColumns(11, 12);
733     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
734     assertEquals(1, startEnd[0]);
735     assertEquals(25, startEnd[1]);
736
737     hc.hideColumns(24, 25);
738     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
739     System.out.println(startEnd[0] + " : " + startEnd[1]);
740     assertEquals(1, startEnd[0]);
741     assertEquals(23, startEnd[1]);
742   }
743
744   @Test(groups = "Functional")
745   public void testGetRegionWithEdgeAtRes()
746   {
747     HiddenColumns hc = new HiddenColumns();
748
749     int[] result = hc.getRegionWithEdgeAtRes(5);
750     assertNull(result);
751
752     hc.hideColumns(3, 7);
753     hc.hideColumns(10, 10);
754     hc.hideColumns(14, 15);
755
756     result = hc.getRegionWithEdgeAtRes(2);
757     assertEquals(3, result[0]);
758     assertEquals(7, result[1]);
759
760     result = hc.getRegionWithEdgeAtRes(5);
761     assertEquals(10, result[0]);
762     assertEquals(10, result[1]);
763
764     result = hc.getRegionWithEdgeAtRes(6);
765     assertNull(result);
766
767     result = hc.getRegionWithEdgeAtRes(0);
768     assertNull(result);
769
770     result = hc.getRegionWithEdgeAtRes(7);
771     assertEquals(14, result[0]);
772     assertEquals(15, result[1]);
773
774     result = hc.getRegionWithEdgeAtRes(8);
775     assertEquals(14, result[0]);
776     assertEquals(15, result[1]);
777
778     result = hc.getRegionWithEdgeAtRes(16);
779     assertNull(result);
780   }
781
782   @Test(groups = "Functional")
783   public void testPropagateInsertions()
784   {
785     // create an alignment with no gaps - this will be the profile seq and other
786     // JPRED seqs
787     AlignmentGenerator gen = new AlignmentGenerator(false);
788     AlignmentI al = gen.generate(25, 10, 1234, 0, 0);
789
790     // get the profileseq
791     SequenceI profileseq = al.getSequenceAt(0);
792     SequenceI gappedseq = new Sequence(profileseq);
793     gappedseq.insertCharAt(5, al.getGapCharacter());
794     gappedseq.insertCharAt(6, al.getGapCharacter());
795     gappedseq.insertCharAt(7, al.getGapCharacter());
796     gappedseq.insertCharAt(8, al.getGapCharacter());
797
798     // create an alignment view with the gapped sequence
799     SequenceI[] seqs = new SequenceI[1];
800     seqs[0] = gappedseq;
801     AlignmentI newal = new Alignment(seqs);
802     HiddenColumns hidden = new HiddenColumns();
803     hidden.hideColumns(15, 17);
804
805     AlignmentView view = new AlignmentView(newal, hidden, null, true, false,
806             false);
807
808     // confirm that original contigs are as expected
809     Iterator<int[]> visible = hidden.getVisContigsIterator(0, 25);
810     int[] region = visible.next();
811     assertEquals("[0, 14]", Arrays.toString(region));
812     region = visible.next();
813     assertEquals("[18, 24]", Arrays.toString(region));
814
815     // propagate insertions
816     HiddenColumns result = HiddenColumns.propagateInsertions(profileseq, al,
817             view);
818
819     // confirm that the contigs have changed to account for the gaps
820     visible = result.getVisContigsIterator(0, 25);
821     region = visible.next();
822     assertEquals("[0, 10]", Arrays.toString(region));
823     region = visible.next();
824     assertEquals("[14, 24]", Arrays.toString(region));
825
826     // confirm the alignment has been changed so that the other sequences have
827     // gaps inserted where the columns are hidden
828     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[10]));
829     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[11]));
830     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[12]));
831     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[13]));
832     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[14]));
833
834   }
835
836   @Test(groups = "Functional")
837   public void testPropagateInsertionsOverlap()
838   {
839     // test propagateInsertions where gaps and hiddenColumns overlap
840
841     // create an alignment with no gaps - this will be the profile seq and other
842     // JPRED seqs
843     AlignmentGenerator gen = new AlignmentGenerator(false);
844     AlignmentI al = gen.generate(20, 10, 1234, 0, 0);
845
846     // get the profileseq
847     SequenceI profileseq = al.getSequenceAt(0);
848     SequenceI gappedseq = new Sequence(profileseq);
849     gappedseq.insertCharAt(5, al.getGapCharacter());
850     gappedseq.insertCharAt(6, al.getGapCharacter());
851     gappedseq.insertCharAt(7, al.getGapCharacter());
852     gappedseq.insertCharAt(8, al.getGapCharacter());
853
854     // create an alignment view with the gapped sequence
855     SequenceI[] seqs = new SequenceI[1];
856     seqs[0] = gappedseq;
857     AlignmentI newal = new Alignment(seqs);
858
859     // hide columns so that some overlap with the gaps
860     HiddenColumns hidden = new HiddenColumns();
861     hidden.hideColumns(7, 10);
862
863     AlignmentView view = new AlignmentView(newal, hidden, null, true, false,
864             false);
865
866     // confirm that original contigs are as expected
867     Iterator<int[]> visible = hidden.getVisContigsIterator(0, 20);
868     int[] region = visible.next();
869     assertEquals("[0, 6]", Arrays.toString(region));
870     region = visible.next();
871     assertEquals("[11, 19]", Arrays.toString(region));
872     assertFalse(visible.hasNext());
873
874     // propagate insertions
875     HiddenColumns result = HiddenColumns.propagateInsertions(profileseq, al,
876             view);
877
878     // confirm that the contigs have changed to account for the gaps
879     visible = result.getVisContigsIterator(0, 20);
880     region = visible.next();
881     assertEquals("[0, 4]", Arrays.toString(region));
882     region = visible.next();
883     assertEquals("[7, 19]", Arrays.toString(region));
884     assertFalse(visible.hasNext());
885
886     // confirm the alignment has been changed so that the other sequences have
887     // gaps inserted where the columns are hidden
888     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[4]));
889     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[5]));
890     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[6]));
891     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[7]));
892   }
893
894   @Test(groups = "Functional")
895   public void testHasHiddenColumns()
896   {
897     HiddenColumns h = new HiddenColumns();
898
899     // new HiddenColumns2 has no hidden cols
900     assertFalse(h.hasHiddenColumns());
901
902     // some columns hidden, returns true
903     h.hideColumns(5, 10);
904     assertTrue(h.hasHiddenColumns());
905
906     // reveal columns, no hidden cols again
907     ColumnSelection sel = new ColumnSelection();
908     h.revealAllHiddenColumns(sel);
909     assertFalse(h.hasHiddenColumns());
910   }
911
912   @Test(groups = "Functional")
913   public void testHasManyHiddenColumns()
914   {
915     HiddenColumns h = new HiddenColumns();
916
917     // new HiddenColumns2 has no hidden cols
918     assertFalse(h.hasManyHiddenColumns());
919
920     // one set of columns hidden, returns false
921     h.hideColumns(5, 10);
922     assertFalse(h.hasManyHiddenColumns());
923
924     // two sets hidden, returns true
925     h.hideColumns(15, 17);
926     assertTrue(h.hasManyHiddenColumns());
927
928     // back to one block, asserts false
929     h.hideColumns(11, 14);
930     assertFalse(h.hasManyHiddenColumns());
931   }
932
933   @Test(groups = "Functional")
934   public void testAdjustForHiddenColumns()
935   {
936     HiddenColumns h = new HiddenColumns();
937     // returns input value when there are no hidden columns
938     assertEquals(10, h.adjustForHiddenColumns(10));
939
940     h.hideColumns(20, 30);
941     assertEquals(10, h.adjustForHiddenColumns(10));
942     assertEquals(20 + 11, h.adjustForHiddenColumns(20));
943     assertEquals(35 + 11, h.adjustForHiddenColumns(35));
944
945     h.hideColumns(5, 7);
946     assertEquals(10 + 3, h.adjustForHiddenColumns(10));
947     assertEquals(20 + 14, h.adjustForHiddenColumns(20));
948     assertEquals(35 + 14, h.adjustForHiddenColumns(35));
949
950     ColumnSelection sel = new ColumnSelection();
951     h.revealAllHiddenColumns(sel);
952     h.hideColumns(0, 1);
953     assertEquals(4, h.adjustForHiddenColumns(2));
954   }
955
956   @Test(groups = "Functional")
957   public void testGetHiddenBoundaryLeft()
958   {
959     HiddenColumns h = new HiddenColumns();
960
961     // returns same value if no hidden cols
962     assertEquals(3, h.getHiddenBoundaryLeft(3));
963
964     h.hideColumns(5, 10);
965     assertEquals(10, h.getHiddenBoundaryLeft(15));
966     assertEquals(3, h.getHiddenBoundaryLeft(3));
967     assertEquals(7, h.getHiddenBoundaryLeft(7));
968
969     h.hideColumns(15, 20);
970     assertEquals(10, h.getHiddenBoundaryLeft(15));
971     assertEquals(20, h.getHiddenBoundaryLeft(21));
972   }
973
974   @Test(groups = "Functional")
975   public void testGetHiddenBoundaryRight()
976   {
977     HiddenColumns h = new HiddenColumns();
978
979     // returns same value if no hidden cols
980     assertEquals(3, h.getHiddenBoundaryRight(3));
981
982     h.hideColumns(5, 10);
983     assertEquals(5, h.getHiddenBoundaryRight(3));
984     assertEquals(15, h.getHiddenBoundaryRight(15));
985     assertEquals(7, h.getHiddenBoundaryRight(7));
986
987     h.hideColumns(15, 20);
988     assertEquals(15, h.getHiddenBoundaryRight(7));
989     assertEquals(15, h.getHiddenBoundaryRight(14));
990   }
991
992   @Test(groups = "Functional")
993   public void testIterator()
994   {
995     HiddenColumns h = new HiddenColumns();
996     Iterator<int[]> result = h.iterator();
997     assertFalse(result.hasNext());
998
999     h.hideColumns(5, 10);
1000     result = h.iterator();
1001     int[] next = result.next();
1002     assertEquals(5, next[0]);
1003     assertEquals(10, next[1]);
1004     assertFalse(result.hasNext());
1005
1006     h.hideColumns(22, 23);
1007     result = h.iterator();
1008     next = result.next();
1009     assertEquals(5, next[0]);
1010     assertEquals(10, next[1]);
1011     next = result.next();
1012     assertEquals(22, next[0]);
1013     assertEquals(23, next[1]);
1014     assertFalse(result.hasNext());
1015
1016     // test for only one hidden region at start of alignment
1017     ColumnSelection sel = new ColumnSelection();
1018     h.revealAllHiddenColumns(sel);
1019     h.hideColumns(0, 1);
1020     result = h.iterator();
1021     next = result.next();
1022     assertEquals(0, next[0]);
1023     assertEquals(1, next[1]);
1024     assertFalse(result.hasNext());
1025   }
1026
1027   @Test(groups = "Functional")
1028   public void testGetVisibleSequenceStrings()
1029   {
1030     HiddenColumns h = new HiddenColumns();
1031     SequenceI seq1 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
1032     SequenceI seq2 = new Sequence("TEST2", "VICYHRNDTGA");
1033     SequenceI[] seqs = new SequenceI[2];
1034     seqs[0] = seq1;
1035     seqs[1] = seq2;
1036     String[] result = h.getVisibleSequenceStrings(5, 10, seqs);
1037     assertEquals(2, result.length);
1038     assertEquals("WKQES", result[0]);
1039     assertEquals("RNDTG", result[1]);
1040
1041     h.hideColumns(6, 8);
1042     result = h.getVisibleSequenceStrings(5, 10, seqs);
1043     assertEquals(2, result.length);
1044     assertEquals("WS", result[0]);
1045     assertEquals("RG", result[1]);
1046
1047     SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
1048     ColumnSelection sel = new ColumnSelection();
1049     h.revealAllHiddenColumns(sel);
1050     h.hideColumns(1, 3);
1051     h.hideColumns(6, 11);
1052     assertEquals("-D",
1053             h.getVisibleSequenceStrings(0, 5, new SequenceI[]
1054     { seq })[0]);
1055   }
1056
1057   @Test(groups = "Functional")
1058   public void testHideInsertionsFor()
1059   {
1060     HiddenColumns h = new HiddenColumns();
1061     HiddenColumns h2 = new HiddenColumns();
1062     SequenceI seq1 = new Sequence("TEST1", "GAL---MFW-KQESPVICY--HRNDT");
1063     SequenceI seq2 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
1064
1065     h.hideInsertionsFor(seq2);
1066     assertTrue(h.equals(h2));
1067
1068     h.hideInsertionsFor(seq1);
1069     h2.hideColumns(3, 5);
1070     h2.hideColumns(9, 9);
1071     h2.hideColumns(19, 20);
1072     assertTrue(h.equals(h2));
1073   }
1074
1075   @Test(groups = "Functional")
1076   public void testHideMarkedBits()
1077   {
1078     HiddenColumns h = new HiddenColumns();
1079     HiddenColumns h2 = new HiddenColumns();
1080
1081     BitSet tohide = new BitSet(21);
1082     h.hideMarkedBits(tohide);
1083     assertTrue(h.equals(h2));
1084
1085     // NB in hideMarkedBits, the last bit is not set to hidden
1086     tohide.set(3, 6);
1087     tohide.set(9);
1088     tohide.set(19, 21);
1089     h.hideMarkedBits(tohide);
1090
1091     h2.hideColumns(3, 5);
1092     h2.hideColumns(9, 9);
1093     h2.hideColumns(19, 20);
1094     assertTrue(h.equals(h2));
1095   }
1096
1097   @Test(groups = "Functional")
1098   public void testMakeVisibleAnnotation()
1099   {
1100     HiddenColumns h = new HiddenColumns();
1101     Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
1102         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1103         new Annotation(5), new Annotation(6), new Annotation(7),
1104         new Annotation(8) };
1105     AlignmentAnnotation ann = new AlignmentAnnotation("an", "some an",
1106             anns);
1107
1108     // without hidden cols, just truncates
1109     h.makeVisibleAnnotation(3, 5, ann);
1110     assertEquals(3, ann.annotations.length);
1111     assertEquals(2.0f, ann.annotations[0].value);
1112     assertEquals(3.0f, ann.annotations[1].value);
1113     assertNull(ann.annotations[2]);
1114
1115     anns = new Annotation[] { null, null, new Annotation(1),
1116         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1117         new Annotation(5), new Annotation(6), new Annotation(7),
1118         new Annotation(8) };
1119     ann = new AlignmentAnnotation("an", "some an", anns);
1120     h.hideColumns(4, 7);
1121     h.makeVisibleAnnotation(1, 9, ann);
1122     assertEquals(5, ann.annotations.length);
1123     assertNull(ann.annotations[0]);
1124     assertEquals(1.0f, ann.annotations[1].value);
1125     assertEquals(2.0f, ann.annotations[2].value);
1126     assertEquals(5.0f, ann.annotations[3].value);
1127     assertEquals(6.0f, ann.annotations[4].value);
1128
1129     anns = new Annotation[] { null, null, new Annotation(1),
1130         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1131         new Annotation(5), new Annotation(6), new Annotation(7),
1132         new Annotation(8) };
1133     ann = new AlignmentAnnotation("an", "some an", anns);
1134     h.hideColumns(1, 2);
1135     h.makeVisibleAnnotation(1, 9, ann);
1136     assertEquals(3, ann.annotations.length);
1137     assertEquals(2.0f, ann.annotations[0].value);
1138     assertEquals(5.0f, ann.annotations[1].value);
1139     assertEquals(6.0f, ann.annotations[2].value);
1140   }
1141
1142   @Test(groups = "Functional")
1143   public void testSubtractVisibleColumns()
1144   {
1145     HiddenColumns h = new HiddenColumns();
1146     int result = h.subtractVisibleColumns(1, 10);
1147     assertEquals(9, result);
1148
1149     h.hideColumns(7, 9);
1150     result = h.subtractVisibleColumns(4, 10);
1151     assertEquals(3, result);
1152
1153     h.hideColumns(14, 15);
1154     result = h.subtractVisibleColumns(4, 10);
1155     assertEquals(3, result);
1156
1157     result = h.subtractVisibleColumns(10, 17);
1158     assertEquals(2, result);
1159
1160     result = h.subtractVisibleColumns(1, 7);
1161     assertEquals(5, result);
1162
1163     result = h.subtractVisibleColumns(1, 8);
1164     assertEquals(5, result);
1165
1166     result = h.subtractVisibleColumns(3, 15);
1167     assertEquals(10, result);
1168
1169     ColumnSelection sel = new ColumnSelection();
1170     h.revealAllHiddenColumns(sel);
1171     h.hideColumns(0, 30);
1172     result = h.subtractVisibleColumns(31, 0);
1173     assertEquals(-31, result);
1174
1175     HiddenColumns cs = new HiddenColumns();
1176
1177     // test that without hidden columns, findColumnNToLeft returns
1178     // position n to left of provided position
1179     long pos = cs.subtractVisibleColumns(3, 10);
1180     assertEquals(7, pos);
1181
1182     // 0 returns same position
1183     pos = cs.subtractVisibleColumns(0, 10);
1184     assertEquals(10, pos);
1185
1186     // overflow to left returns negative number
1187     pos = cs.subtractVisibleColumns(3, 0);
1188     assertEquals(-3, pos);
1189
1190     // test that with hidden columns to left of result column
1191     // behaviour is the same as above
1192     cs.hideColumns(1, 3);
1193
1194     // position n to left of provided position
1195     pos = cs.subtractVisibleColumns(3, 10);
1196     assertEquals(7, pos);
1197
1198     // 0 returns same position
1199     pos = cs.subtractVisibleColumns(0, 10);
1200     assertEquals(10, pos);
1201
1202     // test with one set of hidden columns between start and required position
1203     cs.hideColumns(12, 15);
1204     pos = cs.subtractVisibleColumns(8, 17);
1205     assertEquals(5, pos);
1206
1207     // test with two sets of hidden columns between start and required position
1208     cs.hideColumns(20, 21);
1209     pos = cs.subtractVisibleColumns(8, 23);
1210     assertEquals(9, pos);
1211
1212     // repeat last 2 tests with no hidden columns to left of required position
1213     ColumnSelection colsel = new ColumnSelection();
1214     cs.revealAllHiddenColumns(colsel);
1215
1216     // test with one set of hidden columns between start and required position
1217     cs.hideColumns(12, 15);
1218     pos = cs.subtractVisibleColumns(8, 17);
1219     assertEquals(5, pos);
1220
1221     // test with two sets of hidden columns between start and required position
1222     cs.hideColumns(20, 21);
1223     pos = cs.subtractVisibleColumns(8, 23);
1224     assertEquals(9, pos);
1225
1226   }
1227
1228
1229   @Test(groups = "Functional")
1230   public void testBoundedIterator()
1231   {
1232     HiddenColumns h = new HiddenColumns();
1233     Iterator<int[]> it = h.getBoundedIterator(0, 10);
1234
1235     // no hidden columns = nothing to iterate over
1236     assertFalse(it.hasNext());
1237
1238     // [start,end] contains all hidden columns
1239     // all regions are returned
1240     h.hideColumns(3, 10);
1241     h.hideColumns(14, 16);
1242     it = h.getBoundedIterator(0, 20);
1243     assertTrue(it.hasNext());
1244     int[] next = it.next();
1245     assertEquals(3, next[0]);
1246     assertEquals(10, next[1]);
1247     next = it.next();
1248     assertEquals(14, next[0]);
1249     assertEquals(16, next[1]);
1250     assertFalse(it.hasNext());
1251
1252     // [start,end] overlaps a region
1253     // 1 region returned
1254     it = h.getBoundedIterator(5, 7);
1255     assertTrue(it.hasNext());
1256     next = it.next();
1257     assertEquals(3, next[0]);
1258     assertEquals(10, next[1]);
1259     assertFalse(it.hasNext());
1260
1261     // [start,end] fully contains 1 region and start of last
1262     // - 2 regions returned
1263     it = h.getBoundedIterator(3, 15);
1264     assertTrue(it.hasNext());
1265     next = it.next();
1266     assertEquals(3, next[0]);
1267     assertEquals(10, next[1]);
1268     next = it.next();
1269     assertEquals(14, next[0]);
1270     assertEquals(16, next[1]);
1271     assertFalse(it.hasNext());
1272
1273     // [start,end] contains end of first region and whole of last region
1274     // - 2 regions returned
1275     it = h.getBoundedIterator(4, 20);
1276     assertTrue(it.hasNext());
1277     next = it.next();
1278     assertEquals(3, next[0]);
1279     assertEquals(10, next[1]);
1280     next = it.next();
1281     assertEquals(14, next[0]);
1282     assertEquals(16, next[1]);
1283     assertFalse(it.hasNext());
1284   }
1285
1286   @Test(groups = "Functional")
1287   public void testBoundedStartIterator()
1288   {
1289     HiddenColumns h = new HiddenColumns();
1290     Iterator<Integer> it = h.getBoundedStartIterator(0, 10);
1291
1292     // no hidden columns = nothing to iterate over
1293     assertFalse(it.hasNext());
1294
1295     // [start,end] contains all hidden columns
1296     // all regions are returned
1297     h.hideColumns(3, 10);
1298     h.hideColumns(14, 16);
1299     it = h.getBoundedStartIterator(0, 20);
1300     assertTrue(it.hasNext());
1301     int next = it.next();
1302     assertEquals(3, next);
1303     next = it.next();
1304     assertEquals(6, next);
1305     assertFalse(it.hasNext());
1306
1307     // [start,end] does not contain a start of a region
1308     // no regions to iterate over
1309     it = h.getBoundedStartIterator(4, 5);
1310     assertFalse(it.hasNext());
1311
1312     // [start,end] fully contains 1 region and start of last
1313     // - 2 regions returned
1314     it = h.getBoundedStartIterator(3, 7);
1315     assertTrue(it.hasNext());
1316     next = it.next();
1317     assertEquals(3, next);
1318     next = it.next();
1319     assertEquals(6, next);
1320     assertFalse(it.hasNext());
1321
1322     // [start,end] contains whole of last region
1323     // - 1 region returned
1324     it = h.getBoundedStartIterator(4, 20);
1325     assertTrue(it.hasNext());
1326     next = it.next();
1327     assertEquals(6, next);
1328     assertFalse(it.hasNext());
1329   }
1330
1331   @Test(groups = "Functional")
1332   public void testVisibleBlocksVisBoundsIterator()
1333   {
1334     HiddenColumns h = new HiddenColumns();
1335     Iterator<int[]> regions = h.getVisibleBlocksIterator(0, 30, true);
1336
1337     // only 1 visible region spanning 0-30 if nothing is hidden
1338     assertTrue(regions.hasNext());
1339     int[] region = regions.next();
1340     assertEquals(0, region[0]);
1341     assertEquals(30, region[1]);
1342     assertFalse(regions.hasNext());
1343
1344     // hide 1 region in middle
1345     // 2 regions one on either side
1346     // second region boundary accounts for hidden columns
1347     h.hideColumns(10, 15);
1348     regions = h.getVisibleBlocksIterator(0, 30, true);
1349
1350     assertTrue(regions.hasNext());
1351     region = regions.next();
1352     assertEquals(0, region[0]);
1353     assertEquals(9, region[1]);
1354     region = regions.next();
1355     assertEquals(16, region[0]);
1356     assertEquals(36, region[1]);
1357     assertFalse(regions.hasNext());
1358
1359     // single hidden region at left
1360     h = new HiddenColumns();
1361     h.hideColumns(0, 5);
1362     regions = h.getVisibleBlocksIterator(0, 30, true);
1363
1364     assertTrue(regions.hasNext());
1365     region = regions.next();
1366     assertEquals(6, region[0]);
1367     assertEquals(36, region[1]);
1368     assertFalse(regions.hasNext());
1369
1370     // single hidden region at right
1371     h = new HiddenColumns();
1372     h.hideColumns(27, 30);
1373     regions = h.getVisibleBlocksIterator(0, 30, true);
1374
1375     assertTrue(regions.hasNext());
1376     region = regions.next();
1377     assertEquals(0, region[0]);
1378     assertEquals(26, region[1]);
1379     region = regions.next();
1380     assertEquals(31, region[0]);
1381     assertEquals(34, region[1]);
1382     assertFalse(regions.hasNext());
1383
1384     // hidden region at left + hidden region in middle
1385     h = new HiddenColumns();
1386     h.hideColumns(0, 5);
1387     h.hideColumns(23, 25);
1388     regions = h.getVisibleBlocksIterator(0, 30, true);
1389
1390     assertTrue(regions.hasNext());
1391     region = regions.next();
1392     assertEquals(6, region[0]);
1393     assertEquals(22, region[1]);
1394     region = regions.next();
1395     assertEquals(26, region[0]);
1396     assertEquals(39, region[1]);
1397     assertFalse(regions.hasNext());
1398
1399     // hidden region at right + hidden region in middle
1400     h = new HiddenColumns();
1401     h.hideColumns(27, 30);
1402     h.hideColumns(11, 14);
1403     regions = h.getVisibleBlocksIterator(0, 30, true);
1404
1405     assertTrue(regions.hasNext());
1406     region = regions.next();
1407     assertEquals(0, region[0]);
1408     assertEquals(10, region[1]);
1409     region = regions.next();
1410     assertEquals(15, region[0]);
1411     assertEquals(26, region[1]);
1412     region = regions.next();
1413     assertEquals(31, region[0]);
1414     assertEquals(38, region[1]);
1415     assertFalse(regions.hasNext());
1416
1417     // hidden region at left and right
1418     h = new HiddenColumns();
1419     h.hideColumns(27, 35);
1420     h.hideColumns(0, 4);
1421     regions = h.getVisibleBlocksIterator(0, 30, true);
1422
1423     assertTrue(regions.hasNext());
1424     region = regions.next();
1425     assertEquals(5, region[0]);
1426     assertEquals(26, region[1]);
1427     region = regions.next();
1428     assertEquals(36, region[0]);
1429     assertEquals(44, region[1]);
1430     assertFalse(regions.hasNext());
1431
1432     // multiple hidden regions
1433     h = new HiddenColumns();
1434     h.hideColumns(1, 1);
1435     h.hideColumns(3, 5);
1436     h.hideColumns(9, 11);
1437     h.hideColumns(22, 26);
1438
1439     regions = h.getVisibleBlocksIterator(0, 30, true);
1440
1441     assertTrue(regions.hasNext());
1442     region = regions.next();
1443     assertEquals(0, region[0]);
1444     assertEquals(0, region[1]);
1445     region = regions.next();
1446     assertEquals(2, region[0]);
1447     assertEquals(2, region[1]);
1448     region = regions.next();
1449     assertEquals(6, region[0]);
1450     assertEquals(8, region[1]);
1451     region = regions.next();
1452     assertEquals(12, region[0]);
1453     assertEquals(21, region[1]);
1454     region = regions.next();
1455     assertEquals(27, region[0]);
1456     assertEquals(42, region[1]);
1457     assertFalse(regions.hasNext());
1458   }
1459 }