RepeatRulepublic class RepeatRule extends Object This class is defined by the JSR-75 specification
PDA Optional Packages for the J2ME™ Platform |
Fields Summary |
---|
private Hashtable | fieldsFields in the rule. | private Vector | exceptionsExceptions caused by the rule. | public static final int | FREQUENCY | public static final int | DAY_IN_MONTH | public static final int | DAY_IN_WEEK | public static final int | DAY_IN_YEAR | public static final int | MONTH_IN_YEAR | public static final int | WEEK_IN_MONTH | public static final int | COUNT | public static final int | END | public static final int | INTERVAL | public static final int | DAILY | public static final int | WEEKLY | public static final int | MONTHLY | public static final int | YEARLY | public static final int | FIRST | public static final int | SECOND | public static final int | THIRD | public static final int | FOURTH | public static final int | FIFTH | public static final int | LAST | public static final int | SECONDLAST | public static final int | THIRDLAST | public static final int | FOURTHLAST | public static final int | FIFTHLAST | public static final int | SATURDAY | public static final int | FRIDAY | public static final int | THURSDAY | public static final int | WEDNESDAY | public static final int | TUESDAY | public static final int | MONDAY | public static final int | SUNDAY | public static final int | JANUARY | public static final int | FEBRUARY | public static final int | MARCH | public static final int | APRIL | public static final int | MAY | public static final int | JUNE | public static final int | JULY | public static final int | AUGUST | public static final int | SEPTEMBER | public static final int | OCTOBER | public static final int | NOVEMBER | public static final int | DECEMBER | private static final int[] | MONTHSMonths of the year. | private static final long | DAY_INCREMENTDAY_INCREMENT = 86400000l. | private static final long | DAY_IN_WEEK_MASKDAY_IN_WEEK_MASK = 0x1fc00l. | private static final long | WEEK_IN_MONTH_MASKWEEK_IN_MONTH_MASK = 0x3ffl. | private static final long | MONTH_IN_YEAR_MASKMONTH_IN_YEAR_MASK = 0x1ffe0000. | private static final int[] | DAYSDays of the week. | private static final long | DAY_LENGTHDAY_LENGTH = 86400000L. | private static final Object | NO_DEFAULTNO_DEFAULT = "". |
Constructors Summary |
---|
public RepeatRule()
// JAVADOC COMMENT ELIDED
|
Methods Summary |
---|
public void | addExceptDate(long date)
exceptions.addElement(new Date(date));
| public java.util.Enumeration | dates(long startDate, long subsetBeginning, long subsetEnding)
// JAVADOC COMMENT ELIDED
if (subsetBeginning > subsetEnding) {
throw new IllegalArgumentException("Bad range: "
+ subsetBeginning + "("
+ PIMHandler.getInstance().composeDateTime(subsetBeginning)
+ ") to " + subsetEnding + "("
+ PIMHandler.getInstance().composeDateTime(subsetEnding));
}
Calendar calendar = Calendar.getInstance();
Date dateObj = new Date(startDate);
calendar.setTime(dateObj);
Vector dates = new Vector();
long date = startDate;
Integer frequency = (Integer) getField(FREQUENCY, null);
int interval = ((Integer) getField(INTERVAL,
new Integer(1))).intValue();
int count = ((Integer)
getField(COUNT,
new Integer(Integer.MAX_VALUE))).intValue();
long end = ((Long) getField(END, new Long(Long.MAX_VALUE))).longValue();
Integer dayInWeek = (Integer) getField(DAY_IN_WEEK, null);
Integer dayInMonth = (Integer) getField(DAY_IN_MONTH, null);
Integer dayInYear = (Integer) getField(DAY_IN_YEAR, null);
Integer weekInMonth = (Integer) getField(WEEK_IN_MONTH, null);
Integer monthInYear = (Integer) getField(MONTH_IN_YEAR, null);
// set defaults, based on starting date
if (dayInMonth == null && weekInMonth == null) {
dayInMonth = new Integer(calendar.get(Calendar.DAY_OF_MONTH));
}
if (dayInWeek == null) {
switch (calendar.get(Calendar.DAY_OF_WEEK)) {
case Calendar.SUNDAY:
dayInWeek = new Integer(SUNDAY);
break;
case Calendar.MONDAY:
dayInWeek = new Integer(MONDAY);
break;
case Calendar.TUESDAY:
dayInWeek = new Integer(TUESDAY);
break;
case Calendar.WEDNESDAY:
dayInWeek = new Integer(WEDNESDAY);
break;
case Calendar.THURSDAY:
dayInWeek = new Integer(THURSDAY);
break;
case Calendar.FRIDAY:
dayInWeek = new Integer(FRIDAY);
break;
case Calendar.SATURDAY:
dayInWeek = new Integer(SATURDAY);
break;
}
}
long rangeStart = Math.max(subsetBeginning, startDate);
long rangeEnd = Math.min(subsetEnding, end);
for (int i = 0; date <= subsetEnding && date <= end && i < count; i++) {
if (frequency == null) {
// no repetitions
storeDate(dates, startDate, rangeStart, rangeEnd);
break;
}
switch (frequency.intValue()) {
case DAILY:
storeDate(dates, date, rangeStart, rangeEnd);
date += DAY_INCREMENT * interval;
dateObj.setTime(date);
calendar.setTime(dateObj);
break;
case WEEKLY:
if (dayInWeek == null) {
storeDate(dates, date, rangeStart, rangeEnd);
} else {
// shift date to the beginning of the week
date -= DAY_INCREMENT *
(calendar.get(Calendar.DAY_OF_WEEK) -
Calendar.SUNDAY);
dateObj.setTime(date);
calendar.setTime(dateObj);
storeDays(dates, date, rangeStart, rangeEnd,
dayInWeek.intValue());
}
// increment the week
date += DAY_INCREMENT * 7;
dateObj.setTime(date);
calendar.setTime(dateObj);
break;
case MONTHLY: {
storeDaysByMonth(dates, date, rangeStart, rangeEnd,
dayInWeek, dayInMonth, weekInMonth);
// increment the month
int currentMonth = calendar.get(Calendar.MONTH);
if (currentMonth == Calendar.DECEMBER) {
int currentYear = calendar.get(Calendar.YEAR);
calendar.set(Calendar.YEAR, currentYear + 1);
calendar.set(Calendar.MONTH, Calendar.JANUARY);
} else {
calendar.set(Calendar.MONTH, currentMonth + 1);
}
dateObj = calendar.getTime();
date = dateObj.getTime();
break;
}
case YEARLY: {
if (monthInYear == null && dayInYear == null) {
storeDate(dates, date, rangeStart, rangeEnd);
} else {
// shift to January
calendar.set(Calendar.MONTH, Calendar.JANUARY);
dateObj = calendar.getTime();
date = dateObj.getTime();
if (monthInYear != null) {
int months = monthInYear.intValue();
for (int m = 0; m < MONTHS.length; m++) {
if ((months & MONTHS[m]) != 0) {
calendar.set(Calendar.MONTH, m);
storeDaysByMonth(dates,
calendar.getTime().getTime(),
rangeStart, rangeEnd,
dayInWeek, dayInMonth, weekInMonth);
}
}
} else {
// dayInYear is non-null
// shift to the first of January
calendar.set(Calendar.DAY_OF_MONTH, 1);
dateObj = calendar.getTime();
date = dateObj.getTime();
storeDate(dates,
date + (dayInYear.intValue() - 1)
* DAY_INCREMENT,
rangeStart,
rangeEnd);
}
}
// increment the year
calendar.set(Calendar.YEAR,
calendar.get(Calendar.YEAR) + 1);
dateObj = calendar.getTime();
date = dateObj.getTime();
break;
}
default:
throw new IllegalArgumentException(
"Unrecognized value for frequency: " + frequency);
} // end switch
} // end for
return dates.elements();
| public boolean | equals(java.lang.Object obj)
if (obj == null || !(obj instanceof RepeatRule)) {
return false;
}
RepeatRule rule = (RepeatRule) obj;
Calendar cal = Calendar.getInstance();
int[] ruleFields = rule.getFields();
for (int i = 0; i < ruleFields.length; i++) {
int field = ruleFields[i];
Object value = fields.get(new Integer(field));
if (value == null) {
// field in other rule is defined, but in this rule is not
return false;
}
switch (getDataType(field)) {
case PIMItem.INT: {
int iValue = ((Integer) value).intValue();
if (rule.getInt(field) != iValue) {
return false;
}
break;
}
case PIMItem.DATE: {
// dates match if they are on the same day
long thisDate = ((Long) value).longValue();
long ruleDate = rule.getDate(field);
if (thisDate == ruleDate) {
return true;
}
if (Math.abs(thisDate - ruleDate) >= DAY_LENGTH) {
return false;
}
cal.setTime(new Date(thisDate));
int day = cal.get(Calendar.DATE);
cal.setTime(new Date(ruleDate));
if (day != cal.get(Calendar.DATE)) {
return false;
}
break;
}
default:
return false; // unreachable
}
}
// see if this rule defines any fields that the other rule does not
for (Enumeration e = fields.keys(); e.hasMoreElements(); ) {
Integer fieldKey = (Integer) e.nextElement();
int field = fieldKey.intValue();
boolean match = false;
for (int i = 0; i < ruleFields.length && !match; i++) {
if (ruleFields[i] == field) {
match = true;
}
}
if (!match) {
return false;
}
}
// check exception dates
// normalize the list of exception dates to represent only the date
// and not the time of day
int[] exceptionDates = new int[exceptions.size()];
for (int i = 0; i < exceptionDates.length; i++) {
Date date = (Date) exceptions.elementAt(i);
cal.setTime(date);
exceptionDates[i] = cal.get(Calendar.DAY_OF_MONTH)
+ 100 * cal.get(Calendar.MONTH)
+ 10000 * cal.get(Calendar.YEAR);
}
boolean[] matchedExceptionDates = new boolean[exceptionDates.length];
for (Enumeration e = rule.getExceptDates(); e.hasMoreElements(); ) {
Date date = (Date) e.nextElement();
cal.setTime(date);
int day = cal.get(Calendar.DAY_OF_MONTH)
+ 100 * cal.get(Calendar.MONTH)
+ 10000 * cal.get(Calendar.YEAR);
boolean match = false;
for (int i = 0; i < exceptionDates.length && !match; i++) {
if (exceptionDates[i] == day) {
match = true;
matchedExceptionDates[i] = true;
}
}
if (!match) {
return false;
}
}
// are there unmatched exception dates?
for (int i = 0; i < matchedExceptionDates.length; i++) {
if (!matchedExceptionDates[i]) {
// make sure this isn't a duplicate of another date
boolean duplicate = false;
for (int j = 0; j < i && !duplicate; j++) {
duplicate = exceptionDates[j] == exceptionDates[i];
}
if (!duplicate) {
return false;
}
}
}
return true;
| private int | getDataType(int field)Gets the data type for the requested field.
switch (field) {
case COUNT:
case DAY_IN_MONTH:
case DAY_IN_WEEK:
case DAY_IN_YEAR:
case FREQUENCY:
case INTERVAL:
case MONTH_IN_YEAR:
case WEEK_IN_MONTH:
return PIMItem.INT;
case END:
return PIMItem.DATE;
default:
throw new IllegalArgumentException("Unrecognized field: "
+ field);
}
| public long | getDate(int field)
validateDataType(field, PIMItem.DATE);
return ((Long) getField(field, NO_DEFAULT)).longValue();
| public java.util.Enumeration | getExceptDates()
Vector results = new Vector();
for (Enumeration e = exceptions.elements();
e.hasMoreElements(); ) {
Date date = (Date) e.nextElement();
results.addElement(new Date(date.getTime()));
}
return results.elements();
| private java.lang.Object | getField(int field, java.lang.Object defaultValue)Gets the requested field contents.
Integer fieldKey = new Integer(field);
Object fieldValue = fields.get(fieldKey);
if (fieldValue == null) {
if (defaultValue == NO_DEFAULT) {
throw new FieldEmptyException();
} else {
return defaultValue;
}
}
return fieldValue;
| public int[] | getFields()
int[] result = new int[fields.size()];
int i = 0;
for (Enumeration e = fields.keys(); e.hasMoreElements(); ) {
Integer fieldKey = (Integer) e.nextElement();
result[i++] = fieldKey.intValue();
}
return result;
| public int | getInt(int field)
validateDataType(field, PIMItem.INT);
return ((Integer) getField(field, NO_DEFAULT)).intValue();
| public void | removeExceptDate(long date)
exceptions.removeElement(new Date(date));
| public void | setDate(int field, long value)
validateDataType(field, PIMItem.DATE);
Integer fieldKey = new Integer(field);
fields.put(fieldKey, new Long(value));
| public void | setInt(int field, int value)
validateDataType(field, PIMItem.INT);
boolean isValid;
switch (field) {
case COUNT:
isValid = (value >= 1);
break;
case DAY_IN_MONTH:
isValid = (value >= 1 && value <= 31);
break;
case DAY_IN_WEEK:
isValid = (value & ~DAY_IN_WEEK_MASK) == 0;
break;
case FREQUENCY:
switch (value) {
case DAILY:
case WEEKLY:
case MONTHLY:
case YEARLY:
isValid = true;
break;
default:
isValid = false;
}
break;
case INTERVAL:
isValid = (value >= 1);
break;
case MONTH_IN_YEAR:
isValid = (value & ~MONTH_IN_YEAR_MASK) == 0;
break;
case WEEK_IN_MONTH:
isValid = (value & ~WEEK_IN_MONTH_MASK) == 0;
break;
case DAY_IN_YEAR:
isValid = (value >= 1 && value <= 366);
break;
default:
isValid = false;
}
if (!isValid) {
throw new IllegalArgumentException("Field value is invalid");
}
Integer fieldKey = new Integer(field);
fields.put(fieldKey, new Integer(value));
| private void | storeDate(java.util.Vector dates, long date, long rangeStart, long rangeEnd)Stores a date.
if (date >= rangeStart && date <= rangeEnd) {
Date dateObj = new Date(date);
if (!exceptions.contains(dateObj)) {
dates.addElement(new Date(date));
}
}
| private void | storeDays(java.util.Vector dates, long date, long rangeStart, long rangeEnd, int days)Store days.
// shift date back to Sunday, if it is not already Sunday
Calendar cal = Calendar.getInstance();
cal.setTime(new Date(date));
int dayShift = cal.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
date -= dayShift * DAY_INCREMENT;
long dateNextWeek = dayShift + DAY_INCREMENT * 7;
for (int i = 0; i < DAYS.length; i++) {
if ((days & DAYS[i]) != 0) {
long targetDate = (dayShift > i) ? dateNextWeek : date;
storeDate(dates,
targetDate + DAY_INCREMENT * i,
rangeStart, rangeEnd);
}
}
| private void | storeDaysByMonth(java.util.Vector dates, long date, long rangeStart, long rangeEnd, java.lang.Integer dayInWeek, java.lang.Integer dayInMonth, java.lang.Integer weekInMonth)Store days by month.
// move date to the first of the month
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date(date));
date -= DAY_INCREMENT *
(calendar.get(Calendar.DAY_OF_MONTH) - 1);
if (dayInMonth != null) {
storeDate(dates,
date + DAY_INCREMENT * (dayInMonth.intValue() - 1),
rangeStart, rangeEnd);
} else if (weekInMonth != null) {
// get a limited range, containing only this month.
long monthRangeStart = Math.max(rangeStart, date);
// find the end of the month, assuming no month is longer
// than 31 days
long monthEnd = date + DAY_INCREMENT * 31;
calendar.setTime(new Date(monthEnd));
while (calendar.get(Calendar.DAY_OF_MONTH) > 1) {
monthEnd -= DAY_INCREMENT;
calendar.setTime(new Date(monthEnd));
}
monthEnd -= DAY_INCREMENT;
long monthRangeEnd = Math.min(rangeEnd, monthEnd);
int weeks = weekInMonth.intValue();
if ((weeks & FIRST) != 0) {
storeDays(dates, date,
monthRangeStart, monthRangeEnd,
dayInWeek.intValue());
}
if ((weeks & SECOND) != 0) {
storeDays(dates, date + DAY_INCREMENT * 7,
monthRangeStart, monthRangeEnd,
dayInWeek.intValue());
}
if ((weeks & THIRD) != 0) {
storeDays(dates, date + DAY_INCREMENT * 14,
monthRangeStart, monthRangeEnd,
dayInWeek.intValue());
}
if ((weeks & FOURTH) != 0) {
storeDays(dates, date + DAY_INCREMENT * 21,
monthRangeStart, monthRangeEnd,
dayInWeek.intValue());
}
if ((weeks & FIFTH) != 0) {
storeDays(dates, date + DAY_INCREMENT * 28,
monthRangeStart, monthRangeEnd,
dayInWeek.intValue());
}
if ((weeks & LAST) != 0) {
storeDays(dates, monthEnd - DAY_INCREMENT * 6,
monthRangeStart, monthRangeEnd,
dayInWeek.intValue());
}
if ((weeks & LAST) != 0) {
storeDays(dates, monthEnd - DAY_INCREMENT * 6,
monthRangeStart, monthRangeEnd,
dayInWeek.intValue());
}
if ((weeks & SECONDLAST) != 0) {
storeDays(dates, monthEnd - DAY_INCREMENT * 13,
monthRangeStart, monthRangeEnd,
dayInWeek.intValue());
}
if ((weeks & THIRDLAST) != 0) {
storeDays(dates, monthEnd - DAY_INCREMENT * 20,
monthRangeStart, monthRangeEnd,
dayInWeek.intValue());
}
if ((weeks & FOURTHLAST) != 0) {
storeDays(dates, monthEnd - DAY_INCREMENT * 27,
monthRangeStart, monthRangeEnd,
dayInWeek.intValue());
}
if ((weeks & FIFTHLAST) != 0) {
storeDays(dates, monthEnd - DAY_INCREMENT * 34,
monthRangeStart, monthRangeEnd,
dayInWeek.intValue());
}
}
| private void | validateDataType(int field, int dataType)Checks that data type is valid.
int correctDataType = getDataType(field);
if (dataType != correctDataType) {
throw new IllegalArgumentException("Invalid field type");
}
|
|