/* ************************************************************************
#
# 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.limit;
import java.util.BitSet;
import org.joda.time.LocalTime;
import divconq.util.StringUtil;
import divconq.xml.XElement;
public class MonthdayWindow {
protected MonthdayKind kind = MonthdayKind.Set;
// window to use for this
protected DayWindow dailyWindow = new DayWindow();
// if type SET then look here for the listed days
protected BitSet dayOfMonth = new BitSet(31);
// does the set include "Last"
protected boolean isLastDayOfMonth = false;
// if other types, besides SET, then list here (0 = monday, 6 = sunday)
protected BitSet dayOfWeek = new BitSet(7);
public void init(LimitHelper helper, XElement config) {
if (config != null) {
String kind = config.getName();
if ("First".equals(kind))
this.kind = MonthdayKind.First;
else if ("Second".equals(kind))
this.kind = MonthdayKind.Second;
else if ("Third".equals(kind))
this.kind = MonthdayKind.Third;
else if ("Fourth".equals(kind))
this.kind = MonthdayKind.Fourth;
else if ("Last".equals(kind))
this.kind = MonthdayKind.Last;
if (this.kind != MonthdayKind.Set) {
if ("True".equals(config.getAttribute("All")))
this.dayOfWeek.set(0, 6);
if ("True".equals(config.getAttribute("Monday")))
this.dayOfWeek.set(0);
if ("True".equals(config.getAttribute("Tuesday")))
this.dayOfWeek.set(1);
if ("True".equals(config.getAttribute("Wednesday")))
this.dayOfWeek.set(2);
if ("True".equals(config.getAttribute("Thursday")))
this.dayOfWeek.set(3);
if ("True".equals(config.getAttribute("Friday")))
this.dayOfWeek.set(4);
if ("True".equals(config.getAttribute("Saturday")))
this.dayOfWeek.set(5);
if ("True".equals(config.getAttribute("Sunday")))
this.dayOfWeek.set(6);
// if none set then default to all
if (this.dayOfWeek.cardinality() == 0)
this.dayOfWeek.set(0, 6);
}
else {
String list = config.getAttribute("List");
if (StringUtil.isEmpty(list) || "All".equals(list)) {
this.isLastDayOfMonth = true;
this.dayOfMonth.set(0, 30);
}
else {
String[] parts = list.split(",");
for (String p : parts) {
if (p.equals("Last")) {
this.isLastDayOfMonth = true;
break;
}
int idx = (int)StringUtil.parseInt(p, 0) - 1;
if (idx > -1)
this.dayOfMonth.set(idx);
}
}
}
this.dailyWindow.init(config);
// True - use default of 24 hours open if there are no windows given
// False - do not include 24 hour open if there are no windows given
// Parent - use only the parent (if present) if there are no windows given
// serves as a hint to the parser to include parent
String defaultWindow = config.getAttribute("DefaultWindow");
if (("Parent".equals(defaultWindow)) && (helper != null))
this.dailyWindow.setParent(helper.getDailyWindow());
}
}
public boolean excludeAll() {
// do we have any open window during the day?
if (this.dailyWindow.excludeAll())
return true;
// if so, are there any days open
if (this.kind == MonthdayKind.Set) {
if ((this.dayOfMonth.cardinality() == 0) && !this.isLastDayOfMonth)
return true;
}
else {
if (this.dayOfWeek.cardinality() == 0)
return true;
}
return false;
}
/*
* search to see if there are any minutes open for this date after or at the current minute
*
* @param si
* @return
*/
public LocalTime nextTimeOn(CheckInfo si) {
if (this.appliesTo(si))
return this.dailyWindow.nextTimeOn(si.getWhen());
return null;
}
public CheckLimitResult check(CheckInfo si) {
if (this.excludeAll())
return CheckLimitResult.Fail;
if (this.appliesTo(si))
return this.dailyWindow.check(si.getWhen());
return CheckLimitResult.NA;
}
public boolean isDateBlocked(CheckInfo si) {
return !this.appliesTo(si);
}
public boolean appliesTo(CheckInfo si) {
if (this.excludeAll())
return false;
if (this.kind == MonthdayKind.Set) {
if (si.isLastDay() && this.isLastDayOfMonth)
return true;
else if (this.dayOfMonth.get(si.getDayOfMonth() - 1))
return true;
}
else if (this.dayOfWeek.get(si.getDayOfWeek() - 1)) {
if ((this.kind == MonthdayKind.First) && (si.getMonthPlacement() == 1))
return true;
else if ((this.kind == MonthdayKind.Second) && (si.getMonthPlacement() == 2))
return true;
else if ((this.kind == MonthdayKind.Third) && (si.getMonthPlacement() == 3))
return true;
else if ((this.kind == MonthdayKind.Fourth) && (si.getMonthPlacement() == 4))
return true;
else if ((this.kind == MonthdayKind.Last) && (si.isLastPlacement()))
return true;
}
return false;
}
}