/* * File : $Source: /alkacon/cvs/alkacon/com.alkacon.opencms.calendar/src/com/alkacon/opencms/calendar/CmsCalendarSerialDateMonthlyOptions.java,v $ * Date : $Date: 2009/02/05 09:49:31 $ * Version: $Revision: 1.2 $ * * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (c) 2002 - 2007 Alkacon Software GmbH (http://www.alkacon.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * 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 * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.alkacon.opencms.calendar; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Options for a monthly serial calendar entry.<p> * * Provides the necessary information about a monthly serial calendar entry.<p> * * @author Andreas Zahner * * @version $Revision: 1.2 $ * * @since 6.0.1 */ public class CmsCalendarSerialDateMonthlyOptions extends A_CmsCalendarSerialDateOptions { /** The number of the day of the month for the serial calendar entry. */ private int m_dayOfMonth; /** The monthly interval for the serial calendar entry. */ private int m_monthlyInterval; /** Indicates if the specified week day should be used or only the number of the day of the month. */ private boolean m_useWeekDay; /** The week day for the serial calendar entry. */ private int m_weekDay; /** * Creates an initialized serial date monthly options object with the standard monthly interval options.<p> * * Standard interval options are: the first day of month every month.<p> */ public CmsCalendarSerialDateMonthlyOptions() { m_dayOfMonth = 1; m_weekDay = -1; m_monthlyInterval = 1; m_useWeekDay = false; } /** * Creates an initialized serial date monthly options object with the given parameters.<p> * * @param dayOfMonth the number of the day of the month for the monthly series * @param weekDay the week day for the monthly series, if less than 1 or more than 7 the week day is not used * @param monthlyInterval the weekly interval for the monthly series */ public CmsCalendarSerialDateMonthlyOptions(int dayOfMonth, int weekDay, int monthlyInterval) { m_dayOfMonth = dayOfMonth; m_weekDay = weekDay; if (weekDay < Calendar.SUNDAY || weekDay > Calendar.SATURDAY) { m_useWeekDay = false; } else { m_useWeekDay = true; } m_monthlyInterval = 1; if (monthlyInterval > 0) { m_monthlyInterval = monthlyInterval; } } /** * @see com.alkacon.opencms.calendar.I_CmsCalendarSerialDateOptions#getConfigurationValuesAsMap() */ public Map getConfigurationValuesAsMap() { // create the Map containing the date settings Map values = new HashMap(); // put interval, day of month and week days to Map values.put(I_CmsCalendarSerialDateOptions.CONFIG_INTERVAL, String.valueOf(getMonthlyInterval())); values.put(I_CmsCalendarSerialDateOptions.CONFIG_DAY_OF_MONTH, String.valueOf(getDayOfMonth())); values.put(I_CmsCalendarSerialDateOptions.CONFIG_WEEKDAYS, String.valueOf(getWeekDay())); return values; } /** * Returns the day of month for the serial entry.<p> * * @return the day of month for the serial entry */ public int getDayOfMonth() { return m_dayOfMonth; } /** * Sets the monthly interval for the serial entry.<p> * * @return the monthly interval for the serial entry */ public int getMonthlyInterval() { return m_monthlyInterval; } /** * @see com.alkacon.opencms.calendar.I_CmsCalendarSerialDateOptions#getSerialType() */ public int getSerialType() { return I_CmsCalendarSerialDateOptions.TYPE_MONTHLY; } /** * Returns the week day used for the serial entry.<p> * * @return the week day used for the serial entry */ public int getWeekDay() { return m_weekDay; } /** * Returns if the week day is used for the serial entry.<p> * * @return true if the week day is used for the serial entry, otherwise false */ public boolean isUseWeekDay() { return m_useWeekDay; } /** * @see com.alkacon.opencms.calendar.I_CmsCalendarSerialDateOptions#matchCalendarView(com.alkacon.opencms.calendar.CmsCalendarEntry, com.alkacon.opencms.calendar.I_CmsCalendarView, int) */ public List matchCalendarView(CmsCalendarEntry entry, I_CmsCalendarView calendarView, int maxCount) { List result = new ArrayList(); int matches = 0; CmsCalendarEntryDateSerial entryDate = (CmsCalendarEntryDateSerial)entry.getEntryDate(); Calendar entryStartDayDate = (Calendar)entry.getEntryDate().getStartDate().clone(); entryStartDayDate.setTimeInMillis(entryDate.getStartDay()); // loop the view date ranges for (int i = 0; i < calendarView.getDates().size(); i++) { // get the current view date object CmsCalendarEntryDate viewDate = (CmsCalendarEntryDate)calendarView.getDates().get(i); // get the start and end times of the view long viewStart = viewDate.getStartDate().getTimeInMillis(); long viewEnd = viewDate.getEndDate().getTimeInMillis(); // set the date for the current run Calendar runDate = entryStartDayDate; if (getMonthlyInterval() == 1 && (entryDate.getSerialEndType() == I_CmsCalendarSerialDateOptions.END_TYPE_NEVER || entryDate.getSerialEndType() == I_CmsCalendarSerialDateOptions.END_TYPE_DATE) && entryStartDayDate.getTimeInMillis() < viewDate.getStartDay()) { // skip to current view start date to optimize performance runDate.setTimeInMillis(viewDate.getStartDay()); } // occurences counter int occurences = 0; while (runDate.before(viewDate.getEndDate())) { // check conditions to leave date series loop if (checkLeaveLoop(entryDate, runDate, viewDate, occurences)) { break; } if (matches >= maxCount) { break; } boolean foundWeekDay = false; // determine current day of the week and the number of the day in the current month if (isUseWeekDay() && runDate.get(Calendar.DAY_OF_WEEK) == getWeekDay()) { // now check which week day is currently shown... int number = runDate.get(Calendar.DAY_OF_MONTH) / 7; if (runDate.get(Calendar.DAY_OF_MONTH) % 7 != 0) { number += 1; } if (number == getDayOfMonth()) { // we are on the matching week day of the month foundWeekDay = true; } } if ((!isUseWeekDay() && runDate.get(Calendar.DAY_OF_MONTH) == getDayOfMonth()) || foundWeekDay) { // the current day contains a series entry occurences++; long entryStart = runDate.getTimeInMillis() + entryDate.getStartTime(); // check if current entry is in view range if (entryStart >= viewStart && entryStart <= viewEnd) { // the entry is in the view time range, clone the entry CmsCalendarEntry cloneEntry = (CmsCalendarEntry)entry.clone(); cloneEntry.getEntryDate().setStartDay(runDate.getTimeInMillis()); cloneEntry = checkChanges(cloneEntry); if (cloneEntry != null) { // add the cloned entry to the result list result.add(cloneEntry); matches += 1; } } } // increase run date with one month for next test depending on options if (isUseWeekDay()) { // week day is specified, roll the run date accordingly if (!foundWeekDay) { // correct week day not found yet, roll to it while (runDate.get(Calendar.DAY_OF_WEEK) != getWeekDay()) { runDate.add(Calendar.DAY_OF_MONTH, 1); } // calculate the number of the week day in the current month int number = runDate.get(Calendar.DAY_OF_MONTH) / 7; if (runDate.get(Calendar.DAY_OF_MONTH) % 7 != 0) { number += 1; } if (number > getDayOfMonth()) { // we are already past the specified date runDate.add(Calendar.DAY_OF_MONTH, -(runDate.get(Calendar.DAY_OF_MONTH) - 1)); runDate.add(Calendar.MONTH, getMonthlyInterval() - 1); } else { // try to go to the specified week day int oldMonth = runDate.get(Calendar.MONTH); for (int k = 0; k < (getDayOfMonth() - number); k++) { runDate.add(Calendar.WEEK_OF_YEAR, 1); if (runDate.get(Calendar.MONTH) != oldMonth) { // we have come to the next month, set day to the first day of the next month to check and leave loop runDate.add(Calendar.DAY_OF_MONTH, -(runDate.get(Calendar.DAY_OF_MONTH) - 1)); runDate.add(Calendar.MONTH, getMonthlyInterval() - 1); break; } } } } else { // found week day, go to the first day of the next month to check runDate.add(Calendar.DAY_OF_MONTH, -(runDate.get(Calendar.DAY_OF_MONTH) - 1)); runDate.add(Calendar.MONTH, getMonthlyInterval()); } } else { // only the number of the day of the month is specified if (runDate.getActualMaximum(Calendar.DAY_OF_MONTH) < getDayOfMonth()) { runDate.add(Calendar.MONTH, getMonthlyInterval()); } else { if (runDate.get(Calendar.DAY_OF_MONTH) < getDayOfMonth()) { // go forward to the specified day of the month runDate.add(Calendar.DAY_OF_MONTH, (getDayOfMonth() - runDate.get(Calendar.DAY_OF_MONTH))); } else { // we are exactly at the specified day or beyond it, skip months if (runDate.get(Calendar.DAY_OF_MONTH) > getDayOfMonth()) { runDate.set(Calendar.DAY_OF_MONTH, getDayOfMonth()); } runDate.add(Calendar.MONTH, getMonthlyInterval()); } } } } } return result; } /** * Sets the day of month for the serial entry.<p> * * @param dayOfMonth the day of month for the serial entry */ public void setDayOfMonth(int dayOfMonth) { m_dayOfMonth = dayOfMonth; } /** * Sets the monthly interval for the serial entry.<p> * * @param monthlyInterval the monthly interval for the serial entry */ public void setMonthlyInterval(int monthlyInterval) { m_monthlyInterval = monthlyInterval; } /** * Sets if the week day is used for the serial entry.<p> * * @param useWeekDay true if the week day is used for the serial entry, otherwise false */ public void setUseWeekDay(boolean useWeekDay) { m_useWeekDay = useWeekDay; } /** * Sets the week day used for the serial entry.<p> * * @param weekDay the week day used for the serial entry */ public void setWeekDay(int weekDay) { m_weekDay = weekDay; } }