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