public void onExecute() throws Exception
{
BOrd ord = getScheduleOrd();
if (ord == null || ord.isNull())
throw new IllegalStateException("Program slot 'scheduleOrd' is null.");
BComponent target = (BComponent) ord.get();
BValue schedVal = target.get("schedule");
if (!(schedVal instanceof BCompositeSchedule))
throw new IllegalStateException("Target does not contain slot 'schedule' of type schedule:CompositeSchedule.");
BCompositeSchedule composite = (BCompositeSchedule) schedVal;
BValue weekVal = composite.get("week");
if (!(weekVal instanceof BWeekSchedule))
throw new IllegalStateException("CompositeSchedule.week is not a schedule:WeekSchedule.");
BWeekSchedule week = (BWeekSchedule) weekVal;
final String ranges = getRanges();
final BStatusBoolean desired = getDesiredFromValueSlot();
if (getClearFirst())
clearEntireWeek(week);
if (getApplySunday()) applyToDay(week, "sunday", ranges, desired);
if (getApplyMonday()) applyToDay(week, "monday", ranges, desired);
if (getApplyTuesday()) applyToDay(week, "tuesday", ranges, desired);
if (getApplyWednesday()) applyToDay(week, "wednesday", ranges, desired);
if (getApplyThursday()) applyToDay(week, "thursday", ranges, desired);
if (getApplyFriday()) applyToDay(week, "friday", ranges, desired);
if (getApplySaturday()) applyToDay(week, "saturday", ranges, desired);
try
{
Action exec = target.getAction("execute");
if (exec != null) target.invoke(exec, null);
}
catch (Exception ignored) {}
System.out.println("ScheduleAdjust updated: " + ord);
}
private void clearEntireWeek(BWeekSchedule week)
{
clearDay(week, "sunday");
clearDay(week, "monday");
clearDay(week, "tuesday");
clearDay(week, "wednesday");
clearDay(week, "thursday");
clearDay(week, "friday");
clearDay(week, "saturday");
}
private void clearDay(BWeekSchedule week, String daySlotName)
{
try
{
BValue dayObjVal = week.get(daySlotName);
if (dayObjVal == null) return;
BObject dayObj = (BObject) dayObjVal;
BDaySchedule daySchedule = extractDaySchedule(dayObj);
if (daySchedule != null)
removeTimeChildren(daySchedule);
}
catch (Exception ignored) {}
}
private void applyToDay(BWeekSchedule week, String daySlotName, String ranges,
BStatusBoolean desired) throws Exception
{
BValue dayObjVal = week.get(daySlotName);
if (dayObjVal == null)
throw new IllegalStateException("WeekSchedule." + daySlotName + " is null.");
BObject dayObj = (BObject) dayObjVal;
BDaySchedule daySchedule = extractDaySchedule(dayObj);
if (daySchedule == null)
throw new IllegalStateException("Could not find schedule:DaySchedule under week." + daySlotName +
" (object type: " + dayObj.getType() + ").");
String r = (ranges == null) ? "" : ranges.trim();
if (r.isEmpty() || r.equalsIgnoreCase("closed") || r.equalsIgnoreCase("off"))
return;
if (r.equalsIgnoreCase("24/7") || r.equalsIgnoreCase("24x7"))
{
addTimeBlock(daySchedule, parseTime("00:00"), parseTime("24:00"), desired);
return;
}
String[] blocks = r.split(",");
for (int i = 0; i < blocks.length; i++)
{
String b = blocks[i].trim();
if (b.isEmpty()) continue;
String[] se = b.split("-");
if (se.length != 2)
throw new IllegalArgumentException("Bad time range for " + daySlotName + ": '" + b +
"'. Use 'HH:mm-HH:mm' (comma-separated allowed).");
BTime start = parseTime(se[0].trim());
BTime finish = parseTime(se[1].trim());
addTimeBlock(daySchedule, start, finish, desired);
}
}
private BDaySchedule extractDaySchedule(BObject weekDayObj)
{
if (weekDayObj instanceof BDaySchedule)
return (BDaySchedule) weekDayObj;
try
{
if (weekDayObj instanceof BComplex)
{
BValue v = ((BComplex) weekDayObj).get("day");
if (v instanceof BDaySchedule)
return (BDaySchedule) v;
}
}
catch (Exception ignored) {}
return null;
}
private void removeTimeChildren(BDaySchedule day)
{
BComponent c = (BComponent) day;
SlotCursor sc = c.getSlots();
String[] names = new String[8];
int count = 0;
while (sc.next())
{
Slot s = sc.slot();
if (s == null) continue;
String name = s.getName();
if (name == null) continue;
if (!name.regionMatches(true, 0, "time", 0, 4))
continue;
if (count == names.length)
{
String[] bigger = new String[names.length * 2];
for (int i = 0; i < names.length; i++) bigger[i] = names[i];
names = bigger;
}
names[count++] = name;
}
for (int i = 0; i < count; i++)
{
try { c.remove(names[i]); }
catch (Exception ignored) {}
}
}
private void addTimeBlock(BDaySchedule day, BTime start, BTime finish, BStatusBoolean desired)
{
BComponent dayC = (BComponent) day;
BTimeSchedule ts = new BTimeSchedule();
ts.set("start", start);
ts.set("finish", normalizeFinish(finish));
dayC.add("time?", ts);
BStatusBoolean ev = new BStatusBoolean(desired.getBoolean(), desired.getStatus());
ts.add("effectiveValue", ev);
}
private BTime normalizeFinish(BTime finish)
{
if (finish.getHour() == 24 && finish.getMinute() == 0 && finish.getSecond() == 0)
return BTime.make(0, 0, 0);
return finish;
}
private BStatusBoolean getDesiredFromValueSlot()
{
BStatusBoolean sb = getValue();
if (sb == null) return new BStatusBoolean(true, BStatus.ok);
return sb;
}
private BTime parseTime(String s)
{
s = s.trim().toUpperCase();
boolean pm = s.endsWith("PM");
boolean am = s.endsWith("AM");
if (pm || am)
s = s.replace("AM", "").replace("PM", "").trim();
String[] parts = s.split(":");
int h = Integer.parseInt(parts[0].trim());
int m = (parts.length > 1) ? Integer.parseInt(parts[1].trim()) : 0;
if (pm && h < 12) h += 12;
if (am && h == 12) h = 0;
// allow 24:00
if (h == 24 && m == 0)
return BTime.make(24, 0, 0);
return BTime.make(h, m, 0);
}