package com.lsz.rpg.util;
import java.io.Serializable;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
/**
*
* @author caosi
*
*/
public class CronExpression implements Serializable, Cloneable {
private static final long serialVersionUID = 12423409423L;
private static final int SECOND = 0;
private static final int MINUTE = 1;
private static final int HOUR = 2;
private static final int DAY_OF_MONTH = 3;
private static final int MONTH = 4;
private static final int DAY_OF_WEEK = 5;
private static final int YEAR = 6;
public static final int ALL_SPEC_INT = 99; // '*'
public static final int NO_SPEC_INT = 98; // '?'
public static final Integer ALL_SPEC = new Integer(ALL_SPEC_INT);
public static final Integer NO_SPEC = new Integer(NO_SPEC_INT);
private static final Map<String,Integer> monthMap = new HashMap<String,Integer>(20);
private static final Map<String,Integer> dayMap = new HashMap<String,Integer>(60);
static {
monthMap.put("JAN", new Integer(0));
monthMap.put("FEB", new Integer(1));
monthMap.put("MAR", new Integer(2));
monthMap.put("APR", new Integer(3));
monthMap.put("MAY", new Integer(4));
monthMap.put("JUN", new Integer(5));
monthMap.put("JUL", new Integer(6));
monthMap.put("AUG", new Integer(7));
monthMap.put("SEP", new Integer(8));
monthMap.put("OCT", new Integer(9));
monthMap.put("NOV", new Integer(10));
monthMap.put("DEC", new Integer(11));
dayMap.put("SUN", new Integer(1));
dayMap.put("MON", new Integer(2));
dayMap.put("TUE", new Integer(3));
dayMap.put("WED", new Integer(4));
dayMap.put("THU", new Integer(5));
dayMap.put("FRI", new Integer(6));
dayMap.put("SAT", new Integer(7));
}
private String cronExpression = null;
private transient TreeSet<Integer> seconds;
private transient TreeSet<Integer> minutes;
private transient TreeSet<Integer> hours;
private transient TreeSet<Integer> daysOfMonth;
private transient TreeSet<Integer> months;
private transient TreeSet<Integer> daysOfWeek;
private transient TreeSet<Integer> years;
private transient boolean lastdayOfWeek = false;
private transient int nthdayOfWeek = 0;
private transient boolean lastdayOfMonth = false;
private transient boolean nearestWeekday = false;
public String getCronExpression() {
return cronExpression;
}
public TreeSet<Integer> getSeconds() {
return seconds;
}
public TreeSet<Integer> getMinutes() {
return minutes;
}
public TreeSet<Integer> getHours() {
return hours;
}
public TreeSet<Integer> getDaysOfMonth() {
return daysOfMonth;
}
public TreeSet<Integer> getMonths() {
return months;
}
public TreeSet<Integer> getDaysOfWeek() {
return daysOfWeek;
}
public TreeSet<Integer> getYears() {
return years;
}
public CronExpression(String cronExpression) throws ParseException {
if (cronExpression == null) {
throw new IllegalArgumentException("cronExpression cannot be null");
}
this.cronExpression = cronExpression.toUpperCase(Locale.US);
buildExpression(this.cronExpression);
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("CronExpression:");
buf.append(cronExpression);
buf.append("\n");
buf.append("seconds: ");
buf.append(getExpressionSetSummary(seconds));
buf.append("\n");
buf.append("minutes: ");
buf.append(getExpressionSetSummary(minutes));
buf.append("\n");
buf.append("hours: ");
buf.append(getExpressionSetSummary(hours));
buf.append("\n");
buf.append("daysOfMonth: ");
buf.append(getExpressionSetSummary(daysOfMonth));
buf.append("\n");
buf.append("months: ");
buf.append(getExpressionSetSummary(months));
buf.append("\n");
buf.append("daysOfWeek: ");
buf.append(getExpressionSetSummary(daysOfWeek));
buf.append("\n");
buf.append("lastdayOfWeek: ");
buf.append(lastdayOfWeek);
buf.append("\n");
buf.append("nearestWeekday: ");
buf.append(nearestWeekday);
buf.append("\n");
buf.append("NthDayOfWeek: ");
buf.append(nthdayOfWeek);
buf.append("\n");
buf.append("lastdayOfMonth: ");
buf.append(lastdayOfMonth);
buf.append("\n");
buf.append("years: ");
buf.append(getExpressionSetSummary(years));
buf.append("\n");
return buf.toString();
}
private void buildExpression(String expression) throws ParseException {
try {
if (seconds == null) {
seconds = new TreeSet<Integer>();
}
if (minutes == null) {
minutes = new TreeSet<Integer>();
}
if (hours == null) {
hours = new TreeSet<Integer>();
}
if (daysOfMonth == null) {
daysOfMonth = new TreeSet<Integer>();
}
if (months == null) {
months = new TreeSet<Integer>();
}
if (daysOfWeek == null) {
daysOfWeek = new TreeSet<Integer>();
}
if (years == null) {
years = new TreeSet<Integer>();
}
int exprOn = SECOND;
StringTokenizer exprsTok = new StringTokenizer(expression, " \t",
false);
while (exprsTok.hasMoreTokens() && exprOn <= YEAR) {
String expr = exprsTok.nextToken().trim();
// throw an exception if L is used with other days of the month
if(exprOn == DAY_OF_MONTH && expr.indexOf('L') != -1 && expr.length() > 1 && expr.indexOf(",") >= 0) {
throw new ParseException("Support for specifying 'L' and 'LW' with other days of the month is not implemented", -1);
}
// throw an exception if L is used with other days of the week
if(exprOn == DAY_OF_WEEK && expr.indexOf('L') != -1 && expr.length() > 1 && expr.indexOf(",") >= 0) {
throw new ParseException("Support for specifying 'L' with other days of the week is not implemented", -1);
}
StringTokenizer vTok = new StringTokenizer(expr, ",");
while (vTok.hasMoreTokens()) {
String v = vTok.nextToken();
storeExpressionVals(0, v, exprOn);
}
exprOn++;
}
if (exprOn <= DAY_OF_WEEK) {
throw new ParseException("Unexpected end of expression.",
expression.length());
}
if (exprOn <= YEAR) {
storeExpressionVals(0, "*", YEAR);
}
TreeSet<Integer> dow = getSet(DAY_OF_WEEK);
TreeSet<Integer> dom = getSet(DAY_OF_MONTH);
// Copying the logic from the UnsupportedOperationException below
boolean dayOfMSpec = !dom.contains(NO_SPEC);
boolean dayOfWSpec = !dow.contains(NO_SPEC);
if (dayOfMSpec && !dayOfWSpec) {
// skip
} else if (dayOfWSpec && !dayOfMSpec) {
// skip
} else {
throw new ParseException(
"Support for