JAL-2674 finish with iterators for now
[jalview.git] / src / jalview / datamodel / HiddenColumns.java
index c77fb7b..5554be0 100644 (file)
@@ -714,70 +714,6 @@ public class HiddenColumns
     return copy;
   }
 
-  /**
-   * 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 List<int[]> {[i_start, i_end], ..} where intervals lie in
-   *         start<=i_start<=i_end<end
-   */
-  public List<int[]> getVisibleContigs(int start, int end)
-  {
-    try
-    {
-      LOCK.readLock().lock();
-      List<int[]> vcontigs = new ArrayList<>();
-      if (hiddenColumns != null && hiddenColumns.size() > 0)
-      {
-        int vstart = start;
-        int hideStart;
-        int hideEnd;
-
-        for (int[] region : hiddenColumns)
-        {
-          hideStart = region[0];
-          hideEnd = region[1];
-
-          // navigate to start
-          if (hideEnd < vstart)
-          {
-            continue;
-          }
-          if (hideStart > vstart)
-          {
-            int[] contig = new int[] { vstart, hideStart - 1 };
-            vcontigs.add(contig);
-          }
-          vstart = hideEnd + 1;
-
-          // exit if we're past the end
-          if (vstart >= end)
-          {
-            break;
-          }
-        }
-
-        if (vstart < end)
-        {
-          int[] contig = new int[] { vstart, end - 1 };
-          vcontigs.add(contig);
-        }
-      }
-      else
-      {
-        int[] contig = new int[] { start, end - 1 };
-        vcontigs.add(contig);
-      }
-      return vcontigs;
-    } finally
-    {
-      LOCK.readLock().unlock();
-    }
-  }
-
   public String[] getVisibleSequenceStrings(int start, int end,
           SequenceI[] seqs)
   {
@@ -794,30 +730,18 @@ public class HiddenColumns
 
           int blockStart = start;
           int blockEnd = end;
-          int hideStart;
-          int hideEnd;
 
-          for (int[] region : hiddenColumns)
+          Iterator<int[]> regions = new BoundedHiddenColsIterator(start,
+                  end, false);
+          while (regions.hasNext())
           {
-            hideStart = region[0];
-            hideEnd = region[1];
-
-            if (hideStart < start)
-            {
-              continue;
-            }
-
-            blockStart = Math.min(blockStart, hideEnd + 1);
-            blockEnd = Math.min(blockEnd, hideStart);
-
-            if (blockStart > blockEnd)
-            {
-              break;
-            }
+            int[] region = regions.next();
+            blockStart = Math.min(blockStart, region[1] + 1);
+            blockEnd = Math.min(blockEnd, region[0]);
 
             visibleSeq.append(seqs[i].getSequence(blockStart, blockEnd));
 
-            blockStart = hideEnd + 1;
+            blockStart = region[1] + 1;
             blockEnd = end;
           }
 
@@ -962,95 +886,91 @@ public class HiddenColumns
     try
     {
       LOCK.readLock().lock();
-      if (alignmentAnnotation.annotations == null)
-      {
-        return;
-      }
-      if (start == end && end == -1)
-      {
-        start = 0;
-        end = alignmentAnnotation.annotations.length;
-      }
-      if (hiddenColumns != null && hiddenColumns.size() > 0)
-      {
-        // then mangle the alignmentAnnotation annotation array
-        Vector<Annotation[]> annels = new Vector<>();
-        Annotation[] els = null;
-        int blockStart = start;
-        int blockEnd = end;
-        int hideStart;
-        int hideEnd;
-        int w = 0;
-
-        for (int[] region : hiddenColumns)
-        {
-          hideStart = region[0];
-          hideEnd = region[1];
 
-          if (hideStart < start)
-          {
-            continue;
-          }
-
-          blockStart = Math.min(blockStart, hideEnd + 1);
-          blockEnd = Math.min(blockEnd, hideStart);
-
-          if (blockStart > blockEnd)
-          {
-            break;
-          }
+      int startFrom = start;
+      int endAt = end;
 
-          els = new Annotation[blockEnd - blockStart];
-          annels.addElement(els);
-          System.arraycopy(alignmentAnnotation.annotations, blockStart, els,
-                  0, els.length);
-          w += els.length;
-          blockStart = hideEnd + 1;
-          blockEnd = end;
+      if (alignmentAnnotation.annotations != null)
+      {
+        if (start == end && end == -1)
+        {
+          startFrom = 0;
+          endAt = alignmentAnnotation.annotations.length;
         }
-
-        if (end > blockStart)
+        if (hiddenColumns != null && hiddenColumns.size() > 0)
         {
-          els = new Annotation[end - blockStart + 1];
-          annels.addElement(els);
-          if ((els.length
-                  + blockStart) <= alignmentAnnotation.annotations.length)
-          {
-            // copy just the visible segment of the annotation row
-            System.arraycopy(alignmentAnnotation.annotations, blockStart,
-                    els, 0, els.length);
-          }
-          else
-          {
-            // copy to the end of the annotation row
-            System.arraycopy(alignmentAnnotation.annotations, blockStart,
-                    els, 0,
-                    (alignmentAnnotation.annotations.length - blockStart));
-          }
-          w += els.length;
+          removeHiddenAnnotation(startFrom, endAt, alignmentAnnotation);
         }
-        if (w == 0)
+        else
         {
-          return;
+          alignmentAnnotation.restrict(startFrom, endAt);
         }
+      }
+    } finally
+    {
+      LOCK.readLock().unlock();
+    }
+  }
 
-        alignmentAnnotation.annotations = new Annotation[w];
-        w = 0;
+  private void removeHiddenAnnotation(int start, int end,
+          AlignmentAnnotation alignmentAnnotation)
+  {
+    // mangle the alignmentAnnotation annotation array
+    Vector<Annotation[]> annels = new Vector<>();
+    Annotation[] els = null;
+    int blockStart = start;
+    int blockEnd = end;
+    int w = 0;
+
+    Iterator<int[]> regions = new BoundedHiddenColsIterator(start, end,
+            false);
+    while (regions.hasNext())
+    {
+      int[] region = regions.next();
+      blockStart = Math.min(blockStart, region[1] + 1);
+      blockEnd = Math.min(blockEnd, region[0]);
 
-        for (Annotation[] chnk : annels)
-        {
-          System.arraycopy(chnk, 0, alignmentAnnotation.annotations, w,
-                  chnk.length);
-          w += chnk.length;
-        }
+      els = new Annotation[blockEnd - blockStart];
+      annels.addElement(els);
+      System.arraycopy(alignmentAnnotation.annotations, blockStart, els, 0,
+              els.length);
+      w += els.length;
+
+      blockStart = region[1] + 1;
+      blockEnd = end;
+    }
+
+    if (end > blockStart)
+    {
+      els = new Annotation[end - blockStart + 1];
+      annels.addElement(els);
+      if ((els.length
+              + blockStart) <= alignmentAnnotation.annotations.length)
+      {
+        // copy just the visible segment of the annotation row
+        System.arraycopy(alignmentAnnotation.annotations, blockStart, els,
+                0, els.length);
       }
       else
       {
-        alignmentAnnotation.restrict(start, end);
+        // copy to the end of the annotation row
+        System.arraycopy(alignmentAnnotation.annotations, blockStart, els,
+                0, (alignmentAnnotation.annotations.length - blockStart));
       }
-    } finally
+      w += els.length;
+    }
+
+    if (w != 0)
     {
-      LOCK.readLock().unlock();
+      alignmentAnnotation.annotations = new Annotation[w];
+
+      w = 0;
+      for (Annotation[] chnk : annels)
+      {
+        System.arraycopy(chnk, 0, alignmentAnnotation.annotations, w,
+                chnk.length);
+        w += chnk.length;
+      }
     }
   }
 
@@ -1481,6 +1401,9 @@ public class HiddenColumns
     }
   }
 
