package fr.itldev.koya.action; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; import org.alfresco.repo.workflow.WorkflowModel; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ParameterDefinition; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.workflow.WorkflowDefinition; import org.alfresco.service.cmr.workflow.WorkflowInstance; import org.alfresco.service.cmr.workflow.WorkflowInstanceQuery; import org.alfresco.service.cmr.workflow.WorkflowService; import org.alfresco.service.cmr.workflow.WorkflowTask; import org.alfresco.service.cmr.workflow.WorkflowTaskQuery; import org.alfresco.service.cmr.workflow.WorkflowTaskState; import org.alfresco.service.namespace.QName; import org.alfresco.util.Pair; import fr.itldev.koya.alfservice.KoyaMailService; import fr.itldev.koya.alfservice.KoyaNodeService; import fr.itldev.koya.alfservice.security.SpaceAclService; import fr.itldev.koya.model.KoyaModel; import fr.itldev.koya.model.KoyaNode; import fr.itldev.koya.model.impl.Space; import fr.itldev.koya.model.impl.User; import fr.itldev.koya.model.permissions.KoyaPermissionCollaborator; public class WorkflowAlertsActionExecuter extends ActionExecuterAbstractBase { public static final String NAME = "workflowAlerts"; /** * TODO generic mail alerts : only available for koyares workflow now. */ private static final String WF_RES_1_0 = "http://www.itldev.fr/model/workflow/realEstateSale/1.0"; private static final QName TARGET_TASK = QName.createQName(WF_RES_1_0, "targetTask"); private static Set<QName> REFERENCE_TYPES = new HashSet<QName>() { { add(KoyaModel.TYPE_DOSSIER); } }; private WorkflowService workflowService; private List<String> wfTypes; private List<String> wfTasksDueDate; private List<Integer> alertDelays; private KoyaMailService koyaMailService; private KoyaNodeService koyaNodeService; private SpaceAclService spaceAclService; private NodeService nodeService; public void setWorkflowService(WorkflowService workflowService) { this.workflowService = workflowService; } public void setWfTypes(List<String> wfTypes) { this.wfTypes = wfTypes; } public void setWfTasksDueDate(List<String> wfTasksDueDate) { this.wfTasksDueDate = wfTasksDueDate; } public void setAlertDelays(List<Integer> alertDelays) { this.alertDelays = alertDelays; } public void setKoyaMailService(KoyaMailService koyaMailService) { this.koyaMailService = koyaMailService; } public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } public void setKoyaNodeService(KoyaNodeService koyaNodeService) { this.koyaNodeService = koyaNodeService; } public void setSpaceAclService(SpaceAclService spaceAclService) { this.spaceAclService = spaceAclService; } @Override public void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef) { List<WorkflowInstance> candidates = new ArrayList<>(); for (String wfType : wfTypes) { /** * For each active workflow instance */ for (WorkflowDefinition wfDef : workflowService .getAllDefinitionsByName("activiti$" + wfType)) { WorkflowInstanceQuery workflowInstanceQuery = new WorkflowInstanceQuery(); workflowInstanceQuery.setActive(true); workflowInstanceQuery.setWorkflowDefinitionId(wfDef.getId()); candidates.addAll(workflowService.getWorkflows(workflowInstanceQuery)); } } for (WorkflowInstance wfi : candidates) { processWorkflowInstance(wfi); } } /** * Process workflow instance. * * Check dueDate tasks and send mail to Dossier related members and * responsibles if due date match one of delays. * * @param instance */ private void processWorkflowInstance(WorkflowInstance instance) { List<KoyaNode> koyaNodeReferences = new ArrayList<>(); List<ChildAssociationRef> refs = nodeService.getChildAssocs(instance.getWorkflowPackage(), REFERENCE_TYPES); for (ChildAssociationRef car : refs) { koyaNodeReferences.add(koyaNodeService.getKoyaNode(car.getChildRef())); } /** * Process all DueDate Tasks */ WorkflowTaskQuery taskQuery = new WorkflowTaskQuery(); taskQuery.setTaskState(WorkflowTaskState.COMPLETED); taskQuery.setProcessId(instance.getId()); Map<String, WorkflowTask> targetTaskMap = new HashMap<>(); for (WorkflowTask wt : workflowService.queryTasks(taskQuery, false)) { if (wfTasksDueDate.contains(wt.getName())) { WorkflowTask t = targetTaskMap.get(wt.getProperties().get(TARGET_TASK).toString()); if (t == null || ((Date) t.getProperties().get(WorkflowModel.PROP_COMPLETION_DATE)) .before((Date) wt.getProperties() .get(WorkflowModel.PROP_COMPLETION_DATE))) { targetTaskMap.put(wt.getProperties().get(TARGET_TASK).toString(), wt); } } } /** * filter DueDate Tasks with alertDelays */ List<Pair<WorkflowTask, Integer>> alertablesTasks = new ArrayList<>(); for (Entry<String, WorkflowTask> e : targetTaskMap.entrySet()) { for (Integer delay : alertDelays) { // build dateRage corresponding to delay Calendar cStart = Calendar.getInstance(); cStart.add(Calendar.DATE, delay - 1); Calendar cEnd = Calendar.getInstance(); cEnd.add(Calendar.DATE, delay); Date taskDueDate = (Date) e.getValue().getProperties() .get(WorkflowModel.PROP_DUE_DATE); if (taskDueDate.after(cStart.getTime()) && taskDueDate.before(cEnd.getTime())) { alertablesTasks.add(new Pair<WorkflowTask, Integer>(e.getValue(), delay)); break; } } } /** * Gather alert mail users */ List<User> alertDest = new ArrayList<>(); if (alertablesTasks.size() > 0) { alertDest.addAll(spaceAclService.listMembership((Space) koyaNodeReferences.get(0), KoyaPermissionCollaborator.MEMBER)); alertDest.addAll(spaceAclService.listMembership((Space) koyaNodeReferences.get(0), KoyaPermissionCollaborator.RESPONSIBLE)); } /** * TODO User Mail Alert Filter * */ /** * Send Mail alerts */ for (Pair<WorkflowTask, Integer> t : alertablesTasks) { koyaMailService.sendTaskExpireAlertMail(alertDest, t.getFirst().getProperties().get(TARGET_TASK).toString(), instance.getDefinition().getName(), (Space) koyaNodeReferences.get(0), t.getSecond(), (Date) t.getFirst().getProperties().get(WorkflowModel.PROP_DUE_DATE)); } } @Override protected void addParameterDefinitions(List<ParameterDefinition> paramList) { } }