JAL-2759 convert findColumnPosition 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
779   @Test(groups = "Functional")
780   public void testPropagateInsertions()
781   {
782     // create an alignment with no gaps - this will be the profile seq and other
783     // JPRED seqs
784     AlignmentGenerator gen = new AlignmentGenerator(false);
785     AlignmentI al = gen.generate(25, 10, 1234, 0, 0);
786
787     // get the profileseq
788     SequenceI profileseq = al.getSequenceAt(0);
789     SequenceI gappedseq = new Sequence(profileseq);
790     gappedseq.insertCharAt(5, al.getGapCharacter());
791     gappedseq.insertCharAt(6, al.getGapCharacter());
792     gappedseq.insertCharAt(7, al.getGapCharacter());
793     gappedseq.insertCharAt(8, al.getGapCharacter());
794
795     // create an alignment view with the gapped sequence
796     SequenceI[] seqs = new SequenceI[1];
797     seqs[0] = gappedseq;
798     AlignmentI newal = new Alignment(seqs);
799     HiddenColumns hidden = new HiddenColumns();
800     hidden.hideColumns(15, 17);
801
802     AlignmentView view = new AlignmentView(newal, hidden, null, true, false,
803             false);
804
805     // confirm that original contigs are as expected
806     Iterator<int[]> visible = hidden.getVisContigsIterator(0, 25);
807     int[] region = visible.next();
808     assertEquals("[0, 14]", Arrays.toString(region));
809     region = visible.next();
810     assertEquals("[18, 24]", Arrays.toString(region));
811
812     // propagate insertions
813     HiddenColumns result = HiddenColumns.propagateInsertions(profileseq, al,
814             view);
815
816     // confirm that the contigs have changed to account for the gaps
817     visible = result.getVisContigsIterator(0, 25);
818     region = visible.next();
819     assertEquals("[0, 10]", Arrays.toString(region));
820     region = visible.next();
821     assertEquals("[14, 24]", Arrays.toString(region));
822
823     // confirm the alignment has been changed so that the other sequences have
824     // gaps inserted where the columns are hidden
825     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[10]));
826     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[11]));
827     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[12]));
828     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[13]));
829     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[14]));
830
831   }
832
833   @Test(groups = "Functional")
834   public void testPropagateInsertionsOverlap()
835   {
836     // test propagateInsertions where gaps and hiddenColumns overlap
837
838     // create an alignment with no gaps - this will be the profile seq and other
839     // JPRED seqs
840     AlignmentGenerator gen = new AlignmentGenerator(false);
841     AlignmentI al = gen.generate(20, 10, 1234, 0, 0);
842
843     // get the profileseq
844     SequenceI profileseq = al.getSequenceAt(0);
845     SequenceI gappedseq = new Sequence(profileseq);
846     gappedseq.insertCharAt(5, al.getGapCharacter());
847     gappedseq.insertCharAt(6, al.getGapCharacter());
848     gappedseq.insertCharAt(7, al.getGapCharacter());
849     gappedseq.insertCharAt(8, al.getGapCharacter());
850
851     // create an alignment view with the gapped sequence
852     SequenceI[] seqs = new SequenceI[1];
853     seqs[0] = gappedseq;
854     AlignmentI newal = new Alignment(seqs);
855
856     // hide columns so that some overlap with the gaps
857     HiddenColumns hidden = new HiddenColumns();
858     hidden.hideColumns(7, 10);
859
860     AlignmentView view = new AlignmentView(newal, hidden, null, true, false,
861             false);
862
863     // confirm that original contigs are as expected
864     Iterator<int[]> visible = hidden.getVisContigsIterator(0, 20);
865     int[] region = visible.next();
866     assertEquals("[0, 6]", Arrays.toString(region));
867     region = visible.next();
868     assertEquals("[11, 19]", Arrays.toString(region));
869     assertFalse(visible.hasNext());
870
871     // propagate insertions
872     HiddenColumns result = HiddenColumns.propagateInsertions(profileseq, al,
873             view);
874
875     // confirm that the contigs have changed to account for the gaps
876     visible = result.getVisContigsIterator(0, 20);
877     region = visible.next();
878     assertEquals("[0, 4]", Arrays.toString(region));
879     region = visible.next();
880     assertEquals("[7, 19]", Arrays.toString(region));
881     assertFalse(visible.hasNext());
882
883     // confirm the alignment has been changed so that the other sequences have
884     // gaps inserted where the columns are hidden
885     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[4]));
886     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[5]));
887     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[6]));
888     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[7]));
889   }
890
891   @Test(groups = "Functional")
892   public void testHasHiddenColumns()
893   {
894     HiddenColumns h = new HiddenColumns();
895
896     // new HiddenColumns2 has no hidden cols
897     assertFalse(h.hasHiddenColumns());
898
899     // some columns hidden, returns true
900     h.hideColumns(5, 10);
901     assertTrue(h.hasHiddenColumns());
902
903     // reveal columns, no hidden cols again
904     ColumnSelection sel = new ColumnSelection();
905     h.revealAllHiddenColumns(sel);
906     assertFalse(h.hasHiddenColumns());
907   }
908
909   @Test(groups = "Functional")
910   public void testHasManyHiddenColumns()
911   {
912     HiddenColumns h = new HiddenColumns();
913
914     // new HiddenColumns2 has no hidden cols
915     assertFalse(h.hasManyHiddenColumns());
916
917     // one set of columns hidden, returns false
918     h.hideColumns(5, 10);
919     assertFalse(h.hasManyHiddenColumns());
920
921     // two sets hidden, returns true
922     h.hideColumns(15, 17);
923     assertTrue(h.hasManyHiddenColumns());
924
925     // back to one block, asserts false
926     h.hideColumns(11, 14);
927     assertFalse(h.hasManyHiddenColumns());
928   }
929
930   @Test(groups = "Functional")
931   public void testAdjustForHiddenColumns()
932   {
933     HiddenColumns h = new HiddenColumns();
934     // returns input value when there are no hidden columns
935     assertEquals(10, h.adjustForHiddenColumns(10));
936
937     h.hideColumns(20, 30);
938     assertEquals(10, h.adjustForHiddenColumns(10));
939     assertEquals(20 + 11, h.adjustForHiddenColumns(20));
940     assertEquals(35 + 11, h.adjustForHiddenColumns(35));
941
942     h.hideColumns(5, 7);
943     assertEquals(10 + 3, h.adjustForHiddenColumns(10));
944     assertEquals(20 + 14, h.adjustForHiddenColumns(20));
945     assertEquals(35 + 14, h.adjustForHiddenColumns(35));
946
947     ColumnSelection sel = new ColumnSelection();
948     h.revealAllHiddenColumns(sel);
949     h.hideColumns(0, 1);
950     assertEquals(4, h.adjustForHiddenColumns(2));
951   }
952
953   @Test(groups = "Functional")
954   public void testGetHiddenBoundaryLeft()
955   {
956     HiddenColumns h = new HiddenColumns();
957
958     // returns same value if no hidden cols
959     assertEquals(3, h.getHiddenBoundaryLeft(3));
960
961     h.hideColumns(5, 10);
962     assertEquals(10, h.getHiddenBoundaryLeft(15));
963     assertEquals(3, h.getHiddenBoundaryLeft(3));
964     assertEquals(7, h.getHiddenBoundaryLeft(7));
965
966     h.hideColumns(15, 20);
967     assertEquals(10, h.getHiddenBoundaryLeft(15));
968     assertEquals(20, h.getHiddenBoundaryLeft(21));
969   }
970
971   @Test(groups = "Functional")
972   public void testGetHiddenBoundaryRight()
973   {
974     HiddenColumns h = new HiddenColumns();
975
976     // returns same value if no hidden cols
977     assertEquals(3, h.getHiddenBoundaryRight(3));
978
979     h.hideColumns(5, 10);
980     assertEquals(5, h.getHiddenBoundaryRight(3));
981     assertEquals(15, h.getHiddenBoundaryRight(15));
982     assertEquals(7, h.getHiddenBoundaryRight(7));
983
984     h.hideColumns(15, 20);
985     assertEquals(15, h.getHiddenBoundaryRight(7));
986     assertEquals(15, h.getHiddenBoundaryRight(14));
987   }
988
989   @Test(groups = "Functional")
990   public void testIterator()
991   {
992     HiddenColumns h = new HiddenColumns();
993     Iterator<int[]> result = h.iterator();
994     assertFalse(result.hasNext());
995
996     h.hideColumns(5, 10);
997     result = h.iterator();
998     int[] next = result.next();
999     assertEquals(5, next[0]);
1000     assertEquals(10, next[1]);
1001     assertFalse(result.hasNext());
1002
1003     h.hideColumns(22, 23);
1004     result = h.iterator();
1005     next = result.next();
1006     assertEquals(5, next[0]);
1007     assertEquals(10, next[1]);
1008     next = result.next();
1009     assertEquals(22, next[0]);
1010     assertEquals(23, next[1]);
1011     assertFalse(result.hasNext());
1012
1013     // test for only one hidden region at start of alignment
1014     ColumnSelection sel = new ColumnSelection();
1015     h.revealAllHiddenColumns(sel);
1016     h.hideColumns(0, 1);
1017     result = h.iterator();
1018     next = result.next();
1019     assertEquals(0, next[0]);
1020     assertEquals(1, next[1]);
1021     assertFalse(result.hasNext());
1022   }
1023
1024   @Test(groups = "Functional")
1025   public void testGetVisibleSequenceStrings()
1026   {
1027     HiddenColumns h = new HiddenColumns();
1028     SequenceI seq1 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
1029     SequenceI seq2 = new Sequence("TEST2", "VICYHRNDTGA");
1030     SequenceI[] seqs = new SequenceI[2];
1031     seqs[0] = seq1;
1032     seqs[1] = seq2;
1033     String[] result = h.getVisibleSequenceStrings(5, 10, seqs);
1034     assertEquals(2, result.length);
1035     assertEquals("WKQES", result[0]);
1036     assertEquals("RNDTG", result[1]);
1037
1038     h.hideColumns(6, 8);
1039     result = h.getVisibleSequenceStrings(5, 10, seqs);
1040     assertEquals(2, result.length);
1041     assertEquals("WS", result[0]);
1042     assertEquals("RG", result[1]);
1043
1044     SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
1045     ColumnSelection sel = new ColumnSelection();
1046     h.revealAllHiddenColumns(sel);
1047     h.hideColumns(1, 3);
1048     h.hideColumns(6, 11);
1049     assertEquals("-D",
1050             h.getVisibleSequenceStrings(0, 5, new SequenceI[]
1051     { seq })[0]);
1052   }
1053
1054   @Test(groups = "Functional")
1055   public void testHideInsertionsFor()
1056   {
1057     HiddenColumns h = new HiddenColumns();
1058     HiddenColumns h2 = new HiddenColumns();
1059     SequenceI seq1 = new Sequence("TEST1", "GAL---MFW-KQESPVICY--HRNDT");
1060     SequenceI seq2 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
1061
1062     h.hideInsertionsFor(seq2);
1063     assertTrue(h.equals(h2));
1064
1065     h.hideInsertionsFor(seq1);
1066     h2.hideColumns(3, 5);
1067     h2.hideColumns(9, 9);
1068     h2.hideColumns(19, 20);
1069     assertTrue(h.equals(h2));
1070   }
1071
1072   @Test(groups = "Functional")
1073   public void testHideMarkedBits()
1074   {
1075     HiddenColumns h = new HiddenColumns();
1076     HiddenColumns h2 = new HiddenColumns();
1077
1078     BitSet tohide = new BitSet(21);
1079     h.hideMarkedBits(tohide);
1080     assertTrue(h.equals(h2));
1081
1082     // NB in hideMarkedBits, the last bit is not set to hidden
1083     tohide.set(3, 6);
1084     tohide.set(9);
1085     tohide.set(19, 21);
1086     h.hideMarkedBits(tohide);
1087
1088     h2.hideColumns(3, 5);
1089     h2.hideColumns(9, 9);
1090     h2.hideColumns(19, 20);
1091     assertTrue(h.equals(h2));
1092   }
1093
1094   @Test(groups = "Functional")
1095   public void testMakeVisibleAnnotation()
1096   {
1097     HiddenColumns h = new HiddenColumns();
1098     Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
1099         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1100         new Annotation(5), new Annotation(6), new Annotation(7),
1101         new Annotation(8) };
1102     AlignmentAnnotation ann = new AlignmentAnnotation("an", "some an",
1103             anns);
1104
1105     // without hidden cols, just truncates
1106     h.makeVisibleAnnotation(3, 5, ann);
1107     assertEquals(3, ann.annotations.length);
1108     assertEquals(2.0f, ann.annotations[0].value);
1109     assertEquals(3.0f, ann.annotations[1].value);
1110     assertNull(ann.annotations[2]);
1111
1112     anns = new Annotation[] { null, null, new Annotation(1),
1113         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1114         new Annotation(5), new Annotation(6), new Annotation(7),
1115         new Annotation(8) };
1116     ann = new AlignmentAnnotation("an", "some an", anns);
1117     h.hideColumns(4, 7);
1118     h.makeVisibleAnnotation(1, 9, ann);
1119     assertEquals(5, ann.annotations.length);
1120     assertNull(ann.annotations[0]);
1121     assertEquals(1.0f, ann.annotations[1].value);
1122     assertEquals(2.0f, ann.annotations[2].value);
1123     assertEquals(5.0f, ann.annotations[3].value);
1124     assertEquals(6.0f, ann.annotations[4].value);
1125
1126     anns = new Annotation[] { null, null, new Annotation(1),
1127         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1128         new Annotation(5), new Annotation(6), new Annotation(7),
1129         new Annotation(8) };
1130     ann = new AlignmentAnnotation("an", "some an", anns);
1131     h.hideColumns(1, 2);
1132     h.makeVisibleAnnotation(1, 9, ann);
1133     assertEquals(3, ann.annotations.length);
1134     assertEquals(2.0f, ann.annotations[0].value);
1135     assertEquals(5.0f, ann.annotations[1].value);
1136     assertEquals(6.0f, ann.annotations[2].value);
1137   }
1138
1139   @Test(groups = "Functional")
1140   public void testSubtractVisibleColumns()
1141   {
1142     HiddenColumns h = new HiddenColumns();
1143     int result = h.subtractVisibleColumns(1, 10);
1144     assertEquals(9, result);
1145
1146     h.hideColumns(7, 9);
1147     result = h.subtractVisibleColumns(4, 10);
1148     assertEquals(3, result);
1149
1150     h.hideColumns(14, 15);
1151     result = h.subtractVisibleColumns(4, 10);
1152     assertEquals(3, result);
1153
1154     result = h.subtractVisibleColumns(10, 17);
1155     assertEquals(2, result);
1156
1157     result = h.subtractVisibleColumns(1, 7);
1158     assertEquals(5, result);
1159
1160     result = h.subtractVisibleColumns(1, 8);
1161     assertEquals(5, result);
1162
1163     result = h.subtractVisibleColumns(3, 15);
1164     assertEquals(10, result);
1165
1166     ColumnSelection sel = new ColumnSelection();
1167     h.revealAllHiddenColumns(sel);
1168     h.hideColumns(0, 30);
1169     result = h.subtractVisibleColumns(31, 0);
1170     assertEquals(-31, result);
1171
1172     HiddenColumns cs = new HiddenColumns();
1173
1174     // test that without hidden columns, findColumnNToLeft returns
1175     // position n to left of provided position
1176     long pos = cs.subtractVisibleColumns(3, 10);
1177     assertEquals(7, pos);
1178
1179     // 0 returns same position
1180     pos = cs.subtractVisibleColumns(0, 10);
1181     assertEquals(10, pos);
1182
1183     // overflow to left returns negative number
1184     pos = cs.subtractVisibleColumns(3, 0);
1185     assertEquals(-3, pos);
1186
1187     // test that with hidden columns to left of result column
1188     // behaviour is the same as above
1189     cs.hideColumns(1, 3);
1190
1191     // position n to left of provided position
1192     pos = cs.subtractVisibleColumns(3, 10);
1193     assertEquals(7, pos);
1194
1195     // 0 returns same position
1196     pos = cs.subtractVisibleColumns(0, 10);
1197     assertEquals(10, pos);
1198
1199     // test with one set of hidden columns between start and required position
1200     cs.hideColumns(12, 15);
1201     pos = cs.subtractVisibleColumns(8, 17);
1202     assertEquals(5, pos);
1203
1204     // test with two sets of hidden columns between start and required position
1205     cs.hideColumns(20, 21);
1206     pos = cs.subtractVisibleColumns(8, 23);
1207     assertEquals(9, pos);
1208
1209     // repeat last 2 tests with no hidden columns to left of required position
1210     ColumnSelection colsel = new ColumnSelection();
1211     cs.revealAllHiddenColumns(colsel);
1212
1213     // test with one set of hidden columns between start and required position
1214     cs.hideColumns(12, 15);
1215     pos = cs.subtractVisibleColumns(8, 17);
1216     assertEquals(5, pos);
1217
1218     // test with two sets of hidden columns between start and required position
1219     cs.hideColumns(20, 21);
1220     pos = cs.subtractVisibleColumns(8, 23);
1221     assertEquals(9, pos);
1222
1223   }
1224
1225
1226   @Test(groups = "Functional")
1227   public void testBoundedIterator()
1228   {
1229     HiddenColumns h = new HiddenColumns();
1230     Iterator<int[]> it = h.getBoundedIterator(0, 10);
1231
1232     // no hidden columns = nothing to iterate over
1233     assertFalse(it.hasNext());
1234
1235     // [start,end] contains all hidden columns
1236     // all regions are returned
1237     h.hideColumns(3, 10);
1238     h.hideColumns(14, 16);
1239     it = h.getBoundedIterator(0, 20);
1240     assertTrue(it.hasNext());
1241     int[] next = it.next();
1242     assertEquals(3, next[0]);
1243     assertEquals(10, next[1]);
1244     next = it.next();
1245     assertEquals(14, next[0]);
1246     assertEquals(16, next[1]);
1247     assertFalse(it.hasNext());
1248
1249     // [start,end] overlaps a region
1250     // 1 region returned
1251     it = h.getBoundedIterator(5, 7);
1252     assertTrue(it.hasNext());
1253     next = it.next();
1254     assertEquals(3, next[0]);
1255     assertEquals(10, next[1]);
1256     assertFalse(it.hasNext());
1257
1258     // [start,end] fully contains 1 region and start of last
1259     // - 2 regions returned
1260     it = h.getBoundedIterator(3, 15);
1261     assertTrue(it.hasNext());
1262     next = it.next();
1263     assertEquals(3, next[0]);
1264     assertEquals(10, next[1]);
1265     next = it.next();
1266     assertEquals(14, next[0]);
1267     assertEquals(16, next[1]);
1268     assertFalse(it.hasNext());
1269
1270     // [start,end] contains end of first region and whole of last region
1271     // - 2 regions returned
1272     it = h.getBoundedIterator(4, 20);
1273     assertTrue(it.hasNext());
1274     next = it.next();
1275     assertEquals(3, next[0]);
1276     assertEquals(10, next[1]);
1277     next = it.next();
1278     assertEquals(14, next[0]);
1279     assertEquals(16, next[1]);
1280     assertFalse(it.hasNext());
1281   }
1282
1283   @Test(groups = "Functional")
1284   public void testBoundedStartIterator()
1285   {
1286     HiddenColumns h = new HiddenColumns();
1287     Iterator<Integer> it = h.getBoundedStartIterator(0, 10);
1288
1289     // no hidden columns = nothing to iterate over
1290     assertFalse(it.hasNext());
1291
1292     // [start,end] contains all hidden columns
1293     // all regions are returned
1294     h.hideColumns(3, 10);
1295     h.hideColumns(14, 16);
1296     it = h.getBoundedStartIterator(0, 20);
1297     assertTrue(it.hasNext());
1298     int next = it.next();
1299     assertEquals(3, next);
1300     next = it.next();
1301     assertEquals(6, next);
1302     assertFalse(it.hasNext());
1303
1304     // [start,end] does not contain a start of a region
1305     // no regions to iterate over
1306     it = h.getBoundedStartIterator(4, 5);
1307     assertFalse(it.hasNext());
1308
1309     // [start,end] fully contains 1 region and start of last
1310     // - 2 regions returned
1311     it = h.getBoundedStartIterator(3, 7);
1312     assertTrue(it.hasNext());
1313     next = it.next();
1314     assertEquals(3, next);
1315     next = it.next();
1316     assertEquals(6, next);
1317     assertFalse(it.hasNext());
1318
1319     // [start,end] contains whole of last region
1320     // - 1 region returned
1321     it = h.getBoundedStartIterator(4, 20);
1322     assertTrue(it.hasNext());
1323     next = it.next();
1324     assertEquals(6, next);
1325     assertFalse(it.hasNext());
1326   }
1327
1328   @Test(groups = "Functional")
1329   public void testVisibleBlocksVisBoundsIterator()
1330   {
1331     HiddenColumns h = new HiddenColumns();
1332     Iterator<int[]> regions = h.getVisibleBlocksIterator(0, 30, true);
1333
1334     // only 1 visible region spanning 0-30 if nothing is hidden
1335     assertTrue(regions.hasNext());
1336     int[] region = regions.next();
1337     assertEquals(0, region[0]);
1338     assertEquals(30, region[1]);
1339     assertFalse(regions.hasNext());
1340
1341     // hide 1 region in middle
1342     // 2 regions one on either side
1343     // second region boundary accounts for hidden columns
1344     h.hideColumns(10, 15);
1345     regions = h.getVisibleBlocksIterator(0, 30, true);
1346
1347     assertTrue(regions.hasNext());
1348     region = regions.next();
1349     assertEquals(0, region[0]);
1350     assertEquals(9, region[1]);
1351     region = regions.next();
1352     assertEquals(16, region[0]);
1353     assertEquals(36, region[1]);
1354     assertFalse(regions.hasNext());
1355
1356     // single hidden region at left
1357     h = new HiddenColumns();
1358     h.hideColumns(0, 5);
1359     regions = h.getVisibleBlocksIterator(0, 30, true);
1360
1361     assertTrue(regions.hasNext());
1362     region = regions.next();
1363     assertEquals(6, region[0]);
1364     assertEquals(36, region[1]);
1365     assertFalse(regions.hasNext());
1366
1367     // single hidden region at right
1368     h = new HiddenColumns();
1369     h.hideColumns(27, 30);
1370     regions = h.getVisibleBlocksIterator(0, 30, true);
1371
1372     assertTrue(regions.hasNext());
1373     region = regions.next();
1374     assertEquals(0, region[0]);
1375     assertEquals(26, region[1]);
1376     region = regions.next();
1377     assertEquals(31, region[0]);
1378     assertEquals(34, region[1]);
1379     assertFalse(regions.hasNext());
1380
1381     // hidden region at left + hidden region in middle
1382     h = new HiddenColumns();
1383     h.hideColumns(0, 5);
1384     h.hideColumns(23, 25);
1385     regions = h.getVisibleBlocksIterator(0, 30, true);
1386
1387     assertTrue(regions.hasNext());
1388     region = regions.next();
1389     assertEquals(6, region[0]);
1390     assertEquals(22, region[1]);
1391     region = regions.next();
1392     assertEquals(26, region[0]);
1393     assertEquals(39, region[1]);
1394     assertFalse(regions.hasNext());
1395
1396     // hidden region at right + hidden region in middle
1397     h = new HiddenColumns();
1398     h.hideColumns(27, 30);
1399     h.hideColumns(11, 14);
1400     regions = h.getVisibleBlocksIterator(0, 30, true);
1401
1402     assertTrue(regions.hasNext());
1403     region = regions.next();
1404     assertEquals(0, region[0]);
1405     assertEquals(10, region[1]);
1406     region = regions.next();
1407     assertEquals(15, region[0]);
1408     assertEquals(26, region[1]);
1409     region = regions.next();
1410     assertEquals(31, region[0]);
1411     assertEquals(38, region[1]);
1412     assertFalse(regions.hasNext());
1413
1414     // hidden region at left and right
1415     h = new HiddenColumns();
1416     h.hideColumns(27, 35);
1417     h.hideColumns(0, 4);
1418     regions = h.getVisibleBlocksIterator(0, 30, true);
1419
1420     assertTrue(regions.hasNext());
1421     region = regions.next();
1422     assertEquals(5, region[0]);
1423     assertEquals(26, region[1]);
1424     region = regions.next();
1425     assertEquals(36, region[0]);
1426     assertEquals(44, region[1]);
1427     assertFalse(regions.hasNext());
1428
1429     // multiple hidden regions
1430     h = new HiddenColumns();
1431     h.hideColumns(1, 1);
1432     h.hideColumns(3, 5);
1433     h.hideColumns(9, 11);
1434     h.hideColumns(22, 26);
1435
1436     regions = h.getVisibleBlocksIterator(0, 30, true);
1437
1438     assertTrue(regions.hasNext());
1439     region = regions.next();
1440     assertEquals(0, region[0]);
1441     assertEquals(0, region[1]);
1442     region = regions.next();
1443     assertEquals(2, region[0]);
1444     assertEquals(2, region[1]);
1445     region = regions.next();
1446     assertEquals(6, region[0]);
1447     assertEquals(8, region[1]);
1448     region = regions.next();
1449     assertEquals(12, region[0]);
1450     assertEquals(21, region[1]);
1451     region = regions.next();
1452     assertEquals(27, region[0]);
1453     assertEquals(42, region[1]);
1454     assertFalse(regions.hasNext());
1455   }
1456 }