JAL=2674 Removed getHiddenColumnsCopy
[jalview.git] / src / jalview / datamodel / HiddenColumns.java
index eda8850..c77fb7b 100644 (file)
@@ -27,6 +27,7 @@ import java.util.BitSet;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.NoSuchElementException;
 import java.util.Vector;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -95,7 +96,7 @@ public class HiddenColumns
       if (copy != null)
       {
         hiddenColumns = new ArrayList<>();
-        Iterator<int[]> it = copy.getBoundedIterator(start, end, true);
+        Iterator<int[]> it = copy.getBoundedIterator(start, end);
         while (it.hasNext())
         {
           int[] region = it.next();
@@ -714,54 +715,26 @@ public class HiddenColumns
   }
 
   /**
-   * Returns a copy of the vector of hidden regions, as an ArrayList. Before
-   * using this method please consider if you really need access to the hidden
-   * regions - a new (or existing!) method on HiddenColumns might be more
-   * appropriate.
-   * 
-   * @return hidden regions as an ArrayList of [start,end] pairs
-   */
-  public ArrayList<int[]> getHiddenColumnsCopy()
-  {
-    try
-    {
-      LOCK.readLock().lock();
-      return copyHiddenRegionsToArrayList(0);
-    } finally
-    {
-      LOCK.readLock().unlock();
-    }
-  }
-
-  /**
    * return all visible segments between the given start and end boundaries
    * 
    * @param start
    *          (first column inclusive from 0)
    * @param end
    *          (last column - not inclusive)
-   * @return int[] {i_start, i_end, ..} where intervals lie in
+   * @return List<int[]> {[i_start, i_end], ..} where intervals lie in
    *         start<=i_start<=i_end<end
    */
-  public int[] getVisibleContigs(int start, int end)
+  public List<int[]> getVisibleContigs(int start, int end)
   {
     try
     {
       LOCK.readLock().lock();
+      List<int[]> vcontigs = new ArrayList<>();
       if (hiddenColumns != null && hiddenColumns.size() > 0)
       {
-        // max limit on number of visible contigs
-        // so we can dimension array
-        int maxcontigs = end - start + 1;
-        if (maxcontigs > (hiddenColumns.size() + 1) * 2)
-        {
-          maxcontigs = (hiddenColumns.size() + 1) * 2;
-        }
-        int[] vcontigs = new int[maxcontigs];
         int vstart = start;
         int hideStart;
         int hideEnd;
-        int i = 0;
 
         for (int[] region : hiddenColumns)
         {
@@ -775,9 +748,8 @@ public class HiddenColumns
           }
           if (hideStart > vstart)
           {
-            vcontigs[i * 2] = vstart;
-            vcontigs[i * 2 + 1] = hideStart - 1;
-            i++;
+            int[] contig = new int[] { vstart, hideStart - 1 };
+            vcontigs.add(contig);
           }
           vstart = hideEnd + 1;
 
@@ -790,21 +762,16 @@ public class HiddenColumns
 
         if (vstart < end)
         {
-          vcontigs[i * 2] = vstart;
-          vcontigs[i * 2 + 1] = end - 1;
-          i++;
+          int[] contig = new int[] { vstart, end - 1 };
+          vcontigs.add(contig);
         }
-
-        // copy final array into array of correct size
-        int[] trimmmedContigs = new int[i * 2];
-        System.arraycopy(vcontigs, 0, trimmmedContigs, 0, i * 2);
-
-        return trimmmedContigs;
       }
       else
       {
-        return new int[] { start, end - 1 };
+        int[] contig = new int[] { start, end - 1 };
+        vcontigs.add(contig);
       }
+      return vcontigs;
     } finally
     {
       LOCK.readLock().unlock();
@@ -1527,16 +1494,19 @@ public class HiddenColumns
     }
   }
 
-  public Iterator<int[]> getBoundedIterator(int start, int end,
-          boolean useCopy)
+  public Iterator<int[]> getBoundedIterator(int start, int end)
   {
-    return new BoundedHiddenColsIterator(start, end, useCopy);
+    return new BoundedHiddenColsIterator(start, end, true);
   }
 
-  public Iterator<Integer> getBoundedStartIterator(int start, int end,
-          boolean useCopy)
+  public Iterator<Integer> getBoundedStartIterator(int start, int end)
   {
-    return new BoundedStartRegionIterator(start, end, useCopy);
+    return new BoundedStartRegionIterator(start, end, true);
+  }
+
+  public Iterator<Integer> getVisibleColsIterator(int start, int end)
+  {
+    return new VisibleColsIterator(start, end, true);
   }
 
   /**
@@ -1545,11 +1515,8 @@ public class HiddenColumns
    * @author kmourao
    *
    */
-
-
   class BoundedHiddenColsIterator implements Iterator<int[]>
   {
-
     private int start; // start position to iterate from
 
     private int end; // end position to iterate to
@@ -1742,4 +1709,133 @@ public class HiddenColumns
       return result;
     }
   }
