package org.oddjob.schedules.schedules;
import java.io.Serializable;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import org.oddjob.OddjobException;
import org.oddjob.arooa.utils.SpringSafeCalendar;
import org.oddjob.arooa.utils.TimeParser;
import org.oddjob.schedules.CalendarUnit;
import org.oddjob.schedules.ConstrainedSchedule;
import org.oddjob.schedules.DateUtils;
import org.oddjob.scheduling.Timer;
/**
* @oddjob.description A schedule for each day at, or from a given time.
* This schedule
* enables job to be scheduled daily at a particular time or a from/to time which
* could be used to constrain a sub schedule.
* <p>
* If the 'to' time is less than the 'from' time it is assumed that the 'to'
* time is the next day.
*
* @oddjob.example
*
* A simple daily schedule. Used with a {@link Timer} this would run a job
* every day at 10am.
*
* {@oddjob.xml.resource org/oddjob/schedules/schedules/DailyScheduleSimpleExample.xml}
*
* @oddjob.example
*
* Using an interval with a daily schedule to schedules something every 15 minutes
* between 10pm and 4am. The end time is 03:50 yet the last interval is
* 03:45 to 04:00 because the interval starts before the end time.
*
* {@oddjob.xml.resource org/oddjob/schedules/schedules/DailyWithIntervalExample.xml}
*
* @author Rob Gordon
*/
final public class DailySchedule extends ConstrainedSchedule implements Serializable {
private static final long serialVersionUID = 20050226;
private String from;
private String to;
/**
* @oddjob.property from
* @oddjob.description The from time.
* @oddjob.required No. Default to the start of the day.
*
* @param from The from date.
*/
public void setFrom(String from) {
this.from = from;
}
/*
* (non-Javadoc)
* @see org.treesched.ConstrainedSchedule#getFrom()
*/
public String getFrom() {
return from;
}
/**
* @oddjob.property to
* @oddjob.description The to time.
* @oddjob.required No. Default to the end of the day.
*
* @param to The to date.
*
*/
public void setTo(String to) {
this.to = to;
}
/*
* (non-Javadoc)
* @see org.treesched.ConstrainedSchedule#getTo()
*/
public String getTo() {
return to;
}
/**
* @oddjob.property at
* @oddjob.description The time at which this schedule is for.
* This has the same effect as setting from and to to the same thing.
* @oddjob.required No.
*
* @param at The at time.
*/
public void setAt(String at) {
this.setFrom(at);
this.setTo(at);
}
@Override
protected CalendarUnit intervalBetween() {
return new CalendarUnit(Calendar.DATE, 1);
}
static Date parseTime(String textField, Date referenceDate,
TimeZone timeZone, String fieldName) {
TimeParser timeFormatter = new TimeParser(
new SpringSafeCalendar(referenceDate, timeZone));
try {
Date now = timeFormatter.parse(textField);
return now;
} catch (ParseException e) {
throw new OddjobException("Failed to parse " + fieldName
+ "[" + textField + "]");
}
}
protected Calendar fromCalendar(Date referenceDate, TimeZone timeZone) {
Calendar fromCal = Calendar.getInstance(timeZone);
if (from == null) {
fromCal.setTime(DateUtils.startOfDay(referenceDate, timeZone));
}
else {
fromCal.setTime(parseTime(from, referenceDate, timeZone, "from"));
}
return fromCal;
}
protected Calendar toCalendar(Date referenceDate, TimeZone timeZone) {
Calendar toCal = Calendar.getInstance(timeZone);
if (to == null) {
toCal.setTime(DateUtils.endOfDay(referenceDate, timeZone));
}
else {
toCal.setTime(parseTime(to, referenceDate, timeZone, "to"));
}
Calendar fromCal = fromCalendar(referenceDate, timeZone);
if (toCal.equals(fromCal)) {
// For 'at' times.
toCal.add(Calendar.MILLISECOND, 1);
}
return toCal;
}
/**
* Override toString.
*
* @return A description of the schedule.
*/
public String toString() {
String from;
if (this.from == null) {
from = "the start of the day";
} else {
from = this.from;
}
String to;
if (this.to == null) {
to = "the end of the day";
}
else {
to = this.to;
}
StringBuilder description = new StringBuilder();
if (from.equals(to)) {
description.append(" at ");
description.append(from);
}
else {
description.append(" from ");
description.append(from);
description.append(" to ");
description.append(to);
}
if (getRefinement() != null) {
description.append(" with refinement ");
description.append(getRefinement().toString());
}
return "Daily" + description;
}
}