package pl.net.bluesoft.rnd.pt.ext.deadline.step;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.apache.commons.beanutils.PropertyUtils;
import pl.net.bluesoft.rnd.processtool.ProcessToolContext;
import pl.net.bluesoft.rnd.processtool.bpm.exception.ProcessToolException;
import pl.net.bluesoft.rnd.processtool.model.BpmStep;
import pl.net.bluesoft.rnd.processtool.model.ProcessInstance;
import pl.net.bluesoft.rnd.processtool.model.ProcessInstanceAttribute;
import pl.net.bluesoft.rnd.processtool.model.processdata.ProcessDeadline;
import pl.net.bluesoft.rnd.processtool.steps.ProcessToolProcessStep;
import pl.net.bluesoft.rnd.processtool.ui.widgets.annotations.AliasName;
import pl.net.bluesoft.rnd.processtool.ui.widgets.annotations.AutoWiredProperty;
import pl.net.bluesoft.util.lang.Strings;
@AliasName(name = "SetupDeadlineStep")
public class SetupDeadlineStep implements ProcessToolProcessStep {
public static final String DEFAULT_TEMPLATE_NAME = "deadlineEmailTemplate";
private static final String DEFAULT_PROFILE_NAME = "DefaultDeadLineProfile";
private final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); // multithread correctness
private static final Logger logger = Logger.getLogger(SetupDeadlineStep.class.getName());
@AutoWiredProperty
private String taskName;
@AutoWiredProperty
private String profileName = DEFAULT_PROFILE_NAME;
@AutoWiredProperty
private String templateName = DEFAULT_TEMPLATE_NAME;
@AutoWiredProperty
private String unit = "day";
@AutoWiredProperty
private String value;
@AutoWiredProperty
private String notifyUsersWithLogin;
@AutoWiredProperty
private String notifyUsersWithRole;
@AutoWiredProperty
private String skipAssignee;
@AutoWiredProperty
private String workingDays;
@Override
public String invoke(BpmStep step, Map<String, String> params) throws Exception
{
ProcessInstance processInstance = step.getProcessInstance();
ProcessToolContext ctx = ProcessToolContext.Util.getThreadProcessToolContext();
List<String> taskNames = Strings.hasText(taskName) ? Arrays.asList(taskName.split(",")) : step.getOutgoingTransitions();
Date dueDate = extractDate("dueDate", processInstance, params);
if (dueDate == null) {
Date baseDate = extractDate("baseDate", processInstance, params);
if (!Strings.hasText(value)) {
throw new ProcessToolException("Unable to calculate due date");
}
Calendar cal = Calendar.getInstance();
cal.setTime(baseDate != null ? baseDate : new Date());
if(useWorkingDays())
{
int nv = Integer.valueOf(Integer.valueOf(value));
nv = getWeekOffset(cal.getTime(),nv);
cal.add(Calendar.DAY_OF_YEAR, nv);
dueDate = cal.getTime();
}
else
{
cal.add("min".equals(unit) ? Calendar.MINUTE : Calendar.DAY_OF_YEAR, Integer.valueOf(value));
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.SECOND, 0);
if (!"min".equals(unit)) {
cal.set(Calendar.MINUTE, 0);
}
dueDate = cal.getTime();
}
}
for (String tn : taskNames)
{
String attrKey = "deadline_" + tn;
ProcessDeadline pid = null;
for (ProcessInstanceAttribute attr : processInstance.getProcessAttributes()) {
if (attr.getKey() == null) {
logger.info("Attribute key is null! Process instance: " + processInstance.getInternalId());
}
if (attrKey.equals(attr.getKey())) {
pid = (ProcessDeadline) attr;
break;
}
}
if (pid == null) {
pid = new ProcessDeadline();
pid.setKey("deadline_" + tn);
pid.setProcessInstance(processInstance);
processInstance.getProcessAttributes().add(pid);
}
pid.setProfileName(profileName);
pid.setNotifyUsersWithLogin(notifyUsersWithLogin);
pid.setNotifyUsersWithRole(notifyUsersWithRole);
pid.setSkipAssignee("true".equalsIgnoreCase(skipAssignee));
pid.setTemplateName(templateName);
pid.setTaskName(tn);
pid.setAlreadyNotified(false);
pid.setDueDate(dueDate);
}
ctx.getProcessInstanceDAO().saveProcessInstance(processInstance);
return STATUS_OK;
}
public static int getWeekOffset(Date start,int offset){
Calendar cal = Calendar.getInstance();
cal.setTime(start);
int weekday = cal.get(Calendar.DAY_OF_WEEK);
int days = offset%5;
int fullweeks = ((offset - days)/5)*7;
int final_offset = 0;
if(weekday == 0){ // start sobota
final_offset = 2;
weekday = 2; //poniedziale
}else if(weekday == 1){ // start niedziela
final_offset = 1;
weekday = 2; //poniedziale
}
if(weekday+days > 6){
final_offset +=2;
}
offset = final_offset + fullweeks +days;
return offset;
}
private boolean useWorkingDays()
{
return Strings.hasText(workingDays) && workingDays.equals("true");
}
private Date extractDate(String prefix, ProcessInstance processInstance, Map<String, String> params) throws InvocationTargetException,
NoSuchMethodException, IllegalAccessException, ParseException {
Date date = null;
if (params.containsKey(prefix)) {
date = DATE_FORMAT.parse(params.get(prefix));
}
else if (params.containsKey(prefix + "Attribute")) {
String[] paramValue = params.get(prefix + "Attribute").split("\\.", 2);
for (ProcessInstanceAttribute attr : processInstance.getProcessAttributes()) {
if (attr.getKey().equals(paramValue[0])) {
date = (Date) PropertyUtils.getProperty(attr, paramValue.length > 1 ? paramValue[1] : "value");
break;
}
}
}
return date;
}
}