if (bpmTask == null || bpmTask.isFinished())
return bpmTask;
ProcessInstance processInstance = bpmTask.getProcessInstance();
ProcessInstanceLog log = addActionLogEntry(action, task, ctx);
Map<String, Object> vars = new HashMap<String, Object>();
vars.put("ACTION", action.getBpmName());
processInstance.setSimpleAttribute("ACTION", action.getBpmName());
List<String> outgoingTransitionNames = getOutgoingTransitionNames(task.getInternalTaskId(), ctx);
ProcessEngine processEngine = getProcessEngine(ctx);
Task bpmTaskInstance = processEngine.getTaskService().getTask(task.getInternalTaskId());
String executionId = bpmTaskInstance.getExecutionId();
Set<String> taskIdsBeforeCompletion = new HashSet<String>();
pl.net.bluesoft.util.lang.Collections.collect(findProcessTasksWithUser(processInstance, ctx), new Transformer<BpmTask, String>() {
@Override
public String transform(BpmTask obj) {
return obj.getInternalTaskId();
}
}, taskIdsBeforeCompletion);
if (outgoingTransitionNames.size() == 1)
processEngine.getTaskService().completeTask(task.getInternalTaskId(), outgoingTransitionNames.get(0), vars); //BPMN2.0 style, decision is taken on the XOR gateway
else
processEngine.getTaskService().completeTask(task.getInternalTaskId(), action.getBpmName(), vars);
broadcastEvent(ctx, new BpmEvent(BpmEvent.Type.TASK_FINISHED, task, user));
/* Inform queue manager about task finish and process state change */
ctx.getUserProcessQueueManager().onTaskFinished(task);
String processState = getProcessState(processInstance, ctx);
/* Check if new subProcess is created */
boolean startsSubprocess = updateSubprocess(processInstance, executionId, ctx);
fillProcessAssignmentData(processEngine, processInstance, ctx);
processInstance.setState(processState);
if (startsSubprocess == false && processState == null && processInstance.getRunning() && !isProcessRunning(processInstance.getInternalId(), ctx)) {
processInstance.setRunning(false);
}
if (log.getUserSubstitute() == null)
broadcastEvent(ctx, new BpmEvent(BpmEvent.Type.SIGNAL_PROCESS, bpmTask, user));
else
broadcastEvent(ctx, new BpmEvent(BpmEvent.Type.SIGNAL_PROCESS, bpmTask, log.getUserSubstitute()));
if (Strings.hasText(action.getAssignProcessStatus())) {
String processStatus = action.getAssignProcessStatus();
ProcessStatus ps = processStatus.length() == 1 ? ProcessStatus.fromChar(processStatus.charAt(0)) : ProcessStatus.fromString(processStatus);
processInstance.setStatus(ps);
}
else
{
boolean isProcessRunning = processInstance.isProcessRunning();
//boolean isProcessRunning = isProcessRunning(pi.getInternalId(), ctx);
/* Process is not running and no new suprocesses are created, so process should
* be finished by now
*/
if(!isProcessRunning && !startsSubprocess)
{
broadcastEvent(ctx, new BpmEvent(BpmEvent.Type.END_PROCESS, bpmTask, user));
/* Inform queue manager about process ending. Only main process is stored */
if(!processInstance.isSubprocess())
ctx.getUserProcessQueueManager().onProcessFinished(processInstance, bpmTask);
processInstance.setStatus(ProcessStatus.FINISHED);
}
/* Process is running or is halted, but new subprocess are created */
else if(!isProcessRunning && startsSubprocess)
{
broadcastEvent(ctx, new BpmEvent(BpmEvent.Type.PROCESS_HALTED, bpmTask, user));
/* Inform queue manager about process halt */
ctx.getUserProcessQueueManager().onProcessHalted(processInstance, bpmTask);
processInstance.setStatus(ProcessStatus.RUNNING);
}
else
{
processInstance.setStatus(ProcessStatus.RUNNING);
}
}
ctx.getProcessInstanceDAO().saveProcessInstance(processInstance);
BpmTask userTask = null;
BpmTask autoSkipTask = null;
/* Is process finished */
boolean isProcessFinished = processInstance.getStatus().equals(ProcessStatus.FINISHED);
boolean isSubProcess = processInstance.getParent() != null;
List<BpmTask> tasksAfterCompletion = null;
if(startsSubprocess && processInstance.getChildren() != null) {
for(ProcessInstance child : processInstance.getChildren()) {
tasksAfterCompletion = findProcessTasks(child, ctx);
if(tasksAfterCompletion != null && tasksAfterCompletion.size() > 0)
break;
}
}
if(tasksAfterCompletion == null || tasksAfterCompletion.size() == 0) {
tasksAfterCompletion = findProcessTasks(processInstance, ctx);
}
if(processInstance.getParent() != null && (tasksAfterCompletion == null || tasksAfterCompletion.size() == 0)) {
tasksAfterCompletion = findProcessTasks(processInstance.getParent(), ctx);
}
if(tasksAfterCompletion != null) {
for (BpmTask createdTask : tasksAfterCompletion) {
if (!taskIdsBeforeCompletion.contains(createdTask.getInternalTaskId()))
{
broadcastEvent(ctx, new BpmEvent(BpmEvent.Type.ASSIGN_TASK, createdTask, user));
/* Inform queue manager about task assigne */
ctx.getUserProcessQueueManager().onTaskAssigne(createdTask);
}
if (Lang.equals(user.getId(), createdTask.getOwner().getId())) {
userTask = createdTask;
}
if(createdTask.getTaskName().toLowerCase().startsWith(AUTO_SKIP_TASK_NAME_PREFIX.toLowerCase())) {
autoSkipTask = createdTask;
}
}
}
if(autoSkipTask != null) {
ProcessStateAction skipAction = new ProcessStateAction();
skipAction.setBpmName(AUTO_SKIP_ACTION_NAME);
return performAction(skipAction, autoSkipTask, ctx);
}
/* Task assigned to queue */
if (userTask == null)
{
/* Process is finished, ask about parent process queues */
if(isProcessFinished && isSubProcess)
processInstance = processInstance.getParent();
/* Get task assigned to queues */
Collection<BpmTask> queueTasks = getProcessTaskInQueues(ctx, processInstance);
for(BpmTask queueTask: queueTasks)