001 /* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019 package org.apache.wiki.tags; 020 021 import java.io.IOException; 022 import java.util.Calendar; 023 import java.util.Date; 024 import java.text.SimpleDateFormat; 025 import java.text.ParseException; 026 027 import javax.servlet.jsp.JspWriter; 028 import javax.servlet.http.HttpServletRequest; 029 030 import org.apache.log4j.Logger; 031 import org.apache.wiki.WikiEngine; 032 import org.apache.wiki.WikiPage; 033 import org.apache.wiki.WikiContext; 034 import org.apache.wiki.api.exceptions.ProviderException; 035 import org.apache.wiki.util.TextUtil; 036 037 038 /** 039 * Provides a nice calendar. Responds to the following HTTP parameters: 040 * <ul> 041 * <li>calendar.date - If this parameter exists, then the calendar 042 * date is taken from the month and year. The date must be in ddMMyy 043 * format. 044 * <li>weblog.startDate - If calendar.date parameter does not exist, 045 * we then check this date. 046 * </ul> 047 * 048 * If neither calendar.date nor weblog.startDate parameters exist, 049 * then the calendar will default to the current month. 050 * 051 * 052 * @since 2.0 053 */ 054 055 // FIXME: This class is extraordinarily lacking. 056 public class CalendarTag extends WikiTagBase { 057 058 private static final long serialVersionUID = 0L; 059 private static final Logger log = Logger.getLogger( CalendarTag.class ); 060 061 private SimpleDateFormat m_pageFormat = null; 062 private SimpleDateFormat m_urlFormat = null; 063 private SimpleDateFormat m_monthUrlFormat = null; 064 private SimpleDateFormat m_dateFormat = new SimpleDateFormat( "ddMMyy" ); 065 066 /** 067 * {@inheritDoc} 068 */ 069 @Override 070 public void initTag() 071 { 072 super.initTag(); 073 m_pageFormat = m_urlFormat = m_monthUrlFormat = null; 074 m_dateFormat = new SimpleDateFormat( "ddMMyy" ); 075 } 076 077 /* 078 public void setYear( String year ) 079 { 080 m_year = year; 081 } 082 083 public void setMonth( String month ) 084 { 085 m_month = month; 086 } 087 */ 088 089 /** 090 * Sets the page format. If a page corresponding to the format is found when 091 * the calendar is being rendered, a link to that page is created. E.g. if the 092 * format is set to <tt>'Main_blogentry_'ddMMyy</tt>, it works nicely in 093 * conjuction to the WeblogPlugin. 094 * 095 * @param format The format in the SimpleDateFormat fashion. 096 * 097 * @see SimpleDateFormat 098 * @see org.apache.wiki.plugin.WeblogPlugin 099 */ 100 public void setPageformat( String format ) 101 { 102 m_pageFormat = new SimpleDateFormat(format); 103 } 104 105 /** 106 * Set the URL format. If the pageformat is not set, all dates are 107 * links to pages according to this format. The pageformat 108 * takes precedence. 109 * 110 * @param format The URL format in the SimpleDateFormat fashion. 111 * @see SimpleDateFormat 112 */ 113 public void setUrlformat( String format ) 114 { 115 m_urlFormat = new SimpleDateFormat(format); 116 } 117 118 /** 119 * Set the format to be used for links for the months. 120 * 121 * @param format The format to set in the SimpleDateFormat fashion. 122 * 123 * @see SimpleDateFormat 124 */ 125 public void setMonthurlformat( String format ) 126 { 127 m_monthUrlFormat = new SimpleDateFormat( format ); 128 } 129 130 private String format( String txt ) 131 { 132 WikiPage p = m_wikiContext.getPage(); 133 134 if( p != null ) 135 { 136 return TextUtil.replaceString( txt, "%p", p.getName() ); 137 } 138 139 return txt; 140 } 141 142 /** 143 * Returns a link to the given day. 144 */ 145 private String getDayLink( Calendar day ) 146 { 147 WikiEngine engine = m_wikiContext.getEngine(); 148 String result = ""; 149 150 if( m_pageFormat != null ) 151 { 152 String pagename = m_pageFormat.format( day.getTime() ); 153 154 if( engine.pageExists( pagename ) ) 155 { 156 if( m_urlFormat != null ) 157 { 158 String url = m_urlFormat.format( day.getTime() ); 159 160 result = "<td class=\"link\"><a href=\""+url+"\">"+day.get( Calendar.DATE )+"</a></td>"; 161 } 162 else 163 { 164 result = "<td class=\"link\"><a href=\""+m_wikiContext.getViewURL( pagename )+"\">"+ 165 day.get( Calendar.DATE )+"</a></td>"; 166 } 167 } 168 else 169 { 170 result = "<td class=\"days\">"+day.get(Calendar.DATE)+"</td>"; 171 } 172 } 173 else if( m_urlFormat != null ) 174 { 175 String url = m_urlFormat.format( day.getTime() ); 176 177 result = "<td><a href=\""+url+"\">"+day.get( Calendar.DATE )+"</a></td>"; 178 } 179 else 180 { 181 result = "<td class=\"days\">"+day.get(Calendar.DATE)+"</td>"; 182 } 183 184 return format(result); 185 } 186 187 private String getMonthLink( Calendar day ) 188 { 189 SimpleDateFormat monthfmt = new SimpleDateFormat( "MMMM yyyy" ); 190 String result; 191 192 if( m_monthUrlFormat == null ) 193 { 194 result = monthfmt.format( day.getTime() ); 195 } 196 else 197 { 198 Calendar cal = (Calendar)day.clone(); 199 int firstDay = cal.getActualMinimum( Calendar.DATE ); 200 int lastDay = cal.getActualMaximum( Calendar.DATE ); 201 202 cal.set( Calendar.DATE, lastDay ); 203 String url = m_monthUrlFormat.format( cal.getTime() ); 204 205 url = TextUtil.replaceString( url, "%d", Integer.toString( lastDay-firstDay+1 ) ); 206 207 result = "<a href=\""+url+"\">"+monthfmt.format(cal.getTime())+"</a>"; 208 } 209 210 return format(result); 211 212 } 213 private String getMonthNaviLink( Calendar day, String txt, String queryString ) 214 { 215 String result = ""; 216 queryString = TextUtil.replaceEntities( queryString ); 217 Calendar nextMonth = Calendar.getInstance(); 218 nextMonth.set( Calendar.DATE, 1 ); 219 nextMonth.add( Calendar.DATE, -1); 220 nextMonth.add( Calendar.MONTH, 1 ); // Now move to 1st day of next month 221 222 if ( day.before(nextMonth) ) 223 { 224 WikiPage thePage = m_wikiContext.getPage(); 225 String pageName = thePage.getName(); 226 227 String calendarDate = m_dateFormat.format(day.getTime()); 228 String url = m_wikiContext.getURL( WikiContext.VIEW, pageName, 229 "calendar.date="+calendarDate ); 230 231 if ( (queryString != null) && (queryString.length() > 0) ) 232 { 233 // 234 // Ensure that the 'calendar.date=ddMMyy' has been removed 235 // from the queryString 236 // 237 238 // FIXME: Might be useful to have an entire library of 239 // routines for this. Will fail if it's not calendar.date 240 // but something else. 241 242 int pos1 = queryString.indexOf("calendar.date="); 243 if (pos1 >= 0) 244 { 245 String tmp = queryString.substring(0,pos1); 246 // FIXME: Will this fail when we use & instead of &? 247 // FIXME: should use some parsing routine 248 int pos2 = queryString.indexOf("&",pos1) + 1; 249 if ( (pos2 > 0) && (pos2 < queryString.length()) ) 250 { 251 tmp = tmp + queryString.substring(pos2); 252 } 253 queryString = tmp; 254 } 255 256 if( queryString != null && queryString.length() > 0 ) 257 { 258 url = url + "&"+queryString; 259 } 260 } 261 result = "<td><a href=\""+url+"\">"+txt+"</a></td>"; 262 } 263 else 264 { 265 result="<td> </td>"; 266 } 267 268 return format(result); 269 } 270 271 /** 272 * {@inheritDoc} 273 */ 274 @Override 275 public final int doWikiStartTag() 276 throws IOException, 277 ProviderException 278 { 279 WikiEngine engine = m_wikiContext.getEngine(); 280 JspWriter out = pageContext.getOut(); 281 Calendar cal = Calendar.getInstance(); 282 Calendar prevCal = Calendar.getInstance(); 283 Calendar nextCal = Calendar.getInstance(); 284 285 // 286 // Check if there is a parameter in the request to set the date. 287 // 288 String calendarDate = pageContext.getRequest().getParameter( "calendar.date" ); 289 if( calendarDate == null ) 290 { 291 calendarDate = pageContext.getRequest().getParameter( "weblog.startDate" ); 292 } 293 294 if( calendarDate != null ) 295 { 296 try 297 { 298 Date d = m_dateFormat.parse( calendarDate ); 299 cal.setTime( d ); 300 prevCal.setTime( d ); 301 nextCal.setTime( d ); 302 } 303 catch( ParseException e ) 304 { 305 log.warn( "date format wrong: "+calendarDate ); 306 } 307 } 308 309 cal.set( Calendar.DATE, 1 ); // First, set to first day of month 310 prevCal.set( Calendar.DATE, 1 ); 311 nextCal.set( Calendar.DATE, 1 ); 312 313 prevCal.add(Calendar.MONTH, -1); // Now move to first day of previous month 314 nextCal.add(Calendar.MONTH, 1); // Now move to first day of next month 315 316 out.write( "<table class=\"calendar\">\n" ); 317 318 HttpServletRequest httpServletRequest = m_wikiContext.getHttpRequest(); 319 String queryString = engine.safeGetQueryString( httpServletRequest ); 320 out.write( "<tr>"+ 321 getMonthNaviLink(prevCal,"<<", queryString)+ 322 "<td colspan=5 class=\"month\">"+ 323 getMonthLink( cal )+ 324 "</td>"+ 325 getMonthNaviLink(nextCal,">>", queryString)+ 326 "</tr>\n" 327 ); 328 329 int month = cal.get( Calendar.MONTH ); 330 cal.set( Calendar.DAY_OF_WEEK, Calendar.MONDAY ); // Then, find the first day of the week. 331 332 out.write( "<tr><td class=\"weekdays\">Mon</td>"+ 333 "<td class=\"weekdays\">Tue</td>"+ 334 "<td class=\"weekdays\">Wed</td>"+ 335 "<td class=\"weekdays\">Thu</td>"+ 336 "<td class=\"weekdays\">Fri</td>"+ 337 "<td class=\"weekdays\">Sat</td>"+ 338 "<td class=\"weekdays\">Sun</td></tr>\n" ); 339 340 boolean noMoreDates = false; 341 while( !noMoreDates ) 342 { 343 out.write( "<tr>" ); 344 345 for( int i = 0; i < 7; i++ ) 346 { 347 int mth = cal.get( Calendar.MONTH ); 348 349 if( mth != month ) 350 { 351 out.write("<td class=\"othermonth\">"+cal.get(Calendar.DATE)+"</td>"); 352 } 353 else 354 { 355 out.write( getDayLink(cal) ); 356 } 357 358 cal.add( Calendar.DATE, 1 ); 359 } 360 361 if( cal.get( Calendar.MONTH ) != month ) 362 { 363 noMoreDates = true; 364 } 365 366 out.write( "</tr>\n" ); 367 } 368 369 out.write( "</table>\n" ); 370 371 return EVAL_BODY_INCLUDE; 372 } 373 374 }