2c5d949c931dd4136f1cbd9f59e2a67552abda8d
[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 regions in a range. Works with a copy of the
9  * collection of regions.
10  */
11 public class RangeIterator implements Iterator<int[]>
12 {
13   // current index in regionsList
14   private int currentPosition = 0;
15
16   // current column in regionsList
17   private int[] currentRegion;
18
19   // local copy or reference to regionsList
20   private List<int[]> localRegions;
21
22   /**
23    * Unbounded constructor
24    * 
25    * @param regionsList
26    *          list of regions to iterate over
27    */
28   RangeIterator(List<int[]> regionsList)
29   {
30     if (!regionsList.isEmpty())
31     {
32       int last = regionsList.get(regionsList.size() - 1)[1];
33       init(0, last, regionsList);
34     }
35     else
36     {
37       init(0, 0, regionsList);
38     }
39   }
40
41   /**
42    * Construct an iterator over regionsList 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 regionsList
49    *          list of regions to iterate over
50    */
51   RangeIterator(int lowerBound, int upperBound,
52           List<int[]> regionsList)
53   {
54     init(lowerBound, upperBound, regionsList);
55   }
56
57   /**
58    * Construct an iterator over regionsList 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[]> regionsList)
67   {
68     int start = lowerBound;
69     int end = upperBound;
70
71     if (regionsList != null)
72     {
73       localRegions = new ArrayList<>();
74
75       // iterate until a region overlaps with [start,end]
76       int i = 0;
77       while ((i < regionsList.size()) && (regionsList.get(i)[1] < start))
78       {
79         i++;
80       }
81
82       // iterate from start to end, adding each region. Positions are
83       // absolute, and all regions which *overlap* [start,end] are added.
84       while (i < regionsList.size() && (regionsList.get(i)[0] <= end))
85       {
86         int[] rh = regionsList.get(i);
87         int[] cp = new int[2];
88         System.arraycopy(rh, 0, cp, 0, rh.length);
89         localRegions.add(cp);
90         i++;
91       }
92     }
93   }
94
95   @Override
96   public boolean hasNext()
97   {
98     return (localRegions != null) && (currentPosition < localRegions.size());
99   }
100
101   @Override
102   public int[] next()
103   {
104     currentRegion = localRegions.get(currentPosition);
105     currentPosition++;
106     return currentRegion;
107   }
108
109   @Override
110   public void remove()
111   {
112     localRegions.remove(--currentPosition);
113   }
114 }