/*
* File : $Source: /alkacon/cvs/alkacon/com.alkacon.opencms.v8.calendar/src/com/alkacon/opencms/v8/calendar/CmsCalendarSerialDateYearlyOptions.java,v $
* Date : $Date: 2009/02/05 09:49:31 $
* Version: $Revision: 1.2 $
*
* 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.v8.calendar;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Options for a yearly serial calendar entry.<p>
*
* Provides the necessary information about a yearly serial calendar entry.<p>
*
* @author Andreas Zahner
*
* @version $Revision: 1.2 $
*
* @since 6.0.1
*/
public class CmsCalendarSerialDateYearlyOptions extends A_CmsCalendarSerialDateOptions {
/** The number of the day of the month for the serial calendar entry. */
private int m_dayOfMonth;
/** The monthfor the serial calendar entry. */
private int m_month;
/** 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 yearly interval options.<p>
*
* Standard interval options are: the first day of January.<p>
*/
public CmsCalendarSerialDateYearlyOptions() {
m_dayOfMonth = 1;
m_weekDay = -1;
m_month = 0;
m_useWeekDay = false;
}
/**
* Creates an initialized serial date yearly options object with the given parameters.<p>
*
* @param dayOfMonth the number of the day of the month for the yearly series
* @param weekDay the week day for the yearly series, if less than 1 or more than 7 the week day is not used
* @param month the month for the yearly series
*/
public CmsCalendarSerialDateYearlyOptions(int dayOfMonth, int weekDay, int month) {
m_dayOfMonth = dayOfMonth;
m_weekDay = weekDay;
if ((weekDay < Calendar.SUNDAY) || (weekDay > Calendar.SATURDAY)) {
m_useWeekDay = false;
} else {
m_useWeekDay = true;
}
m_month = 0;
if ((month > -1) && (month < 12)) {
m_month = month;
}
}
/**
* @see com.alkacon.opencms.v8.calendar.I_CmsCalendarSerialDateOptions#getConfigurationValuesAsMap()
*/
public Map getConfigurationValuesAsMap() {
// create the Map containing the date settings
Map values = new HashMap();
// put day of month, week days and month to Map
values.put(I_CmsCalendarSerialDateOptions.CONFIG_DAY_OF_MONTH, String.valueOf(getDayOfMonth()));
values.put(I_CmsCalendarSerialDateOptions.CONFIG_WEEKDAYS, String.valueOf(getWeekDay()));
values.put(I_CmsCalendarSerialDateOptions.CONFIG_MONTH, String.valueOf(getMonth()));
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 month for the serial entry.<p>
*
* @return the month for the serial entry
*/
public int getMonth() {
return m_month;
}
/**
* @see com.alkacon.opencms.v8.calendar.I_CmsCalendarSerialDateOptions#getSerialType()
*/
public int getSerialType() {
return I_CmsCalendarSerialDateOptions.TYPE_YEARLY;
}
/**
* 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.v8.calendar.I_CmsCalendarSerialDateOptions#matchCalendarView(com.alkacon.opencms.v8.calendar.CmsCalendarEntry, com.alkacon.opencms.v8.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 (((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.MONTH) == getMonth())
&& (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()) && (runDate.get(Calendar.MONTH) == getMonth()))
|| 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 month is not found yet
if (runDate.get(Calendar.MONTH) < getMonth()) {
runDate.set(Calendar.MONTH, getMonth());
runDate.add(Calendar.DAY_OF_MONTH, -(runDate.get(Calendar.DAY_OF_MONTH) - 1));
} else if (runDate.get(Calendar.MONTH) > getMonth()) {
runDate.set(Calendar.MONTH, getMonth());
runDate.add(Calendar.DAY_OF_MONTH, -(runDate.get(Calendar.DAY_OF_MONTH) - 1));
runDate.add(Calendar.YEAR, 1);
}
// 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.YEAR, 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 previous month to check next year and leave loop
runDate.add(Calendar.DAY_OF_MONTH, -(runDate.get(Calendar.DAY_OF_MONTH) - 1));
runDate.add(Calendar.MONTH, -1);
runDate.add(Calendar.YEAR, 1);
break;
}
}
}
} else {
// found week day, set month day to first day of the month and go to the next year
runDate.add(Calendar.DAY_OF_MONTH, -(runDate.get(Calendar.DAY_OF_MONTH) - 1));
runDate.add(Calendar.YEAR, 1);
}
} else {
// only the number of the day of the month is specified
if (runDate.get(Calendar.MONTH) < getMonth()) {
// we are before the month, go forward to it and set the correct day
runDate.add(Calendar.MONTH, getMonth() - runDate.get(Calendar.MONTH));
} else {
// we are at specified month or beyond it, go to next year
runDate.add(Calendar.YEAR, 1);
runDate.set(Calendar.MONTH, getMonth());
}
if (runDate.get(Calendar.DAY_OF_MONTH) != getDayOfMonth()) {
runDate.set(Calendar.DAY_OF_MONTH, getDayOfMonth());
}
}
}
}
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 month for the serial entry.<p>
*
* @param month the month for the serial entry
*/
public void setMonthlyInterval(int month) {
m_month = month;
}
/**
* 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;
}
}