JAL-2759 Rationalise VisibleColsIterator and HiddenColsIterator
authorkiramt <k.mourao@dundee.ac.uk>
Wed, 31 Jan 2018 16:38:57 +0000 (16:38 +0000)
committerkiramt <k.mourao@dundee.ac.uk>
Wed, 31 Jan 2018 16:38:57 +0000 (16:38 +0000)
src/jalview/datamodel/HiddenColumns.java
src/jalview/datamodel/RangeElementsIterator.java [new file with mode: 0644]
src/jalview/datamodel/RangeIterator.java
src/jalview/datamodel/VisibleColsIterator.java [deleted file]
test/jalview/datamodel/HiddenColumnsTest.java
test/jalview/datamodel/RangeElementsIteratorTest.java [moved from test/jalview/datamodel/VisibleColsIteratorTest.java with 99% similarity]

index 3e1f205..4b647db 100644 (file)
@@ -1084,7 +1084,8 @@ public class HiddenColumns
     try
     {
       LOCK.readLock().lock();
-      return new VisibleColsIterator(start, end, hiddenColumns);
+      return new RangeElementsIterator(start, end,
+              new RangeIterator(hiddenColumns));
     } finally
     {
       LOCK.readLock().unlock();
diff --git a/src/jalview/datamodel/RangeElementsIterator.java b/src/jalview/datamodel/RangeElementsIterator.java
new file mode 100644 (file)
index 0000000..ca6c4f7
--- /dev/null
@@ -0,0 +1,89 @@
+package jalview.datamodel;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Iterator over each element in a set of ranges i.e. if ranges is {[3,6],
+ * [12,15]} it will iterate over {3,4,5,6,12,13,14,15}. Uses a local copy of the
+ * set of ranges.
+ * 
+ * @author kmourao
+ *
+ */
+public class RangeElementsIterator implements Iterator<Integer>
+{
+  private int last;
+
+  private int current;
+
+  private int next;
+
+  private Iterator<int[]> rangeIterator;
+
+  private int[] nextRange = null;
+
+  RangeElementsIterator(int from, int to, Iterator<int[]> it)
+  {
+    last = to;
+    current = from;
+    next = from;
+    rangeIterator = it;
+    if (rangeIterator.hasNext())
+    {
+      nextRange = rangeIterator.next();
+    }
+    checkNextRange();
+  }
+
+  @Override
+  public boolean hasNext()
+  {
+    return next <= last;
+  }
+
+  @Override
+  public Integer next()
+  {
+    if (next > last)
+    {
+      throw new NoSuchElementException();
+    }
+
+    current = next;
+
+    // recalculate next
+    next++;
+
+    // if there are more ranges need to check if next is in a range
+    checkNextRange();
+    return current;
+  }
+
+  /**
+   * Check how next position relates to next range, and update next position if
+   * necessary
+   */
+  private void checkNextRange()
+  {
+    if (nextRange != null && next >= nextRange[0])
+    {
+      next = nextRange[1] + 1;
+      if (rangeIterator.hasNext())
+      {
+        nextRange = rangeIterator.next();
+      }
+      else
+      {
+        nextRange = null;
+      }
+
+    }
+  }
+
+  @Override
+  public void remove()
+  {
+    throw new UnsupportedOperationException();
+  }
+}
index 2c5d949..7a69ac6 100644 (file)
@@ -5,57 +5,57 @@ import java.util.Iterator;
 import java.util.List;
 
 /**
- * An iterator which iterates over regions in a range. Works with a copy of the
- * collection of regions.
+ * An iterator which iterates over a list of ranges. Works with a copy of the
+ * collection of ranges.
  */
 public class RangeIterator implements Iterator<int[]>
 {
-  // current index in regionsList
+  // current index in rangeList
   private int currentPosition = 0;
 
-  // current column in regionsList
-  private int[] currentRegion;
+  // current range in rangeList
+  private int[] currentRange;
 
-  // local copy or reference to regionsList
-  private List<int[]> localRegions;
+  // local copy or reference to rangeList
+  private List<int[]> localRanges;
 
   /**
    * Unbounded constructor
    * 
-   * @param regionsList
-   *          list of regions to iterate over
+   * @param rangeList
+   *          list of ranges to iterate over
    */
-  RangeIterator(List<int[]> regionsList)
+  RangeIterator(List<int[]> rangeList)
   {
-    if (!regionsList.isEmpty())
+    if (!rangeList.isEmpty())
     {
-      int last = regionsList.get(regionsList.size() - 1)[1];
-      init(0, last, regionsList);
+      int last = rangeList.get(rangeList.size() - 1)[1];
+      init(0, last, rangeList);
     }
     else
     {
-      init(0, 0, regionsList);
+      init(0, 0, rangeList);
     }
   }
 
   /**
-   * Construct an iterator over regionsList bounded at [lowerBound,upperBound]
+   * Construct an iterator over rangeList bounded at [lowerBound,upperBound]
    * 
    * @param lowerBound
    *          lower bound to iterate from
    * @param upperBound
    *          upper bound to iterate to
-   * @param regionsList
-   *          list of regions to iterate over
+   * @param rangeList
+   *          list of ranges to iterate over
    */
   RangeIterator(int lowerBound, int upperBound,
-          List<int[]> regionsList)
+          List<int[]> rangeList)
   {
-    init(lowerBound, upperBound, regionsList);
+    init(lowerBound, upperBound, rangeList);
   }
 
   /**
-   * Construct an iterator over regionsList bounded at [lowerBound,upperBound]
+   * Construct an iterator over rangeList bounded at [lowerBound,upperBound]
    * 
    * @param lowerBound
    *          lower bound to iterate from
@@ -63,30 +63,30 @@ public class RangeIterator implements Iterator<int[]>
    *          upper bound to iterate to
    */
   private void init(int lowerBound, int upperBound,
-          List<int[]> regionsList)
+          List<int[]> rangeList)
   {
     int start = lowerBound;
     int end = upperBound;
 
-    if (regionsList != null)
+    if (rangeList != null)
     {
-      localRegions = new ArrayList<>();
+      localRanges = new ArrayList<>();
 
-      // iterate until a region overlaps with [start,end]
+      // iterate until a range overlaps with [start,end]
       int i = 0;
-      while ((i < regionsList.size()) && (regionsList.get(i)[1] < start))
+      while ((i < rangeList.size()) && (rangeList.get(i)[1] < start))
       {
         i++;
       }
 
-      // iterate from start to end, adding each region. Positions are
-      // absolute, and all regions which *overlap* [start,end] are added.
-      while (i < regionsList.size() && (regionsList.get(i)[0] <= end))
+      // iterate from start to end, adding each range. Positions are
+      // absolute, and all ranges which *overlap* [start,end] are added.
+      while (i < rangeList.size() && (rangeList.get(i)[0] <= end))
       {
-        int[] rh = regionsList.get(i);
+        int[] rh = rangeList.get(i);
         int[] cp = new int[2];
         System.arraycopy(rh, 0, cp, 0, rh.length);
-        localRegions.add(cp);
+        localRanges.add(cp);
         i++;
       }
     }
@@ -95,20 +95,20 @@ public class RangeIterator implements Iterator<int[]>
   @Override
   public boolean hasNext()
   {
-    return (localRegions != null) && (currentPosition < localRegions.size());
+    return (localRanges != null) && (currentPosition < localRanges.size());
   }
 
   @Override
   public int[] next()
   {
-    currentRegion = localRegions.get(currentPosition);
+    currentRange = localRanges.get(currentPosition);
     currentPosition++;
-    return currentRegion;
+    return currentRange;
   }
 
   @Override
   public void remove()
   {
-    localRegions.remove(--currentPosition);
+    localRanges.remove(--currentPosition);
   }
 }
