1 /***
2 * Calendar Tag Library
3 * Copyright (C) 2005 James Smith
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * You should be able to download a copy of the LGPL from
19 * www.opensource.org/licenses/lgpl-license.php
20 */
21 package org.calendartag.tags;
22
23 import java.util.Date;
24 import java.util.Calendar;
25 import java.util.GregorianCalendar;
26 import java.util.Enumeration;
27 import java.text.SimpleDateFormat;
28 import javax.servlet.jsp.tagext.Tag;
29 import javax.servlet.jsp.PageContext;
30 import javax.servlet.jsp.JspException;
31
32 import org.apache.taglibs.standard.tag.el.core.ExpressionUtil;
33 import org.calendartag.decorator.DefaultCalendarDecorator;
34 import org.calendartag.decorator.CalendarDecorator;
35 import org.calendartag.util.CalendarTagUtil;
36
37 import javax.servlet.http.HttpServletRequest;
38
39 /***
40 * Author: James Smith
41 * Date: Aug 23, 2004
42 * Time: 8:22:03 PM
43 */
44 public class CalendarTag implements Tag {
45
46 private final static String EMPTY_DAY_STYLE = "calendarEmptyDayStyle";
47 private final static String TABLE_STYLE = "calendarTableStyle";
48 private final static String TITLE_STYLE = "calendarTitleStyle";
49 private final static String WEEKDAY_STYLE = "calendarWeekdayStyle";
50 private final static String PREVIOUS_LINK_STYLE = "calendarPreviousLinkStyle";
51 private final static String NEXT_LINK_STYLE = "calendarNextLinkStyle";
52
53 private final static boolean INTERACTIVE_DEFAULT = true;
54 private final static String WEEK_START_DEFAULT = "Sunday";
55 private final static int DAY_HEIGHT_DEFAULT = 85;
56 private final static int DAY_WIDTH_DEFAULT = 85;
57
58 private SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM-dd-yyyy");
59
60 private PageContext pageContext;
61 private Tag parent;
62
63 private String decorator;
64 private String requestURI;
65 private int dayHeight;
66 private int dayWidth;
67
68 private String id;
69 private String cssPrefix;
70 private String weekStart;
71 private String showPreviousNextLinks;
72
73 private String startDate;
74 private String endDate;
75
76 private String date;
77
78 private int day = 0;
79 private int month = 0;
80 private int year = 0;
81
82 private Calendar startCalendar;
83 private Calendar endCalendar;
84 private Calendar calendar;
85 private Boolean showPreviousNextLinksBoolean;
86
87 private CalendarDecorator decoratorObject;
88
89 private Calendar todayCalendar = new GregorianCalendar();
90
91 private boolean singleMonth = false;
92
93 public void setPageContext(PageContext pageContext) {
94 this.pageContext = pageContext;
95 }
96
97 public void setParent(Tag parent) {
98 this.parent = parent;
99 }
100
101 public Tag getParent() {
102 return parent;
103 }
104
105 public int doStartTag() throws JspException {
106 return Tag.EVAL_BODY_INCLUDE;
107 }
108
109 private void initializeAttributes() throws JspException {
110
111 CalendarTagUtil.trimCalendar(todayCalendar);
112
113 if (id == null) {
114 id = "";
115 }
116
117 if (cssPrefix == null) {
118 cssPrefix = "";
119 }
120
121
122 if (!"".equals(decorator) && decorator != null) {
123
124 try {
125 Class decoratorClass = Class.forName(decorator);
126 decoratorObject = (CalendarDecorator) decoratorClass.newInstance();
127 } catch (Exception e) {
128 throw new JspException("Cannot resolve decorator: " + decorator);
129 }
130 } else {
131
132 decoratorObject = new DefaultCalendarDecorator();
133 }
134
135
136 if ("true".equalsIgnoreCase(showPreviousNextLinks)) {
137 showPreviousNextLinksBoolean = new Boolean(true);
138 } else if ("false".equalsIgnoreCase(showPreviousNextLinks)) {
139 showPreviousNextLinksBoolean = new Boolean(false);
140 } else {
141 try {
142 showPreviousNextLinksBoolean = (Boolean) ExpressionUtil.evalNotNull("calendartag", "calendar", showPreviousNextLinks, Boolean.class, this, pageContext);
143 } catch (Exception e) {
144 showPreviousNextLinksBoolean = null;
145 }
146 }
147
148 if (showPreviousNextLinksBoolean == null) {
149 showPreviousNextLinksBoolean = new Boolean(INTERACTIVE_DEFAULT);
150 }
151
152 if (day == 0 && month == 0 && year == 0) {
153
154
155 try {
156 Date tempDate = (Date) ExpressionUtil.evalNotNull("calendartag", "calendar", date, Date.class, this, pageContext);
157 if (tempDate != null) {
158 calendar = new GregorianCalendar();
159 calendar.setTime(tempDate);
160 CalendarTagUtil.trimCalendar(calendar);
161 }
162 } catch (Exception e) {
163 calendar = null;
164 }
165
166
167 try {
168 Date tempDate = (Date) ExpressionUtil.evalNotNull("calendartag", "calendar", startDate, Date.class, this, pageContext);
169 if (tempDate != null) {
170 startCalendar = new GregorianCalendar();
171 startCalendar.setTime(tempDate);
172 CalendarTagUtil.trimCalendar(startCalendar);
173 }
174 } catch (Exception e) {
175 startCalendar = null;
176 }
177
178
179 try {
180 Date tempDate = (Date) ExpressionUtil.evalNotNull("calendartag", "calendar", endDate, Date.class, this, pageContext);
181 if (tempDate != null) {
182 endCalendar = new GregorianCalendar();
183 endCalendar.setTime(tempDate);
184 CalendarTagUtil.trimCalendar(endCalendar);
185 }
186 } catch (Exception e) {
187 endCalendar = null;
188 }
189 if (startCalendar == null && endCalendar != null) {
190 throw new JspException("You specified an endDate but not a startDate");
191 }
192
193 if (endCalendar == null && startCalendar != null) {
194 throw new JspException("You specified a startDate but not an endDate");
195 }
196
197 if (startCalendar != null && endCalendar != null) {
198
199
200 CalendarTagUtil.trimCalendar(startCalendar);
201 CalendarTagUtil.trimCalendar(endCalendar);
202
203
204 if (startCalendar.after(endCalendar)) {
205 throw new JspException("You startDate is after your endDate.");
206 }
207 System.out.println("startCalendar and endCalendar were not null");
208 if (calendar == null) {
209
210
211 System.out.println("calendar is null");
212 calendar = (Calendar) startCalendar.clone();
213 System.out.println("calendar is " + calendar.getTime());
214 }
215
216 }
217
218 }
219
220
221 if (calendar == null) {
222 calendar = (Calendar) todayCalendar.clone();
223
224 if (day != 0) {
225 calendar.set(Calendar.DATE, day);
226 }
227 if (month != 0) {
228 calendar.set(Calendar.MONTH, month);
229 }
230 if (year != 0) {
231 calendar.set(Calendar.YEAR, year);
232 }
233 }
234
235
236 if (startCalendar == null && endCalendar == null) {
237
238 endCalendar = (Calendar) todayCalendar.clone();
239 startCalendar = (Calendar) todayCalendar.clone();
240
241
242 startCalendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR));
243 startCalendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH));
244 startCalendar.set(Calendar.DATE, startCalendar.getActualMinimum(Calendar.DATE));
245
246
247 endCalendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR));
248 endCalendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH));
249 endCalendar.set(Calendar.DATE, startCalendar.getActualMaximum(Calendar.DATE));
250
251 singleMonth = true;
252
253 }
254
255
256 try {
257
258 Date tempDate = DATE_FORMAT.parse(pageContext.getRequest().getParameter(id + "date"));
259 Calendar parameterCalendar = new GregorianCalendar();
260 parameterCalendar.setTime(tempDate);
261 if (parameterCalendar != null && !singleMonth) {
262
263 calendar = parameterCalendar;
264
265
266
267 if (endCalendar != null && startCalendar != null
268 && CalendarTagUtil.dayCompare(calendar, endCalendar) > 0) {
269
270 int dayDifference = CalendarTagUtil.differenceInDays(startCalendar, endCalendar) + 1;
271
272
273 while (CalendarTagUtil.dayCompare(calendar, endCalendar) > 0) {
274
275
276 endCalendar.set(Calendar.DATE, endCalendar.get(Calendar.DATE) + dayDifference);
277 startCalendar.set(Calendar.DATE, startCalendar.get(Calendar.DATE) + dayDifference);
278
279 }
280
281 } else if (endCalendar != null && startCalendar != null
282 && CalendarTagUtil.dayCompare(calendar, startCalendar) < 0) {
283
284 int dayDifference = CalendarTagUtil.differenceInDays(startCalendar, endCalendar) + 1;
285
286
287 while (CalendarTagUtil.dayCompare(calendar, startCalendar) < 0) {
288
289
290 endCalendar.set(Calendar.DATE, endCalendar.get(Calendar.DATE) - dayDifference);
291 startCalendar.set(Calendar.DATE, startCalendar.get(Calendar.DATE) - dayDifference);
292
293 }
294
295 }
296
297 } else {
298
299 calendar = parameterCalendar;
300
301
302 startCalendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR));
303 startCalendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH));
304 startCalendar.set(Calendar.DATE, startCalendar.getActualMinimum(Calendar.DATE));
305
306
307 endCalendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR));
308 endCalendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH));
309 endCalendar.set(Calendar.DATE, startCalendar.getActualMaximum(Calendar.DATE));
310
311 }
312 } catch (Exception e) {
313
314 }
315
316
317
318 if (dayHeight == 0) {
319 dayHeight = DAY_HEIGHT_DEFAULT;
320 }
321
322 if (dayWidth == 0) {
323 dayWidth = DAY_WIDTH_DEFAULT;
324 }
325
326 }
327
328 public int doEndTag() throws JspException {
329
330 StringBuffer link = new StringBuffer();
331
332
333 initializeAttributes();
334
335
336 if ("".equals(weekStart) || weekStart == null) {
337 weekStart = WEEK_START_DEFAULT;
338 }
339 if (weekStart.toLowerCase().equals("sunday")) {
340 calendar.setFirstDayOfWeek(Calendar.SUNDAY);
341 } else if (weekStart.toLowerCase().equals("monday")) {
342 calendar.setFirstDayOfWeek(Calendar.MONDAY);
343 } else if (weekStart.toLowerCase().equals("tuesday")) {
344 calendar.setFirstDayOfWeek(Calendar.TUESDAY);
345 } else if (weekStart.toLowerCase().equals("wednesday")) {
346 calendar.setFirstDayOfWeek(Calendar.WEDNESDAY);
347 } else if (weekStart.toLowerCase().equals("thursday")) {
348 calendar.setFirstDayOfWeek(Calendar.THURSDAY);
349 } else if (weekStart.toLowerCase().equals("friday")) {
350 calendar.setFirstDayOfWeek(Calendar.FRIDAY);
351 } else if (weekStart.toLowerCase().equals("saturday")) {
352 calendar.setFirstDayOfWeek(Calendar.SATURDAY);
353 }
354
355 decoratorObject.setCalendar(calendar);
356 decoratorObject.setPageContext(pageContext);
357 decoratorObject.setCalendar(startCalendar);
358 decoratorObject.setStart(startCalendar);
359 decoratorObject.setEnd(endCalendar);
360 decoratorObject.initializeCalendar();
361
362
363 if ("".equals(requestURI) || requestURI == null) {
364
365 requestURI = ((HttpServletRequest) pageContext.getRequest()).getRequestURI();
366 }
367
368 link.append(requestURI);
369
370 Enumeration parameterEnumeration = pageContext.getRequest().getParameterNames();
371 while (parameterEnumeration.hasMoreElements()) {
372 String name = (String) parameterEnumeration.nextElement();
373 String value = pageContext.getRequest().getParameter(name);
374
375 if (!(id + "date").equals(name)) {
376 link.append("&" + name + "=" + value);
377 }
378 }
379 link.append("&" + id + "date=");
380
381 int firstDelim = link.indexOf("&");
382 link.replace(firstDelim, firstDelim + 1, "?");
383
384 StringBuffer endTag = new StringBuffer();
385
386
387 endTag.append("<table border=\"0\" class=\"" + cssPrefix + TABLE_STYLE + "\"");
388 if (!"".equals(id) && id != null) {
389 endTag.append(" id=\"" + id + "\"");
390 }
391 endTag.append(">\r\n <tr>\r\n");
392
393
394
395 if (showPreviousNextLinksBoolean.booleanValue()) {
396
397
398 int dateDiff = 0;
399 if (!singleMonth) {
400
401 dateDiff = CalendarTagUtil.differenceInDays(startCalendar, endCalendar) + 1;
402 }
403
404 Calendar newCalendar = (Calendar) calendar.clone();
405
406 if (!singleMonth) {
407 newCalendar.set(Calendar.DATE, newCalendar.get(Calendar.DATE) - dateDiff);
408 } else {
409 newCalendar.add(Calendar.MONTH, -1);
410 }
411
412 endTag.append(" <td colspan=\"1\" class=\"" + cssPrefix + PREVIOUS_LINK_STYLE + "\" >");
413 endTag.append(decoratorObject.getPreviousLink(link + DATE_FORMAT.format(newCalendar.getTime())));
414 endTag.append("</td>\r\n");
415
416 endTag.append(" <td colspan=\"5\" class=\"" + cssPrefix + TITLE_STYLE + "\" >");
417 endTag.append(decoratorObject.getCalendarTitle());
418 endTag.append("</td>\r\n");
419
420 newCalendar = (Calendar) calendar.clone();
421 if (!singleMonth) {
422 newCalendar.set(Calendar.DATE, newCalendar.get(Calendar.DATE) + dateDiff);
423 } else {
424 newCalendar.add(Calendar.MONTH, 1);
425 }
426
427 endTag.append(" <td colspan=\"1\" class=\"" + cssPrefix + NEXT_LINK_STYLE + "\" >");
428 endTag.append(decoratorObject.getNextLink(link + DATE_FORMAT.format(newCalendar.getTime())));
429 endTag.append("</td>\r\n");
430
431 } else {
432
433 endTag.append(" <td colspan=\"7\" class=\"" + cssPrefix + TITLE_STYLE + "\" >");
434 endTag.append(decoratorObject.getCalendarTitle());
435 endTag.append("</td>\r\n");
436 }
437
438 endTag.append(" </tr>\r\n");
439
440 endTag.append(" <tr>\r\n");
441
442 for (int i = 0; i < Calendar.DAY_OF_WEEK; i++) {
443 int day = i + calendar.getFirstDayOfWeek();
444 if (day > 7) {
445 day = day - 7;
446 }
447 endTag.append(" <td class=\"" + cssPrefix + WEEKDAY_STYLE + "\">" + decoratorObject.getWeekdayTitle(day) + "</td>\r\n");
448 }
449 endTag.append(" </tr>\r\n");
450
451 endTag.append(" <tr>\r\n");
452
453
454
455 int emptyDays;
456 int column = 0;
457
458
459 int firstDayOfWeek = startCalendar.get(Calendar.DAY_OF_WEEK);
460 if (calendar.getFirstDayOfWeek() > firstDayOfWeek) {
461 emptyDays = firstDayOfWeek - calendar.getFirstDayOfWeek() + 7;
462 } else {
463 emptyDays = firstDayOfWeek - calendar.getFirstDayOfWeek();
464 }
465
466
467 for (int i = 0; i < emptyDays; i++) {
468 endTag.append(" <td class=\"" + cssPrefix + EMPTY_DAY_STYLE + "\" height=\"" + dayHeight + "\" width=\"" + dayWidth + "\">" + decoratorObject.getEmptyDay() + "</td>\r\n");
469 column++;
470 }
471
472 Calendar iteratingDate = (Calendar) startCalendar.clone();
473 boolean isOddMonth = true;
474 while (!iteratingDate.after(endCalendar)) {
475
476 decoratorObject.setCalendar(iteratingDate);
477
478 if (column == 0) {
479 endTag.append(" <tr>\r\n");
480 }
481
482 endTag.append(" <td class=\"" + cssPrefix + decoratorObject.getDayStyleClass(isOddMonth, CalendarTagUtil.isSameDay(calendar, iteratingDate))
483 + "\" height=\"" + dayHeight + "\" width=\"" + dayWidth + "\">");
484
485 endTag.append(decoratorObject.getDay(link + DATE_FORMAT.format(iteratingDate.getTime())));
486 endTag.append("</td>\r\n");
487
488
489 column++;
490
491 if (column == Calendar.DAY_OF_WEEK) {
492 endTag.append(" </tr>\r\n");
493 column = 0;
494 }
495
496
497 if (iteratingDate.getActualMaximum(Calendar.DATE) == iteratingDate.get(Calendar.DATE)) {
498 if (isOddMonth) {
499 isOddMonth = false;
500 } else {
501 isOddMonth = true;
502 }
503 }
504
505
506 iteratingDate.set(Calendar.DATE, iteratingDate.get(Calendar.DATE) + 1);
507
508 }
509
510 while (column < Calendar.DAY_OF_WEEK && column > 0) {
511 endTag.append(" <td class=\"" + cssPrefix + EMPTY_DAY_STYLE + "\" height=\"" + dayHeight + "\" width=\"" + dayWidth + "\">" + decoratorObject.getEmptyDay() + "</td>\r\n");
512 column++;
513 }
514
515 endTag.append(" </tr>\r\n");
516 endTag.append("</table>\r\n");
517
518 try {
519 this.pageContext.getOut().print(endTag.toString());
520 } catch (Exception e) {
521 System.out.println(e.getMessage());
522 e.printStackTrace();
523 throw new JspException(e);
524 }
525
526
527 release();
528
529 return Tag.EVAL_PAGE;
530 }
531
532 public String getId() {
533 return id;
534 }
535
536 public void setId(String id) {
537 this.id = id;
538 }
539
540 public int getDayHeight() {
541 return dayHeight;
542 }
543
544 public void setDayHeight(int dayHeight) {
545 this.dayHeight = dayHeight;
546 }
547
548 public int getDayWidth() {
549 return dayWidth;
550 }
551
552 public void setDayWidth(int dayWidth) {
553 this.dayWidth = dayWidth;
554 }
555
556 public String getStartDate() {
557 return startDate;
558 }
559
560 public void setStartDate(String startDate) {
561 this.startDate = startDate;
562 }
563
564 public String getEndDate() {
565 return endDate;
566 }
567
568 public void setEndDate(String endDate) {
569 this.endDate = endDate;
570 }
571
572 public String getShowPreviousNextLinks() {
573 return showPreviousNextLinks;
574 }
575
576 public void setShowPreviousNextLink(String showPreviousNextLinks) {
577 this.showPreviousNextLinks = showPreviousNextLinks;
578 }
579
580 public String getDecorator() {
581 return decorator;
582 }
583
584 public void setDecorator(String decorator) {
585 this.decorator = decorator;
586 }
587
588 public String getRequestURI() {
589 return requestURI;
590 }
591
592 public void setRequestURI(String requestURI) {
593 this.requestURI = requestURI;
594 }
595
596 public String getWeekStart() {
597 return weekStart;
598 }
599
600 public void setWeekStart(String weekStart) {
601 this.weekStart = weekStart;
602 }
603
604 public String getDate() {
605 return date;
606 }
607
608 public void setDate(String date) {
609 this.date = date;
610 }
611
612 public int getDay() {
613 return day;
614 }
615
616 public void setDay(int day) {
617 this.day = day;
618 }
619
620 public int getMonth() {
621 return month;
622 }
623
624 public void setMonth(int month) {
625 this.month = month;
626 }
627
628 public int getYear() {
629 return year;
630 }
631
632 public void setYear(int year) {
633 this.year = year;
634 }
635
636 public String getCssPrefix() {
637 return cssPrefix;
638 }
639
640 public void setCssPrefix(String cssPrefix) {
641 this.cssPrefix = cssPrefix;
642 }
643
644 /***
645 * Ensures everything is reset
646 */
647 public void release() {
648 day = 0;
649 month = 0;
650 year = 0;
651 startCalendar = null;
652 endCalendar = null;
653 calendar = null;
654 showPreviousNextLinks = null;
655 decoratorObject = null;
656 todayCalendar = new GregorianCalendar();
657 date = null;
658 endDate = null;
659 startDate = null;
660 decorator = null;
661 requestURI = "";
662 dayHeight = 0;
663 dayWidth = 0;
664 id = null;
665 cssPrefix = null;
666 weekStart = null;
667 singleMonth = false;
668 }
669 }