JAL-2388 New iterators and tests
authorkiramt <k.mourao@dundee.ac.uk>
Wed, 29 Mar 2017 09:51:59 +0000 (10:51 +0100)
committerkiramt <k.mourao@dundee.ac.uk>
Wed, 29 Mar 2017 09:51:59 +0000 (10:51 +0100)
src/jalview/datamodel/AllColsIterator.java [new file with mode: 0644]
src/jalview/datamodel/AllRowsIterator.java [new file with mode: 0644]
src/jalview/datamodel/VisibleColsIterator.java [new file with mode: 0644]
src/jalview/datamodel/VisibleRowsIterator.java [new file with mode: 0644]
test/jalview/datamodel/AllColsIteratorTest.java [new file with mode: 0644]
test/jalview/datamodel/AllRowsIteratorTest.java [new file with mode: 0644]
test/jalview/datamodel/VisibleColsIteratorTest.java [new file with mode: 0644]
test/jalview/datamodel/VisibleRowsIteratorTest.java [new file with mode: 0644]

diff --git a/src/jalview/datamodel/AllColsIterator.java b/src/jalview/datamodel/AllColsIterator.java
new file mode 100644 (file)
index 0000000..4e1ff2e
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * An iterator which iterates over all columns or rows in an alignment, whether
+ * hidden or visible.
+ * 
+ * @author kmourao
+ *
+ */
+public class AllColsIterator implements Iterator<Integer>
+{
+  private int last;
+
+  private int next;
+
+  private int current;
+
+  ColumnSelection hidden;
+
+  public AllColsIterator(int firstcol, int lastcol,
+          ColumnSelection hiddenCols)
+  {
+    last = lastcol;
+    next = firstcol;
+    current = firstcol;
+    hidden = hiddenCols;
+  }
+
+  @Override
+  public boolean hasNext()
+  {
+    return current + 1 <= last;
+  }
+
+  @Override
+  public Integer next()
+  {
+    if (current + 1 > last)
+    {
+      throw new NoSuchElementException();
+    }
+    current = next;
+    next++;
+
+    return current;
+  }
+
+  @Override
+  public void remove()
+  {
+    throw new UnsupportedOperationException();
+  }
+}
+
diff --git a/src/jalview/datamodel/AllRowsIterator.java b/src/jalview/datamodel/AllRowsIterator.java
new file mode 100644 (file)
index 0000000..aefed60
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * An iterator which iterates over all columns or rows in an alignment, whether
+ * hidden or visible.
+ * 
+ * @author kmourao
+ *
+ */
+public class AllRowsIterator implements Iterator<Integer>
+{
+  private int last;
+
+  private int next;
+
+  private int current;
+
+  private AlignmentI al;
+
+  public AllRowsIterator(int firstrow, int lastrow, AlignmentI alignment)
+  {
+    last = lastrow;
+    current = firstrow;
+    next = firstrow;
+    al = alignment;
+  }
+
+  @Override
+  public boolean hasNext()
+  {
+    return current + 1 <= last;
+  }
+
+  @Override
+  public Integer next()
+  {
+    if (current + 1 > last)
+    {
+      throw new NoSuchElementException();
+    }
+    current = next;
+    next++;
+
+    return current;
+  }
+
+  @Override
+  public void remove()
+  {
+    throw new UnsupportedOperationException();
+  }
+}
+
+
diff --git a/src/jalview/datamodel/VisibleColsIterator.java b/src/jalview/datamodel/VisibleColsIterator.java
new file mode 100644 (file)
index 0000000..2a69a82
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * An iterator which iterates over all visible columns in an alignment
+ * 
+ * @author kmourao
+ *
+ */
+public class VisibleColsIterator implements Iterator<Integer>
+{
+  private int last;
+
+  private int current;
+
+  private int next;
+
+  private List<int[]> hidden;
+
+  private int lasthiddenregion;
+
+  public VisibleColsIterator(int firstcol, int lastcol,
+          ColumnSelection hiddenCols)
+  {
+    last = lastcol;
+    current = firstcol;
+    next = firstcol;
+    hidden = hiddenCols.getHiddenColumns();
+    lasthiddenregion = -1;
+
+    if (hidden != null)
+    {
+      int i = 0;
+      for (i = 0; i < hidden.size(); ++i)
+      {
+        if (current >= hidden.get(i)[0] && current <= hidden.get(i)[1])
+        {
+          // current is hidden, move to right
+          current = hidden.get(i)[1] + 1;
+          next = current;
+        }
+        if (current < hidden.get(i)[0])
+        {
+          break;
+        }
+      }
+      lasthiddenregion = i - 1;
+
+      for (i = hidden.size() - 1; i >= 0; --i)
+      {
+        if (last >= hidden.get(i)[0] && last <= hidden.get(i)[1])
+        {
+          // last is hidden, move to left
+          last = hidden.get(i)[0] - 1;
+        }
+        if (last > hidden.get(i)[1])
+        {
+          break;
+        }
+      }
+    }
+  }
+
+  @Override
+  public boolean hasNext()
+  {
+    return next <= last;
+  }
+
+  @Override
+  public Integer next()
+  {
+    if (next > last)
+    {
+      throw new NoSuchElementException();
+    }
+    current = next;
+    if ((hidden != null) && (lasthiddenregion + 1 < hidden.size()))
+    {
+      // still some more hidden regions
+      if (next + 1 < hidden.get(lasthiddenregion + 1)[0])
+      {
+        // next+1 is still before the next hidden region
+        next++;
+      }
+      else if ((next + 1 >= hidden.get(lasthiddenregion + 1)[0])
+              && (next + 1 <= hidden.get(lasthiddenregion + 1)[1]))
+      {
+        // next + 1 is in the next hidden region
+        next = hidden.get(lasthiddenregion + 1)[1] + 1;
+        lasthiddenregion++;
+      }
+    }
+    else
+    {
+      // finished with hidden regions, just increment normally
+      next++;
+    }
+    return current;
+  }
+
+  @Override
+  public void remove()
+  {
+    throw new UnsupportedOperationException();
+  }
+}
+
diff --git a/src/jalview/datamodel/VisibleRowsIterator.java b/src/jalview/datamodel/VisibleRowsIterator.java
new file mode 100644 (file)
index 0000000..0259fd3
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * An iterator which iterates over all visible rows in an alignment
+ * 
+ * @author kmourao
+ *
+ */
+public class VisibleRowsIterator implements Iterator<Integer>
+{
+  private int last;
+
+  private int current;
+
+  private int next;
+
+  private HiddenSequences hidden;
+
+  private AlignmentI al;
+
+  /**
+   * Create an iterator for all visible rows in the alignment
+   * 
+   * @param firstrow
+   *          absolute row index to start from
+   * @param lastrow
+   *          absolute row index to end at
+   * @param alignment
+   *          alignment to work with
+   */
+  public VisibleRowsIterator(int firstrow, int lastrow, AlignmentI alignment)
+  {
+    al = alignment;
+    current = firstrow;
+    last = lastrow;
+    hidden = al.getHiddenSequences();
+    while (hidden.isHidden(last) && last > current)
+    {
+      last--;
+    }
+    current = firstrow;
+    while (hidden.isHidden(current) && current < last)
+    {
+      current++;
+    }
+    next = current;
+  }
+
+  @Override
+  public boolean hasNext()
+  {
+    return next <= last;
+  }
+
+  @Override
+  public Integer next()
+  {
+    if (next > last)
+    {
+      throw new NoSuchElementException();
+    }
+    current = next;
+    do
+    {
+      next++;
+    } while (hidden.isHidden(next) && next <= last);
+    return current;
+  }
+
+  @Override
+  public void remove()
+  {
+    throw new UnsupportedOperationException();
+  }
+}
+
diff --git a/test/jalview/datamodel/AllColsIteratorTest.java b/test/jalview/datamodel/AllColsIteratorTest.java
new file mode 100644 (file)
index 0000000..ee82340
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import static org.testng.Assert.assertTrue;
+
+import java.util.NoSuchElementException;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class AllColsIteratorTest
+{
+  ColumnSelection hiddenCols;
+  
+  @BeforeClass
+  public void setup()
+  {
+   hiddenCols = new ColumnSelection();
+   hiddenCols.hideColumns(2,4);
+  }
+  
+
+  /*
+   * Test iterator iterates through collection correctly
+   */
+  @Test(groups = { "Functional" })
+  public void testHasNextAndNext()
+  {
+    AllColsIterator it = new AllColsIterator(0, 3, hiddenCols);
+    int count = 0;
+    while (it.hasNext())
+    {
+      it.next();
+      count++;
+    }
+    assertTrue(count == 4, "hasNext() is false after 4 iterations");
+  }
+
+  /*
+   * Test iterator throws NoSuchElementException at end of iteration
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { NoSuchElementException.class })
+  public void testLastNext() throws NoSuchElementException
+  {
+    AllColsIterator it = new AllColsIterator(0, 3, hiddenCols);
+    while (it.hasNext())
+    {
+      it.next();
+    }
+    it.next();
+  }
+
+  /*
+   * Test iterator throws UnsupportedOperationException on call to remove
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { UnsupportedOperationException.class })
+  public void testRemove() throws UnsupportedOperationException
+  {
+    AllColsIterator it = new AllColsIterator(0, 3, hiddenCols);
+    it.remove();
+  }
+}
diff --git a/test/jalview/datamodel/AllRowsIteratorTest.java b/test/jalview/datamodel/AllRowsIteratorTest.java
new file mode 100644 (file)
index 0000000..fd1d29d
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import static org.testng.Assert.assertTrue;
+
+import jalview.analysis.AlignmentGenerator;
+
+import java.util.Hashtable;
+import java.util.NoSuchElementException;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class AllRowsIteratorTest
+{
+  AlignmentI al;
+
+  Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences = new Hashtable<SequenceI, SequenceCollectionI>();
+
+  @BeforeClass
+  public void setup()
+  {
+    // create random alignment
+    AlignmentGenerator gen = new AlignmentGenerator(false);
+    al = gen.generate(20, 15, 123, 5, 5);
+    if (!hiddenRepSequences.isEmpty())
+    {
+      al.getHiddenSequences().showAll(hiddenRepSequences);
+    }
+    hideSequences(2, 4);
+  }
+
+  /*
+   * Test iterator iterates through collection correctly
+   */
+  @Test(groups = { "Functional" })
+  public void testHasNextAndNext()
+  {
+    AllRowsIterator it = new AllRowsIterator(0, 3, al);
+    int count = 0;
+    while (it.hasNext())
+    {
+      it.next();
+      count++;
+    }
+    assertTrue(count == 4, "hasNext() is false after 4 iterations");
+  }
+
+  /*
+   * Test iterator throws NoSuchElementException at end of iteration
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { NoSuchElementException.class })
+  public void testLastNext() throws NoSuchElementException
+  {
+    AllRowsIterator it = new AllRowsIterator(0, 3, al);
+    while (it.hasNext())
+    {
+      it.next();
+    }
+    it.next();
+  }
+
+  /*
+   * Test iterator throws UnsupportedOperationException on call to remove
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { UnsupportedOperationException.class })
+  public void testRemove() throws UnsupportedOperationException
+  {
+    AllRowsIterator it = new AllRowsIterator(0, 3, al);
+    it.remove();
+  }
+
+
+  /*
+   * Hide sequences between start and end
+   */
+  private void hideSequences(int start, int end)
+  {
+    SequenceI[] allseqs = al.getSequencesArray();
+    SequenceGroup theseSeqs = new SequenceGroup();
+
+    for (int i = start; i <= end; i++)
+    {
+      theseSeqs.addSequence(allseqs[i], false);
+      al.getHiddenSequences().hideSequence(allseqs[i]);
+    }
+
+    hiddenRepSequences.put(allseqs[start], theseSeqs);
+  }
+}
diff --git a/test/jalview/datamodel/VisibleColsIteratorTest.java b/test/jalview/datamodel/VisibleColsIteratorTest.java
new file mode 100644 (file)
index 0000000..c07b3c9
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import static org.testng.Assert.assertTrue;
+
+import java.util.NoSuchElementException;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class VisibleColsIteratorTest
+{
+  ColumnSelection hiddenCols;
+
+  ColumnSelection hiddenColsAtStart;
+
+  @BeforeClass
+  public void setup()
+  {
+    hiddenCols = new ColumnSelection();
+    hiddenCols.hideColumns(2, 4);
+
+    hiddenColsAtStart = new ColumnSelection();
+    hiddenColsAtStart.hideColumns(0, 2);
+  }
+
+  /*
+   * Test iterator iterates correctly through the columns
+   * when alignment has hidden cols
+   */
+  @Test(groups = { "Functional" })
+  public void testHasNextAndNextWithHidden()
+  {
+    VisibleColsIterator it = new VisibleColsIterator(0, 6, hiddenCols);
+    int count = 0;
+    while (it.hasNext())
+    {
+      it.next();
+      count++;
+    }
+    assertTrue(count == 4, "hasNext() is false after 4 iterations");
+  }
+
+  /*
+   * Test iterator iterates correctly through the columns
+   * when alignment has no hidden cols
+   */
+  @Test(groups = { "Functional" })
+  public void testHasNextAndNextNoHidden()
+  {
+    VisibleColsIterator it2 = new VisibleColsIterator(0, 3,
+            new ColumnSelection());
+    int count = 0;
+    while (it2.hasNext())
+    {
+      it2.next();
+      count++;
+    }
+    assertTrue(count == 4, "hasNext() is false after 4 iterations");
+  }
+
+  /*
+   * Test iterator iterates correctly through the columns
+   * when alignment has hidden cols at start
+   */
+  @Test(groups = { "Functional" })
+  public void testHasNextAndNextStartHidden()
+  {
+    VisibleColsIterator it3 = new VisibleColsIterator(0, 6,
+            hiddenColsAtStart);
+    int count = 0;
+    while (it3.hasNext())
+    {
+      it3.next();
+      count++;
+    }
+    assertTrue(count == 4, "hasNext() is false after 4 iterations");
+  }
+
+  /*
+   * Test iterator iterates correctly through the columns
+   * when alignment has hidden cols at end
+   */
+  @Test(groups = { "Functional" })
+  public void testHasNextAndNextEndHidden()
+  {
+    VisibleColsIterator it4 = new VisibleColsIterator(0, 4, hiddenCols);
+    int count = 0;
+    while (it4.hasNext())
+    {
+      it4.next();
+      count++;
+    }
+    assertTrue(count == 2, "hasNext() is false after 2 iterations");
+
+  }
+
+  /*
+   * Test iterator always throws NoSuchElementException at end of iteration
+   * when alignment has hidden cols
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { NoSuchElementException.class })
+  public void testLastNextWithHidden() throws NoSuchElementException
+  {
+    VisibleColsIterator it = new VisibleColsIterator(0, 3, hiddenCols);
+    while (it.hasNext())
+    {
+      it.next();
+    }
+    it.next();
+  }
+
+  /*
+   * Test iterator always throws NoSuchElementException at end of iteration
+   * when alignment has no hidden cols
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { NoSuchElementException.class })
+  public void testLastNextNoHidden() throws NoSuchElementException
+  {
+    VisibleColsIterator it2 = new VisibleColsIterator(0, 3,
+            new ColumnSelection());
+    while (it2.hasNext())
+    {
+      it2.next();
+    }
+    it2.next();
+  }
+
+  /*
+   * Test iterator always throws NoSuchElementException at end of iteration
+   * when alignment has hidden cols at start
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { NoSuchElementException.class })
+  public void testLastNextStartHidden() throws NoSuchElementException
+  {
+    VisibleColsIterator it3 = new VisibleColsIterator(0, 6,
+            hiddenColsAtStart);
+    while (it3.hasNext())
+    {
+      it3.next();
+    }
+    it3.next();
+  }
+
+  /*
+   * Test iterator always throws NoSuchElementException at end of iteration
+   * when alignment has hidden cols at end
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { NoSuchElementException.class })
+  public void testLastNextEndHidden() throws NoSuchElementException
+  {
+    VisibleColsIterator it4 = new VisibleColsIterator(0, 4, hiddenCols);
+    while (it4.hasNext())
+    {
+      it4.next();
+    }
+    it4.next();
+  }
+
+  /*
+   * Test calls to remove throw UnsupportedOperationException
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { UnsupportedOperationException.class })
+  public void testRemove() throws UnsupportedOperationException
+  {
+    VisibleColsIterator it = new VisibleColsIterator(0, 3, hiddenCols);
+    it.remove();
+  }
+}
diff --git a/test/jalview/datamodel/VisibleRowsIteratorTest.java b/test/jalview/datamodel/VisibleRowsIteratorTest.java
new file mode 100644 (file)
index 0000000..da93dab
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import static org.testng.Assert.assertTrue;
+
+import jalview.analysis.AlignmentGenerator;
+
+import java.util.Hashtable;
+import java.util.NoSuchElementException;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class VisibleRowsIteratorTest
+{
+  AlignmentI al;
+
+  AlignmentI al2;
+
+  AlignmentI al3;
+
+  Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences = new Hashtable<SequenceI, SequenceCollectionI>();
+
+  Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences2 = new Hashtable<SequenceI, SequenceCollectionI>();
+
+  @BeforeClass
+  public void setup()
+  {
+    // create random alignment
+    AlignmentGenerator gen = new AlignmentGenerator(false);
+    al = gen.generate(20, 15, 123, 5, 5);
+    if (!hiddenRepSequences.isEmpty())
+    {
+      al.getHiddenSequences().showAll(hiddenRepSequences);
+    }
+    hideSequences(al, hiddenRepSequences, 2, 4);
+
+    al2 = gen.generate(20, 15, 123, 5, 5);
+    if (!hiddenRepSequences2.isEmpty())
+    {
+      al2.getHiddenSequences().showAll(hiddenRepSequences2);
+    }
+    hideSequences(al2, hiddenRepSequences2, 0, 2);
+
+    al3 = gen.generate(20, 15, 123, 5, 5);
+  }
+
+  /*
+   * Test iterator iterates correctly through the rows
+   * when alignment has hidden rows
+   */
+  @Test(groups = { "Functional" })
+  public void testHasNextAndNextWithHidden()
+  {
+    VisibleRowsIterator it = new VisibleRowsIterator(0, 6, al);
+    int count = 0;
+    while (it.hasNext())
+    {
+      it.next();
+      count++;
+    }
+    assertTrue(count == 4, "hasNext() is false after 4 iterations");
+  }
+
+  /*
+   * Test iterator iterates correctly through the rows
+   * when alignment has no hidden rows
+   */
+  @Test(groups = { "Functional" })
+  public void testHasNextAndNextNoHidden()
+  {
+    VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al3);
+    int count = 0;
+    while (it.hasNext())
+    {
+      it.next();
+      count++;
+    }
+    assertTrue(count == 4, "hasNext() is false after 4 iterations");
+  }
+
+  /*
+   * Test iterator iterates correctly through the rows
+   * when alignment has hidden rows at start
+   */
+  @Test(groups = { "Functional" })
+  public void testHasNextAndNextStartHidden()
+  {
+    VisibleRowsIterator it = new VisibleRowsIterator(0, 6, al2);
+    int count = 0;
+    while (it.hasNext())
+    {
+      it.next();
+      count++;
+    }
+    assertTrue(count == 4, "hasNext() is false after 4 iterations");
+  }
+
+  /*
+   * Test iterator iterates correctly through the rows
+   * when alignment has hidden rows at end
+   */
+  @Test(groups = { "Functional" })
+  public void testHasNextAndNextEndHidden()
+  {
+    VisibleRowsIterator it = new VisibleRowsIterator(0, 4, al);
+    int count = 0;
+    while (it.hasNext())
+    {
+      it.next();
+      count++;
+    }
+    assertTrue(count == 2, "hasNext() is false after 2 iterations");
+  }
+
+  /*
+   * Test iterator always throws NoSuchElementException at end of iteration
+   * when alignment has hidden rows
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { NoSuchElementException.class })
+  public void testLastNextWithHidden() throws NoSuchElementException
+  {
+    VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al);
+    while (it.hasNext())
+    {
+      it.next();
+    }
+    it.next();
+  }
+
+  /*
+   * Test iterator always throws NoSuchElementException at end of iteration
+   * when alignment has no hidden rows
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { NoSuchElementException.class })
+  public void testLastNextNoHidden() throws NoSuchElementException
+  {
+    VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al3);
+    while (it.hasNext())
+    {
+      it.next();
+    }
+    it.next();
+  }
+
+  /*
+   * Test iterator always throws NoSuchElementException at end of iteration
+   * when alignment has hidden rows at start
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { NoSuchElementException.class })
+  public void testLastNextStartHidden() throws NoSuchElementException
+  {
+    VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al2);
+    while (it.hasNext())
+    {
+      it.next();
+    }
+    it.next();
+  }
+
+  /*
+   * Test iterator always throws NoSuchElementException at end of iteration
+   * when alignment has hidden rows at end
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { NoSuchElementException.class })
+  public void testLastNextEndHidden() throws NoSuchElementException
+  {
+    VisibleRowsIterator it = new VisibleRowsIterator(0, 4, al);
+    while (it.hasNext())
+    {
+      it.next();
+    }
+    it.next();
+  }
+
+  /*
+   * Test calls to remove throw UnsupportedOperationException
+   */
+  @Test(
+    groups = { "Functional" },
+    expectedExceptions = { UnsupportedOperationException.class })
+  public void testRemove() throws UnsupportedOperationException
+  {
+    VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al);
+    it.remove();
+  }
+
+  /*
+   * Hide sequences between start and end
+   */
+  private void hideSequences(AlignmentI alignment,
+          Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences,
+          int start, int end)
+  {
+    SequenceI[] allseqs = alignment.getSequencesArray();
+    SequenceGroup theseSeqs = new SequenceGroup();
+
+    for (int i = start; i <= end; i++)
+    {
+      theseSeqs.addSequence(allseqs[i], false);
+      alignment.getHiddenSequences().hideSequence(allseqs[i]);
+    }
+
+    hiddenRepSequences.put(allseqs[start], theseSeqs);
+  }
+}