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