-
- }
-
- /**
- * Finds the hidden region (if any) which starts or ends at res
- *
- * @param res
- * visible residue position, unadjusted for hidden columns
- * @return region as [start,end] or null if no matching region is found
- */
- public int[] getRegionWithEdgeAtRes(int res)
- {
- try
- {
- LOCK.readLock().lock();
- int adjres = adjustForHiddenColumns(res);
-
- int[] reveal = null;
- if (hiddenColumns != null)
- {
- for (int[] region : hiddenColumns)
- {
- if (adjres + 1 == region[0] || adjres - 1 == region[1])
- {
- reveal = region;
- break;
- }
- }
- }
- return reveal;
- } finally
- {
- LOCK.readLock().unlock();
- }
- }
-
- public Iterator<int[]> iterator()
- {
- if (hiddenColumns != null)
- {
- int last = hiddenColumns.get(hiddenColumns.size() - 1)[1];
- return new BoundedHiddenColsIterator(0, last, true);
- }
- else
- {
- return new BoundedHiddenColsIterator(0, 0, true);
- }
- }
-
- public Iterator<int[]> getBoundedIterator(int start, int end)
- {
- return new BoundedHiddenColsIterator(start, end, true);
- }
-
- public Iterator<Integer> getBoundedStartIterator(int start, int end)
- {
- return new BoundedStartRegionIterator(start, end, true);
- }
-
- 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.
- *
- * @author kmourao
- *
- */
- class BoundedHiddenColsIterator implements Iterator<int[]>
- {
- private int start; // start position to iterate from
-
- private int end; // end position to iterate to
-
- // current index in hiddenColumns
- private int currentPosition = 0;
-
- // current column in hiddenColumns
- private int[] currentRegion;
-
- // whether to make a local copy of hiddenColumns
- private final boolean useCopy;
-
- // local copy or reference to hiddenColumns
- private List<int[]> localHidden;
-
- /**
- * Construct an iterator over hiddenColums bounded at
- * [lowerBound,upperBound]
- *
- * @param lowerBound
- * 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)
- */
- BoundedHiddenColsIterator(int lowerBound, int upperBound,
- boolean useCopyCols)
- {
- start = lowerBound;
- end = upperBound;
- useCopy = useCopyCols;
-
- try
- {
- if (useCopy)
- {
- // assume that if useCopy is false the calling code has locked
- // hiddenColumns
- LOCK.readLock().lock();
- }
-
- if (hiddenColumns != null)
- {
- localHidden = new ArrayList<>();
-
- // 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 added.
- while (i < hiddenColumns.size()
- && (hiddenColumns.get(i)[0] <= end))
- {
- int[] rh;
- int[] cp;
- rh = hiddenColumns.get(i);
- if (rh != null)
- {
- cp = new int[rh.length];
- System.arraycopy(rh, 0, cp, 0, rh.length);
- localHidden.add(cp);
- }
- i++;
- }
- }
- }
- finally
- {
- if (useCopy)
- {
- LOCK.readLock().unlock();
- }
- }
- }
-
- @Override
- public boolean hasNext()
- {
- return (localHidden != null)
- && (currentPosition < localHidden.size());
- }
-
- @Override
- public int[] next()
- {
- currentRegion = localHidden.get(currentPosition);
- currentPosition++;
- return currentRegion;
- }
- }
-
- class BoundedStartRegionIterator implements Iterator<Integer>
- {
-
- private int start; // start position to iterate from
-
- private int end; // end position to iterate to
-
- // current index in hiddenColumns
- private int currentPosition = 0;
-
- // local copy or reference to hiddenColumns
- private List<Integer> positions = null;
-
- /**
- * Construct an iterator over hiddenColums bounded at
- * [lowerBound,upperBound]
- *
- * @param lowerBound
- * 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)
- */
- BoundedStartRegionIterator(int lowerBound, int upperBound,
- boolean useCopy)
- {
- start = lowerBound;
- end = upperBound;
-
- try
- {
- if (useCopy)
- {
- // assume that if useCopy is false the calling code has locked
- // hiddenColumns
- LOCK.readLock().lock();
- }
-
- if (hiddenColumns != null)
- {
- positions = new ArrayList<>(hiddenColumns.size());
-
- // navigate to start, keeping count of hidden columns
- int i = 0;
- int hiddenSoFar = 0;
- while ((i < hiddenColumns.size())
- && (hiddenColumns.get(i)[0] < start + hiddenSoFar))
- {
- int[] region = hiddenColumns.get(i);
- hiddenSoFar += region[1] - region[0] + 1;
- i++;
- }
-
- // iterate from start to end, adding start positions of each
- // hidden region. Positions are visible columns count, not absolute
- while (i < hiddenColumns.size()
- && (hiddenColumns.get(i)[0] <= end + hiddenSoFar))
- {
- int[] region = hiddenColumns.get(i);
- positions.add(region[0] - hiddenSoFar);
- hiddenSoFar += region[1] - region[0] + 1;
- i++;
- }
- }
- else
- {
- positions = new ArrayList<>();
- }
- } finally
- {
- if (useCopy)
- {
- LOCK.readLock().unlock();
- }
- }
- }
-
- @Override
- public boolean hasNext()
- {
- return (currentPosition < positions.size());
- }
-
- @Override
- public Integer next()
- {
- int result = positions.get(currentPosition);
- currentPosition++;
- 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();
- }