+  /**
+   * Return an iterator over the hidden regions
+   */
   public Iterator<int[]> iterator()
   {
     if (hiddenColumns != null)
@@ -1494,28 +1417,66 @@ public class HiddenColumns
     }
   }
 
+  /**
+   * Return a bounded iterator over the hidden regions
+   * 
+   * @param start
+   *          position to start from (inclusive, absolute column position)
+   * @param end
+   *          position to end at (inclusive, absolute column position)
+   * @return
+   */
   public Iterator<int[]> getBoundedIterator(int start, int end)
   {
     return new BoundedHiddenColsIterator(start, end, true);
   }
 
+  /**
+   * Return a bounded iterator over the *visible* start positions of hidden
+   * regions
+   * 
+   * @param start
+   *          position to start from (inclusive, visible column position)
+   * @param end
+   *          position to end at (inclusive, visible column position)
+   */
   public Iterator<Integer> getBoundedStartIterator(int start, int end)
   {
     return new BoundedStartRegionIterator(start, end, true);
   }
 
+  /**
+   * Return an iterator over visible columns between the given start and end
+   * boundaries
+   * 
+   * @param start
+   *          first column (inclusive)
+   * @param end
+   *          last column (inclusive)
+   */
   public Iterator<Integer> getVisibleColsIterator(int start, int end)
   {
     return new VisibleColsIterator(start, end, true);
   }
 
   /**
-   * An iterator which iterates over hidden column regions in a range.
+   * return an iterator over visible segments between the given start and end
+   * boundaries
    * 
-   * @author kmourao
-   *
+   * @param start
+   *          (first column inclusive from 0)
+   * @param end
+   *          (last column - not inclusive)
    */
