package org.obe.engine.calendar;
import java.util.BitSet;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
public class MonthRule extends CalendarRule {
// private static final long serialVersionUID = 4565221466107361462L;
/**
* The month to which this rule applies.
*/
private int _month;
/**
* Specifies a particular occurrence of a day-of-the-week.
*/
private Ordinal _ordinal;
/**
* The day-of-the-month or day-of-the-week to which this rule applies.
*/
private int _day;
/**
* If this and day are both set, the rule applies to every occurrence of the
* specified day-of-the-week in that month.
*/
private boolean _every;
public MonthRule() {
}
public MonthRule(int month, int day, Ordinal ordinal) {
_month = month;
_ordinal = ordinal;
_day = day;
}
public MonthRule(int month, int day, boolean every) {
_month = month;
_day = day;
_every = every;
}
public int getMonth() {
return _month;
}
public Ordinal getOrdinal() {
return _ordinal;
}
public int getDay() {
return _day;
}
public boolean isEvery() {
return _every;
}
public void setMonth(int month) {
_month = month;
}
public void setOrdinal(Ordinal ordinal) {
_ordinal = ordinal;
}
public void setDay(int day) {
_day = day;
}
public void setEvery(boolean every) {
_every = every;
}
/**
* Month is a bit trickier than the rest. It is such a long object that it
* can be both in and out of a BusinessCalendar. The code here may seem
* excessive, but it has to be to handle this case.
*
* @param mask
* @param length
* @param startDate
* @param endDate
* @param tz
*/
public void applyRule(BitSet mask, int length, GregorianCalendar startDate,
GregorianCalendar endDate, TimeZone tz) {
GregorianCalendar calendar = (GregorianCalendar)startDate.clone();
calendar.set(Calendar.MONTH, _month);
calendar.set(Calendar.DAY_OF_MONTH, 1);
while (calendar.get(Calendar.MONTH) != _month)
calendar.add(Calendar.MONTH, 1);
// Set the calendar to the start of the day.
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
// The month is after the end of the BC
// TODO: SHOULD THIS THROW AN EXCEPTION?
if (calendar.after(endDate)) {
if (_LOGGER.isDebugEnabled())
_LOGGER.debug("Out of scope");
return;
}
if (_ordinal == null && !_every) {
// This is the entire month rule
int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
int startIndex = BusinessCalendarUtilities.getIntervalIndex(
startDate.getTime(), calendar.getTime(), tz);
int ruleLength = BusinessCalendarUtilities
.getIntervalsInDate(calendar);
if (_LOGGER.isDebugEnabled()) {
_LOGGER.debug("applyRule(" + "StartIndex: " + startIndex +
", RuleLength: " + ruleLength + ", MaxDays:" +
calendar.getActualMaximum(Calendar.DAY_OF_MONTH) +
", Month: " + calendar.get(Calendar.MONTH) + ')');
}
for (int i = 0; i < daysInMonth; i++) {
BusinessCalendarUtilities
.setBitSetBits(mask, startIndex, ruleLength);
calendar.add(Calendar.DATE, 1);
ruleLength = BusinessCalendarUtilities
.getIntervalsInDate(calendar);
startIndex = BusinessCalendarUtilities.getIntervalIndex(
startDate.getTime(), calendar.getTime(), tz);
}
} else if (_ordinal != null && !_every) {
// This is a rule like 'third Monday of May'
while (calendar.get(Calendar.DAY_OF_WEEK) != _day)
calendar.add(Calendar.DATE, 1);
// Now add the number of weeks to bring it up to the ordinal value
calendar.add(Calendar.DATE, _ordinal.value() * 7);
int ruleLength = BusinessCalendarUtilities.getIntervalsInDate(
calendar);
int startIndex = BusinessCalendarUtilities.getIntervalIndex(
startDate.getTime(), calendar.getTime(), tz);
BusinessCalendarUtilities
.setBitSetBits(mask, startIndex, ruleLength);
} else if (_every) {
// This is a rule like 'every Monday of May'
while (calendar.get(Calendar.DAY_OF_WEEK) != _day)
calendar.add(Calendar.DATE, 1);
while (calendar.get(Calendar.MONTH) == _month) {
int ruleLength = BusinessCalendarUtilities
.getIntervalsInDate(calendar);
int startIndex = BusinessCalendarUtilities.getIntervalIndex(
startDate.getTime(), calendar.getTime(), tz);
if (_LOGGER.isDebugEnabled()) {
_LOGGER.debug("EveryRule - ruleLength: " + ruleLength +
", startIndex: " + startIndex + ", date: " +
calendar.getTime());
}
BusinessCalendarUtilities.setBitSetBits(mask, startIndex,
ruleLength);
// Add a week.
calendar.add(Calendar.DATE, 7);
}
}
}
public String toString() {
return "MonthRule[" +
"_month=" + _month +
", _ordinal='" + _ordinal + '\'' +
", _day=" + _day +
", _every=" + _every +
']';
}
}
|