JAL-2759 Generalised HiddenColsIterator naming
[jalview.git] / src / jalview / datamodel / RangeIterator.java
diff --git a/src/jalview/datamodel/RangeIterator.java b/src/jalview/datamodel/RangeIterator.java
new file mode 100644 (file)
index 0000000..2c5d949
--- /dev/null
@@ -0,0 +1,114 @@
+package jalview.datamodel;
+
+import java.util.ArrayList;
+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.
+ */
+public class RangeIterator implements Iterator<int[]>
+{
+  // current index in regionsList
+  private int currentPosition = 0;
+
+  // current column in regionsList
+  private int[] currentRegion;
+
+  // local copy or reference to regionsList
+  private List<int[]> localRegions;
+
+  /**
+   * Unbounded constructor
+   * 
+   * @param regionsList
+   *          list of regions to iterate over
+   */
+  RangeIterator(List<int[]> regionsList)
+  {
+    if (!regionsList.isEmpty())
+    {
+      int last = regionsList.get(regionsList.size() - 1)[1];
+      init(0, last, regionsList);
+    }
+    else
+    {
+      init(0, 0, regionsList);
+    }
+  }
+
+  /**
+   * Construct an iterator over regionsList 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
+   */
+  RangeIterator(int lowerBound, int upperBound,
+          List<int[]> regionsList)
+  {
+    init(lowerBound, upperBound, regionsList);
+  }
+
+  /**
+   * Construct an iterator over regionsList bounded at [lowerBound,upperBound]
+   * 
+   * @param lowerBound
+   *          lower bound to iterate from
+   * @param upperBound
+   *          upper bound to iterate to
+   */
+  private void init(int lowerBound, int upperBound,
+          List<int[]> regionsList)
+  {
+    int start = lowerBound;
+    int end = upperBound;
+
+    if (regionsList != null)
+    {
+      localRegions = new ArrayList<>();
+
+      // iterate until a region overlaps with [start,end]
+      int i = 0;
+      while ((i < regionsList.size()) && (regionsList.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))
+      {
+        int[] rh = regionsList.get(i);
+        int[] cp = new int[2];
+        System.arraycopy(rh, 0, cp, 0, rh.length);
+        localRegions.add(cp);
+        i++;
+      }
+    }
+  }
+
+  @Override
+  public boolean hasNext()
+  {
+    return (localRegions != null) && (currentPosition < localRegions.size());
+  }
+
+  @Override
+  public int[] next()
+  {
+    currentRegion = localRegions.get(currentPosition);
+    currentPosition++;
+    return currentRegion;
+  }
+
+  @Override
+  public void remove()
+  {
+    localRegions.remove(--currentPosition);
+  }
+}