/*
* File : $Source: /alkacon/cvs/alkacon/com.alkacon.opencms.calendar/src/com/alkacon/opencms/calendar/CmsCalendarDisplay.java,v $
* Date : $Date: 2010/02/10 08:54:49 $
* Version: $Revision: 1.4 $
*
* This file is part of the Alkacon OpenCms Add-On Module Package
*
* Copyright (c) 2008 Alkacon Software GmbH (http://www.alkacon.com)
*
* The Alkacon OpenCms Add-On Module Package is free software:
* you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Alkacon OpenCms Add-On Module Package is distributed
* in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the Alkacon OpenCms Add-On Module Package.
* If not, see http://www.gnu.org/licenses/.
*
* For further information about Alkacon Software GmbH, please see the
* company website: http://www.alkacon.com.
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org.
*/
package com.alkacon.opencms.calendar;
import com.alkacon.opencms.commons.CmsCollectorConfiguration;
import com.alkacon.opencms.commons.CmsConfigurableCollector;
import org.opencms.file.CmsFile;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsPropertyDefinition;
import org.opencms.file.CmsResource;
import org.opencms.file.collectors.I_CmsResourceCollector;
import org.opencms.i18n.CmsMessages;
import org.opencms.jsp.CmsJspActionElement;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.main.OpenCms;
import org.opencms.util.CmsStringUtil;
import org.opencms.xml.content.CmsXmlContent;
import org.opencms.xml.content.CmsXmlContentFactory;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.logging.Log;
/**
* Provides help methods to display calendar entries for the frontend.<p>
*
* This includes methods to get calendar entries for a given date range as well as common settings
* usable on the frontend to render holiday days and output tables.<p>
*
* Extend this class to create special frontend views of a calendar, e.g. monthly or yearly views.<p>
*
* @author Andreas Zahner
* @author Peter Bonrad
*
* @version $Revision: 1.4 $
*
* @since 6.0.1
*/
public class CmsCalendarDisplay extends CmsCalendar {
/** Node name of the UseConfig element. */
public static final String NODE_USECONFIG = "UseConfig";
/** Request parameter name for the calendar date. */
public static final String PARAM_DATE = "calDat";
/** Request parameter name for the calendar day. */
public static final String PARAM_DAY = "calDay";
/** Request parameter name for the calendar month. */
public static final String PARAM_MONTH = "calMonth";
/** Request parameter name for the uri. */
public static final String PARAM_URI = "uri";
/** Request parameter name for the view type. */
public static final String PARAM_VIEWTYPE = "calView";
/** Request parameter name for the calendar year. */
public static final String PARAM_YEAR = "calYear";
/** The type of the page for the day view. */
public static final int PERIOD_DAY = 0;
/** The type of the page for the month view. */
public static final int PERIOD_MONTH = 1;
/** The type of the page for the week view. */
public static final int PERIOD_WEEK = 2;
/** The type of the page for the year view. */
public static final int PERIOD_YEAR = 3;
/** Name of the property that stores the calendar end date. */
public static final String PROPERTY_CALENDAR_ENDDATE = "calendar.enddate";
/** Name of the property that determines if the calendar should be shown. */
public static final String PROPERTY_CALENDAR_SHOW = "calendar.show";
/** Name of the property that stores the calendar start date. */
public static final String PROPERTY_CALENDAR_STARTDATE = "calendar.startdate";
/** Name of the property that stores the calendar view URI. */
public static final String PROPERTY_CALENDAR_URI = "calendar.uri";
/** The name of the resource bundle for localized frontend messages. */
public static final String RESOURCEBUNDLE_FRONTEND = "com.alkacon.opencms.calendar.display";
/** Resource type name for a calendar entry. */
public static final String RESTYPE_ENTRY = "alkacon-cal-entry";
/** Resource type name for a calendar serial entry. */
public static final String RESTYPE_ENTRY_SERIAL = "alkacon-cal-serial";
/** The log object for this class. */
private static final Log LOG = CmsLog.getLog(CmsCalendarDisplay.class);
/** The calendar object for the current date to display. */
private Calendar m_currentDate;
/** Flag if a real entry was found. */
private boolean m_foundRealEntry;
/** The JSP action element to use. */
private CmsJspActionElement m_jsp;
/** The calendar messages to use for the frontend. */
private CmsMessages m_messages;
/** The style. */
private CmsCalendarStyle m_style;
/** Flag to determine if AJAX links should be created. */
private boolean m_useAjaxLinks;
/** The type of the view which is displayed when clicking on a day. */
private int m_viewPeriod;
/** The week day that should be marked as holiday day. */
private int m_weekdayHoliday;
/** The week day that should be marked as maybe holiday day. */
private int m_weekdayMaybeHoliday;
/**
* Empty constructor.<p>
*
* Be sure to call the {@link #init(CmsJspActionElement)} method with an JSP action element.<p>
*/
public CmsCalendarDisplay() {
super();
}
/**
* Constructor with initialized calendar object and JSP action element.<p>
*
* @param jsp the JSP action element to use
*/
public CmsCalendarDisplay(CmsJspActionElement jsp) {
super();
init(jsp);
}
/**
* Determines if the calendar day to check is the current day.<p>
*
* @param current the current date
* @param day the day to check
* @return true if the calendar day to check is the current day, otherwise false
*/
public static boolean isCurrentDay(Calendar current, Calendar day) {
return ((current.get(Calendar.DATE) == day.get(Calendar.DATE))
&& (current.get(Calendar.YEAR) == day.get(Calendar.YEAR)) && (current.get(Calendar.MONTH) == day.get(Calendar.MONTH)));
}
/**
* Sets the time of a calendar object.<p>
*
* @param calendar the calendar to set the time
* @param hour the new hour
* @param minute the new minute
* @param second the new second
* @return the calendar object with adjusted time
*/
public static Calendar setDayTime(Calendar calendar, int hour, int minute, int second) {
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
calendar.set(Calendar.MILLISECOND, 0);
return calendar;
}
/**
* Adds optional calendar holiday days to the entry list.<p>
*
* The bundle to use must have a key "calendar.holidays.datepattern" to specify the date pattern used in the bundle.
* The holidays are stored in the format: "date = title_of_holiday;weekdaystatus". The date is used as key, the
* weekday status has to be 1 (maybe holiday) or 2 (holiday).<p>
* Example: <code>01/01/2006=New year;2</code> is a valid holiday entry.<p>
*
* @param bundleName the name of the resource bundle
*/
public void addHolidays(String bundleName) {
addHolidays(bundleName, getJsp().getRequestContext().getLocale());
}
/**
* Adds optional calendar holiday days to the entry list.<p>
*
* The bundle to use must have a key "calendar.holidays.datepattern" to specify the date pattern used in the bundle.
* The holidays are stored in the format: "date = title_of_holiday;weekdaystatus". The date is used as key, the
* weekday status has to be 1 (maybe holiday) or 2 (holiday).<p>
* Example: <code>1/1/2009=New year;2</code> is a valid holiday entry.<p>
*
* @param bundleName the name of the resource bundle
* @param calendarLocale the Locale for the calendar to build
*/
public void addHolidays(String bundleName, Locale calendarLocale) {
CmsMessages holidays = new CmsMessages(bundleName, calendarLocale);
String datePattern = holidays.key("calendar.holidays.datepattern");
DateFormat df = new SimpleDateFormat(datePattern, calendarLocale);
// get all keys from the bundle
Enumeration en = holidays.getResourceBundle().getKeys();
while (en.hasMoreElements()) {
String key = (String)en.nextElement();
try {
// try to get a valid date from the key
Date holidayDate = df.parse(key);
String value = holidays.key(key);
String[] data = value.split(";");
int weekdayStatus = 1;
if (CmsStringUtil.isNotEmpty(data[1])) {
try {
weekdayStatus = Integer.parseInt(data[1].trim());
} catch (Exception e) {
// invalid entry, skip it
continue;
}
}
// create the calendar objects
CmsCalendarEntryData entryData = new CmsCalendarEntryData(data[0].trim(), "", "", "", weekdayStatus);
CmsCalendarEntryDate entryDate = new CmsCalendarEntryDate(
holidayDate.getTime(),
CmsCalendarEntryDate.MILLIS_01_PER_HOUR,
2 * CmsCalendarEntryDate.MILLIS_01_PER_HOUR,
0);
CmsCalendarEntry entry = new CmsCalendarEntry(entryData, entryDate);
// add the new entry to the calendar
addEntry(entry);
} catch (Exception e) {
// ignore this exception, simply skip the entry
}
}
}
/**
* Returns the HTML for a single calendar entry on an overview page.<p>
*
* @param entry the calendar entry to use
* @return the HTML for a single calendar entry on an overview page
*/
public String buildOverviewDayEntry(CmsCalendarEntry entry) {
return buildOverviewDayEntry(entry, true);
}
/**
* Returns the HTML for a single calendar entry on an overview page.<p>
*
* @param entry the calendar entry to use
* @param timeFirst flag to check if the time information should be shown first or not
* @return the HTML for a single calendar entry on an overview page
*/
public String buildOverviewDayEntry(CmsCalendarEntry entry, boolean timeFirst) {
StringBuffer result = new StringBuffer(2048);
Calendar start = entry.getEntryDate().getStartDate();
Calendar end = entry.getEntryDate().getEndDate();
if (timeFirst && entry.getEntryData().isShowTime()) {
// create entry date and time information at the beginning
result.append("<span class=\"cal_entry_date\">");
result.append(getMessages().key("calendar.day.starttime", new Object[] {start.getTime()}));
if (entry.getEntryDate().getDuration() < 1) {
// entry ends the same day
if (entry.getEntryDate().getStartTime() != entry.getEntryDate().getEndTime()) {
result.append(" ");
result.append(getMessages().key("calendar.day.endtime", new Object[] {end.getTime()}));
}
} else {
// entry ends on other day
result.append(" ");
result.append(getMessages().key("calendar.day.enddate", new Object[] {end.getTime()}));
}
result.append("</span><br/>");
}
// create the (linked) title of the entry
String link = entry.getEntryData().getDetailUri();
boolean linkPresent = false;
if (CmsStringUtil.isNotEmpty(link)) {
linkPresent = true;
result.append("<a class=\"cal_entry_link\" href=\"");
if (entry.getEntryDate().isSerialDate()) {
// a serial entry has to get the time information in a request parameter to show the entry correctly
StringBuffer params = new StringBuffer(64);
params.append("?");
params.append(CmsCalendarDisplay.PARAM_DATE);
params.append("=");
params.append(start.getTimeInMillis());
result.append(getJsp().link(link + params));
} else {
result.append(getJsp().link(link));
}
result.append("\">");
}
result.append(entry.getEntryData().getTitle());
if (linkPresent) {
result.append("</a>");
}
// show the entry type if present and localized
if (CmsStringUtil.isNotEmpty(entry.getEntryData().getType())) {
String localizedType = getMessages().key("calendar.entry.type." + entry.getEntryData().getType());
if (!localizedType.startsWith(CmsMessages.UNKNOWN_KEY_EXTENSION)) {
result.append(" <span class=\"cal_entry_type\">(").append(localizedType).append(")</span>");
}
}
// show the description if present
String description = entry.getEntryData().getDescription();
if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(description)) {
result.append("<br/><span class=\"cal_entry_description\">");
result.append(description);
result.append("</span>");
}
if (!timeFirst && entry.getEntryData().isShowTime()) {
// create entry date and time information at the end
result.append("<br/>");
result.append("<span class=\"cal_entry_date\">");
result.append(getMessages().key("calendar.day.starttime", new Object[] {start.getTime()}));
if (entry.getEntryDate().getDuration() < 1) {
// entry ends the same day
if (entry.getEntryDate().getStartTime() != entry.getEntryDate().getEndTime()) {
result.append(" ");
result.append(getMessages().key("calendar.day.endtime", new Object[] {end.getTime()}));
}
} else {
// entry ends on other day
result.append(" ");
result.append(getMessages().key("calendar.day.enddate", new Object[] {end.getTime()}));
}
result.append("</span>");
}
return result.toString();
}
/**
* Returns the HTML to generate a link to a overview page using the specified calendar date.<p>
* The needed parameters are added to the currently requested uri.
*
* @param calendar the calendar date to build the link
* @return the HTML to generate a link to the overview
* @see #createLink(Calendar, String, boolean)
*/
public String createLink(Calendar calendar) {
return createLink(calendar, getJsp().getRequestContext().getUri(), true);
}
/**
* Returns the HTML to generate a link to a overview page using the specified calendar date.<p>
* The needed parameters are added to the currently requested uri.
*
* @param calendar the calendar date to build the link
* @param viewPeriod the view period type to link to
* @return the HTML to generate a link to the overview
* @see #createLink(Calendar, String, boolean)
*/
public String createLink(Calendar calendar, int viewPeriod) {
return createLink(calendar, getJsp().getRequestContext().getUri(), true, viewPeriod);
}
/**
* Returns the HTML to generate a link to a overview page using the specified calendar date.<p>
* The needed parameters are added to the given uri.
*
* @param calendar the calendar date to build the link
* @param uri the uri of the overview page
* @return the HTML to generate a link to the overview
* @see #createLink(Calendar, String, boolean)
*/
public String createLink(Calendar calendar, String uri) {
return createLink(calendar, uri, true);
}
/**
* Returns the HTML to generate a link to a overview page using the specified calendar date.<p>
* The needed parameters are added to the given uri.
*
* @param calendar the calendar date to build the link
* @param uri the uri of the overview page
* @param useCmsLink should the generated link be handled by the OpenCms Link Handler
* @return the HTML to generate a link to the overview
*/
public String createLink(Calendar calendar, String uri, boolean useCmsLink) {
return createLink(calendar, uri, useCmsLink, getViewPeriod());
}
/**
* Returns the HTML to generate a link to a overview page using the specified calendar date.<p>
* The needed parameters are added to the given uri.
*
* @param calendar the calendar date to build the link
* @param uri the uri of the overview page
* @param useCmsLink should the generated link be handled by the OpenCms Link Handler
* @param viewPeriod the view period type to link to
* @return the HTML to generate a link to the overview
*/
public String createLink(Calendar calendar, String uri, boolean useCmsLink, int viewPeriod) {
if (isUseAjaxLinks()) {
StringBuffer ajaxLink = new StringBuffer(64);
String viewType = "";
switch (viewPeriod) {
case PERIOD_DAY:
viewType = "day";
break;
case PERIOD_WEEK:
viewType = "week";
break;
case PERIOD_MONTH:
viewType = "month";
break;
case PERIOD_YEAR:
viewType = "year";
break;
default:
viewType = "day";
}
ajaxLink.append("calendarCenterShow('");
ajaxLink.append(viewType).append("', ");
ajaxLink.append(calendar.get(Calendar.DATE)).append(", ");
ajaxLink.append(calendar.get(Calendar.MONTH)).append(", ");
ajaxLink.append(calendar.get(Calendar.YEAR)).append(");");
return ajaxLink.toString();
} else {
StringBuffer nextLink = new StringBuffer(64);
// append the URI to the JSP
nextLink.append(uri);
// append date parameters
nextLink.append("?").append(PARAM_YEAR).append("=").append(calendar.get(Calendar.YEAR));
nextLink.append("&").append(PARAM_MONTH).append("=").append(calendar.get(Calendar.MONTH));
nextLink.append("&").append(PARAM_DAY).append("=").append(calendar.get(Calendar.DATE));
// append view type parameter
nextLink.append("&").append(PARAM_VIEWTYPE).append("=").append(viewPeriod);
// return a valid OpenCms link
if (useCmsLink) {
return getJsp().link(nextLink.toString());
} else {
return nextLink.toString();
}
}
}
/**
* Returns the current date to display, depending on the found request parameters.<p>
*
* @return the current date to display, depending on the found request parameters
*/
public Calendar getCurrentDate() {
if (m_currentDate == null) {
Calendar calendar = new GregorianCalendar(getJsp().getRequestContext().getLocale());
// get day parameters from request
String yearParam = getJsp().getRequest().getParameter(PARAM_YEAR);
String monthParam = getJsp().getRequest().getParameter(PARAM_MONTH);
String dayParam = getJsp().getRequest().getParameter(PARAM_DAY);
if (CmsStringUtil.isNotEmpty(yearParam)
&& CmsStringUtil.isNotEmpty(monthParam)
&& CmsStringUtil.isNotEmpty(dayParam)) {
// build calendar settings specified by given request parameters
int year = Integer.parseInt(yearParam);
int month = Integer.parseInt(monthParam);
int day = Integer.parseInt(dayParam);
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DATE, day);
}
m_currentDate = calendar;
}
return m_currentDate;
}
/**
* Returns the default collector that reads the calendar entries from the VFS.<p>
*
* This basic implementation checks the calendar view file for configuration settings.
*
* As fallback, it recursively collects entries and serial entries from the root folder.
* Overwrite this to change the logic of the default collection.<p>
*
* @return the default collector that reads the calendar entries from the VFS
*/
public I_CmsResourceCollector getDefaultCollector() {
String calFilePath = getJsp().property(
CmsCalendarDisplay.PROPERTY_CALENDAR_URI,
"search",
getJsp().getRequestContext().getUri());
try {
// read the calendar view file to determine if special collector configuration should be used
CmsFile calFile = getJsp().getCmsObject().readFile(calFilePath);
CmsXmlContent content = CmsXmlContentFactory.unmarshal(getJsp().getCmsObject(), calFile);
Locale locale = getJsp().getRequestContext().getLocale();
if (content.hasValue(NODE_USECONFIG, locale)) {
// found the use configuration element, now check the value
String useConf = content.getStringValue(getJsp().getCmsObject(), NODE_USECONFIG, locale);
if (Boolean.valueOf(useConf).booleanValue()) {
// individual configuration should be used, configure collector accordingly
I_CmsResourceCollector collector = new CmsConfigurableCollector();
collector.setDefaultCollectorParam(calFilePath);
return collector;
}
}
} catch (CmsException e) {
// ignore, the simple default configuration will be used
}
// simple default configuration with calendar entries and serial date entries
List defaultConfiguration = new ArrayList();
defaultConfiguration.add(new CmsCollectorConfiguration("/", RESTYPE_ENTRY, null));
defaultConfiguration.add(new CmsCollectorConfiguration("/", RESTYPE_ENTRY_SERIAL, null));
return new CmsConfigurableCollector(defaultConfiguration);
}
/**
* Returns the calendar entries of the collected resources that match the actual
* time period.<p>
*
* @param type the type of time period
* @return all entries for the days of the specified range with their corresponding entries as lists
*/
public Map getEntriesForCurrentPeriod(int type) {
Calendar current = getCurrentDate();
switch (type) {
case PERIOD_DAY:
return getEntriesForDay(current.get(Calendar.YEAR), current.get(Calendar.DAY_OF_YEAR));
case PERIOD_WEEK:
return getEntriesForWeek(current.get(Calendar.YEAR), current.get(Calendar.WEEK_OF_YEAR));
case PERIOD_MONTH:
return getEntriesForMonth(current.get(Calendar.YEAR), current.get(Calendar.MONTH));
case PERIOD_YEAR:
return getEntriesForYear(current.get(Calendar.YEAR));
default:
return new TreeMap();
}
}
/**
* Returns the list of calendar entries as {@link CmsCalendarEntry} objects for the specified day.<p>
*
* @param year the year of the day to display
* @param day the day of the year to get the entries for
* @return the list of calendar entries for the specified day
*/
public Map getEntriesForDay(int year, int day) {
Calendar startDay = new GregorianCalendar(getJsp().getRequestContext().getLocale());
startDay.set(Calendar.YEAR, year);
startDay.set(Calendar.DAY_OF_YEAR, day);
Calendar endDay = (Calendar)startDay.clone();
return getEntriesForDays(startDay, endDay);
}
/**
* Returns all entries for the days of the specified range with their corresponding entries as lists.<p>
*
* The key of the Map has to be a Date object.<p>
*
* The Map values are always lists of {@link CmsCalendarEntry} objects, if no entries are available for a specific day,
* an empty List is stored in the Map.<p>
*
* @param startDay the start day of the range
* @param endDay the end day of the range
* @return all entries for the days of the specified range with their corresponding entries as lists
*/
public Map getEntriesForDays(Calendar startDay, Calendar endDay) {
Map displayDays = new TreeMap();
// first get all entries to display
Map displayEntries = getDisplayedEntries(startDay, endDay);
Calendar runDay = setDayTime(startDay, 0, 0, 0);
while (true) {
List entries = (List)displayEntries.get(runDay.getTime());
if (entries == null) {
entries = new ArrayList(0);
}
displayDays.put(runDay.getTime(), entries);
// increase day to next day
runDay.add(Calendar.DAY_OF_YEAR, 1);
if (runDay.after(endDay)) {
// runDay has reached endDay -> stop loop
break;
}
}
return displayDays;
}
/**
* Returns all displayed days of the specified month with their corresponding entries as lists.<p>
*
* The key of the Map has to be a Date object.<p>
*
* The Map values are always lists of {@link CmsCalendarEntry} objects, if no entries are available for a specific day,
* an empty List is returned.<p>
*
* @param year the year of the month to display
* @param month the month to display
* @return all displayed days of the specified day range with their corresponding entries as lists
*/
public Map getEntriesForMonth(int year, int month) {
Calendar startDay = new GregorianCalendar(year, month, 1);
Calendar endDay = new GregorianCalendar(year, month, startDay.getActualMaximum(Calendar.DAY_OF_MONTH));
return getEntriesForDays(startDay, endDay);
}
/**
* Returns all displayed days of the specified week with their corresponding entries as lists.<p>
*
* The key of the Map has to be a Date object.<p>
*
* The Map values are always lists of {@link CmsCalendarEntry} objects, if no entries are available for a specific day,
* an empty List is returned.<p>
*
* @param year the year of the month to display
* @param week the week of the year to display
* @return all displayed days of the specified day range with their corresponding entries as lists
*/
public Map getEntriesForWeek(int year, int week) {
Calendar startDay = new GregorianCalendar(getJsp().getRequestContext().getLocale());
startDay.set(Calendar.YEAR, year);
startDay.set(Calendar.WEEK_OF_YEAR, week);
startDay.set(Calendar.DAY_OF_WEEK, startDay.getFirstDayOfWeek());
Calendar endDay = (Calendar)startDay.clone();
endDay.add(Calendar.DAY_OF_YEAR, 6);
return getEntriesForDays(startDay, endDay);
}
/**
* Returns all displayed days of the specified year with their corresponding entries as lists.<p>
*
* The key of the Map has to be a Date object.<p>
*
* The Map values are always lists of {@link CmsCalendarEntry} objects, if no entries are available for a specific day,
* an empty List is returned.<p>
*
* @param year the year of the month to display
* @return all displayed days of the specified day range with their corresponding entries as lists
*/
public Map getEntriesForYear(int year) {
Calendar startDay = new GregorianCalendar(getJsp().getRequestContext().getLocale());
startDay.set(Calendar.YEAR, year);
startDay.set(Calendar.MONTH, Calendar.JANUARY);
startDay.set(Calendar.DAY_OF_MONTH, 1);
Calendar endDay = (Calendar)startDay.clone();
endDay.set(Calendar.MONTH, Calendar.DECEMBER);
endDay.set(Calendar.DAY_OF_MONTH, 31);
return getEntriesForDays(startDay, endDay);
}
/**
* Returns the name of the resource bundle to use for frontend output.<p>
*
* @return the name of the resource bundle to use for frontend output
*/
public String getFrontendResourceBundle() {
return "com.alkacon.opencms.calendar.display";
}
/**
* Filters the calendar entries and separates them depending if they are holiday or common entries.<p>
*
* @param entries a list of calendar entries
* @return a list where only "holiday" entries are in the list (holidays are filtered out)
*/
public List getHolidayEntries(List entries) {
ArrayList result = new ArrayList();
for (int j = 0; j < entries.size(); j++) {
CmsCalendarEntry entry = (CmsCalendarEntry)entries.get(j);
if (entry.getEntryData().getWeekdayStatus() > I_CmsCalendarEntryData.WEEKDAYSTATUS_WORKDAY) {
result.add(entry);
}
}
return result;
}
/**
* Returns a string with the holiday included in the given list with calendar entries.<p>
*
* @param entries list of calendar entries with the included holidays
* @return a string with all holiday included in the given list of calendar entries
*/
public String getHolidays(List entries) {
StringBuffer result = new StringBuffer();
List holidays = getHolidayEntries(entries);
Iterator i = holidays.iterator();
if (i.hasNext()) {
boolean isFirst = true;
while (i.hasNext()) {
if (!isFirst) {
result.append(" - ");
}
CmsCalendarEntry entry = (CmsCalendarEntry)i.next();
result.append(entry.getEntryData().getTitle());
isFirst = false;
}
}
return result.toString();
}
/**
* Returns the JSP action element to use.<p>
*
* @return the JSP action element to use
*/
public CmsJspActionElement getJsp() {
return m_jsp;
}
/**
* Returns the calendar messages to use for the frontend.<p>
*
* @return the calendar messages to use for the frontend
*/
public CmsMessages getMessages() {
return m_messages;
}
/**
* Returns the specified amount of most current entries, starting from the current date.<p>
*
* The result is sorted by the start date of the entries, ascending.<p>
*
* @param count the amount of entries to return
* @return the most current entries
*/
public List getMostCurrentEntries(int count) {
List result = new ArrayList(count);
// determine start date
Calendar startDay = new GregorianCalendar(getJsp().getRequestContext().getLocale());
startDay.setTimeInMillis(System.currentTimeMillis());
startDay = setDayTime(startDay, 0, 0, 0);
// determine current view range
Calendar endDay = (GregorianCalendar)startDay.clone();
endDay.add(Calendar.YEAR, 30);
List viewDates = new ArrayList(1);
CmsCalendarEntryDate viewDate = new CmsCalendarEntryDate(startDay, setDayTime(endDay, 23, 59, 59));
viewDates.add(viewDate);
// create the simple view
CmsCalendarViewSimple calendarView = new CmsCalendarViewSimple(viewDates);
Iterator i = getEntries().iterator();
while (i.hasNext()) {
CmsCalendarEntry entry = (CmsCalendarEntry)i.next();
if (entry.getEntryDate().isSerialDate()) {
// serial date, create entry clones for every future occurance
CmsCalendarEntryDateSerial serialDate = (CmsCalendarEntryDateSerial)entry.getEntryDate();
result.addAll(serialDate.matchCalendarView(entry, calendarView, count));
} else if (entry.getEntryDate().getStartDate().getTimeInMillis() > startDay.getTimeInMillis()) {
// common entry that is in the future, add it to result
result.add(entry);
}
}
// sort the collected entries by date ascending
calendarView.sort(result);
if ((count > 0) && (result.size() > count)) {
// cut off all items > count
result = result.subList(0, count);
}
return result;
}
/**
* Returns the next time range to show calendar entries for.<p>
* Used for the navigation.
*
* @param actual the actual date from which the next time range should be calculated
* @param type the type of period
* @return a date for which a list of calendar entries should be shown
*/
public Calendar getNextPeriod(Calendar actual, int type) {
Calendar cal = (Calendar)actual.clone();
switch (type) {
case PERIOD_DAY:
cal.add(Calendar.DAY_OF_YEAR, 1);
break;
case PERIOD_MONTH:
cal.add(Calendar.MONTH, 1);
break;
case PERIOD_WEEK:
cal.add(Calendar.WEEK_OF_YEAR, 1);
break;
case PERIOD_YEAR:
cal.add(Calendar.YEAR, 1);
break;
default:
break;
}
return cal;
}
/**
* Returns the next time range to the actual date to show calendar entries for.<p>
* Used for the navigation.
*
* @param type the type of period
* @return a date for which a list of calendar entries should be shown
*/
public Calendar getNextPeriod(int type) {
return getNextPeriod(getCurrentDate(), type);
}
/**
* Returns the previous time range to show calendar entries for.<p>
* Used for the navigation.
*
* @param actual the actual date from which the previous time range should be calculated
* @param type the type of period
* @return a date for which a list of calendar entries should be shown
*/
public Calendar getPreviousPeriod(Calendar actual, int type) {
Calendar cal = (Calendar)actual.clone();
switch (type) {
case PERIOD_DAY:
cal.add(Calendar.DAY_OF_YEAR, -1);
break;
case PERIOD_MONTH:
cal.add(Calendar.MONTH, -1);
break;
case PERIOD_WEEK:
cal.add(Calendar.WEEK_OF_YEAR, -1);
break;
case PERIOD_YEAR:
cal.add(Calendar.YEAR, -1);
break;
default:
break;
}
return cal;
}
/**
* Returns the previous time range to the actual date to show calendar entries for.<p>
* Used for the navigation.
*
* @param type the type of period
* @return a date for which a list of calendar entries should be shown
*/
public Calendar getPreviousPeriod(int type) {
return getPreviousPeriod(getCurrentDate(), type);
}
/**
* Filters the calendar entries and separates them depending if they are holiday or common entries.<p>
*
* @param entries a list of calendar entries
* @return a list where only "real" entries are in the list (holidays are filtered out)
*/
public List getRealEntries(List entries) {
ArrayList result = new ArrayList();
for (int j = 0; j < entries.size(); j++) {
CmsCalendarEntry entry = (CmsCalendarEntry)entries.get(j);
if (entry.getEntryData().getWeekdayStatus() <= I_CmsCalendarEntryData.WEEKDAYSTATUS_WORKDAY) {
result.add(entry);
}
}
return result;
}
/**
* Returns the CSS style object that is used to format the calendar output.<p>
*
* @return the CSS style object that is used to format the calendar output
*/
public CmsCalendarStyle getStyle() {
return m_style;
}
/**
* Returns the type of the view which is displayed when clicking on a day.<p>
*
* @return the type of the view which is displayed when clicking on a day
*/
public int getViewPeriod() {
return m_viewPeriod;
}
/**
* Returns the week day that should be marked as holiday day.<p>
*
* @return the week day that should be marked as holiday day
*/
public int getWeekdayHoliday() {
return m_weekdayHoliday;
}
/**
* Returns the week day that should be marked as maybe holiday day.<p>
*
* @return the week day that should be marked as maybe holiday day
*/
public int getWeekdayMaybeHoliday() {
return m_weekdayMaybeHoliday;
}
/**
* Returns if a real entry was found.<p>
*
* @return if a real entry was found
*/
public boolean hasRealEntries() {
return m_foundRealEntry;
}
/**
* Initializes the JSP action element and the calendar messages to use for the frontend.<p>
*
* @param jsp the JSP action element to use
*/
public void init(CmsJspActionElement jsp) {
// initialize style class
m_style = new CmsCalendarStyle();
// initialize other members
m_foundRealEntry = false;
if (jsp != null) {
m_jsp = jsp;
// initializes localized messages
m_messages = getJsp().getMessages(
getFrontendResourceBundle(),
getJsp().getRequestContext().getLocale().toString());
m_weekdayHoliday = Integer.parseInt(getMessages().key("calendar.weekday.holiday", "-1"));
m_weekdayMaybeHoliday = Integer.parseInt(getMessages().key("calendar.weekday.maybeholiday", "-1"));
// initialize view period type
String period = getJsp().getRequest().getParameter(PARAM_VIEWTYPE);
if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(period)) {
try {
setViewPeriod(Integer.parseInt(period));
} catch (NumberFormatException e) {
setViewPeriod(PERIOD_DAY);
}
} else {
setViewPeriod(PERIOD_DAY);
}
} else {
m_weekdayHoliday = -1;
m_weekdayMaybeHoliday = -1;
setViewPeriod(PERIOD_DAY);
}
}
/**
* Initializes the calendar entries using the default resource collector.<p>
*
* @return the List of collected resources using the default resource collector
*/
public List initCalendarEntries() {
return initCalendarEntries(getDefaultCollector());
}
/**
* Initializes the calendar entries using the specified resource collector.<p>
*
* @param collector the collector to use for collecting the resources
* @return the List of collected resources using the specified resource collector
*/
public List initCalendarEntries(I_CmsResourceCollector collector) {
List result = null;
try {
result = collector.getResults(getJsp().getCmsObject());
setEntries(createCalendarEntries(
result,
PROPERTY_CALENDAR_STARTDATE,
PROPERTY_CALENDAR_ENDDATE,
CmsPropertyDefinition.PROPERTY_TITLE,
CmsPropertyDefinition.PROPERTY_DESCRIPTION));
} catch (CmsException e) {
// error collecting resources, an empty calendar is returned
if (LOG.isErrorEnabled()) {
LOG.error(Messages.get().getBundle().key(
Messages.LOG_CALENDAR_RESOURCES_1,
getJsp().getRequestContext().getUri()));
}
}
return result;
}
/**
* Returns if AJAX links should be created for calendar pagination.<p>
*
* @return true if AJAX links should be created for calendar pagination, otherwise false
*/
public boolean isUseAjaxLinks() {
return m_useAjaxLinks;
}
/**
* Sets the JSP action element to use.<p>
*
* @param jsp the JSP action element to use
*/
public void setJsp(CmsJspActionElement jsp) {
m_jsp = jsp;
}
/**
* Sets the calendar messages to use for the frontend.<p>
*
* @param messages the calendar messages to use for the frontend
*/
public void setMessages(CmsMessages messages) {
m_messages = messages;
}
/**
* Sets the CSS style object that is used to format the calendar output.<p>
*
* @param style the CSS style object that is used to format the calendar output
*/
public void setStyle(CmsCalendarStyle style) {
m_style = style;
}
/**
* Sets if AJAX links should be created for calendar pagination.<p>
*
* @param useAjaxLinks true if AJAX links should be created for calendar pagination, otherwise false
*/
public void setUseAjaxLinks(boolean useAjaxLinks) {
m_useAjaxLinks = useAjaxLinks;
}
/**
* Sets the type of the view which is displayed when clicking on a day.<p>
*
* @param viewPeriod the type of the view which is displayed when clicking on a day
*/
public void setViewPeriod(int viewPeriod) {
m_viewPeriod = viewPeriod;
}
/**
* Creates calendar entries from the given list of resources and their properties.<p>
*
* The following properties are read to create calendar entries from the resources:
* <ul>
* <li>the start date (mandatory)</li>
* <li>the end date (optional)</li>
* <li>the entry title (mandatory)</li>
* <li>the entry description (optional)</li>
* </ul>
* The mandatory properties must have been set to create correct calendar entries.<p>
*
* @param resources the resources to create calendar entries from
* @param pStartDate the name of the property to use for the start date
* @param pEndDate the name of the property to use for the end date
* @param pTitle the name of the property to use for the title
* @param pDescription the name of the property to use for the description
* @return the calendar entries from the given list of resources and their properties
*/
protected List createCalendarEntries(
List resources,
String pStartDate,
String pEndDate,
String pTitle,
String pDescription) {
CmsObject cms = getJsp().getCmsObject();
List result = new ArrayList(resources.size());
// instanciate default serial date content class
I_CmsCalendarSerialDateContent defaultContent = new CmsSerialDateContentBean();
for (int i = resources.size() - 1; i > -1; i--) {
// loop the resources
CmsResource res = (CmsResource)resources.get(i);
// read the title of the resource
String title = getPropertyValue(cms, res, pTitle, null);
// read the start date property
String startDate = getPropertyValue(cms, res, pStartDate, null);
if (CmsStringUtil.isNotEmpty(title) && CmsStringUtil.isNotEmpty(startDate)) {
// required properties were found, resource can be used as an entry
String endDate = getPropertyValue(cms, res, pEndDate, startDate);
String description = getPropertyValue(cms, res, pDescription, "");
String showTimeStr = getPropertyValue(
cms,
res,
I_CmsCalendarEntryData.PROPERTY_CALENDAR_SHOWTIME,
CmsStringUtil.TRUE);
// determine entry resource type
String type = "";
try {
type = OpenCms.getResourceManager().getResourceType(res.getTypeId()).getTypeName();
} catch (CmsException e) {
// ignore, this information is not important
LOG.warn(e.getLocalizedMessage(), e);
}
// create the calendar entry data
String resPath = getJsp().getRequestContext().getSitePath(res);
CmsCalendarEntryData entryData = new CmsCalendarEntryData(title, description, type, resPath, 0);
entryData.setShowTime(Boolean.valueOf(showTimeStr).booleanValue());
// create the calendar entry date
CmsCalendarEntryDate entryDate = null;
if (startDate.indexOf('=') == -1) {
// start date property does not contain key/value pairs, this is a common entry
Calendar start = new GregorianCalendar(getJsp().getRequestContext().getLocale());
start.setTimeInMillis(Long.parseLong(startDate));
Calendar end = new GregorianCalendar(getJsp().getRequestContext().getLocale());
end.setTimeInMillis(Long.parseLong(endDate));
// create a new calendar entry date
entryDate = new CmsCalendarEntryDate(start, end);
// create the calendar entry
CmsCalendarEntry entry = new CmsCalendarEntry(entryData, entryDate);
// add the entry to the result
result.add(entry);
} else {
// this might be a serial date, try to create it
CmsCalendarEntry entry = null;
String clazzName = getPropertyValue(cms, res, pEndDate, null);
if (CmsStringUtil.isEmpty(clazzName)) {
// did not find a class name in the property, use default content bean to get entry
entry = defaultContent.getSerialEntryForCalendar(cms, res);
} else {
// found a class name, use it to get the entry
try {
I_CmsCalendarSerialDateContent serialContent = (I_CmsCalendarSerialDateContent)Class.forName(
clazzName).newInstance();
entry = serialContent.getSerialEntryForCalendar(cms, res);
} catch (Exception e) {
// implementing class was not found
if (LOG.isErrorEnabled()) {
LOG.error(
Messages.get().getBundle().key(
Messages.LOG_CALENDAR_SERIALDATE_CLASS_3,
clazzName,
PROPERTY_CALENDAR_ENDDATE,
resPath),
e);
}
}
}
if (entry != null) {
result.add(entry);
}
}
}
}
return result;
}
/**
* Returns value of the given property from the given resource, or the given default value if any problem.<p>
*
* @param cms the current CMS context
* @param resource the resource
* @param propertyName the property name
* @param defaultValue the default value
*
* @return value of the given property from the given resource
*/
protected String getPropertyValue(CmsObject cms, CmsResource resource, String propertyName, String defaultValue) {
try {
return cms.readPropertyObject(resource, propertyName, false).getValue(defaultValue);
} catch (CmsException e) {
LOG.warn(e.getLocalizedMessage(), e);
return defaultValue;
}
}
/**
* Creates a sorted Map of entries for the given date range.<p>
*
* The Map uses the Date object representing a day of the range (with time information 0:00:00) as key,
* the value is a (sorted) list of calendar entries for the day.<p>
*
* @param startDay the start day of the range
* @param endDay the end day of the range
* @return a sorted Map of entries for the given date range
*/
private Map getDisplayedEntries(Calendar startDay, Calendar endDay) {
// create the list of view dates
List viewDates = new ArrayList(1);
CmsCalendarEntryDate viewDate = new CmsCalendarEntryDate(setDayTime(startDay, 0, 0, 0), setDayTime(
endDay,
23,
59,
59));
viewDates.add(viewDate);
// create the simple view
CmsCalendarViewSimple view = new CmsCalendarViewSimple(viewDates);
// get all entries for the view range
List entries = getEntries(view);
Map displayEntries = new TreeMap();
for (int i = 0; i < entries.size(); i++) {
CmsCalendarEntry entry = (CmsCalendarEntry)entries.get(i);
// get the entry start date
Calendar entryStart = (Calendar)entry.getEntryDate().getStartDate().clone();
entryStart = setDayTime(entryStart, 0, 0, 0);
// get the list of entries for the start day
List dayEntries = (List)displayEntries.get(entryStart.getTime());
if (dayEntries == null) {
// no entries for the current day found, create empty list
dayEntries = new ArrayList(3);
}
// check if a real entry was found
if (entry.getEntryData().getWeekdayStatus() <= I_CmsCalendarEntryData.WEEKDAYSTATUS_WORKDAY) {
m_foundRealEntry = true;
}
// add current entry to list
dayEntries.add(entry);
// put list of entries to Map
displayEntries.put(entryStart.getTime(), dayEntries);
}
return displayEntries;
}
}