From: kiramt Date: Wed, 31 Jan 2018 16:38:57 +0000 (+0000) Subject: JAL-2759 Rationalise VisibleColsIterator and HiddenColsIterator X-Git-Tag: Release_2_10_4~55^2~1^2~6 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=fc2e3528b130c13e655058493637eb2b624c0759;p=jalview.git JAL-2759 Rationalise VisibleColsIterator and HiddenColsIterator --- diff --git a/src/jalview/datamodel/HiddenColumns.java b/src/jalview/datamodel/HiddenColumns.java index 3e1f205..4b647db 100644 --- a/src/jalview/datamodel/HiddenColumns.java +++ b/src/jalview/datamodel/HiddenColumns.java @@ -1084,7 +1084,8 @@ public class HiddenColumns try { LOCK.readLock().lock(); - return new VisibleColsIterator(start, end, hiddenColumns); + return new RangeElementsIterator(start, end, + new RangeIterator(hiddenColumns)); } finally { LOCK.readLock().unlock(); diff --git a/src/jalview/datamodel/RangeElementsIterator.java b/src/jalview/datamodel/RangeElementsIterator.java new file mode 100644 index 0000000..ca6c4f7 --- /dev/null +++ b/src/jalview/datamodel/RangeElementsIterator.java @@ -0,0 +1,89 @@ +package jalview.datamodel; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * Iterator over each element in a set of ranges i.e. if ranges is {[3,6], + * [12,15]} it will iterate over {3,4,5,6,12,13,14,15}. Uses a local copy of the + * set of ranges. + * + * @author kmourao + * + */ +public class RangeElementsIterator implements Iterator +{ + private int last; + + private int current; + + private int next; + + private Iterator rangeIterator; + + private int[] nextRange = null; + + RangeElementsIterator(int from, int to, Iterator it) + { + last = to; + current = from; + next = from; + rangeIterator = it; + if (rangeIterator.hasNext()) + { + nextRange = rangeIterator.next(); + } + checkNextRange(); + } + + @Override + public boolean hasNext() + { + return next <= last; + } + + @Override + public Integer next() + { + if (next > last) + { + throw new NoSuchElementException(); + } + + current = next; + + // recalculate next + next++; + + // if there are more ranges need to check if next is in a range + checkNextRange(); + return current; + } + + /** + * Check how next position relates to next range, and update next position if + * necessary + */ + private void checkNextRange() + { + if (nextRange != null && next >= nextRange[0]) + { + next = nextRange[1] + 1; + if (rangeIterator.hasNext()) + { + nextRange = rangeIterator.next(); + } + else + { + nextRange = null; + } + + } + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/jalview/datamodel/RangeIterator.java b/src/jalview/datamodel/RangeIterator.java index 2c5d949..7a69ac6 100644 --- a/src/jalview/datamodel/RangeIterator.java +++ b/src/jalview/datamodel/RangeIterator.java @@ -5,57 +5,57 @@ import java.util.Iterator; import java.util.List; /** - * An iterator which iterates over regions in a range. Works with a copy of the - * collection of regions. + * An iterator which iterates over a list of ranges. Works with a copy of the + * collection of ranges. */ public class RangeIterator implements Iterator { - // current index in regionsList + // current index in rangeList private int currentPosition = 0; - // current column in regionsList - private int[] currentRegion; + // current range in rangeList + private int[] currentRange; - // local copy or reference to regionsList - private List localRegions; + // local copy or reference to rangeList + private List localRanges; /** * Unbounded constructor * - * @param regionsList - * list of regions to iterate over + * @param rangeList + * list of ranges to iterate over */ - RangeIterator(List regionsList) + RangeIterator(List rangeList) { - if (!regionsList.isEmpty()) + if (!rangeList.isEmpty()) { - int last = regionsList.get(regionsList.size() - 1)[1]; - init(0, last, regionsList); + int last = rangeList.get(rangeList.size() - 1)[1]; + init(0, last, rangeList); } else { - init(0, 0, regionsList); + init(0, 0, rangeList); } } /** - * Construct an iterator over regionsList bounded at [lowerBound,upperBound] + * Construct an iterator over rangeList bounded at [lowerBound,upperBound] * * @param lowerBound * lower bound to iterate from * @param upperBound * upper bound to iterate to - * @param regionsList - * list of regions to iterate over + * @param rangeList + * list of ranges to iterate over */ RangeIterator(int lowerBound, int upperBound, - List regionsList) + List rangeList) { - init(lowerBound, upperBound, regionsList); + init(lowerBound, upperBound, rangeList); } /** - * Construct an iterator over regionsList bounded at [lowerBound,upperBound] + * Construct an iterator over rangeList bounded at [lowerBound,upperBound] * * @param lowerBound * lower bound to iterate from @@ -63,30 +63,30 @@ public class RangeIterator implements Iterator * upper bound to iterate to */ private void init(int lowerBound, int upperBound, - List regionsList) + List rangeList) { int start = lowerBound; int end = upperBound; - if (regionsList != null) + if (rangeList != null) { - localRegions = new ArrayList<>(); + localRanges = new ArrayList<>(); - // iterate until a region overlaps with [start,end] + // iterate until a range overlaps with [start,end] int i = 0; - while ((i < regionsList.size()) && (regionsList.get(i)[1] < start)) + while ((i < rangeList.size()) && (rangeList.get(i)[1] < start)) { i++; } - // iterate from start to end, adding each region. Positions are - // absolute, and all regions which *overlap* [start,end] are added. - while (i < regionsList.size() && (regionsList.get(i)[0] <= end)) + // iterate from start to end, adding each range. Positions are + // absolute, and all ranges which *overlap* [start,end] are added. + while (i < rangeList.size() && (rangeList.get(i)[0] <= end)) { - int[] rh = regionsList.get(i); + int[] rh = rangeList.get(i); int[] cp = new int[2]; System.arraycopy(rh, 0, cp, 0, rh.length); - localRegions.add(cp); + localRanges.add(cp); i++; } } @@ -95,20 +95,20 @@ public class RangeIterator implements Iterator @Override public boolean hasNext() { - return (localRegions != null) && (currentPosition < localRegions.size()); + return (localRanges != null) && (currentPosition < localRanges.size()); } @Override public int[] next() { - currentRegion = localRegions.get(currentPosition); + currentRange = localRanges.get(currentPosition); currentPosition++; - return currentRegion; + return currentRange; } @Override public void remove() { - localRegions.remove(--currentPosition); + localRanges.remove(--currentPosition); } } diff --git a/src/jalview/datamodel/VisibleColsIterator.java b/src/jalview/datamodel/VisibleColsIterator.java deleted file mode 100644 index 2fa27ed..0000000 --- a/src/jalview/datamodel/VisibleColsIterator.java +++ /dev/null @@ -1,116 +0,0 @@ -package jalview.datamodel; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -/** - * Iterator over the visible *columns* (not regions) as determined by the set of - * hidden columns. Uses a local copy of hidden columns. - * - * @author kmourao - * - */ -public class VisibleColsIterator implements Iterator -{ - private int last; - - private int current; - - private int next; - - private List localHidden = new ArrayList<>(); - - private int nexthiddenregion; - - VisibleColsIterator(int firstcol, int lastcol, List hiddenColumns) - { - last = lastcol; - current = firstcol; - next = firstcol; - nexthiddenregion = 0; - - if (hiddenColumns != null) - { - int i = 0; - for (i = 0; i < hiddenColumns.size() - && (current <= hiddenColumns.get(i)[0]); ++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; - nexthiddenregion = i + 1; - } - } - - for (i = hiddenColumns.size() - 1; i >= 0 - && (last >= hiddenColumns.get(i)[1]); --i) - { - if (last >= hiddenColumns.get(i)[0] - && last <= hiddenColumns.get(i)[1]) - { - // last is hidden, move to left - last = hiddenColumns.get(i)[0] - 1; - } - } - - // make a local copy of the bit we need - i = nexthiddenregion; - 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++; - } - } - } - - @Override - public boolean hasNext() - { - return next <= last; - } - - @Override - public Integer next() - { - if (next > last) - { - throw new NoSuchElementException(); - } - current = next; - if ((localHidden != null) && (nexthiddenregion < localHidden.size())) - { - // still some more hidden regions - if (next + 1 < localHidden.get(nexthiddenregion)[0]) - { - // next+1 is still before the next hidden region - next++; - } - else if ((next + 1 >= localHidden.get(nexthiddenregion)[0]) - && (next + 1 <= localHidden.get(nexthiddenregion)[1])) - { - // next + 1 is in the next hidden region - next = localHidden.get(nexthiddenregion)[1] + 1; - nexthiddenregion++; - } - } - else - { - // finished with hidden regions, just increment normally - next++; - } - return current; - } - - @Override - public void remove() - { - throw new UnsupportedOperationException(); - } -} diff --git a/test/jalview/datamodel/HiddenColumnsTest.java b/test/jalview/datamodel/HiddenColumnsTest.java index cc5744f..f15f7ad 100644 --- a/test/jalview/datamodel/HiddenColumnsTest.java +++ b/test/jalview/datamodel/HiddenColumnsTest.java @@ -1309,7 +1309,7 @@ public class HiddenColumnsTest HiddenColumns h = new HiddenColumns(); Iterator it = h.getVisibleColsIterator(0, 10); - assertTrue(it instanceof VisibleColsIterator); + assertTrue(it instanceof RangeElementsIterator); } @Test(groups = "Functional") diff --git a/test/jalview/datamodel/VisibleColsIteratorTest.java b/test/jalview/datamodel/RangeElementsIteratorTest.java similarity index 99% rename from test/jalview/datamodel/VisibleColsIteratorTest.java rename to test/jalview/datamodel/RangeElementsIteratorTest.java index f9b01bd..9d14822 100644 --- a/test/jalview/datamodel/VisibleColsIteratorTest.java +++ b/test/jalview/datamodel/RangeElementsIteratorTest.java @@ -28,7 +28,7 @@ import java.util.NoSuchElementException; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -public class VisibleColsIteratorTest +public class RangeElementsIteratorTest { HiddenColumns hiddenCols;