-  class BoundedHiddenColsIterator implements Iterator<int[]>
+  public Iterator<int[]> getVisContigsIterator(int start, int end)
+  {
+    return new VisibleContigsIterator(start, end, true);
+  }
+
+  /**
+   * An iterator which iterates over hidden column regions in a range.
+   */
+  private class BoundedHiddenColsIterator implements Iterator<int[]>
   {
     private int start; // start position to iterate from
 
@@ -1616,12 +1577,17 @@ public class HiddenColumns
     }
   }
 
-  class BoundedStartRegionIterator implements Iterator<Integer>
+  /**
+   * An iterator which iterates over visible start positions of hidden column
+   * regions in a range.
+   */
+  private class BoundedStartRegionIterator implements Iterator<Integer>
   {
+    // start position to iterate from
+    private int start;
 
-    private int start; // start position to iterate from
-
-    private int end; // end position to iterate to
+    // end position to iterate to
+    private int end;
 
     // current index in hiddenColumns
     private int currentPosition = 0;
@@ -1701,6 +1667,11 @@ public class HiddenColumns
       return (currentPosition < positions.size());
     }
 
+    /**
+     * Get next hidden region start position
+     * 
+     * @return the start position in *visible* coordinates
+     */
     @Override
     public Integer next()
     {
@@ -1710,7 +1681,7 @@ public class HiddenColumns
     }
   }
 
-  public class VisibleColsIterator implements Iterator<Integer>
+  private class VisibleColsIterator implements Iterator<Integer>
   {
     private int last;
 
@@ -1722,7 +1693,7 @@ public class HiddenColumns
 
     private int lasthiddenregion;
 
-    public VisibleColsIterator(int firstcol, int lastcol, boolean useCopy)
+    VisibleColsIterator(int firstcol, int lastcol, boolean useCopy)
     {
       last = lastcol;
       current = firstcol;
@@ -1838,4 +1809,87 @@ public class HiddenColumns
       throw new UnsupportedOperationException();
     }
   }
+
+  /**
+   * An iterator which iterates over visible regions in a range.
+   */
+  private class VisibleContigsIterator implements Iterator<int[]>
+  {
+    private List<int[]> vcontigs = new ArrayList<>();
+
+    private int currentPosition = 0;
+
+    VisibleContigsIterator(int start, int end, boolean usecopy)
+    {
+      try
+      {
+        if (usecopy)
+        {
+          LOCK.readLock().lock();
+        }
+
+        if (hiddenColumns != null && hiddenColumns.size() > 0)
+        {
+          int vstart = start;
+          int hideStart;
+          int hideEnd;
+
+          for (int[] region : hiddenColumns)
+          {
+            hideStart = region[0];
+            hideEnd = region[1];
+
+            // navigate to start
+            if (hideEnd < vstart)
+            {
+              continue;
+            }
+            if (hideStart > vstart)
+            {
+              int[] contig = new int[] { vstart, hideStart - 1 };
+              vcontigs.add(contig);
+            }
+            vstart = hideEnd + 1;
+
+            // exit if we're past the end
+            if (vstart >= end)
+            {
+              break;
+            }
+          }
+
+          if (vstart < end)
+          {
+            int[] contig = new int[] { vstart, end - 1 };
+            vcontigs.add(contig);
+          }
+        }
+        else
+        {
+          int[] contig = new int[] { start, end - 1 };
+          vcontigs.add(contig);
+        }
+      } finally
+      {
+        if (usecopy)
+        {
+          LOCK.readLock().unlock();
+        }
+      }
+    }
+
+    @Override
+    public boolean hasNext()
+    {
+      return (currentPosition < vcontigs.size());
+    }
+
+    @Override
+    public int[] next()
+    {
+      int[] result = vcontigs.get(currentPosition);
+      currentPosition++;
+      return result;
+    }
+  }
 }