View Javadoc

1   package com.atlassian.user.search.page;
2   
3   import com.atlassian.user.EntityException;
4   import org.apache.log4j.Category;
5   
6   import java.util.*;
7   
8   public abstract class AbstractPrefetchingPager<T> implements Pager<T>, Iterator<T>
9   {
10      public static final Category log = Category.getInstance(AbstractPrefetchingPager.class);
11      protected int idx = 0;
12      private final int preloadLimit = PRELOAD_LIMIT;
13      private final List<T> prefetched = new ArrayList<T>(preloadLimit);
14      protected int indexOfFirstItemInCurrentPage = 0;
15      public boolean lastPage;
16  
17      public Iterator<T> iterator()
18      {
19          return this;
20      }
21  
22      public boolean isEmpty()
23      {
24          return !hasNext();
25      }
26  
27      public List<T> getCurrentPage()
28      {
29          return new ArrayList<T>(prefetched);
30      }
31  
32      public boolean hasNext()
33      {
34         int indexWithinPage = getIndexWithinPage();
35         if (indexWithinPage == prefetched.size() && !lastPage)
36         {
37              preload();
38              indexWithinPage = getIndexWithinPage();
39         }
40         return indexWithinPage < prefetched.size() || !lastPage;
41      }
42  
43      protected abstract void preload();
44  
45      public void remove()
46      {
47          throw new UnsupportedOperationException();
48      }
49  
50      protected void preload(Iterator iterator)
51      {
52          prefetched.clear();
53          int currentPos = 0;
54  
55          try
56          {
57              while (!lastPage && prefetched.size() < preloadLimit)
58              {
59                  if (!iterator.hasNext())
60                  {
61                      lastPage = true;
62                      break;
63                  }
64  
65                  Object element = iterator.next();
66  
67                  List<T> entities = new ArrayList<T>();
68                  fetch(element, entities);
69  
70                  for (Iterator<T> i = entities.iterator(); i.hasNext() && prefetched.size() < preloadLimit;)
71                  {
72                      T r = i.next();
73                      if (currentPos >= idx)
74                      {
75                          prefetched.add(r);
76                      }
77                      ++currentPos;
78                  }
79              }
80              if (prefetched.size() < preloadLimit)
81              {
82                  lastPage = true;
83              }
84          }
85          catch (Exception e)
86          {
87              log.error("At index [" + idx + "]: " + e.getMessage(), e);
88              lastPage = true;
89          }
90      }
91  
92      abstract protected List<T> fetch(Object element, List<T> prefetched) throws EntityException;
93  
94      public void nextPage()
95      {
96          idx += PRELOAD_LIMIT;
97          preload();
98      }
99  
100     public int getIndex()
101     {
102         return idx;
103     }
104 
105     public void skipTo(int idx) throws PagerException
106     {
107         this.idx = idx;
108         preload();
109 
110         if (prefetched == null || prefetched.size() == 0)
111         {
112             this.idx = NO_POSITION;
113         }
114     }
115 
116     public boolean onLastPage()
117     {
118         return lastPage;
119     }
120 
121     public int getIndexOfFirstItemInCurrentPage()
122     {
123         return indexOfFirstItemInCurrentPage;
124     }
125 
126     public T next()
127     {
128         if (!hasNext())
129             throw new NoSuchElementException();
130         int indexWithinPage = getIndexWithinPage();
131         T nextObj = prefetched.get(indexWithinPage);
132         idx++;
133 
134         return nextObj;
135     }
136 
137     protected int getIndexWithinPage()
138     {
139         return idx - indexOfFirstItemInCurrentPage;
140     }
141 }