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 }