JAL-2674 iterator for visible blocks with absolute positions
authorkiramt <k.mourao@dundee.ac.uk>
Mon, 2 Oct 2017 12:58:45 +0000 (13:58 +0100)
committerkiramt <k.mourao@dundee.ac.uk>
Mon, 2 Oct 2017 12:58:45 +0000 (13:58 +0100)
src/jalview/datamodel/HiddenColumns.java

index aa34461..b6e6ce3 100644 (file)
@@ -660,26 +660,12 @@ public class HiddenColumns
         {
           StringBuffer visibleSeq = new StringBuffer();
 
-          int blockStart = start;
-          int blockEnd = end;
-
-          Iterator<int[]> regions = new BoundedHiddenColsIterator(start,
+          Iterator<int[]> blocks = new VisibleBlocksIterator(start,
                   end, false);
-          while (regions.hasNext())
-          {
-            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 = region[1] + 1;
-            blockEnd = end;
-          }
-
-          if (end > blockStart)
+          while (blocks.hasNext())
           {
-            visibleSeq.append(seqs[i].getSequence(blockStart, end));
+            int[] block = blocks.next();
+            visibleSeq.append(seqs[i].getSequence(block[0], block[1]));
           }
 
           selections[i] = visibleSeq.toString();
@@ -845,48 +831,45 @@ public class HiddenColumns
     // 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,
+    int w = 0;
+    
+    Iterator<int[]> blocks = new VisibleBlocksIterator(start, end,
             false);
-    while (regions.hasNext())
-    {
-      int[] region = regions.next();
-      blockStart = Math.min(blockStart, region[1] + 1);
-      blockEnd = Math.min(blockEnd, region[0]);
-
-      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)
+    int copylength;
+    int annotationLength;
+    while (blocks.hasNext())
     {
-      els = new Annotation[end - blockStart + 1];
-      annels.addElement(els);
-      if ((els.length
-              + blockStart) <= alignmentAnnotation.annotations.length)
+      int[] block = blocks.next();
+    
+      if (blocks.hasNext())
       {
+        annotationLength = block[1] - block[0];
         // copy just the visible segment of the annotation row
-        System.arraycopy(alignmentAnnotation.annotations, blockStart, els,
-                0, els.length);
+        copylength = annotationLength;
       }
       else
       {
-        // copy to the end of the annotation row
-        System.arraycopy(alignmentAnnotation.annotations, blockStart, els,
-                0, (alignmentAnnotation.annotations.length - blockStart));
+        annotationLength = block[1] - block[0] + 1;
+        if (annotationLength + block[0] <= alignmentAnnotation.annotations.length)
+        {
+          // copy just the visible segment of the annotation row
+          copylength = annotationLength;
+        }
+        else
+        {
+          // copy to the end of the annotation row
+          copylength = alignmentAnnotation.annotations.length - block[0];
+        }
       }
-      w += els.length;
+      
+      els = new Annotation[annotationLength];
+      annels.addElement(els);
+      System.arraycopy(alignmentAnnotation.annotations, block[0], els, 0,
+              copylength);
+      w += annotationLength;
     }
-
+    
     if (w != 0)
     {
       alignmentAnnotation.annotations = new Annotation[w];
@@ -1822,4 +1805,90 @@ public class HiddenColumns
       return result;
     }
   }
+
+  /**
+   * An iterator which iterates over visible regions in a range.
+   */
+  private class VisibleBlocksIterator implements Iterator<int[]>
+  {
+    private List<int[]> vcontigs = new ArrayList<>();
+
+    private int currentPosition = 0;
+
+    VisibleBlocksIterator(int start, int end, boolean usecopy)
+    {
+      try
+      {
+        if (usecopy)
+        {
+          LOCK.readLock().lock();
+        }
+
+        if (hiddenColumns != null && hiddenColumns.size() > 0)
+        {
+          int blockStart = start;
+          int blockEnd = end;
+
+          // iterate until a region overlaps with [start,end]
+          int i = 0;
+          while ((i < hiddenColumns.size())
+                  && (hiddenColumns.get(i)[1] < start))
+          {
+            i++;
+          }
+
+          // iterate from start to end, adding each hidden region. Positions are
+          // absolute, and all regions which *overlap* [start,end] are used.
+          while (i < hiddenColumns.size()
+                  && (hiddenColumns.get(i)[0] <= end))
+          {
+            int[] region = hiddenColumns.get(i);
+
+            blockStart = Math.min(blockStart, region[1] + 1);
+            blockEnd = Math.min(blockEnd, region[0]);
+
+            int[] contig = new int[] { blockStart, blockEnd };
+            vcontigs.add(contig);
+
+            blockStart = region[1] + 1;
+            blockEnd = end;
+
+            i++;
+          }
+
+          if (end > blockStart)
+          {
+            int[] contig = new int[] { blockStart, end };
+            vcontigs.add(contig);
+          }
+        }
+        else
+        {
+          int[] contig = new int[] { start, end };
+          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;
+    }
+  }
+
 }