Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: jreceiver/util/taglibs/PageNavigationTag.java


1   /* $Header: /cvsroot/jreceiver/jreceiver/src/jreceiver/util/taglibs/PageNavigationTag.java,v 1.5 2002/07/31 11:29:43 reedesau Exp $ */
2   
3   package jreceiver.util.taglibs;
4   
5   import java.io.IOException;
6   import java.text.MessageFormat;
7   import javax.servlet.jsp.*;
8   import javax.servlet.jsp.tagext.*;
9   
10  import org.apache.commons.logging.*;
11  
12  /**
13   * JSP Tag <b>pageNavigation</b>, used to display an array of
14   * page numbers to traverse a large set of data.
15   * <p>
16   * Required attributes are <b>total_pages</b> and <b>page_no</b>.
17   *
18   * <b>url_pattern</b> is optional and defaults to page{0}.html which
19   * produces page1.html, page2.html, etc.   It uses a MessageFormat
20   * pattern where {0} is replaced by the page number (pageNo) and {1}
21   * is replaced by the page count (totalPages).
22   * <p>
23   * Example of default output for page numbers 1 through 16:<br>
24   * <pre>
25   * <<- 1 2 3 4 .. 16 ->>
26   * <<- 1 2 3 4 5 .. 16 ->>
27   * <<- 1 2 3 4 5 6 .. 16 ->>
28   * <<- 1 2 3 4 5 6 7 .. 16 ->>
29   * <<- 1 2 3 4 5 6 7 8 .. 16 ->>
30   * <<- 1 2 3 4 5 6 7 8 9 .. 16 ->>
31   * <<- 1 .. 4 5 6 7 8 9 10 .. 16 ->>
32   * <<- 1 .. 5 6 7 8 9 10 11 .. 16 ->>
33   * <<- 1 .. 6 7 8 9 10 11 12 .. 16 ->>
34   * <<- 1 .. 7 8 9 10 11 12 13 .. 16 ->>
35   * <<- 1 .. 8 9 10 11 12 13 14 15 16 ->>
36   * <<- 1 .. 9 10 11 12 13 14 15 16 ->>
37   * <<- 1 .. 10 11 12 13 14 15 16 ->>
38   * <<- 1 .. 11 12 13 14 15 16 ->>
39   * <<- 1 .. 12 13 14 15 16 ->>
40   * <<- 1 .. 13 14 15 16 ->>
41   * </pre>
42   * <p>
43   * Example usage:
44   * <p>
45   * <pre>
46   * <jrec:pageNavigation pageNo="1"
47   *                       totalPages="16"
48   *                       urlPattern="food{0}.jsp?pages={1}"
49   *                       prev="&amp;laquo;" next="&amp;raquo;"/>
50   * </pre>
51   *
52   * @author Reed Esau
53   * @version $Revision: 1.5 $ $Date: 2002/07/31 11:29:43 $
54   */
55  public class PageNavigationTag extends TagSupport {
56  
57      private static final int DEFAULT_BLOCK_SIZE = 7;
58      private static final int DEFAULT_THRESHOLD = 4;
59      private static final String DEFAULT_PREV = "&lt;&lt;-";
60      private static final String DEFAULT_NEXT = "-&gt;&gt;";
61      private static final String DEFAULT_URL_PATTERN = "page{0}.html";  // where {0} is the replaceable param
62  
63      /**
64       * The current page number, 1-indexed
65       */
66      private int page_no = 0;
67      /**
68       * The size of the floating block of numbers, with (block_size/2)
69       * number on either side of the current page no.
70       * <p>
71       * Must be an odd number, three or greater.
72       */
73      private int block_size = DEFAULT_BLOCK_SIZE;
74      /**
75       * The point at which diresis (sp?) will begin to show up on either
76       * side of the list of numbers as the floating block moves away from
77       * the edge.
78       * <p>
79       * Must be greater than 3.
80       */
81      private int threshold = DEFAULT_THRESHOLD;
82      /**
83       * The string (or image) to represent the left arrow
84       */
85      private String prev = DEFAULT_PREV;
86      /**
87       * The string (or image) to represent the right arrow
88       */
89      private String next = DEFAULT_NEXT;
90      /**
91       * The number of pages we provide navigation over
92       */
93      private int total_pages = 0;
94      /**
95       * The template used to generate links for each page number we display
96       */
97      private MessageFormat url_format = null;
98  
99      /**
100      * The default text if the tag or number given is invalid/null
101      */
102     private String default_text = "Invalid navigation";
103 
104     /**
105      * Method called at start of tag -- extract attributes
106      */
107     public final int doStartTag() throws JspException {
108         if (log.isDebugEnabled())
109             log.debug("doStartTag, page_no=" + page_no + " total_pages=" + total_pages);
110 
111         if ( page_no == 0 ) {
112             Object attr = pageContext.findAttribute("pageNo");
113             if ( attr == null )
114                 throw new JspException("pageNo is a required attribute");
115             try {
116                 if (log.isDebugEnabled())
117                     log.debug("getting page_no: " + attr.toString());
118                 page_no = Integer.parseInt( attr.toString() );
119             }
120             catch (NumberFormatException nfe) {
121                 throw new JspException("number problem with pageNo: " + nfe.getMessage());
122             }
123         }
124 
125         if ( total_pages == 0 ) {
126             Object attr = pageContext.findAttribute("totalPages");
127             if ( attr == null )
128                 throw new JspException("totalPages is a required attribute");
129             try {
130                 total_pages = Integer.parseInt( attr.toString() );
131             }
132             catch (NumberFormatException nfe) {
133                 throw new JspException("number problem with totalPages: " + nfe.getMessage());
134             }
135         }
136 
137         if ( url_format == null ) {
138             Object attr = pageContext.findAttribute("urlPattern");
139             if ( attr != null )
140                 url_format = new MessageFormat(attr.toString());
141             else
142                 url_format = new MessageFormat(DEFAULT_URL_PATTERN);
143         }
144 
145         return SKIP_BODY;
146     }
147 
148     /**
149      * Method called at end of Tag
150      *
151      * @return EVAL_PAGE
152      */
153     public final int doEndTag() throws JspException {
154 
155         if (log.isDebugEnabled())
156             log.debug("doEndTag: page_no=" + page_no
157                       + " total_pages=" + total_pages);
158 
159         if (page_no <= 0 || total_pages < 0)
160             throw new JspException("bad pageNo or totalPages");
161 
162         if (total_pages < 2)  // don't show navigation if user can't do anything
163             return EVAL_PAGE;
164 
165         try {
166             JspWriter writer = pageContext.getOut();
167 
168             // show left arrow
169             if (prev != null) {
170                 if (page_no == 1)
171                     writer.write(prev);
172                 else
173                     writer.write(getHref(page_no-1, prev));
174                 writer.write(" ");
175             }
176 
177             // determine range
178             int min, max;
179             {
180                 int left  = page_no - (block_size/2);
181                 int right = page_no + (block_size/2);
182 
183                 if (left < threshold) {                           // if far left
184                     min = 1;
185                     max = right < total_pages ? right : total_pages;
186                 }
187                 else if (right > total_pages - threshold + 1) {   // if far right
188                     min = left;
189                     max = total_pages;
190                 }
191                 else {
192                     min = left;
193                     max = right;
194                 }
195 
196                 //max = right < total_pages ? right : total_pages;
197             }
198 
199             if (log.isDebugEnabled())
200                 log.debug("doEndTag: min=" + min + " max=" + max);
201 
202             // show first page no
203             if (page_no == 1)
204                 writer.write("<b>1</b>");
205             else
206                 writer.write(getHref(1, new Integer(1)));
207             writer.write(" ");
208 
209             // show diresis (sp?) if necessary
210             if ( min > 1 )
211                 writer.write(".. ");
212 
213             // show array of page nos
214             for (int i = min; i <= max; i++) {
215 
216                 if (i == 1 || i == total_pages)
217                     continue;   // we do these anyway
218 
219                 if (i == page_no)
220                     writer.write("<b>" + i + "</b>");
221                 else
222                     writer.write(getHref(i, new Integer(i)));
223                 writer.write(" ");      // space them
224             }
225 
226             // show diresis (sp?) if necessary
227             if ( max < total_pages )
228                 writer.write(".. ");
229 
230             // show last page no, if not the same as first
231             if (min != max) {
232                 if (page_no == total_pages)
233                     writer.write("<b>" + total_pages + "</b>");
234                 else
235                     writer.write(getHref(total_pages, new Integer(total_pages)));
236                 writer.write(" ");
237             }
238 
239             // show right arrow
240             if (next != null) {
241                 if (page_no == total_pages)
242                     writer.write(next);
243                 else
244                     writer.write(getHref(page_no+1, next));
245             }
246         }
247         catch (IOException e) {
248             throw new JspException("io-problem writing navigation tag: " + e.getMessage());
249         }
250 
251         return EVAL_PAGE;
252     }
253 
254 
255     /**
256      * Do a MessageFormat of the url_pattern with the following
257      * optional parameters:
258      * <p>
259      * <pre>
260      *   {0} the page number
261      *   {1} total pages
262      * </pre>
263      * <p>
264      *
265      * @param param
266      * @return
267      */
268     private String getHref(int page_no, Object displayed) {
269 
270         StringBuffer buf = new StringBuffer(32);
271         Object[] params = new Object[2];
272         params[0] = Integer.toString(page_no);            // pass as a string to avoid "6,666" formatting
273         params[1] = Integer.toString(total_pages);        // ...
274 
275         buf.append("<a href='")
276         .append( url_format.format(params) )
277         .append("'>")
278         .append(displayed)
279         .append("</a>");
280 
281         return buf.toString();
282     }
283 
284 
285     /**
286      * Assign the threshold
287      */
288     public final void setThreshold(int threshold) throws JspException {
289         log.debug("setThreshold");
290         if (threshold < 3)
291             throw new JspException("threshold must be 3 or greater");
292         this.threshold = threshold;
293     }
294 
295     /**
296      * Assign the block size
297      */
298     public final void setBlockSize(int block_size) throws JspException {
299         log.debug("setBlockSize");
300         if (block_size < 3 || (block_size % 2 != 1))
301             throw new JspException("blockSize must be an odd number 3 or greater");
302         this.block_size = block_size;
303     }
304 
305     /**
306      * Set the left arrow text or image
307      */
308     public final void setPrev(String prev) {
309         log.debug("setPrev");
310         this.prev = prev;
311     }
312 
313     /**
314      * Set the right arrow text or image
315      */
316     public final void setNext(String next) {
317         log.debug("setNext");
318         this.next = next;
319     }
320 
321     /**
322      * Assign the current page number
323      */
324     public final void setPageNo(int page_no) throws JspException {
325         if (log.isDebugEnabled())
326             log.debug("setPageNo: " + page_no);
327         if (page_no < 1)
328             throw new JspException("page number must be 1 or greater");
329         this.page_no = page_no;
330     }
331 
332     /**
333      * Assign the total pages
334      */
335     public final void setTotalPages(int total_pages) throws JspException {
336         log.debug("setTotalPages");
337         if (total_pages < 1)
338             throw new JspException("total pages must be 1 or greater");
339         this.total_pages = total_pages;
340     }
341 
342     /**
343      * Set the url template
344      */
345     public final void setUrlPattern(String url_pattern) {
346         log.debug("setUrlTemplate");
347         this.url_format = new MessageFormat(url_pattern);
348     }
349 
350     /**
351      * Set the default text if an invalid number or no tag body is given
352      *
353      * @param String to use as default text
354      */
355     public final void setDefault(String default_text) {
356         log.debug("setDefault");
357         this.default_text = default_text;
358     }
359 
360 
361     /**
362     * logging sink
363     */
364     protected static Log log = LogFactory.getLog(PageNavigationTag.class);
365 }
366 /*
367 JRECEIVER MODIFIED BSD LICENSE
368 
369 Copyright (c) 2001-2002, Reed Esau (reed.esau@pobox.com) All rights reserved.
370 
371 Redistribution and use in source and binary forms, with or without
372 modification, are permitted provided that the following conditions are
373 met:
374 
375 Redistributions of source code must retain the above copyright notice,
376 this list of conditions and the following disclaimer.
377 
378 Redistributions in binary form must reproduce the above copyright notice,
379 this list of conditions and the following disclaimer in the documentation
380 and/or other materials provided with the distribution.
381 
382 Neither the name of the JReceiver Project
383 (http://jreceiver.sourceforge.net) nor the names of its contributors may
384 be used to endorse or promote products derived from this software without
385 specific prior written permission.
386 
387 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
388 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
389 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
390 PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
391 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
392 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
393 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
394 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
395 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
396 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
397 POSSIBILITY OF SUCH DAMAGE.
398 */
399