JAL-1460 temp variable for clearer conditional and some extra brackets for readabilit...
[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,
72           List<int[]> rangeList)
73   {
74     init(lowerBound, upperBound, rangeList);
75   }
76
77   /**
78    * Construct an iterator over rangeList bounded at [lowerBound,upperBound]
79    * 
80    * @param lowerBound
81    *          lower bound to iterate from
82    * @param upperBound
83    *          upper bound to iterate to
84    */
85   private void init(int lowerBound, int upperBound,
86           List<int[]> rangeList)
87   {
88     int start = lowerBound;
89     int end = upperBound;
90
91     if (rangeList != null)
92     {
93       localRanges = new ArrayList<>();
94
95       // iterate until a range overlaps with [start,end]
96       int i = 0;
97       while ((i < rangeList.size()) && (rangeList.get(i)[1] < start))
98       {
99         i++;
100       }
101
102       // iterate from start to end, adding each range. Positions are
103       // absolute, and all ranges which *overlap* [start,end] are added.
104       while (i < rangeList.size() && (rangeList.get(i)[0] <= end))
105       {
106         int[] rh = rangeList.get(i);
107         int[] cp = new int[2];
108         System.arraycopy(rh, 0, cp, 0, rh.length);
109         localRanges.add(cp);
110         i++;
111       }
112     }
113   }
114
115   @Override
116   public boolean hasNext()
117   {
118     return (localRanges != null) && (currentPosition < localRanges.size());
119   }
120
121   @Override
122   public int[] next()
123   {
124     currentRange = localRanges.get(currentPosition);
125     currentPosition++;
126     return currentRange;
127   }
128
129   @Override
130   public void remove()
131   {
132     localRanges.remove(--currentPosition);
133   }
134 }