/* * JBoss, Home of Professional Open Source. * Copyright 2012, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.processFlow.tasks.handlers; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.drools.runtime.process.WorkItem; import org.drools.runtime.process.WorkItemManager; import org.jboss.processFlow.tasks.ITaskService; import org.jboss.processFlow.util.DateTimeUtils; import org.jboss.processFlow.workItem.WorkItemHandlerLifecycle; import org.jbpm.process.workitem.wsht.HumanTaskHandlerHelper; import org.jbpm.task.AccessType; import org.jbpm.task.Group; import org.jbpm.task.I18NText; import org.jbpm.task.OrganizationalEntity; import org.jbpm.task.PeopleAssignments; import org.jbpm.task.SubTasksStrategy; import org.jbpm.task.SubTasksStrategyFactory; import org.jbpm.task.Task; import org.jbpm.task.TaskData; import org.jbpm.task.User; import org.jbpm.task.service.ContentData; /* * 15 Sept 2011 * Purpose : * - create a new Task object and invoke the taskService.addTask(...) method * * invocation and lifecycle : * - this.executeWorkItem() is invoked by the JPAWorkIteManager * - an instance of this class shares the same lifecycle as its corresponding knowledge session and workItemManager * * * deadlines * - this custom work item handler assumes a process instance variable of 'Deadline_Time' of type String * - if 'Deadline_Time' is set, this custom work item handler will create a new Deadline with Escalation and flush to database */ public class PFPAddHumanTaskHandler extends BasePFPTaskHandler implements WorkItemHandlerLifecycle { public static final Logger log = Logger.getLogger("PFPAddHumanTaskHandler"); public void executeWorkItem(WorkItem workItem, WorkItemManager manager) { String taskName = (String) workItem.getParameter("TaskName"); // 1) create a Task instance from this workItem instance Task task = new Task(); if (taskName != null) { List<I18NText> names = new ArrayList<I18NText>(); names.add(new I18NText("en-UK", taskName)); task.setNames(names); } String comment = (String) workItem.getParameter("Comment"); if (comment != null) { List<I18NText> descriptions = new ArrayList<I18NText>(); descriptions.add(new I18NText("en-UK", comment)); task.setDescriptions(descriptions); List<I18NText> subjects = new ArrayList<I18NText>(); subjects.add(new I18NText("en-UK", comment)); task.setSubjects(subjects); } String priorityString = (String) workItem.getParameter("Priority"); int priority = 0; if (priorityString != null) { try { priority = new Integer(priorityString); } catch (NumberFormatException e) { // do nothing } } task.setPriority(priority); TaskData taskData = new TaskData(); taskData.setWorkItemId(workItem.getId()); taskData.setProcessInstanceId(workItem.getProcessInstanceId()); taskData.setSkipable(!"false".equals(workItem.getParameter("Skippable"))); taskData.setProcessSessionId(ksessionId); //Sub Task Data Long parentId = (Long) workItem.getParameter("ParentId"); if(parentId != null){ taskData.setParentId(parentId); } String subTaskStrategiesCommaSeparated = (String) workItem.getParameter("SubTaskStrategies"); if(subTaskStrategiesCommaSeparated!= null && !subTaskStrategiesCommaSeparated.equals("")){ String[] subTaskStrategies = subTaskStrategiesCommaSeparated.split(","); List<SubTasksStrategy> strategies = new ArrayList<SubTasksStrategy>(); for(String subTaskStrategyString : subTaskStrategies){ SubTasksStrategy subTaskStrategy = SubTasksStrategyFactory.newStrategy(subTaskStrategyString); strategies.add(subTaskStrategy); } task.setSubTaskStrategies(strategies); } PeopleAssignments assignments = new PeopleAssignments(); List<OrganizationalEntity> potentialOwners = new ArrayList<OrganizationalEntity>(); User adminUser = new User(ITaskService.ADMINISTRATOR); String actorId = (String) workItem.getParameter("ActorId"); if (actorId != null && actorId.trim().length() > 0) { String[] actorIds = actorId.split(","); for (String id: actorIds) { potentialOwners.add(new User(id.trim())); } //Set the first user as creator ID??? hmmm might be wrong if (potentialOwners.size() > 0){ taskData.setCreatedBy((User)potentialOwners.get(0)); taskData.setActualOwner((User)potentialOwners.get(0)); } } String groupId = (String) workItem.getParameter("GroupId"); if (groupId != null && groupId.trim().length() > 0) { String[] groupIds = groupId.split(","); for (String id: groupIds) { potentialOwners.add(new Group(id.trim())); } taskData.setCreatedBy(adminUser); taskData.setActualOwner(adminUser); } //ddoyle: Backported support for DueDate from jBPM6. String dueDateString = (String) workItem.getParameter("DueDate"); Date date = null; if(dueDateString != null && !dueDateString.isEmpty()){ if(DateTimeUtils.isPeriod(dueDateString)){ Long longDateValue = DateTimeUtils.parseDateAsDuration(dueDateString.substring(1)); date = new Date(System.currentTimeMillis() + longDateValue); }else{ date = new Date(DateTimeUtils.parseDateTime(dueDateString)); } } if(date != null){ taskData.setExpirationTime(date); } // JAB: throw RuntimeException if createdBy has not been set if(taskData.getCreatedBy() == null) throw new RuntimeException("executeWorkItem() neither actorId nor groupId has been set for task = "+taskName); assignments.setPotentialOwners(potentialOwners); List<OrganizationalEntity> businessAdministrators = new ArrayList<OrganizationalEntity>(); // JA Bride : ITaskService.ADMINISTRATOR being added as business administrator to allow for subsequent operations on the task if need be as per : // jbpm-human-task/src/main/resources/org/jbpm/task/service/operations-dsl.mvel businessAdministrators.add(adminUser); assignments.setBusinessAdministrators(businessAdministrators); task.setPeopleAssignments(assignments); // not specifying Environment property : "jbpm.business.calendar" task.setDeadlines(HumanTaskHandlerHelper.setDeadlines(workItem, businessAdministrators)); task.setTaskData(taskData); // grab existing content from workItem or initialize empty content HashMap if doesn't exist in workItem ContentData content = null; // Nick: retrieve all parameters as the input contentData HashMap<String, Object> contentObject = new HashMap<String, Object>(); contentObject.putAll(workItem.getParameters()); Map<String, Object> contentMap = (HashMap<String, Object>) workItem.getParameter("Content"); if(contentMap == null) { if(enableLog) { log.warn("executeWorkItem() processInstance-->task variable 'Content' is null for workItemId = "+workItem.getId()+ "\n\tthis could occur for either one (or both) of the following reasons\n\t\t1) upstream to this workItem, a knowledge context variable of type java.util.HashMap with key = 'map' was not set.\n\t\t2) Parameter Mapping of 'Content=map' was not set in this task node in the process definition \n\twill initialize an empty hashmap and use this empty hashmap when invoking TaskServiceSession.addTask()"); } //Jeff: the FreeMarker templates used in the gwt-console use it and if that hash doesn't exist and/or it doesn't have the right key/values in it contentMap = new HashMap<String, Object>(); } else { if(enableLog) { StringBuilder sBuilder = new StringBuilder(); sBuilder.append("executeWorkItem() processInstance-->task variables as follows for pInstanceId = "); sBuilder.append(workItem.getProcessInstanceId()); sBuilder.append(" : taskName = "); sBuilder.append(taskName); for (Map.Entry<String, Object> entry: contentMap.entrySet()) { sBuilder.append("\n\t"); sBuilder.append(entry.getKey()); sBuilder.append(" : "); sBuilder.append(entry.getValue()); } log.info(sBuilder.toString()); } } // Nick: use "Content" anyway if it is defined contentObject.putAll(contentMap); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = null; try { out = new ObjectOutputStream(bos); out.writeObject(contentObject); out.close(); content = new ContentData(); content.setContent(bos.toByteArray()); content.setAccessType(AccessType.Inline); } catch (IOException e) { e.printStackTrace(); } finally { try { if(out != null) out.close(); } catch(Exception x){ x.printStackTrace(); } } try { // 5) synch call to task proxy to add newly created task long taskId = taskProxy.addTask(task, content); } catch(Exception x) { throw new RuntimeException(x); } } public void abortWorkItem(WorkItem workItem, WorkItemManager manager) { log.error("abortWorkItem() workItemId = "+workItem.getId() +" : workItemName = "+workItem.getName()); taskProxy.skipTaskByWorkItemId(workItem.getId()); } }