/*
* Copyright 2012 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jbpm.services.task.lifecycle.listeners;
import java.util.Comparator;
import java.util.Date;
import javax.persistence.EntityManagerFactory;
import org.jbpm.services.task.audit.impl.model.BAMTaskSummaryImpl;
import org.jbpm.services.task.persistence.PersistableEventListener;
import org.kie.api.task.TaskEvent;
import org.kie.api.task.model.Status;
import org.kie.api.task.model.Task;
import org.kie.internal.task.api.TaskContext;
import org.kie.internal.task.api.TaskPersistenceContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <p></p>This listener implementation populates a table named BAMTASKCUMMARY in order to allow BAM module to query all tasks.</p>
*
* <p>The available status for a task instance are:</p>
* @see org.kie.api.task.model.Status
* <ul>
* <li>Created</li>
* <li>Ready</li>
* <li>Reserved</li>
* <li>InProgress</li>
* <li>Suspended</li>
* <li>Completed</li>
* <li>Failed</li>
* <li>Error</li>
* <li>Exited</li>
* <li>Obsolete</li>
* </ul>
*
* <p>The BAM module does not use all task predefined stauts, the following list shows the status for a jBPM task and the relationship with the BAM task status:</p>
* <ul>
* <li>Kie Task status - BAM task status</li>
* <li>Created - Created</li>
* <li>Ready - Ready</li>
* <li>Reserved - Reserved</li>
* <li>InProgress - InProgress</li>
* <li>Suspended - Suspended</li>
* <li>Completed - Completed</li>
* <li>Exited - Exited</li>
* <li>Failed - Error</li>
* <li>Error - Error</li>
* <li>Obsolete - Error</li>
* </ul>
*/
public class BAMTaskEventListener extends PersistableEventListener {
/** Class logger. */
private static final Logger logger = LoggerFactory.getLogger(BAMTaskEventListener.class);
public BAMTaskEventListener(boolean flag) {
super(null);
}
public BAMTaskEventListener(EntityManagerFactory emf) {
super(emf);
}
public void afterTaskStartedEvent(TaskEvent event) {
updateTask(event, new BAMTaskWorker() {
@Override
public BAMTaskSummaryImpl createTask(BAMTaskSummaryImpl bamTask, Task task) {
bamTask.setStartDate(new Date());
return bamTask;
}
@Override
public BAMTaskSummaryImpl updateTask(BAMTaskSummaryImpl bamTask, Task task) {
bamTask.setStartDate(new Date());
return bamTask;
}
});
}
public void afterTaskActivatedEvent(TaskEvent event) {
updateTask(event);
}
public void afterTaskClaimedEvent(TaskEvent event) {
updateTask(event);
}
public void afterTaskCompletedEvent(TaskEvent event) {
updateTask(event, new BAMTaskWorker() {
@Override
public BAMTaskSummaryImpl createTask(BAMTaskSummaryImpl bamTask, Task task) {
return bamTask;
}
@Override
public BAMTaskSummaryImpl updateTask(BAMTaskSummaryImpl bamTask, Task task) {
Date completedDate = new Date();
bamTask.setEndDate(completedDate);
bamTask.setDuration(completedDate.getTime() - bamTask.getStartDate().getTime());
return bamTask;
}
});
}
public void afterTaskAddedEvent(TaskEvent event) {
createTask(event, null, null);
}
/**
* When a task is skipped, the status for dashbuilder integration task must be Exited.
*
* @param ti The task.
*/
public void afterTaskSkippedEvent(TaskEvent event) {
createOrUpdateTask(event, Status.Exited);
}
public void afterTaskStoppedEvent(TaskEvent event) {
updateTask(event);
}
/**
* When a task is failed, the status for dashbuilder integration task must be Exited.
*
* @param ti The task.
*/
public void afterTaskFailedEvent(TaskEvent event) {
createOrUpdateTask(event, Status.Error);
}
public void afterTaskExitedEvent(TaskEvent event) {
createOrUpdateTask(event, Status.Exited);
}
public void afterTaskReleasedEvent(TaskEvent event) {
updateTask(event);
}
public void afterTaskDelegatedEvent(TaskEvent event) {
updateTask(event);
}
public void afterTaskForwaredEvent(TaskEvent event) {
updateTask(event);
}
public void afterTaskNomiatedEvent(TaskEvent event) {
updateTask(event);
}
public void afterTaskResumedEvent(TaskEvent event) {
updateTask(event);
}
public void afterTaskSuspendedEvent(TaskEvent event) {
updateTask(event);
}
@Override
public void afterTaskForwardedEvent(TaskEvent event) {
updateTask(event);
}
@Override
public void afterTaskNominatedEvent(TaskEvent event) {
updateTask(event);
}
/**
* Creates or updates a bam task summary instance.
*
* @param ti The source task
* @param worker Perform additional operations to the bam task summary instance.
* @return The created or updated bam task summary instance.
*/
protected BAMTaskSummaryImpl updateTask(TaskEvent event, BAMTaskWorker worker) {
return updateTask(event, null, worker);
}
/**
* Creates or updates a bam task summary instance.
*
* @param ti The source task
* @return The created or updated bam task summary instance.
*/
protected BAMTaskSummaryImpl updateTask(TaskEvent event) {
return updateTask(event, null, null);
}
/**
* Creates or updates a bam task summary instance.
*
* @param ti The source task
* @param newStatus The new state for the task.
* @return The created or updated bam task summary instance.
*/
protected BAMTaskSummaryImpl createOrUpdateTask(TaskEvent event, Status newStatus) {
return updateTask(event, newStatus, null);
}
/**
* Creates or updates a bam task summary instance.
*
* @param ti The source task
* @param newStatus The new state for the task.
* @param worker Perform additional operations to the bam task summary instance.
* @return The created or updated bam task summary instance.
*/
protected BAMTaskSummaryImpl createTask(TaskEvent event, Status newStatus, BAMTaskWorker worker) {
BAMTaskSummaryImpl result = null;
Task ti = event.getTask();
TaskPersistenceContext persistenceContext = getPersistenceContext(((TaskContext)event.getTaskContext()).getPersistenceContext());
try {
if (ti == null) {
logger.error("The task instance does not exist.");
return result;
}
Status status = newStatus != null ? newStatus : ti.getTaskData().getStatus();
String actualOwner = "";
if (ti.getTaskData().getActualOwner() != null) {
actualOwner = ti.getTaskData().getActualOwner().getId();
}
result = new BAMTaskSummaryImpl(ti.getId(), ti.getName(), status.toString(), new Date(), actualOwner, ti.getTaskData().getProcessInstanceId());
if (worker != null) worker.createTask(result, ti);
persistenceContext.persist(result);
return result;
} finally {
cleanup(persistenceContext);
}
}
protected BAMTaskSummaryImpl updateTask(TaskEvent event, Status newStatus, BAMTaskWorker worker) {
BAMTaskSummaryImpl result = null;
Task ti = event.getTask();
TaskPersistenceContext persistenceContext = getPersistenceContext(((TaskContext)event.getTaskContext()).getPersistenceContext());
try {
if (ti == null) {
logger.error("The task instance does not exist.");
return result;
}
Status status = newStatus != null ? newStatus : ti.getTaskData().getStatus();
result = persistenceContext.queryStringWithParametersInTransaction("select bts from BAMTaskSummaryImpl bts where bts.taskId=:taskId", true,
persistenceContext.addParametersToMap("taskId", ti.getId()),
BAMTaskSummaryImpl.class);
if (result == null) {
logger.warn("Unable find bam task entry for task id {} '{}', skipping bam task update", ti.getId(), ti.getName());
return null;
}
result.setStatus(status.toString());
if (ti.getTaskData().getActualOwner() != null) {
result.setUserId(ti.getTaskData().getActualOwner().getId());
}
if (worker != null) worker.updateTask(result, ti);
persistenceContext.merge(result);
return result;
} finally {
cleanup(persistenceContext);
}
}
/**
* Interface for performing additional operations to a <code>org.jbpm.services.task.impl.model.BAMTaskSummaryImpl</code> instance.
*/
protected interface BAMTaskWorker {
BAMTaskSummaryImpl createTask(BAMTaskSummaryImpl bamTask, Task task);
BAMTaskSummaryImpl updateTask(BAMTaskSummaryImpl bamTask, Task task);
}
@Override
public void beforeTaskActivatedEvent(TaskEvent event) {
}
@Override
public void beforeTaskClaimedEvent(TaskEvent event) {
}
@Override
public void beforeTaskSkippedEvent(TaskEvent event) {
}
@Override
public void beforeTaskStartedEvent(TaskEvent event) {
}
@Override
public void beforeTaskStoppedEvent(TaskEvent event) {
}
@Override
public void beforeTaskCompletedEvent(TaskEvent event) {
}
@Override
public void beforeTaskFailedEvent(TaskEvent event) {
}
@Override
public void beforeTaskAddedEvent(TaskEvent event) {
}
@Override
public void beforeTaskExitedEvent(TaskEvent event) {
}
@Override
public void beforeTaskReleasedEvent(TaskEvent event) {
}
@Override
public void beforeTaskResumedEvent(TaskEvent event) {
}
@Override
public void beforeTaskSuspendedEvent(TaskEvent event) {
}
@Override
public void beforeTaskForwardedEvent(TaskEvent event) {
}
@Override
public void beforeTaskDelegatedEvent(TaskEvent event) {
}
@Override
public void beforeTaskNominatedEvent(TaskEvent event) {
}
@Override
public boolean equals(Object obj) {
if ( this == obj )
return true;
if ( obj == null )
return false;
if ( (obj instanceof BAMTaskEventListener) )
return true;
return false;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + this.getClass().getName().hashCode();
return result;
}
private class BAMSummaryComparator implements Comparator<BAMTaskSummaryImpl> {
@Override
public int compare(BAMTaskSummaryImpl o1, BAMTaskSummaryImpl o2) {
return (o1.getTaskId()<o2.getTaskId() ? -1 : (o1.getTaskId()==o2.getTaskId() ? 0 : 1));
}
}
}