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

Quick Search    Search Deep

Source code: com/clra/web/YearViewSelectorTag.java


1   /*
2    * Copyright (c) Carnegie Lake Rowing Association 2002. All rights reserved.
3    * Distributed under the GPL license. See doc/COPYING.
4    * $RCSfile: YearViewSelectorTag.java,v $
5    * $Date: 2003/02/26 03:38:46 $
6    * $Revision: 1.3 $
7    */
8   
9   package com.clra.web;
10  
11  import java.io.IOException;
12  import java.io.Serializable;
13  import java.util.Calendar;
14  import java.util.GregorianCalendar;
15  import java.util.Hashtable;
16  import java.util.Iterator;
17  import javax.servlet.http.HttpServletRequest;
18  import javax.servlet.http.HttpServletResponse;
19  import javax.servlet.http.HttpUtils;
20  import javax.servlet.jsp.JspException;
21  import javax.servlet.jsp.JspWriter;
22  import javax.servlet.jsp.PageContext;
23  import javax.servlet.jsp.tagext.TagSupport;
24  import org.apache.log4j.Category;
25  import org.apache.struts.util.MessageResources;
26  import org.apache.struts.util.ResponseUtils;
27  
28  /**
29   * Stuff.
30   *
31   * @author <a mailto:"rphall@pluto.njcc.com">Rick Hall</a>
32   * @version $Revision: 1.3 $ $Date: 2003/02/26 03:38:46 $
33   */
34  public class YearViewSelectorTag extends TagSupport {
35  
36    private final static String base = YearViewSelectorTag.class.getName();
37    private final static Category theLog = Category.getInstance( base );
38  
39    /** The message resources for this package */
40    protected static MessageResources messages =
41      MessageResources.getMessageResources("com.clra.web.clra");
42  
43    /** The context-relative URI */
44    protected String page = null;
45  
46    /** The currently selected year (4 digits) */
47    private Integer currentYear = null;
48  
49    /** Return the context-relative URI */
50    public String getPage() {
51      return (this.page);
52    }
53  
54    /** Set the context-relative URI */
55    public void setPage(String page) {
56      this.page = page;
57    }
58  
59    /** Return the currently selected year (4 digits, or null) */
60    public Integer getCurrentYear() {
61      return this.currentYear;
62    }
63  
64    /** Set the currently selected year (4 digits, or null) */
65    public void setCurrentYear( Integer currentYear ) throws JspException {
66      if ( currentYear != null ) {
67        if ( !hasFourDigits( currentYear ) ) {
68          String msg = messages.getMessage(
69              "yearselector.badcurrentYear", currentYear );
70          throw new JspException(msg);
71        }
72      }
73      this.currentYear = currentYear;
74    }
75  
76    /**
77     * A slightly mis-named utility that checks if an Integer is
78     * <strong>positive</strong> and has four digits.
79     */
80    public static boolean hasFourDigits( Integer year ) {
81      if ( year == null ) {
82        throw new IllegalArgumentException( "null Integer" );
83      }
84      return hasFourDigits( year.intValue() );
85    }
86  
87    /**
88     * A slightly mis-named utility that checks if an int is
89     * <strong>positive</strong> and has four digits.
90     */
91    public static boolean hasFourDigits( int year ) {
92      boolean retVal = 999 < year && year < 10000;
93      return retVal;
94    }
95  
96    /**
97     * A utility which determines what year should be currently selected
98     * based on the page context. The algorithm is:<ol>
99     * <li>Check for a request parameter named IEventList.AN_YEAR. If
100    * found, and it is a valid Integer (4 digits), use it.</li>
101    * <li>Check for a request attribute named IEventList.AN_YEAR. If
102    * found, and it is valid, use it.</li>
103    * <li>Check for a session attribute named IEventList.AN_YEAR. If
104    * found, and it is valid, use it.</li>
105    * <li>If a valid year hasn't been determined yet, return the current
106    * calendar year</li>
107    * </ol>
108    */
109   public static Integer yearFromContext( PageContext context ) {
110 
111     final String NAME = IEventList.AN_YEAR;
112     Integer retVal = null;
113 
114     // Try request parameter first
115     try {
116       String s = context.getRequest().getParameter(NAME);
117       if ( s != null ) {
118         retVal = Integer.valueOf(s);
119         if ( !hasFourDigits( retVal ) ) {
120           throw new IllegalArgumentException( "bad year == " + retVal );
121         }
122       }
123     }
124     catch( Exception x ) {
125       String msg = "requestParameter: " + NAME + "; "
126           + x.getClass().getName() + ": " + x.getMessage();
127       theLog.error( msg, x );
128     }
129 
130     // Try request attribute second
131     try {
132       if ( retVal == null ) {
133         Object o = context.getRequest().getAttribute(NAME);
134         if ( o != null && o instanceof Integer ) {
135           retVal = (Integer) o;
136           if ( !hasFourDigits( retVal ) ) {
137             throw new IllegalArgumentException( "bad year == " + retVal );
138           } // if invalid Integer
139         } // if o
140       } // if null retVal
141     } // try
142     catch( Exception x ) {
143       String msg = "requestAttribute: " + NAME + "; "
144           + x.getClass().getName() + ": " + x.getMessage();
145       theLog.error( msg, x );
146     }
147     
148     // Try session attribute third
149     try {
150       if ( retVal == null ) {
151         Object o = context.getSession().getAttribute(NAME);
152         if ( o != null && o instanceof Integer ) {
153           retVal = (Integer) o;
154           if ( !hasFourDigits( retVal ) ) {
155             throw new IllegalArgumentException( "bad year == " + retVal );
156           } // if valid Integer
157         } // if o
158       } // if null retVal
159     } // try
160     catch( Exception x ) {
161       String msg = "sessionAttribute: " + NAME + "; "
162           + x.getClass().getName() + ": " + x.getMessage();
163       theLog.error( msg, x );
164     }
165 
166     // Use the current year as a fallback
167     if ( retVal == null ) {
168       int year = new GregorianCalendar().get( Calendar.YEAR );
169       retVal = new Integer( year );
170     }
171 
172     return retVal;
173   } // yearFromContext(PageContext)
174 
175   /**
176    * A utility which resets request and session attributes so that only
177    * the session attribute AN_YEAR holds the currently selected year.
178    * The algorithm is:<ol>
179    * <li>Check for a request attribute named IEventList.AN_YEAR. If
180    * found, remove it.</li>
181    * <li>Check for a session attribute named IEventList.AN_YEAR. If
182    * found, reset to the specified value; otherwise create and set it.</li>
183    * </ol>
184    * If the specified year is invalid (not 4 digits),
185    * no action is taken and an error is logged.
186    */
187   public static void resetYearInContexts(PageContext context, Integer year) {
188 
189     // Check the context and year.
190     // If either is invalid, log an error and null both as a flag.
191     if ( context == null || year == null || !hasFourDigits(year) ) {
192       theLog.error( "invalid context/year == " + context + "/" + year );
193       context = null;
194       year = null;
195     }
196 
197     final String NAME = IEventList.AN_YEAR;
198 
199     // Reset the request attribute
200     if ( context != null ) {
201       context.getRequest().removeAttribute(NAME);
202     }
203 
204     // Set the session attribute
205     if ( context != null ) {
206       context.getSession().setAttribute(NAME,year);
207     }
208 
209     return;
210   } // resetYearInContexts(PageContext,Integer)
211 
212   /** Form a query string from current parameter and the specified year */
213   protected String createQueryString( int year, Hashtable queryParams ) {
214 
215     // FIXME consolidate code with MonthViewSelectorTag.createQueryString(..)
216 
217     // Preconditions
218     if ( !hasFourDigits(year) ) {
219       throw new IllegalArgumentException( "invalid year == " + year );
220     }
221     if ( queryParams == null ) {
222       throw new IllegalArgumentException( "null queryParams" );
223     }
224 
225     StringBuffer sb = new StringBuffer();
226     sb.append( "?" );
227 
228     // Overwrite existing query params related to this control
229     queryParams.put(
230       IEventList.AN_ISRESTRICTED, new Boolean(true).toString() );
231     queryParams.put(
232       IEventList.AN_YEAR, new Integer(year).toString() );
233     
234     // Form the query string
235     boolean isFirst = true;
236     Iterator keys = queryParams.keySet().iterator();
237     while ( keys.hasNext() ) {
238 
239       if ( isFirst ) {
240         isFirst = false;
241       }
242       else {
243         sb.append( "&" );
244       }
245 
246       String key = (String) keys.next();
247       Object value = queryParams.get( key );
248       if ( value instanceof String ) {
249         sb.append( key + "=" + value );
250       }
251       else {
252         String[] values = (String[]) value;
253         for ( int i=0; i<values.length; i++ ) {
254           if ( i > 0 ) {
255             sb.append( "&" );
256           }
257           sb.append( key + "=" + values[i] );
258         } // for String[]
259       } // else String[]
260 
261     } // while keys
262 
263     return sb.toString();
264   } // createQueryString(int,Hashtable)
265 
266   /** Create a link from the specified page */
267   protected String createLink( int year,
268     String contextPath, String page ) throws JspException {
269 
270     // Preconditions
271     if ( contextPath == null ) {
272       throw new IllegalArgumentException( "null contextPath" );
273     }
274     if ( page == null ) {
275       throw new IllegalArgumentException( "null page" );
276     }
277 
278     StringBuffer sb = new StringBuffer( contextPath );
279     sb.append(page);
280 
281     Hashtable queryParams;
282     String tmp = sb.toString();
283     int idx = tmp.indexOf("?");
284     if ( idx > -1 && idx < page.length()-1 ) {
285       String s = tmp.substring( idx+1 );
286       queryParams = HttpUtils.parseQueryString(s);
287     }
288     else {
289       queryParams = new Hashtable();
290     }
291     String queryString = createQueryString( year, queryParams );
292 
293     String url;
294     if ( idx < 0 ) {
295       url = tmp + "?";
296     }
297     else {
298       url = sb.substring( 0, idx );
299     }
300     url = url + queryString;
301 
302     return url;
303   } // createLink(int,String,String)
304 
305   /** Creates a link from the currentYear request */
306   protected String createLink( int year, HttpServletRequest request ) {
307 
308     StringBuffer url = HttpUtils.getRequestURL( request );
309 
310     String s = request.getQueryString();
311     Hashtable queryParams;
312     if ( s != null ) {
313       queryParams = HttpUtils.parseQueryString(s);
314     }
315     else {
316       queryParams = new Hashtable();
317     }
318 
319     String queryString = createQueryString( year, queryParams );
320     url.append( queryString );
321 
322     return url.toString();
323   } // createLink(int,HttpServletRequest)
324 
325   protected void doStartLink( int year ) throws JspException {
326 
327     // Create a link
328     HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
329     String url = null;
330     if ( this.page != null ) {
331       // Use the specified page
332       String contextPath = request.getContextPath();
333       url = createLink( year, contextPath, page );
334     }
335     else {
336       // Link back to the currentYear page by default
337       url = createLink( year, request );
338     }
339 
340     // Generate the hyperlink start element
341     HttpServletResponse response =
342       (HttpServletResponse) pageContext.getResponse();
343     StringBuffer results = new StringBuffer("<a href=\"");
344     results.append( response.encodeURL(url) );
345     results.append("\">");
346 
347     // Print this element to our output writer
348     JspWriter writer = pageContext.getOut();
349     try {
350       writer.print(results.toString());
351     } catch (IOException e) {
352       throw new JspException
353           (messages.getMessage("yearselector.io", e.toString()));
354     }
355 
356     return;
357   } // doStartLink(int)
358 
359   protected void doEndLink() throws JspException {
360 
361     // Print the ending element to our output writer
362     JspWriter writer = pageContext.getOut();
363     try {
364       writer.print("</a>");
365     } catch (IOException e) {
366       throw new JspException
367           (messages.getMessage("yearselector.io", e.toString()));
368     }
369 
370     return;
371   } // doEndLink()
372 
373   /** Writes a Calendar-based year (4 digits) as user-friendly text */
374   protected void doYearText( int year ) throws JspException {
375 
376     JspWriter writer = pageContext.getOut();
377     try {
378       writer.print("" + year );
379     } catch (IOException e) {
380       throw new JspException(
381         messages.getMessage("yearselector.io", e.toString()) );
382     }
383 
384     return;
385   } // doYearText(int)
386 
387   /** Writes the text that separates year links */
388   protected void doYearLeadingSeparationText(int unused) throws JspException{
389 
390     JspWriter writer = pageContext.getOut();
391     try {
392       writer.print( "&nbsp;" );
393     } catch (IOException e) {
394       throw new JspException(
395         messages.getMessage("yearselector.io", e.toString()) );
396     }
397 
398     return;
399   } // doYearLeadingSeparationText(int)
400 
401   /** Writes the text that separates year links */
402   protected void doYearTrailingSeparationText(int unused) throws JspException{
403 
404     JspWriter writer = pageContext.getOut();
405     try {
406       writer.print( "&nbsp;" );
407     } catch (IOException e) {
408       throw new JspException(
409         messages.getMessage("yearselector.io", e.toString()) );
410     }
411 
412     return;
413   } // doYearTrailingSeparationText(int)
414 
415   /** Write a year link */
416   protected void doYearLink( int year ) throws JspException {
417 
418     doYearLeadingSeparationText( year );
419     if ( currentYear == null ) {
420       doStartLink( year );
421     }
422     else if ( currentYear != null && year != currentYear.intValue() ) {
423       doStartLink( year );
424     }
425     doYearText( year );
426     if ( currentYear == null ) {
427       doEndLink();
428     }
429     else if ( currentYear != null && year != currentYear.intValue() ) {
430       doEndLink();
431     }
432     doYearTrailingSeparationText( year );
433 
434     return;
435   } // doYearLink()
436 
437   /** Writes several year links */
438   protected void doYearLinks() throws JspException {
439 
440     // Preconditions
441     if ( currentYear == null ) {
442       throw new IllegalStateException( "current year is null" );
443     }
444     final int cy = currentYear.intValue();
445 
446     for ( int year=cy-1; year<cy+2; year++ ) {
447       doYearLink( year );
448     }
449 
450     return;
451   } // doYearLinks(int)
452 
453   /** Render the beginning of the selector */
454   public int doStartTag() throws JspException {
455     return (EVAL_BODY_INCLUDE);
456   }
457 
458   /** Render the end of the selector */
459   public int doEndTag() throws JspException {
460     doYearLinks();
461     return (EVAL_PAGE);
462   }
463 
464   /**
465    * Release any acquired resources.
466    */
467   public void release() {
468     super.release();
469     this.page = null;
470     return;
471   }
472 
473 } // YearViewSelector
474 
475 /*
476  * $Log: YearViewSelectorTag.java,v $
477  * Revision 1.3  2003/02/26 03:38:46  rphall
478  * Added copyright and GPL license
479  *
480  * Revision 1.2  2002/02/18 18:07:33  rphall
481  * Ran dos2unix to remove ^M (carriage return) from end of lines
482  *
483  * Revision 1.1.1.1  2002/01/03 21:57:28  rphall
484  * Initial load, 5th try, Jan-03-2002 4:57 PM
485  *
486  * Revision 1.2  2002/01/01 03:40:33  rphall
487  * Moved getName() from MemberName to MemberView
488  *
489  * Revision 1.1  2001/12/14 00:47:33  rphall
490  * YearViewSelectorTag JSP tag controls year display
491  *
492  */
493 
494