diff --git a/src/jalview/datamodel/VisibleColsIterator.java b/src/jalview/datamodel/VisibleColsIterator.java
deleted file mode 100644 (file)
index 2fa27ed..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-package jalview.datamodel;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-
-/**
- * Iterator over the visible *columns* (not regions) as determined by the set of
- * hidden columns. Uses a local copy of hidden columns.
- * 
- * @author kmourao
- *
- */
-public class VisibleColsIterator implements Iterator<Integer>
-{
-  private int last;
-
-  private int current;
-
-  private int next;
-
-  private List<int[]> localHidden = new ArrayList<>();
-
-  private int nexthiddenregion;
-
-  VisibleColsIterator(int firstcol, int lastcol, List<int[]> hiddenColumns)
-  {
-    last = lastcol;
-    current = firstcol;
-    next = firstcol;
-    nexthiddenregion = 0;
-
-    if (hiddenColumns != null)
-    {
-      int i = 0;
-      for (i = 0; i < hiddenColumns.size()
-              && (current <= hiddenColumns.get(i)[0]); ++i)
-      {
-        if (current >= hiddenColumns.get(i)[0]
-                && current <= hiddenColumns.get(i)[1])
-        {
-          // current is hidden, move to right
-          current = hiddenColumns.get(i)[1] + 1;
-          next = current;
-          nexthiddenregion = i + 1;
-        }
-      }
-
-      for (i = hiddenColumns.size() - 1; i >= 0
-              && (last >= hiddenColumns.get(i)[1]); --i)
-      {
-        if (last >= hiddenColumns.get(i)[0]
-                && last <= hiddenColumns.get(i)[1])
-        {
-          // last is hidden, move to left
-          last = hiddenColumns.get(i)[0] - 1;
-        }
-      }
-
-      // make a local copy of the bit we need
-      i = nexthiddenregion;
-      while (i < hiddenColumns.size() && hiddenColumns.get(i)[0] <= last)
-      {
-        int[] region = new int[] { hiddenColumns.get(i)[0],
-            hiddenColumns.get(i)[1] };
-        localHidden.add(region);
-        i++;
-      }
-    }
-  }
-
-  @Override
-  public boolean hasNext()
-  {
-    return next <= last;
-  }
-
-  @Override
-  public Integer next()
-  {
-    if (next > last)
-    {
-      throw new NoSuchElementException();
-    }
-    current = next;
-    if ((localHidden != null) && (nexthiddenregion < localHidden.size()))
-    {
-      // still some more hidden regions
-      if (next + 1 < localHidden.get(nexthiddenregion)[0])
-      {
-        // next+1 is still before the next hidden region
-        next++;
-      }
-      else if ((next + 1 >= localHidden.get(nexthiddenregion)[0])
-              && (next + 1 <= localHidden.get(nexthiddenregion)[1]))
-      {
-        // next + 1 is in the next hidden region
-        next = localHidden.get(nexthiddenregion)[1] + 1;
-        nexthiddenregion++;
-      }
-    }
-    else
-    {
-      // finished with hidden regions, just increment normally
-      next++;
-    }
-    return current;
-  }
-
-  @Override
-  public void remove()
-  {
-    throw new UnsupportedOperationException();
-  }
-}
index cc5744f..f15f7ad 100644 (file)
@@ -1309,7 +1309,7 @@ public class HiddenColumnsTest
     HiddenColumns h = new HiddenColumns();
     Iterator<Integer> it = h.getVisibleColsIterator(0, 10);
 
-    assertTrue(it instanceof VisibleColsIterator);
+    assertTrue(it instanceof RangeElementsIterator);
   }
 
   @Test(groups = "Functional")
@@ -28,7 +28,7 @@ import java.util.NoSuchElementException;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
-public class VisibleColsIteratorTest
+public class RangeElementsIteratorTest
 {
   HiddenColumns hiddenCols;