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