/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library 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 library 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.
*/
package com.liferay.portal.workflow.kaleo.runtime.internal;
import com.liferay.osgi.util.ServiceTrackerFactory;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.Role;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.transaction.Isolation;
import com.liferay.portal.kernel.transaction.Propagation;
import com.liferay.portal.kernel.transaction.Transactional;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.workflow.WorkflowConstants;
import com.liferay.portal.kernel.workflow.WorkflowException;
import com.liferay.portal.kernel.workflow.WorkflowTask;
import com.liferay.portal.spring.extender.service.ServiceReference;
import com.liferay.portal.workflow.kaleo.KaleoWorkflowModelConverter;
import com.liferay.portal.workflow.kaleo.definition.ExecutionType;
import com.liferay.portal.workflow.kaleo.model.KaleoInstance;
import com.liferay.portal.workflow.kaleo.model.KaleoNode;
import com.liferay.portal.workflow.kaleo.model.KaleoTask;
import com.liferay.portal.workflow.kaleo.model.KaleoTaskAssignmentInstance;
import com.liferay.portal.workflow.kaleo.model.KaleoTaskForm;
import com.liferay.portal.workflow.kaleo.model.KaleoTaskInstanceToken;
import com.liferay.portal.workflow.kaleo.model.KaleoTransition;
import com.liferay.portal.workflow.kaleo.runtime.ExecutionContext;
import com.liferay.portal.workflow.kaleo.runtime.TaskManager;
import com.liferay.portal.workflow.kaleo.runtime.action.KaleoActionExecutor;
import com.liferay.portal.workflow.kaleo.runtime.form.FormDefinitionRetriever;
import com.liferay.portal.workflow.kaleo.runtime.notification.NotificationHelper;
import com.liferay.portal.workflow.kaleo.runtime.util.WorkflowContextUtil;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.osgi.util.tracker.ServiceTracker;
/**
* @author Michael C. Han
*/
@Transactional(
isolation = Isolation.PORTAL, propagation = Propagation.REQUIRED,
rollbackFor = {Exception.class}
)
public class DefaultTaskManagerImpl
extends BaseKaleoBean implements TaskManager {
@Override
public WorkflowTask assignWorkflowTaskToRole(
long workflowTaskInstanceId, long roleId, String comment,
Date dueDate, Map<String, Serializable> workflowContext,
ServiceContext serviceContext)
throws WorkflowException {
try {
return assignWorkflowTask(
workflowTaskInstanceId, Role.class.getName(), roleId, comment,
dueDate, workflowContext, serviceContext);
}
catch (Exception e) {
throw new WorkflowException(e);
}
}
@Override
public WorkflowTask assignWorkflowTaskToUser(
long workflowTaskInstanceId, long assigneeUserId, String comment,
Date dueDate, Map<String, Serializable> workflowContext,
ServiceContext serviceContext)
throws WorkflowException {
try {
return assignWorkflowTask(
workflowTaskInstanceId, User.class.getName(), assigneeUserId,
comment, dueDate, workflowContext, serviceContext);
}
catch (Exception e) {
throw new WorkflowException(e);
}
}
@Override
public WorkflowTask completeWorkflowTask(
long workflowTaskInstanceId, long workflowTaskFormId,
String formValues, Map<String, Serializable> workflowContext,
ServiceContext serviceContext)
throws WorkflowException {
return completeWorkflowTask(
workflowTaskInstanceId, workflowTaskFormId, formValues, null,
workflowContext, serviceContext);
}
@Override
public WorkflowTask completeWorkflowTask(
long workflowTaskInstanceId, long workflowTaskFormId,
String formValues, String transitionName,
Map<String, Serializable> workflowContext,
ServiceContext serviceContext)
throws WorkflowException {
try {
KaleoTaskInstanceToken kaleoTaskInstanceToken =
kaleoTaskInstanceTokenLocalService.getKaleoTaskInstanceToken(
workflowTaskInstanceId);
kaleoTaskFormInstanceLocalService.addKaleoTaskFormInstance(
kaleoTaskInstanceToken.getGroupId(), workflowTaskFormId,
formValues, kaleoTaskInstanceToken, serviceContext);
if (kaleoTaskInstanceTokenLocalService.hasPendingKaleoTaskForms(
workflowTaskInstanceId)) {
return _kaleoWorkflowModelConverter.toWorkflowTask(
kaleoTaskInstanceToken, workflowContext);
}
if (Validator.isNull(transitionName)) {
KaleoTask kaleoTask = kaleoTaskLocalService.getKaleoTask(
kaleoTaskInstanceToken.getKaleoTaskId());
KaleoNode kaleoNode = kaleoTask.getKaleoNode();
List<KaleoTransition> kaleoTransitions =
kaleoNode.getKaleoTransitions();
if (kaleoTransitions.size() == 1) {
if (_log.isDebugEnabled()) {
_log.debug(
"Automatically completing form task: " +
kaleoTask.getName());
}
KaleoTransition kaleoTransition = kaleoTransitions.get(0);
transitionName = kaleoTransition.getName();
}
}
return doCompleteWorkflowTask(
workflowTaskInstanceId, transitionName, null, workflowContext,
serviceContext);
}
catch (Exception e) {
throw new WorkflowException(e);
}
}
@Override
public WorkflowTask completeWorkflowTask(
long workflowTaskInstanceId, String transitionName, String comment,
Map<String, Serializable> workflowContext,
ServiceContext serviceContext)
throws WorkflowException {
try {
return doCompleteWorkflowTask(
workflowTaskInstanceId, transitionName, comment,
workflowContext, serviceContext);
}
catch (Exception e) {
throw new WorkflowException(e);
}
}
@Override
public List<String> getWorkflowTaskFormDefinitions(
long workflowTaskInstanceId, ServiceContext serviceContext)
throws WorkflowException {
try {
KaleoTaskInstanceToken kaleoTaskInstanceToken =
kaleoTaskInstanceTokenLocalService.getKaleoTaskInstanceToken(
workflowTaskInstanceId);
List<KaleoTaskForm> kaleoTaskForms =
kaleoTaskFormLocalService.getKaleoTaskForms(
kaleoTaskInstanceToken.getKaleoTaskId());
List<String> kaleoTaskFormDefinitions = new ArrayList<>(
kaleoTaskForms.size());
for (KaleoTaskForm kaleoTaskForm : kaleoTaskForms) {
String kaleoFormDefinition = kaleoTaskForm.getFormDefinition();
if (Validator.isNull(kaleoFormDefinition)) {
FormDefinitionRetriever formDefinitionRetriever =
getFormDefinitionRetriever();
if (formDefinitionRetriever != null) {
kaleoFormDefinition =
formDefinitionRetriever.getFormDefinition(
kaleoTaskForm, kaleoTaskInstanceToken);
}
else {
if (_log.isWarnEnabled()) {
_log.warn("No form definition retriever defined");
}
}
}
if (Validator.isNotNull(kaleoFormDefinition)) {
kaleoTaskFormDefinitions.add(kaleoFormDefinition);
}
}
return kaleoTaskFormDefinitions;
}
catch (PortalException pe) {
throw new WorkflowException(pe);
}
}
@Override
public WorkflowTask updateDueDate(
long workflowTaskInstanceId, String comment, Date dueDate,
ServiceContext serviceContext)
throws WorkflowException {
try {
KaleoTaskInstanceToken kaleoTaskInstanceToken =
kaleoTaskInstanceTokenLocalService.getKaleoTaskInstanceToken(
workflowTaskInstanceId);
if (kaleoTaskInstanceToken.isCompleted()) {
throw new WorkflowException(
"Cannot update due date for completed task " +
workflowTaskInstanceId);
}
if (dueDate != null) {
kaleoTaskInstanceTokenLocalService.updateDueDate(
workflowTaskInstanceId, dueDate, serviceContext);
}
Map<String, Serializable> workflowContext =
WorkflowContextUtil.convert(
kaleoTaskInstanceToken.getWorkflowContext());
kaleoLogLocalService.addTaskUpdateKaleoLog(
kaleoTaskInstanceToken, comment, workflowContext,
serviceContext);
return _kaleoWorkflowModelConverter.toWorkflowTask(
kaleoTaskInstanceToken, workflowContext);
}
catch (Exception e) {
throw new WorkflowException(e);
}
}
protected WorkflowTask assignWorkflowTask(
long workflowTaskInstanceId, String assigneeClassName,
long assigneeClassPK, String comment, Date dueDate,
Map<String, Serializable> workflowContext,
ServiceContext serviceContext)
throws Exception {
KaleoTaskInstanceToken kaleoTaskInstanceToken =
kaleoTaskInstanceTokenLocalService.getKaleoTaskInstanceToken(
workflowTaskInstanceId);
List<KaleoTaskAssignmentInstance> previousTaskAssignmentInstances =
kaleoTaskInstanceToken.getKaleoTaskAssignmentInstances();
workflowContext = updateWorkflowContext(
workflowContext, kaleoTaskInstanceToken);
if (kaleoTaskInstanceToken.isCompleted()) {
throw new WorkflowException(
"Cannot reassign a completed task " + workflowTaskInstanceId);
}
if (dueDate != null) {
kaleoTaskInstanceTokenLocalService.updateDueDate(
workflowTaskInstanceId, dueDate, serviceContext);
}
kaleoTaskInstanceToken =
kaleoTaskInstanceTokenLocalService.assignKaleoTaskInstanceToken(
kaleoTaskInstanceToken.getKaleoTaskInstanceTokenId(),
assigneeClassName, assigneeClassPK, workflowContext,
serviceContext);
workflowContext.put(WorkflowConstants.CONTEXT_TASK_COMMENTS, comment);
ExecutionContext executionContext = new ExecutionContext(
kaleoTaskInstanceToken.getKaleoInstanceToken(),
kaleoTaskInstanceToken, workflowContext, serviceContext);
KaleoTask kaleoTask = kaleoTaskInstanceToken.getKaleoTask();
_kaleoActionExecutor.executeKaleoActions(
KaleoNode.class.getName(), kaleoTask.getKaleoNodeId(),
ExecutionType.ON_ASSIGNMENT, executionContext);
boolean selfAssignment = false;
if (assigneeClassName.equals(User.class.getName()) &&
(assigneeClassPK == serviceContext.getUserId())) {
selfAssignment = true;
}
if (!selfAssignment) {
_notificationHelper.sendKaleoNotifications(
KaleoNode.class.getName(), kaleoTask.getKaleoNodeId(),
ExecutionType.ON_ASSIGNMENT, executionContext);
}
kaleoLogLocalService.addTaskAssignmentKaleoLog(
previousTaskAssignmentInstances, kaleoTaskInstanceToken, comment,
workflowContext, serviceContext);
return _kaleoWorkflowModelConverter.toWorkflowTask(
kaleoTaskInstanceToken, workflowContext);
}
protected WorkflowTask doCompleteWorkflowTask(
long workflowTaskInstanceId, String transitionName, String comment,
Map<String, Serializable> workflowContext,
ServiceContext serviceContext)
throws Exception {
KaleoTaskInstanceToken kaleoTaskInstanceToken =
kaleoTaskInstanceTokenLocalService.getKaleoTaskInstanceToken(
workflowTaskInstanceId);
if (Validator.isNotNull(transitionName)) {
// Validate that the transition actually exists before moving
// forward
KaleoTask kaleoTask = kaleoTaskInstanceToken.getKaleoTask();
KaleoNode currentKaleoNode = kaleoTask.getKaleoNode();
currentKaleoNode.getKaleoTransition(transitionName);
}
workflowContext = updateWorkflowContext(
workflowContext, kaleoTaskInstanceToken);
if (kaleoTaskInstanceToken.isCompleted()) {
throw new WorkflowException(
"Cannot complete an already completed task " +
workflowTaskInstanceId + " for user " +
serviceContext.getUserId());
}
serviceContext.setScopeGroupId(kaleoTaskInstanceToken.getGroupId());
kaleoTaskInstanceToken =
kaleoTaskInstanceTokenLocalService.completeKaleoTaskInstanceToken(
kaleoTaskInstanceToken.getKaleoTaskInstanceTokenId(),
serviceContext);
kaleoLogLocalService.addTaskCompletionKaleoLog(
kaleoTaskInstanceToken, comment, workflowContext, serviceContext);
return _kaleoWorkflowModelConverter.toWorkflowTask(
kaleoTaskInstanceToken, workflowContext);
}
protected FormDefinitionRetriever getFormDefinitionRetriever() {
return _serviceTracker.getService();
}
protected Map<String, Serializable> updateWorkflowContext(
Map<String, Serializable> workflowContext,
KaleoTaskInstanceToken kaleoTaskInstanceToken)
throws PortalException {
KaleoInstance kaleoInstance =
kaleoInstanceLocalService.getKaleoInstance(
kaleoTaskInstanceToken.getKaleoInstanceId());
if (workflowContext == null) {
workflowContext = WorkflowContextUtil.convert(
kaleoInstance.getWorkflowContext());
}
else {
Map<String, Serializable> storedWorkflowContext =
WorkflowContextUtil.convert(kaleoInstance.getWorkflowContext());
for (Map.Entry<String, Serializable> entry :
storedWorkflowContext.entrySet()) {
String key = entry.getKey();
if (!workflowContext.containsKey(key)) {
workflowContext.put(key, entry.getValue());
}
}
}
return workflowContext;
}
private static final Log _log = LogFactoryUtil.getLog(
DefaultTaskManagerImpl.class);
private static final ServiceTracker
<FormDefinitionRetriever, FormDefinitionRetriever> _serviceTracker =
ServiceTrackerFactory.open(FormDefinitionRetriever.class);
@ServiceReference(type = KaleoActionExecutor.class)
private KaleoActionExecutor _kaleoActionExecutor;
@ServiceReference(type = KaleoWorkflowModelConverter.class)
private KaleoWorkflowModelConverter _kaleoWorkflowModelConverter;
@ServiceReference(type = NotificationHelper.class)
private NotificationHelper _notificationHelper;
}