private ScheduleStatus ProbeSchedule(XPathNavigator document, XPathNavigator exceptionsDocument, ScheduleStatus schedule, ScheduleStatus exceptionsSchedule) { ScheduleStatus testSched = new ScheduleStatus(); ScheduleStatus testExceptionSched = new ScheduleStatus(); DateTime nextDate = DateTime.Now; bool initialState = schedule.Success; for (int probeCount = 0; (probeCount <= 30); probeCount++) { nextDate = nextDate.AddSeconds(1); // reset variables testSched.Success = false; testSched.Expired = false; document.MoveToRoot(); document.MoveToFirstChild(); if (exceptionsDocument != null) { exceptionsDocument.MoveToRoot(); exceptionsDocument.MoveToFirstChild(); testExceptionSched.Success = false; testExceptionSched.Expired = false; } bool valid = (CheckNode(document, nextDate, ref testSched) && ((exceptionsDocument == null) || !(CheckNode(exceptionsDocument, nextDate, ref testExceptionSched)))); if (valid != initialState) { return(schedule); } schedule.NextTestDate = nextDate; } return(schedule); }
/// Check an XML schedule with exceptions. public virtual ScheduleStatus CheckSchedule(Stream schedule, Stream exceptions) { ScheduleStatus sched = new ScheduleStatus(); sched.Precision = String.Empty; ScheduleStatus xSched = new ScheduleStatus(); xSched.Precision = String.Empty; XPathNavigator nav = null; XPathNavigator xNav = null; if ((schedule == null) || schedule.Equals(Stream.Null)) { sched.Success = true; } else { XPathDocument doc = new XPathDocument(schedule); nav = doc.CreateNavigator(); if (!(nav.MoveToChild(XPathNodeType.Element)) || nav.Name != "schedule") { sched.Success = true; } else { CheckNode(nav, DateTime.Now, ref sched); } } if ((exceptions != null) && !(exceptions.Equals(Stream.Null))) { XPathDocument xDoc = new XPathDocument(exceptions); xNav = xDoc.CreateNavigator(); if (!(xNav.MoveToChild(XPathNodeType.Element)) || xNav.Name != "schedule") { xSched.Success = true; } else { CheckNode(xNav, DateTime.Now, ref xSched); } } if (xSched.Success) { sched.Success = false; } if (UsePreciseProbe) { sched = ProbeScheduleExact(nav, xNav, sched, xSched); } else { sched = ProbeSchedule(nav, xNav, sched, xSched); } return(sched); }
/// Check if a free form text schedule with exceptions is valid on the testDate. public static ScheduleStatus Test(string schedule, string exceptions, DateTime testDate) { Scheduler s = new Scheduler(); s.TestDate = testDate; ScheduleStatus status = s.CheckSchedule(schedule, exceptions); status.Schedule = schedule; status.Exceptions = exceptions; return(status); }
private ScheduleStatus ProbeScheduleExact(XPathNavigator document, XPathNavigator exceptionsDocument, ScheduleStatus schedule, ScheduleStatus exceptionsSchedule) { ScheduleStatus testSched = new ScheduleStatus(); ScheduleStatus testExceptionSched = new ScheduleStatus(); int sign = 1; DateTime nextDate = DateTime.Now; bool initialState = schedule.Success; int jump = 0; if (schedule.Precision.Equals("daily") || exceptionsSchedule.Precision.Equals("daily")) { jump = (6 * 60); } else if (schedule.Precision.Equals("weekly") || exceptionsSchedule.Precision.Equals("weekly")) { jump = (72 * 60); } else if (schedule.Precision.Equals("monthly") || exceptionsSchedule.Precision.Equals("monthly")) { jump = (360 * 60); } else if (schedule.Precision.Equals("yearly") || exceptionsSchedule.Precision.Equals("yearly")) { jump = ((720 * 6) * 60); } else { jump = (6 * 60); } for (int probeCount = 1; (probeCount <= 20); probeCount++) { // reset variables testSched.Success = false; testSched.Expired = false; document.MoveToRoot(); document.MoveToFirstChild(); if (exceptionsDocument != null) { exceptionsDocument.MoveToRoot(); exceptionsDocument.MoveToFirstChild(); testExceptionSched.Success = false; testExceptionSched.Expired = false; } // set next date to check nextDate = nextDate.AddMinutes((jump * sign)); bool valid = (CheckNode(document, nextDate, ref testSched) && ((exceptionsDocument == null) || !(CheckNode(exceptionsDocument, nextDate, ref testExceptionSched)))); if (valid == initialState) { sign = 1; } else { sign = -1; } // keep moving forward and expand jump if no border found, otherwise narrow jump if (sign == -1) { jump = (jump / 2); } else { jump = (jump * 2); probeCount--; } if (jump < 5) { jump++; } // no border found if (nextDate > DateTime.Now.AddYears(5)) { break; } } schedule.NextTestDate = nextDate.AddMinutes((jump * -1)); return(schedule); }
/// Checks the current navigator if the current nodes define an active schedule. An empty schedule will set Match to true. private bool CheckNode(XPathNavigator nav, DateTime checkDate, ref ScheduleStatus sched) { if (nav == null) { return(false); } sched.Precision = nav.Name; if (!(nav.MoveToFirstChild())) { // no schedule limitation sched.Success = true; return(true); } while (true) { // ignore comments if (!(nav.NodeType.Equals(XPathNodeType.Comment))) { string name = nav.Name; if (name == "once") { if (CheckInterval(nav, checkDate)) { sched.Success = true; } } else if (CheckInterval(nav, checkDate)) { string value = nav.GetAttribute("value", String.Empty); string every = nav.GetAttribute("every", String.Empty); int check = 0; if (name == "yearly") { check = checkDate.Year; } else if (name == "monthly") { check = checkDate.Month; } else if (name == "weekly") { check = GetWeekOfMonth(checkDate); } else if (name == "daily") { check = ((int)(checkDate.DayOfWeek)); } if (CheckNumberInterval(value, check, every)) { CheckNode(nav, checkDate, ref sched); } } // found a match if (sched.Expired || sched.Success) { break; } } // no more nodes if (!(nav.MoveToNext())) { break; } } return(sched.Success); }