+
+  public class VisibleColsIterator implements Iterator<Integer>
+  {
+    private int last;
+
+    private int current;
+
+    private int next;
+
+    private List<int[]> localHidden = new ArrayList<>();
+
+    private int lasthiddenregion;
+
+    public VisibleColsIterator(int firstcol, int lastcol, boolean useCopy)
+    {
+      last = lastcol;
+      current = firstcol;
+      next = firstcol;
+      lasthiddenregion = -1;
+
+      try
+      {
+        if (useCopy)
+        {
+          // assume that if useCopy is false the calling code has locked
+          // hiddenColumns
+          LOCK.readLock().lock();
+        }
+
+        if (hiddenColumns != null)
+        {
+          int i = 0;
+          for (i = 0; i < hiddenColumns.size(); ++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;
+            }
+            if (current < hiddenColumns.get(i)[0])
+            {
+              break;
+            }
+          }
+
+          lasthiddenregion = i - 1;
+
+          for (i = hiddenColumns.size() - 1; i >= 0; --i)
+          {
+            if (last >= hiddenColumns.get(i)[0]
+                    && last <= hiddenColumns.get(i)[1])
+            {
+              // last is hidden, move to left
+              last = hiddenColumns.get(i)[0] - 1;
+            }
+            if (last > hiddenColumns.get(i)[1])
+            {
+              break;
+            }
+          }
+
+          // make a local copy of the bit we need
+          i = lasthiddenregion + 1;
+          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++;
+          }
+          lasthiddenregion = -1;
+        }
+      } finally
+      {
+        if (useCopy)
+        {
+          LOCK.readLock().unlock();
+        }
+      }
+    }
+
+    @Override
+    public boolean hasNext()
+    {
+      return next <= last;
+    }
+
+    @Override
+    public Integer next()
+    {
+      if (next > last)
+      {
+        throw new NoSuchElementException();
+      }
+      current = next;
+      if ((localHidden != null)
+              && (lasthiddenregion + 1 < localHidden.size()))
+      {
+        // still some more hidden regions
+        if (next + 1 < localHidden.get(lasthiddenregion + 1)[0])
+        {
+          // next+1 is still before the next hidden region
+          next++;
+        }
+        else if ((next + 1 >= localHidden.get(lasthiddenregion + 1)[0])
+                && (next + 1 <= localHidden.get(lasthiddenregion + 1)[1]))
+        {
+          // next + 1 is in the next hidden region
+          next = localHidden.get(lasthiddenregion + 1)[1] + 1;
+          lasthiddenregion++;
+        }
+      }
+      else
+      {
+        // finished with hidden regions, just increment normally
+        next++;
+      }
+      return current;
+    }
+
+    @Override
+    public void remove()
+    {
+      throw new UnsupportedOperationException();
+    }
+  }
 }