001: package org.quartz.impl.calendar;
002:
003: import java.text.ParseException;
004: import java.util.Date;
005: import java.util.TimeZone;
006:
007: import org.quartz.Calendar;
008: import org.quartz.CronExpression;
009:
010: /**
011: * This implementation of the Calendar excludes the set of times expressed by a
012: * given {@link org.quartz.CronExpression CronExpression}. For example, you
013: * could use this calendar to exclude all but business hours (8AM - 5PM) every
014: * day using the expression "* * 0-7,18-23 ? * *".
015: * <P>
016: * It is important to remember that the cron expression here describes a set of
017: * times to be <I>excluded</I> from firing. Whereas the cron expression in
018: * {@link org.quartz.CronTrigger CronTrigger} describes a set of times that can
019: * be <I>included</I> for firing. Thus, if a <CODE>CronTrigger</CODE> has a
020: * given cron expression and is associated with a <CODE>CronCalendar</CODE> with
021: * the <I>same</I> expression, the calendar will exclude all the times the
022: * trigger includes, and they will cancel each other out.
023: *
024: * @author Aaron Craven
025: */
026: public class CronCalendar extends BaseCalendar {
027: static final long serialVersionUID = -8172103999750856831L;
028:
029: /** @deprecated The use of <code>name</code> is no longer supported. */
030: private String name;
031:
032: CronExpression cronExpression;
033:
034: /**
035: * Create a <CODE>CronCalendar</CODE> with the given cron expression and no
036: * <CODE>baseCalendar</CODE>.
037: *
038: * @param expression a String representation of the desired cron expression
039: */
040: public CronCalendar(String expression) throws ParseException {
041: this (null, expression, null);
042: }
043:
044: /**
045: * Create a <CODE>CronCalendar</CODE> with the given cron expression and
046: * <CODE>baseCalendar</CODE>.
047: *
048: * @param baseCalendar the base calendar for this calendar instance –
049: * see {@link BaseCalendar} for more information on base
050: * calendar functionality
051: * @param expression a String representation of the desired cron expression
052: */
053: public CronCalendar(Calendar baseCalendar, String expression)
054: throws ParseException {
055: this (baseCalendar, expression, null);
056: }
057:
058: /**
059: * Create a <CODE>CronCalendar</CODE> with the given cron exprssion,
060: * <CODE>baseCalendar</CODE>, and <code>TimeZone</code>.
061: *
062: * @param baseCalendar the base calendar for this calendar instance –
063: * see {@link BaseCalendar} for more information on base
064: * calendar functionality
065: * @param expression a String representation of the desired cron expression
066: * @param timeZone
067: * Specifies for which time zone the <code>expression</code>
068: * should be interpreted, i.e. the expression 0 0 10 * * ?, is
069: * resolved to 10:00 am in this time zone. If
070: * <code>timeZone</code> is <code>null</code> then
071: * <code>TimeZone.getDefault()</code> will be used.
072: */
073: public CronCalendar(Calendar baseCalendar, String expression,
074: TimeZone timeZone) throws ParseException {
075: super (baseCalendar);
076: this .cronExpression = new CronExpression(expression);
077: this .cronExpression.setTimeZone(timeZone);
078: }
079:
080: /**
081: * @deprecated The use of <code>name</code> is no longer supported.
082: *
083: * @see #CronCalendar(String)
084: */
085: public CronCalendar(String name, String expression)
086: throws ParseException {
087: this (expression);
088: this .name = name;
089: }
090:
091: /**
092: * @deprecated The use of <code>name</code> is no longer supported.
093: *
094: * @see #CronCalendar(Calendar, String)
095: */
096: public CronCalendar(String name, Calendar baseCalendar,
097: String expression) throws ParseException {
098: this (baseCalendar, expression);
099: this .name = name;
100: }
101:
102: /**
103: * @deprecated The use of <code>name</code> is no longer supported.
104: *
105: * @see #CronCalendar(Calendar, String, TimeZone)
106: */
107: public CronCalendar(String name, Calendar baseCalendar,
108: String expression, TimeZone timeZone) throws ParseException {
109: this (baseCalendar, expression, timeZone);
110: this .name = name;
111: }
112:
113: /**
114: * Returns the time zone for which the <code>CronExpression</code> of
115: * this <code>CronCalendar</code> will be resolved.
116: * <p>
117: * Overrides <code>{@link BaseCalendar#getTimeZone()}</code> to
118: * defer to its <code>CronExpression</code>.
119: * </p>
120: */
121: public TimeZone getTimeZone() {
122: return cronExpression.getTimeZone();
123: }
124:
125: /**
126: * Sets the time zone for which the <code>CronExpression</code> of this
127: * <code>CronCalendar</code> will be resolved. If <code>timeZone</code>
128: * is <code>null</code> then <code>TimeZone.getDefault()</code> will be
129: * used.
130: * <p>
131: * Overrides <code>{@link BaseCalendar#setTimeZone(TimeZone)}</code> to
132: * defer to its <code>CronExpression</code>.
133: * </p>
134: */
135: public void setTimeZone(TimeZone timeZone) {
136: cronExpression.setTimeZone(timeZone);
137: }
138:
139: /**
140: * Returns the name of the <CODE>CronCalendar</CODE>
141: *
142: * @return the name of the <CODE>CronCalendar</CODE>
143: *
144: * @deprecated The use of <code>name</code> is no longer supported.
145: */
146: public String getName() {
147: return name;
148: }
149:
150: /**
151: * Determines whether the given time (in milliseconds) is 'included' by the
152: * <CODE>BaseCalendar</CODE>
153: *
154: * @param timeInMillis the date/time to test
155: * @return a boolean indicating whether the specified time is 'included' by
156: * the <CODE>CronCalendar</CODE>
157: */
158: public boolean isTimeIncluded(long timeInMillis) {
159: if ((getBaseCalendar() != null)
160: && (getBaseCalendar().isTimeIncluded(timeInMillis) == false)) {
161: return false;
162: }
163:
164: return (!(cronExpression.isSatisfiedBy(new Date(timeInMillis))));
165: }
166:
167: /**
168: * Determines the next time included by the <CODE>CronCalendar</CODE>
169: * after the specified time.
170: *
171: * @param timeInMillis the initial date/time after which to find an
172: * included time
173: * @return the time in milliseconds representing the next time included
174: * after the specified time.
175: */
176: public long getNextIncludedTime(long timeInMillis) {
177: long nextIncludedTime = timeInMillis + 1; //plus on millisecond
178:
179: while (!isTimeIncluded(nextIncludedTime)) {
180:
181: //If the time is in a range excluded by this calendar, we can
182: // move to the end of the excluded time range and continue testing
183: // from there. Otherwise, if nextIncludedTime is excluded by the
184: // baseCalendar, ask it the next time it includes and begin testing
185: // from there. Failing this, add one millisecond and continue
186: // testing.
187: if (cronExpression
188: .isSatisfiedBy(new Date(nextIncludedTime))) {
189: nextIncludedTime = cronExpression
190: .getNextInvalidTimeAfter(
191: new Date(nextIncludedTime)).getTime();
192: } else if ((getBaseCalendar() != null)
193: && (!getBaseCalendar().isTimeIncluded(
194: nextIncludedTime))) {
195: nextIncludedTime = getBaseCalendar()
196: .getNextIncludedTime(nextIncludedTime);
197: } else {
198: nextIncludedTime++;
199: }
200: }
201:
202: return nextIncludedTime;
203: }
204:
205: /**
206: * Returns a string representing the properties of the
207: * <CODE>CronCalendar</CODE>
208: *
209: * @return the properteis of the CronCalendar in a String format
210: */
211: public String toString() {
212: StringBuffer buffer = new StringBuffer();
213: if (name != null) {
214: buffer.append(name).append(": ");
215: }
216: buffer.append("base calendar: [");
217: if (getBaseCalendar() != null) {
218: buffer.append(getBaseCalendar().toString());
219: } else {
220: buffer.append("null");
221: }
222: buffer.append("], excluded cron expression: '");
223: buffer.append(cronExpression);
224: buffer.append("'");
225: return buffer.toString();
226: }
227:
228: /**
229: * Returns the object representation of the cron expression that defines the
230: * dates and times this calendar excludes.
231: *
232: * @return the cron expression
233: * @see org.quartz.CronExpression
234: */
235: public CronExpression getCronExpression() {
236: return cronExpression;
237: }
238:
239: /**
240: * Sets the cron expression for the calendar to a new value
241: *
242: * @param expression the new string value to build a cron expression from
243: * @throws ParseException
244: * if the string expression cannot be parsed
245: */
246: public void setCronExpression(String expression)
247: throws ParseException {
248: CronExpression newExp = new CronExpression(expression);
249:
250: this .cronExpression = newExp;
251: }
252:
253: /**
254: * Sets the cron expression for the calendar to a new value
255: *
256: * @param expression the new cron expression
257: */
258: public void setCronExpression(CronExpression expression) {
259: if (expression == null) {
260: throw new IllegalArgumentException(
261: "expression cannot be null");
262: }
263:
264: this.cronExpression = expression;
265: }
266: }
|