/* ************************************************************************
#
# DivConq
#
# http://divconq.com/
#
# Copyright:
# Copyright 2014 eTimeline, LLC. All rights reserved.
#
# License:
# See the license.txt file in the project's top-level directory for details.
#
# Authors:
# * Andy White
#
************************************************************************ */
package divconq.scheduler.common;
import org.joda.time.DateTime;
import divconq.scheduler.limit.CheckInfo;
import divconq.util.TimeUtil;
import divconq.xml.XElement;
/*
* <Daily>
* <Schedule At="" RunIfMissed="True/False" />
* <Schedule At="" RunIfMissed="True/False" />
* <Schedule At="" RunIfMissed="True/False" />
* </Daily>
*/
public class DailyHelper extends CommonHelper implements IDateChecker {
protected ScheduleList list = new ScheduleList();
// first time this code was run since the module/server was started
// requires special check for any missed runs
protected boolean firstCall = true;
@Override
public void init(CommonSchedule schedule, XElement config) {
super.init(schedule, config);
if (config == null)
return;
this.list.init(config);
}
// return null to indicate this can never run again
@Override
public DateTime next() {
this.schedule.setHint("_ScheduleTimeHint", "");
if (this.firstCall) {
this.firstCall = false;
if (this.limits.isEnded())
return null;
// if the valid range for schedule has not started yet, then
// schedule way out
if (!this.limits.isStarted()) {
this.firstCall = false;
this.last = new DateTime(this.limits.getFirstDate());
}
// if there was no past runs, do not try to find them
// or if there are not any required
else if (this.last == null) {
this.last = new DateTime().minusDays(9); // start 8 days ago to allow for Run if Missed
//this.last = TimeUtil.nextDayAtMidnight(new DateTime().minusDays(9)); // start 8 days ago to allow for Run if Missed
}
// see if we need to run because of a missed past schedule
if (this.list.anyRequired()) {
if (this.checkStartupNeedsRun(this.list, this)) {
//System.out.println("run asap!!!!");
this.last = this.limits.nextAllowedRun();
return this.last;
}
}
}
ScheduleEntry se = this.list.next(this.last);
while (true) {
// null means we reached the end, go to next day
if (se == null) {
this.last = TimeUtil.nextDayAtMidnight(this.last);
se = this.list.next(this.last);
}
// add the scheduled entry to the time
// (first time with a given date, this is the time past midnight)
if (se != null)
this.last = TimeUtil.withTime(this.last, se.getTime());
// we cannot schedule again, the schedule is expired
if (this.limits.isEnded(this.last))
return null;
// can we run at the suggested time?
if (this.limits.checkForRun(this.last)) {
this.schedule.setHint("_ScheduleTimeHint", se.getTime().toString());
return this.last;
}
// if not, should we run asap after the suggested time
if (se.isRunIfMissed()) {
this.schedule.setHint("_ScheduleTimeHint", se.getTime().toString());
this.last = this.limits.nextAllowedRunAfter(this.last);
return this.last;
}
// go on and check the next time
se = this.list.next(this.last);
}
}
@Override
public boolean checkDate(CheckInfo info) {
// always allowed
return true;
}
}