1 package com.atlassian.user.search.page;
2
3 import org.apache.log4j.Category;
4
5 import java.util.ArrayList;
6 import java.util.Collections;
7 import java.util.Iterator;
8 import java.util.List;
9
10 public class MergedListPager<T> implements Pager<T>
11 {
12 private static final Category log = Category.getInstance(MergedListPager.class);
13 private List<? extends Pager<T>> pagers;
14 private int combinedIndex;
15 public Pager<? extends T> currentPager;
16 private List<T> currentPage;
17 private int indexOfFirstItemInCurrentPage;
18 private boolean onLastPage = false;
19
20 MergedListPager(List<? extends Pager<T>> pagers)
21 {
22 this.pagers = pagers;
23 }
24
25 public boolean isEmpty()
26 {
27 for (Pager<T> pager : pagers)
28 {
29 if (!pager.isEmpty())
30 return false;
31 }
32
33 return true;
34 }
35
36
37
38
39 public Iterator<T> iterator()
40 {
41 if (pagers == null)
42 {
43 return Collections.<T>emptyList().iterator();
44 }
45 else
46 {
47 return new MergedListIterator(pagers);
48 }
49 }
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public List<T> getCurrentPage()
64 {
65 if (currentPage == null)
66 {
67 currentPage = new ArrayList<T>();
68 indexOfFirstItemInCurrentPage = combinedIndex;
69
70 for (Iterator<T> iterator = iterator(); iterator.hasNext();)
71 {
72 if (currentPage.size() < PRELOAD_LIMIT)
73 {
74 currentPage.add(iterator.next());
75 combinedIndex++;
76 }
77 else
78 break;
79 }
80
81
82 if (currentPage.size() < PRELOAD_LIMIT || !iterator().hasNext())
83 onLastPage = true;
84 }
85
86 return currentPage;
87 }
88
89 public void nextPage()
90 {
91 try
92 {
93
94 skipTo(combinedIndex + (currentPage == null ? PRELOAD_LIMIT : 0));
95 }
96 catch (PagerException e)
97 {
98 log.error("Erroring calling nextPage()", e);
99 }
100 }
101
102 public boolean onLastPage()
103 {
104 return onLastPage;
105 }
106
107
108
109
110
111
112
113
114 public void skipTo(int index) throws PagerException
115 {
116 if (index < combinedIndex)
117 throw new PagerException("Cannot run the index back to [" + index + "] from [" + combinedIndex + "]");
118
119 while (combinedIndex < index)
120 {
121 iterator().next();
122 combinedIndex++;
123 }
124
125
126 currentPage = null;
127 getCurrentPage();
128 }
129
130
131
132
133 public int getIndex()
134 {
135 return combinedIndex;
136 }
137
138 public int getIndexOfFirstItemInCurrentPage()
139 {
140 getCurrentPage();
141 return indexOfFirstItemInCurrentPage;
142 }
143
144 private class MergedListIterator implements Iterator<T>
145 {
146 private List<Iterator<T>> iterators = new ArrayList<Iterator<T>>();
147
148 public MergedListIterator(List<? extends Pager<T>> listOfPagers)
149 {
150 for (Pager<T> listOfPager : listOfPagers)
151 {
152 this.iterators.add(listOfPager.iterator());
153 }
154 }
155
156 private Iterator<T> getCurrentIterator()
157 {
158 for (Iterator<T> iterator : iterators)
159 {
160 if (iterator.hasNext())
161 return iterator;
162 }
163
164 return Collections.<T>emptyList().iterator();
165 }
166
167
168 public void remove()
169 {
170 throw new UnsupportedOperationException("This iterator does not support removal");
171 }
172
173 public boolean hasNext()
174 {
175 return getCurrentIterator().hasNext();
176 }
177
178 public T next()
179 {
180 T nextElement = getCurrentIterator().next();
181
182 if (!hasNext())
183 onLastPage = true;
184
185 return nextElement;
186 }
187 }
188
189 }