JAL-2647 stashing
authorkiramt <k.mourao@dundee.ac.uk>
Fri, 6 Oct 2017 09:29:29 +0000 (10:29 +0100)
committerkiramt <k.mourao@dundee.ac.uk>
Fri, 6 Oct 2017 09:29:29 +0000 (10:29 +0100)
src/jalview/datamodel/HiddenColumns.java

index c8f2bf6..4b0996f 100644 (file)
@@ -128,7 +128,7 @@ public class HiddenColumns
     {
       LOCK.readLock().lock();
       StringBuilder regionBuilder = new StringBuilder();
-      Iterator<int[]> it = new LocalBoundedHiddenColsIterator();
+      Iterator<int[]> it = new RegionsIterator();
       while (it.hasNext())
       {
         int[] range = it.next();
@@ -157,7 +157,7 @@ public class HiddenColumns
     {
       LOCK.readLock().lock();
       int size = 0;
-      Iterator<int[]> it = new LocalBoundedHiddenColsIterator();
+      Iterator<int[]> it = new RegionsIterator();
       while (it.hasNext())
       {
         int[] range = it.next();
@@ -219,7 +219,7 @@ public class HiddenColumns
         return false;
       }
 
-      Iterator<int[]> it = new LocalBoundedHiddenColsIterator();
+      Iterator<int[]> it = new RegionsIterator();
       Iterator<int[]> thatit = that.iterator();
       while (it.hasNext())
       {
@@ -251,7 +251,7 @@ public class HiddenColumns
       LOCK.readLock().lock();
       int result = column;
 
-      Iterator<int[]> it = new LocalBoundedHiddenColsIterator();
+      Iterator<int[]> it = new RegionsIterator();
       while (it.hasNext())
       {
         int[] region = it.next();
@@ -286,7 +286,7 @@ public class HiddenColumns
       int[] region = null;
       if (hiddenColumns != null)
       {
-        Iterator<int[]> it = new LocalBoundedHiddenColsIterator(0,
+        Iterator<int[]> it = new RegionsIterator(0,
                 hiddenColumn);
         while (it.hasNext())
         {
@@ -350,57 +350,87 @@ public class HiddenColumns
       // in case startColumn is in a hidden region, move it to the left
       int start = adjustForHiddenColumns(findColumnPosition(startColumn));
 
-      // get index of hidden region to left of start
-      int index = getHiddenIndexLeft(start);
-      if (index == -1)
-      {
-        // no hidden regions to left of startColumn
-        return start - distance;
-      }
+      Iterator<int[]> it = new ReverseRegionsIterator(0, start);
 
-      // walk backwards through the alignment subtracting the counts of visible
-      // columns from distance
       int[] region;
       int gap = 0;
       int nextstart = start;
 
-      while ((index > -1) && (distance - gap > 0))
+      while (it.hasNext() && (distance - gap > 0))
       {
-        // subtract the gap to right of region from distance
-        distance -= gap;
-        start = nextstart;
+        region = it.next();
+
+        if (start > region[1])
+        {
+          
+
+          // subtract the gap to right of region from distance
+          distance -= start - region[1]; // gap;
+
+          start = nextstart;
+          nextstart = region[0] - 1;// nextstart;
+
 
-        // calculate the next gap
-        region = hiddenColumns.get(index);
-        gap = start - region[1];
+          // calculate the next gap
 
-        // set start to just to left of current region
-        nextstart = region[0] - 1;
-        index--;
+          // gap = start - region[1];
+
+          // set start to just to left of current region
+          // nextstart = region[0] - 1;
+        }
       }
 
-      if (distance - gap > 0)
+      if (!it.hasNext())
       {
-        // fell out of loop because there are no more hidden regions
-        distance -= gap;
-        return nextstart - distance;
+        // no hidden regions to left of startColumn
+        return start - distance;
+      }
+      else
+      {
+
+        /*        // walk backwards through the alignment subtracting the counts of
+        // visible
+        // columns from distance
+        int[] region;
+        int gap = 0;
+        int nextstart = start;
+        
+        while (it.hasNext() && (distance - gap > 0))
+        {
+          region = it.next();
+          
+          // subtract the gap to right of region from distance
+          distance -= gap;
+          start = nextstart;
+        
+          // calculate the next gap
+          
+          gap = start - region[1];
+        
+          // set start to just to left of current region
+          nextstart = region[0] - 1;
+        }
+        */
+        if (distance - gap > 0)
+        {
+          // fell out of loop because there are no more hidden regions
+          distance -= gap;
+          return nextstart - distance;
+        }
+        return start - distance;
       }
-      return start - distance;
     } finally
     {
       LOCK.readLock().unlock();
     }
-
   }
 
-
-
   /**
    * This method returns the rightmost limit of a region of an alignment with
    * hidden columns. In otherwords, the next hidden column.
    * 
-   * @param index
-   *          int
+   * @param alPos
+   *          the (visible) alignmentPosition to find the next hidden column for
    */
   public int getHiddenBoundaryRight(int alPos)
   {
@@ -409,33 +439,30 @@ public class HiddenColumns
       LOCK.readLock().lock();
       if (hiddenColumns != null)
       {
-        int index = 0;
-        do
+        Iterator<int[]> it = new RegionsIterator();
+        while (it.hasNext())
         {
-          int[] region = hiddenColumns.get(index);
+          int[] region = it.next();
           if (alPos < region[0])
           {
             return region[0];
           }
-
-          index++;
-        } while (index < hiddenColumns.size());
+        }
       }
-
       return alPos;
     } finally
     {
       LOCK.readLock().unlock();
     }
-
   }
 
   /**
    * This method returns the leftmost limit of a region of an alignment with
    * hidden columns. In otherwords, the previous hidden column.
    * 
-   * @param index
-   *          int
+   * @param alPos
+   *          the (visible) alignmentPosition to find the previous hidden column
+   *          for
    */
   public int getHiddenBoundaryLeft(int alPos)
   {
@@ -443,19 +470,14 @@ public class HiddenColumns
     {
       LOCK.readLock().lock();
 
-      if (hiddenColumns != null)
+      Iterator<int[]> it = new ReverseRegionsIterator(0, alPos);
+      while (it.hasNext())
       {
-        int index = hiddenColumns.size() - 1;
-        do
+        int[] region = it.next();
+        if (alPos > region[1])
         {
-          int[] region = hiddenColumns.get(index);
-          if (alPos > region[1])
-          {
-            return region[1];
-          }
-
-          index--;
-        } while (index > -1);
+          return region[1];
+        }
       }
 
       return alPos;
@@ -471,29 +493,30 @@ public class HiddenColumns
    * region to the left. If there is no hidden region to the left it returns -1.
    * 
    * @param pos
-   *          int
+   *          position to find index relative to
    */
   private int getHiddenIndexLeft(int pos)
   {
     try
     {
-
       LOCK.readLock().lock();
-      if (hiddenColumns != null)
+
+
+      Iterator<int[]> it = new ReverseRegionsIterator(0, pos);
+      if (it.hasNext())
       {
-        int index = hiddenColumns.size() - 1;
-        do
+        int index = hiddenColumns.size() - 1; // need index of region not last
+                                              // one
+        while (it.hasNext())
         {
-          int[] region = hiddenColumns.get(index);
+          int[] region = it.next();
           if (pos > region[1])
           {
             return index;
           }
-
           index--;
-        } while (index > -1);
+        }
       }
-
       return -1;
     } finally
     {
@@ -610,7 +633,7 @@ public class HiddenColumns
     {
       LOCK.readLock().lock();
 
-      Iterator<int[]> it = new LocalBoundedHiddenColsIterator();
+      Iterator<int[]> it = new RegionsIterator();
       while (it.hasNext())
       {
         int[] region = it.next();
@@ -724,7 +747,7 @@ public class HiddenColumns
 
       // Simply walk along the sequence whilst watching for hidden column
       // boundaries
-      Iterator<int[]> regions = new LocalBoundedHiddenColsIterator();
+      Iterator<int[]> regions = new RegionsIterator();
       int hideStart = seq.getLength();
       int hideEnd = -1;
       int visPrev = 0;
@@ -941,7 +964,7 @@ public class HiddenColumns
     try
     {
       LOCK.writeLock().lock();
-      Iterator<int[]> it = new LocalBoundedHiddenColsIterator();
+      Iterator<int[]> it = new RegionsIterator();
       while (it.hasNext())
       {
         int[] region = it.next();
@@ -969,7 +992,7 @@ public class HiddenColumns
     try
     {
       LOCK.writeLock().lock();
-      Iterator<int[]> it = new LocalBoundedHiddenColsIterator();
+      Iterator<int[]> it = new RegionsIterator();
       while (it.hasNext())
       {
         int[] region = it.next();
@@ -1063,7 +1086,7 @@ public class HiddenColumns
       // of
       // preceding visible gaps
       // update hidden columns at the same time
-      Iterator<int[]> regions = new LocalBoundedHiddenColsIterator();
+      Iterator<int[]> regions = new RegionsIterator();
       ArrayList<int[]> newhidden = new ArrayList<>();
 
       int numGapsBefore = 0;
@@ -1168,7 +1191,7 @@ public class HiddenColumns
     {
       LOCK.readLock().lock();
       int hashCode = 1;
-      Iterator<int[]> it = new LocalBoundedHiddenColsIterator();
+      Iterator<int[]> it = new RegionsIterator();
       while (it.hasNext())
       {
         int[] hidden = it.next();
@@ -1220,7 +1243,7 @@ public class HiddenColumns
       {
         return;
       }
-      Iterator<int[]> it = new LocalBoundedHiddenColsIterator();
+      Iterator<int[]> it = new RegionsIterator();
       while (it.hasNext())
       {
         int[] range = it.next();
@@ -1256,7 +1279,7 @@ public class HiddenColumns
         return new int[] { startPos, endPos };
       }
 
-      Iterator<int[]> it = new LocalBoundedHiddenColsIterator();
+      Iterator<int[]> it = new RegionsIterator();
       while (it.hasNext())
       {
         int[] range = it.next();
@@ -1304,7 +1327,7 @@ public class HiddenColumns
       int adjres = adjustForHiddenColumns(res);
 
       int[] reveal = null;
-      Iterator<int[]> it = new LocalBoundedHiddenColsIterator(adjres - 2,
+      Iterator<int[]> it = new RegionsIterator(adjres - 2,
               adjres + 2);
       while (it.hasNext())
       {
@@ -1420,14 +1443,17 @@ public class HiddenColumns
 
   /**
    * A local iterator which iterates over hidden column regions in a range.
-   * Works with the actual hidden columns collection (so locking before use may
-   * be required).
+   * Intended for use ONLY within the HiddenColumns class, because it works
+   * directly with the hiddenColumns collection without locking (callers should
+   * lock hiddenColumns).
    */
-  private class LocalBoundedHiddenColsIterator implements Iterator<int[]>
+  private class RegionsIterator implements Iterator<int[]>
   {
-    private int start; // start position to iterate from
+    // start position to iterate from
+    private int start;
 
-    private int end; // end position to iterate to
+    // end position to iterate to
+    private int end;
 
     // current index in hiddenColumns
     private int currentPosition = 0;
@@ -1435,20 +1461,24 @@ public class HiddenColumns
     // current column in hiddenColumns
     private int[] nextRegion = null;
 
-    LocalBoundedHiddenColsIterator(int lowerBound, int upperBound)
+    // Constructor with bounds
+    RegionsIterator(int lowerBound, int upperBound)
     {
       init(lowerBound, upperBound);
     }
 
-    LocalBoundedHiddenColsIterator()
+    // Unbounded constructor
+    RegionsIterator()
     {
       if (hiddenColumns != null)
       {
+        // iterator over full hiddenColumns collection
         int last = hiddenColumns.get(hiddenColumns.size() - 1)[1];
         init(0, last);
       }
       else
       {
+        // empty iterator
         init(0, 0);
       }
     }
@@ -1461,9 +1491,6 @@ public class HiddenColumns
      *          lower bound to iterate from
      * @param upperBound
      *          upper bound to iterate to
-     * @param useCopyCols
-     *          whether to make a local copy of hiddenColumns for iteration (set
-     *          to true if calling from outwith the HiddenColumns class)
      */
     private void init(int lowerBound, int upperBound)
     {
@@ -1512,14 +1539,114 @@ public class HiddenColumns
   }
 
   /**
+   * A local iterator which reverse iterates over hidden column regions in a
+   * range. Intended for use ONLY within the HiddenColumns class, because it
+   * works directly with the hiddenColumns collection without locking (callers
+   * should lock hiddenColumns).
+   */
+  private class ReverseRegionsIterator implements Iterator<int[]>
+  {
+    // start position to iterate to
+    private int start;
+
+    // end position to iterate from
+    private int end;
+
+    // current index in hiddenColumns
+    private int currentPosition = 0;
+
+    // current column in hiddenColumns
+    private int[] nextRegion = null;
+
+    // Constructor with bounds
+    ReverseRegionsIterator(int lowerBound, int upperBound)
+    {
+      init(lowerBound, upperBound);
+    }
+
+    // Unbounded constructor
+    ReverseRegionsIterator()
+    {
+      if (hiddenColumns != null)
+      {
+        // iterator over full hiddenColumns collection
+        int last = hiddenColumns.get(hiddenColumns.size() - 1)[1];
+        init(0, last);
+      }
+      else
+      {
+        // empty iterator
+        init(0, 0);
+      }
+    }
+
+    /**
+     * Construct an iterator over hiddenColums bounded at
+     * [lowerBound,upperBound]
+     * 
+     * @param lowerBound
+     *          lower bound to iterate to
+     * @param upperBound
+     *          upper bound to iterate from
+     */
+    private void init(int lowerBound, int upperBound)
+    {
+      start = lowerBound;
+      end = upperBound;
+
+      if (hiddenColumns != null)
+      {
+        // iterate until a region overlaps with [start,end]
+        currentPosition = hiddenColumns.size() - 1;
+        while (currentPosition >= 0
+                && hiddenColumns.get(currentPosition)[1] > end)
+        {
+          currentPosition--;
+        }
+        if (currentPosition >= 0)
+        {
+          nextRegion = hiddenColumns.get(currentPosition);
+        }
+      }
+    }
+
+    @Override
+    public boolean hasNext()
+    {
+      return (hiddenColumns != null) && (nextRegion != null)
+              && (nextRegion[1] >= start);
+    }
+
+    @Override
+    public int[] next()
+    {
+      int[] region = nextRegion;
+      currentPosition--;
+      if (currentPosition >= 0)
+      {
+        nextRegion = hiddenColumns.get(currentPosition);
+      }
+      else
+      {
+        nextRegion = null;
+      }
+      return region;
+    }
+
+  }
+
+  /**
    * An iterator which iterates over hidden column regions in a range. Works
-   * with a copy of the hidden columns collection.
+   * with a copy of the hidden columns collection. Intended to be used by
+   * callers OUTSIDE of HiddenColumns.
    */
   private class BoundedHiddenColsIterator implements Iterator<int[]>
   {
-    private int start; // start position to iterate from
+    // start position to iterate from
+    private int start;
 
-    private int end; // end position to iterate to
+    // end position to iterate to
+    private int end;
 
     // current index in hiddenColumns
     private int currentPosition = 0;
@@ -1530,6 +1657,9 @@ public class HiddenColumns
     // local copy or reference to hiddenColumns
     private List<int[]> localHidden;
 
+    /**
+     * Unbounded constructor
+     */
     BoundedHiddenColsIterator()
     {
       if (hiddenColumns != null)