View Javadoc

1   /*
2    * Copyright 2001,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.commons.scaffold.util;
18  
19  
20  import java.util.Map;
21  
22  import org.apache.commons.scaffold.text.ConvertUtils;
23  
24  
25  /**
26   * Scroller tracks the coordinates needed to manage
27   * flipping through a result list using
28   * LIMIT and OFFSET clauses (or the equivalent).
29   *
30   * Scrolls through entries using a range (10 to 20 of 50)
31   * but does not support paging per se goto page 3 (or entry 30)),
32   * though that would be an easy enhancement.
33   *
34   * @author James Klicman <james@jsptags.com>
35   * @author Ted Husted
36   * @author WXXI Public Broadcasting Council
37   * @author OK State DEQ
38   * @version $Revision: 155464 $ $Date: 2005-02-26 13:26:54 +0000 (Sat, 26 Feb 2005) $
39   */
40  public class Scroller {
41  
42  
43    public Scroller(int entries, int from, int limit, int count) {
44       calculate(entries,from,limit,count);
45    }
46  
47  
48    public Scroller() {
49    }
50  
51  
52    /**
53     * The maximum to return with a scrolling list.
54     */
55    public static final int SCROLL_ROWS = 20;
56  
57  
58  // ---------------------------------------------------------------- Properties
59  
60  
61    /**
62     * The default starting point [1].
63     * The value is for the convenience of SQL, which is one-based.
64     */
65    public static int FROM = 1;
66  
67  
68    /**
69     * The starting point for the current query [FROM].
70     */
71    protected int from = FROM;
72  
73  
74    /**
75     * Set from.
76     * @param from The new from value.
77     */
78    public void setFrom(int from) {
79      this.from = from;
80    }
81  
82  
83    /**
84     * Return from.
85     * @return The form value.
86     */
87    public int getFrom() {
88      return(this.from);
89    }
90  
91  
92    /**
93     * The ending point for the current query [1].
94     */
95    protected int thru = 1;
96  
97  
98    /**
99     * Set thru.
100    * @param thru The new thru value.
101    */
102   public void setThru(int thru) {
103     this.thru = thru;
104   }
105 
106 
107   /**
108    * Return thru.
109    * @return The form value.
110    */
111   public int getThru() {
112     return(this.thru);
113   }
114 
115 
116   /**
117    * The starting point to use for a "backward" query.
118    */
119   protected int prev = 1;
120 
121 
122   /**
123    * Set prev.
124    * @param prev The new prev value.
125    */
126   public void setPrev(int prev) {
127     this.prev = prev;
128   }
129 
130 
131   /**
132    * Return prev.
133    * @return The prev value.
134    */
135   public int getPrev() {
136     return(this.prev);
137   }
138 
139 
140   /**
141    * The starting point to use with a "forward" query.
142    * This should always be a valid value.
143    *
144    */
145   protected int next = 1;
146 
147 
148   /**
149    * Set next.
150    * @param next The new next value.
151    */
152   public void setNext(int next) {
153     this.next = next;
154   }
155 
156 
157   /**
158    * Return next.
159    * @return The next value.
160    */
161   public int getNext() {
162     return(this.next);
163   }
164 
165 
166   /**
167    * The maximum number of entries to fetch at a time
168    * [Integer.MAX_VALUE].
169    */
170   protected int limit = Integer.MAX_VALUE;
171 
172 
173   /**
174    * Set limit.
175    * @param limit The new limit value.
176    */
177   public void setLimit(int limit) {
178     this.limit = limit;
179   }
180 
181 
182   /**
183    * Return limit.
184    * @return The limit value.
185    */
186   public int getLimit() {
187     return(this.limit);
188   }
189 
190 
191   /**
192    * The actual number of entries to fetch (eg length or limit).
193    */
194   protected int entries = 0;
195 
196 
197   /**
198    * Set entries
199    * @param entries The new entries value.
200    */
201   public void setEntries(int entries) {
202     this.entries = entries;
203   }
204 
205 
206   /**
207    * Return entries.
208    * @return The entries value.
209    */
210   public int getEntries() {
211     return(this.entries);
212   }
213 
214 
215   /**
216    * The maximum number of entries available  (the SQL count).
217    *
218    */
219   protected int count = 0;
220 
221 
222   /**
223    * Set count
224    * @param count The new count value.
225    */
226   public void setCount(int count) {
227     this.count = count;
228   }
229 
230 
231   /**
232    * Return count.
233    * @return The count value.
234    */
235   public int getCount() {
236     return(this.count);
237   }
238 
239 
240   /**
241    * Field for the parameters property [java.util.HashMap].
242    */
243   protected Map parameters = new java.util.HashMap();
244 
245 
246   /**
247    * Set parameters
248    * @param parameters The new parameters value.
249    */
250   public void setParameters(Map parameters) {
251     this.parameters = parameters;
252   }
253 
254 
255   /**
256    * Return parameters.
257    * @return The parameters value.
258    */
259   public Map getParameters() {
260     return(this.parameters);
261   }
262 
263 
264   /**
265    * Set a parameter
266    * @param key The parameter name
267    * @param value The parameter value
268    */
269   public void putParameter(String key, String value) {
270     getParameters().put(key,value);
271   }
272 
273 
274   /**
275    * Set a parameter
276    * @param key The parameter name
277    * @param value The parameter value
278    */
279   public boolean isParameters() {
280     return (!getParameters().isEmpty());
281   }
282 
283 
284   /**
285    * Return parameters as a query string for use with a URI.
286    * @return query string
287    */
288   public String getQueryString(String uri) {
289 
290       return ConvertUtils.addParams(uri,getParameters());
291 
292   }
293 
294 
295   /**
296    * Return parameters as a series of hidden HTML fields.
297    * @return parameters as a series of hidden HTML fields.
298    */
299   public String getHiddenFields() {
300 
301       return ConvertUtils.renderHiddenFields(getParameters());
302 
303   }
304 
305 
306 // ------------------------------------------------------------ Public Methods
307 
308 
309   /**
310    * The database offset for the current query [0].
311    *
312    * Convenience method to return one less than from
313    *
314    * @return The offset for this query
315    */
316   public int getOffset() {
317     int from = getFrom();
318     return(--from);
319   }
320 
321 
322   /**
323    * Return page number for given entry.
324    * @return The number of pages
325    */
326   public int getPage(int thru) {
327 
328     int limit = getLimit();
329 
330     if ((0==thru) || (0==limit)) return 1;
331 
332     double page = (thru / limit) + (thru % limit == 0 ? 0 : 1);
333 
334     return new Double(page).intValue();
335   }
336 
337 
338   /**
339    * Return current page number
340    * @return The number of pages
341    */
342   public int getPage() {
343 
344       return getPage(getThru());
345   }
346 
347 
348   /**
349    * Return number of pages.
350    * @return The number of pages
351    */
352   public int getPages() {
353 
354       return getPage(getCount());
355   }
356 
357 
358   /**
359    * Return first entry for given page.
360    * @return first entry for given page
361    */
362   public int getOffsetForPage(int page) {
363 
364       int limit = getLimit();
365 
366       return ((page*limit)-limit)+1;
367   }
368 
369 
370   /**
371    * Calculate the new property values
372    * using a bean that has already had count and limit set.
373    *
374    * @param from The first absolute row
375    */
376   public void calculate() {
377 
378      int from = getFrom();
379      int limit = getLimit();
380      int entries = getEntries();
381      int count = getCount();
382 
383      // Calculate "next" relative to starting point; or wrap to beginning.
384      int thru = (from + entries) - 1 ; if (thru < 1) thru = 1;
385 
386      // Calculate "previous" relative to starting point, but don't go negative
387      int prev = from - limit; if (prev < 1) prev = 1;
388 
389      // Calculate "next" relative to starting point; or wrap to beginning.
390      int next = from + entries; if (next > count) next = 1;
391 
392      setPrev(prev);
393      setNext(next);
394      setThru(thru);
395   }
396 
397 
398 
399   /**
400    * Calculate the new property values
401    * using a bean that has already had count and limit set.
402    *
403    * @param from The first absolute row
404    */
405   public void calculate(int entries) {
406 
407      setEntries(entries);
408      calculate();
409   }
410 
411 
412   /**
413    * Calculate the new property values.
414    *
415    * @param entries The number of matches in this set
416    * @param from The first absolute row in this set
417    * @param count How many rows in the complete set
418    * @param limit The maximum rows in a subset page
419    */
420   public void calculate(int entries, int from, int count, int limit) {
421 
422      if ((from<1) || (from>count)) from = 1;
423 
424      setLimit(limit);
425      setCount(count);
426      setFrom(from);
427      calculate(entries);
428   }
429 
430 } // end Scroller