Merge branch 'releases/Release_2_11_3_Branch'
[jalview.git] / src / jalview / datamodel / RangeIterator.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.datamodel;
22
23 import java.util.ArrayList;
24 import java.util.Iterator;
25 import java.util.List;
26
27 /**
28  * An iterator which iterates over a list of ranges. Works with a copy of the
29  * collection of ranges.
30  */
31 public class RangeIterator implements Iterator<int[]>
32 {
33   // current index in rangeList
34   private int currentPosition = 0;
35
36   // current range in rangeList
37   private int[] currentRange;
38
39   // local copy or reference to rangeList
40   private List<int[]> localRanges;
41
42   /**
43    * Unbounded constructor
44    * 
45    * @param rangeList
46    *          list of ranges to iterate over
47    */
48   RangeIterator(List<int[]> rangeList)
49   {
50     if (!rangeList.isEmpty())
51     {
52       int last = rangeList.get(rangeList.size() - 1)[1];
53       init(0, last, rangeList);
54     }
55     else
56     {
57       init(0, 0, rangeList);
58     }
59   }
60
61   /**
62    * Construct an iterator over rangeList bounded at [lowerBound,upperBound]
63    * 
64    * @param lowerBound
65    *          lower bound to iterate from
66    * @param upperBound
67    *          upper bound to iterate to
68    * @param rangeList
69    *          list of ranges to iterate over
70    */
71   RangeIterator(int lowerBound, int upperBound, List<int[]> rangeList)
72   {
73     init(lowerBound, upperBound, rangeList);
74   }
75
76   /**
77    * Construct an iterator over rangeList bounded at [lowerBound,upperBound]
78    * 
79    * @param lowerBound
80    *          lower bound to iterate from
81    * @param upperBound
82    *          upper bound to iterate to
83    */
84   private void init(int lowerBound, int upperBound, List<int[]> rangeList)
85   {
86     int start = lowerBound;
87     int end = upperBound;
88
89     if (rangeList != null)
90     {
91       localRanges = new ArrayList<>();
92
93       // iterate until a range overlaps with [start,end]
94       int i = 0;
95       while ((i < rangeList.size()) && (rangeList.get(i)[1] < start))
96       {
97         i++;
98       }
99
100       // iterate from start to end, adding each range. Positions are
101       // absolute, and all ranges which *overlap* [start,end] are added.
102       while (i < rangeList.size() && (rangeList.get(i)[0] <= end))
103       {
104         int[] rh = rangeList.get(i);
105         int[] cp = new int[2];
106         System.arraycopy(rh, 0, cp, 0, rh.length);
107         localRanges.add(cp);
108         i++;
109       }
110     }
111   }
112
113   @Override
114   public boolean hasNext()
115   {
116     return (localRanges != null) && (currentPosition < localRanges.size());
117   }
118
119   @Override
120   public int[] next()
121   {
122     currentRange = localRanges.get(currentPosition);
123     currentPosition++;
124     return currentRange;
125   }
126
127   @Override
128   public void remove()
129   {
130     localRanges.remove(--currentPosition);
131   }
132 }