7a69ac64f4a38a80c4c098442d9a63088c70189f
[jalview.git] / src / jalview / datamodel / RangeIterator.java
1 package jalview.datamodel;
2
3 import java.util.ArrayList;
4 import java.util.Iterator;
5 import java.util.List;
6
7 /**
8  * An iterator which iterates over a list of ranges. Works with a copy of the
9  * collection of ranges.
10  */
11 public class RangeIterator implements Iterator<int[]>
12 {
13   // current index in rangeList
14   private int currentPosition = 0;
15
16   // current range in rangeList
17   private int[] currentRange;
18
19   // local copy or reference to rangeList
20   private List<int[]> localRanges;
21
22   /**
23    * Unbounded constructor
24    * 
25    * @param rangeList
26    *          list of ranges to iterate over
27    */
28   RangeIterator(List<int[]> rangeList)
29   {
30     if (!rangeList.isEmpty())
31     {
32       int last = rangeList.get(rangeList.size() - 1)[1];
33       init(0, last, rangeList);
34     }
35     else
36     {
37       init(0, 0, rangeList);
38     }
39   }
40
41   /**
42    * Construct an iterator over rangeList bounded at [lowerBound,upperBound]
43    * 
44    * @param lowerBound
45    *          lower bound to iterate from
46    * @param upperBound
47    *          upper bound to iterate to
48    * @param rangeList
49    *          list of ranges to iterate over
50    */
51   RangeIterator(int lowerBound, int upperBound,
52           List<int[]> rangeList)
53   {
54     init(lowerBound, upperBound, rangeList);
55   }
56
57   /**
58    * Construct an iterator over rangeList bounded at [lowerBound,upperBound]
59    * 
60    * @param lowerBound
61    *          lower bound to iterate from
62    * @param upperBound
63    *          upper bound to iterate to
64    */
65   private void init(int lowerBound, int upperBound,
66           List<int[]> rangeList)
67   {
68     int start = lowerBound;
69     int end = upperBound;
70
71     if (rangeList != null)
72     {
73       localRanges = new ArrayList<>();
74
75       // iterate until a range overlaps with [start,end]
76       int i = 0;
77       while ((i < rangeList.size()) && (rangeList.get(i)[1] < start))
78       {
79         i++;
80       }
81
82       // iterate from start to end, adding each range. Positions are
83       // absolute, and all ranges which *overlap* [start,end] are added.
84       while (i < rangeList.size() && (rangeList.get(i)[0] <= end))
85       {
86         int[] rh = rangeList.get(i);
87         int[] cp = new int[2];
88         System.arraycopy(rh, 0, cp, 0, rh.length);
89         localRanges.add(cp);
90         i++;
91       }
92     }
93   }
94
95   @Override
96   public boolean hasNext()
97   {
98     return (localRanges != null) && (currentPosition < localRanges.size());
99   }
100
101   @Override
102   public int[] next()
103   {
104     currentRange = localRanges.get(currentPosition);
105     currentPosition++;
106     return currentRange;
107   }
108
109   @Override
110   public void remove()
111   {
112     localRanges.remove(--currentPosition);
113   }
114 }