1 16 package org.apache.cocoon.generation; 17 18 import java.io.IOException ; 19 import java.io.Serializable ; 20 import java.text.DateFormat ; 21 import java.text.DecimalFormat ; 22 import java.text.SimpleDateFormat ; 23 import java.util.ArrayList ; 24 import java.util.Calendar ; 25 import java.util.List ; 26 import java.util.Locale ; 27 import java.util.Map ; 28 import java.util.TimeZone ; 29 30 import org.apache.avalon.framework.parameters.Parameters; 31 import org.apache.cocoon.ProcessingException; 32 import org.apache.cocoon.caching.CacheableProcessingComponent; 33 import org.apache.cocoon.environment.SourceResolver; 34 import org.apache.commons.lang.BooleanUtils; 35 import org.apache.excalibur.source.SourceValidity; 36 import org.apache.excalibur.source.impl.validity.NOPValidity; 37 import org.xml.sax.SAXException ; 38 import org.xml.sax.helpers.AttributesImpl ; 39 40 93 public class CalendarGenerator extends ServiceableGenerator implements CacheableProcessingComponent { 94 95 96 protected static final String URI = "http://apache.org/cocoon/calendar/1.0"; 97 98 99 protected static final String PREFIX = "calendar"; 100 101 102 protected static final String CALENDAR_NODE_NAME = "calendar"; 103 protected static final String WEEK_NODE_NAME = "week"; 104 protected static final String DAY_NODE_NAME = "day"; 105 protected static final String MONTH_ATTR_NAME = "month"; 106 protected static final String YEAR_ATTR_NAME = "year"; 107 protected static final String DATE_ATTR_NAME = "date"; 108 protected static final String NUMBER_ATTR_NAME = "number"; 109 protected static final String WEEKDAY_ATTR_NAME = "weekday"; 110 protected static final String PREV_MONTH_ATTR_NAME = "prevMonth"; 111 protected static final String PREV_YEAR_ATTR_NAME = "prevYear"; 112 protected static final String NEXT_MONTH_ATTR_NAME = "nextMonth"; 113 protected static final String NEXT_YEAR_ATTR_NAME = "nextYear"; 114 115 116 protected static final DecimalFormat monthNumberFormatter = new DecimalFormat ("00"); 117 118 119 protected AttributesImpl attributes; 120 121 125 protected List cacheKeyParList; 126 127 128 protected int year; 129 130 131 protected int month; 132 133 134 protected DateFormat dateFormatter; 135 136 137 protected DateFormat monthFormatter; 138 139 140 protected Locale locale; 141 142 143 protected boolean padWeeks; 144 145 150 protected String weekdays[] = { "", 151 "SUNDAY", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", 152 "FRIDAY", "SATURDAY" 153 }; 154 155 163 public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) 164 throws ProcessingException, SAXException , IOException { 165 super.setup(resolver, objectModel, src, par); 166 167 this.cacheKeyParList = new ArrayList (); 168 this.cacheKeyParList.add(src); 169 170 String langString = par.getParameter("lang", null); 172 locale = Locale.getDefault(); 173 if (langString != null) { 174 this.cacheKeyParList.add(langString); 175 String countryString = par.getParameter("country", ""); 176 if (! "".equals(countryString)) { 177 this.cacheKeyParList.add(countryString); 178 } 179 locale = new Locale (langString, countryString); 180 } 181 182 Calendar now = Calendar.getInstance(locale); 184 this.year = par.getParameterAsInteger("year", now.get(Calendar.YEAR)); 185 this.cacheKeyParList.add(String.valueOf(this.year)); 186 this.month = par.getParameterAsInteger("month", now.get(Calendar.MONTH) + 1) - 1; 187 this.cacheKeyParList.add(String.valueOf(this.month)); 188 189 String dateFormatString = par.getParameter("dateFormat", null); 190 this.cacheKeyParList.add(dateFormatString); 191 if (dateFormatString != null) { 192 this.dateFormatter = new SimpleDateFormat (dateFormatString, locale); 193 } else { 194 this.dateFormatter = DateFormat.getDateInstance(DateFormat.LONG, locale); 195 } 196 this.padWeeks = par.getParameterAsBoolean("padWeeks", false); 197 this.cacheKeyParList.add(BooleanUtils.toBooleanObject(this.padWeeks)); 198 this.monthFormatter = new SimpleDateFormat ("MMMM", locale); 199 this.attributes = new AttributesImpl (); 200 } 201 202 207 public void generate() throws SAXException , ProcessingException { 208 Calendar start = Calendar.getInstance(locale); 209 start.clear(); 210 start.set(Calendar.YEAR, this.year); 211 start.set(Calendar.MONTH, this.month); 212 start.set(Calendar.DAY_OF_MONTH, 1); 213 Calendar end = (Calendar ) start.clone(); 214 end.add(Calendar.MONTH, 1); 215 216 Calendar prevMonth = (Calendar ) start.clone(); 218 prevMonth.add(Calendar.MONTH, -1); 219 220 this.contentHandler.startDocument(); 221 this.contentHandler.startPrefixMapping(PREFIX, URI); 222 attributes.clear(); 223 attributes.addAttribute("", YEAR_ATTR_NAME, YEAR_ATTR_NAME, "CDATA", String.valueOf(year)); 224 attributes.addAttribute("", MONTH_ATTR_NAME, MONTH_ATTR_NAME, "CDATA", 225 monthFormatter.format(start.getTime())); 226 227 attributes.addAttribute("", PREV_YEAR_ATTR_NAME, PREV_YEAR_ATTR_NAME, "CDATA", 229 String.valueOf(prevMonth.get(Calendar.YEAR))); 230 attributes.addAttribute("", PREV_MONTH_ATTR_NAME, PREV_MONTH_ATTR_NAME, "CDATA", 231 monthNumberFormatter.format(prevMonth.get(Calendar.MONTH) + 1)); 232 attributes.addAttribute("", NEXT_YEAR_ATTR_NAME, NEXT_YEAR_ATTR_NAME, "CDATA", 233 String.valueOf(end.get(Calendar.YEAR))); 234 attributes.addAttribute("", NEXT_MONTH_ATTR_NAME, NEXT_MONTH_ATTR_NAME, "CDATA", 235 monthNumberFormatter.format(end.get(Calendar.MONTH) + 1)); 236 237 this.contentHandler.startElement(URI, CALENDAR_NODE_NAME, 238 PREFIX + ':' + CALENDAR_NODE_NAME, attributes); 239 int weekNo = start.get(Calendar.WEEK_OF_MONTH); 240 int firstDay = start.getFirstDayOfWeek(); 241 if (start.get(Calendar.DAY_OF_WEEK) != firstDay) { 242 attributes.clear(); 243 attributes.addAttribute("", NUMBER_ATTR_NAME, NUMBER_ATTR_NAME, "CDATA", String.valueOf(weekNo)); 244 this.contentHandler.startElement(URI, WEEK_NODE_NAME, 245 PREFIX + ':' + WEEK_NODE_NAME, attributes); 246 if (padWeeks) { 247 Calendar previous = (Calendar ) start.clone(); 248 while (previous.get(Calendar.DAY_OF_WEEK) != firstDay) { 249 previous.add(Calendar.DAY_OF_MONTH, -1); 250 } 251 while (previous.before(start)) { 252 attributes.clear(); 253 attributes.addAttribute("", NUMBER_ATTR_NAME, NUMBER_ATTR_NAME, "CDATA", 254 String.valueOf(previous.get(Calendar.DAY_OF_MONTH))); 255 attributes.addAttribute("", WEEKDAY_ATTR_NAME, WEEKDAY_ATTR_NAME, "CDATA", 256 weekdays[previous.get(Calendar.DAY_OF_WEEK)]); 257 attributes.addAttribute("", DATE_ATTR_NAME, DATE_ATTR_NAME, "CDATA", 258 dateFormatter.format(previous.getTime())); 259 this.contentHandler.startElement(URI, DAY_NODE_NAME, 260 PREFIX + ':' + DAY_NODE_NAME, attributes); 261 addContent(previous, locale); 262 this.contentHandler.endElement(URI, DAY_NODE_NAME, 263 PREFIX + ':' + DAY_NODE_NAME); 264 previous.add(Calendar.DAY_OF_MONTH, 1); 265 } 266 } 267 } 268 while (start.before(end)) { 269 if (start.get(Calendar.DAY_OF_WEEK) == firstDay) { 270 weekNo = start.get(Calendar.WEEK_OF_MONTH); 271 attributes.clear(); 272 attributes.addAttribute("", NUMBER_ATTR_NAME, NUMBER_ATTR_NAME, "CDATA", String.valueOf(weekNo)); 273 this.contentHandler.startElement(URI, WEEK_NODE_NAME, 274 PREFIX + ':' + WEEK_NODE_NAME, attributes); 275 } 276 attributes.clear(); 277 attributes.addAttribute("", NUMBER_ATTR_NAME, NUMBER_ATTR_NAME, "CDATA", 278 String.valueOf(start.get(Calendar.DAY_OF_MONTH))); 279 attributes.addAttribute("", WEEKDAY_ATTR_NAME, WEEKDAY_ATTR_NAME, "CDATA", 280 weekdays[start.get(Calendar.DAY_OF_WEEK)]); 281 attributes.addAttribute("", DATE_ATTR_NAME, DATE_ATTR_NAME, "CDATA", 282 dateFormatter.format(start.getTime())); 283 this.contentHandler.startElement(URI, DAY_NODE_NAME, 284 PREFIX + ':' + DAY_NODE_NAME, attributes); 285 addContent(start, locale); 286 this.contentHandler.endElement(URI, DAY_NODE_NAME, 287 PREFIX + ':' + DAY_NODE_NAME); 288 start.add(Calendar.DAY_OF_MONTH, 1); 289 if (start.get(Calendar.DAY_OF_WEEK) == firstDay 290 || (!padWeeks && ! start.before(end))) { 291 this.contentHandler.endElement(URI, WEEK_NODE_NAME, 292 PREFIX + ':' + WEEK_NODE_NAME); 293 } 294 } 295 296 if (padWeeks) { 297 while (firstDay != end.get(Calendar.DAY_OF_WEEK)) { 298 attributes.clear(); 299 attributes.addAttribute("", NUMBER_ATTR_NAME, NUMBER_ATTR_NAME, "CDATA", 300 String.valueOf(end.get(Calendar.DAY_OF_MONTH))); 301 attributes.addAttribute("", WEEKDAY_ATTR_NAME, WEEKDAY_ATTR_NAME, "CDATA", 302 weekdays[end.get(Calendar.DAY_OF_WEEK)]); 303 attributes.addAttribute("", DATE_ATTR_NAME, DATE_ATTR_NAME, "CDATA", 304 dateFormatter.format(end.getTime())); 305 this.contentHandler.startElement(URI, DAY_NODE_NAME, 306 PREFIX + ':' + DAY_NODE_NAME, attributes); 307 addContent(end, locale); 308 this.contentHandler.endElement(URI, DAY_NODE_NAME, 309 PREFIX + ':' + DAY_NODE_NAME); 310 end.add(Calendar.DAY_OF_MONTH, 1); 311 if (firstDay == end.get(Calendar.DAY_OF_WEEK)) { 312 this.contentHandler.endElement(URI, WEEK_NODE_NAME, 313 PREFIX + ':' + WEEK_NODE_NAME); 314 } 315 } 316 } 317 this.contentHandler.endElement(URI, CALENDAR_NODE_NAME, 318 PREFIX + ':' + CALENDAR_NODE_NAME); 319 this.contentHandler.endPrefixMapping(PREFIX); 320 this.contentHandler.endDocument(); 321 } 322 323 331 protected void addContent(Calendar date, Locale locale) throws SAXException {} 332 333 336 public Serializable getKey() { 337 StringBuffer buffer = new StringBuffer (); 338 int len = this.cacheKeyParList.size(); 339 for (int i = 0; i < len; i++) { 340 buffer.append(this.cacheKeyParList.get(i) + ":"); 341 } 342 return buffer.toString(); 343 } 344 345 348 public SourceValidity getValidity() { 349 return NOPValidity.SHARED_INSTANCE; 350 } 351 352 356 public void recycle() { 357 this.cacheKeyParList = null; 358 this.attributes = null; 359 this.dateFormatter = null; 360 this.monthFormatter = null; 361 this.locale = null; 362 super.recycle(); 363 } 364 365 } 366 | Popular Tags |