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