
com.centurylink.mdw.workflow.activity.task.ManualTaskActivity Maven / Gradle / Ivy
/*
* Copyright (C) 2017 CenturyLink, Inc.
*
* 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 com.centurylink.mdw.workflow.activity.task;
import java.util.HashMap;
import java.util.Map;
import com.centurylink.mdw.activity.ActivityException;
import com.centurylink.mdw.activity.types.TaskActivity;
import com.centurylink.mdw.constant.OwnerType;
import com.centurylink.mdw.dataaccess.DataAccessException;
import com.centurylink.mdw.model.asset.AssetVersionSpec;
import com.centurylink.mdw.model.event.EventWaitInstance;
import com.centurylink.mdw.model.event.InternalEvent;
import com.centurylink.mdw.model.task.TaskInstance;
import com.centurylink.mdw.model.task.TaskTemplate;
import com.centurylink.mdw.model.workflow.ActivityRuntimeContext;
import com.centurylink.mdw.model.workflow.WorkStatus;
import com.centurylink.mdw.service.data.task.TaskDataAccess;
import com.centurylink.mdw.service.data.task.TaskTemplateCache;
import com.centurylink.mdw.services.ServiceLocator;
import com.centurylink.mdw.services.TaskServices;
import com.centurylink.mdw.workflow.activity.AbstractWait;
public abstract class ManualTaskActivity extends AbstractWait implements TaskActivity {
/**
* Creates a new task instance based on the configured template for this activity.
*/
protected TaskInstance createTaskInstance() throws ActivityException {
try {
String taskTemplate = getAttributeValue(ATTRIBUTE_TASK_TEMPLATE);
if (taskTemplate == null)
throw new ActivityException("Missing attribute: " + ATTRIBUTE_TASK_TEMPLATE);
String templateVersion = getAttributeValue(ATTRIBUTE_TASK_TEMPLATE_VERSION);
AssetVersionSpec spec = new AssetVersionSpec(taskTemplate, templateVersion == null ? "0" : templateVersion);
TaskTemplate template = TaskTemplateCache.getTaskTemplate(spec);
if (template == null)
throw new ActivityException("Task template not found: " + spec);
String taskName = template.getTaskName();
String title = null;
if (ActivityRuntimeContext.isExpression(taskName)) {
title = getRuntimeContext().evaluateToString(taskName);
}
String comments = null;
Exception exception = (Exception) getVariableValue("exception");
if (exception != null) {
comments = exception.toString();
if (exception instanceof ActivityException) {
ActivityRuntimeContext rc = ((ActivityException)exception).getRuntimeContext();
if (rc != null && rc.getProcess() != null) {
comments = rc.getProcess().getQualifiedLabel() + "\n" + comments;
}
}
}
return createTaskInstance(spec, getMasterRequestId(), getProcessInstanceId(),
getActivityInstanceId(), getWorkTransitionInstanceId(), title, comments);
}
catch (Exception ex) {
throw new ActivityException(ex.getMessage(), ex);
}
}
protected TaskInstance createTaskInstance(AssetVersionSpec spec, String masterRequestId, Long processInstanceId,
Long activityInstanceId, Long transitionId, String title, String comments) throws Exception {
TaskTemplate taskVO = TaskTemplateCache.getTaskTemplate(spec);
if (taskVO == null)
throw new DataAccessException("Task template not found: " + spec);
TaskServices taskServices = ServiceLocator.getTaskServices();
TaskInstance instance = taskServices.createTask(taskVO.getTaskId(), masterRequestId, processInstanceId,
OwnerType.WORK_TRANSITION_INSTANCE, transitionId, title, comments);
logger.info("Created task instance " + instance.getId() + " (" + taskVO.getTaskName() + ")");
return instance;
}
protected static final String WAIT_FOR_TASK = "Wait for Task";
public boolean needSuspend() {
String waitForTask = this.getAttributeValue(WAIT_FOR_TASK);
return waitForTask==null || waitForTask.equalsIgnoreCase("true");
}
protected static final String INSTANCE_ID_VAR = "INSTANCE_ID_VAR";
public String getInstanceIdVariable() {
return this.getAttributeValue(INSTANCE_ID_VAR);
}
protected boolean resume(String message, String completionCode) throws ActivityException {
if (messageIsTaskAction(message)) {
processTaskAction(message);
return true;
}
else {
this.setReturnCode(completionCode);
processOtherMessage(message);
Integer actInstStatus = super.handleEventCompletionCode();
if (actInstStatus.equals(WorkStatus.STATUS_CANCELLED)) {
try {
ServiceLocator.getTaskServices().cancelTaskForActivity(getActivityInstanceId());
}
catch (Exception ex) {
logger.error("Failed to cancel task instance - process moves on", ex);
}
} else if (actInstStatus.equals(WorkStatus.STATUS_WAITING)) {
try {
getEngine().createEventWaitInstance(getProcessInstanceId(), getActivityInstanceId(), getWaitEvent(), null, true, true);
}
catch (Exception ex) {
logger.error("Failed to re-register task action listening", ex);
}
// unsolicited event listening is already registered by handleEventCompletionCode
}
return true;
}
}
protected abstract String getWaitEvent() throws ActivityException;
protected abstract boolean messageIsTaskAction(String message) throws ActivityException;
protected abstract void processTaskAction(String message) throws ActivityException;
/**
* The resume method for ManualTaskAndEventWait is handling internal functions related to
* task completion as well as custom events, so it is not supposed to be overriden. The method
* is therefore declared as final. To customize handling of events, please override
* the method {@link #processOtherMessage(String, String)}
*/
public final boolean resume(InternalEvent event) throws ActivityException {
// secondary owner type must be OwnerType.EXTERNAL_EVENT_INSTANCE
String messageString = super.getMessageFromEventMessage(event);
return resume(messageString, event.getCompletionCode());
}
/**
* This method is made final for the class, as it contains internal logic handling resumption
* of waiting. It re-register the event waits including waiting for task to complete.
* If any event has already arrived, it processes it immediately.
*
* Customization should be done with the methods {@link #processOtherMessage(String, String)}
* and {@link #registerWaitEvents()}.
*/
public final boolean resumeWaiting(InternalEvent event) throws ActivityException {
boolean done;
EventWaitInstance received;
try {
received = getEngine().createEventWaitInstance(getProcessInstanceId(), getActivityInstanceId(), getWaitEvent(), null, true, false);
if (received == null)
received = registerWaitEvents(true);
}
catch (Exception e) {
throw new ActivityException(-1, e.getMessage(), e);
}
if (received != null) {
done = resume(getExternalEventInstanceDetails(received.getMessageDocumentId()),
received.getCompletionCode());
}
else {
done = false;
}
return done;
}
/**
* This method is invoked to process a received event (other than task completion).
* You will need to override this method to customize processing of the event.
*
* The default method does nothing.
*
* The status of the activity after processing the event is configured at design time, which
* can be either Hold or Waiting.
*
* When you override this method, you can optionally set different completion
* code from those configured at design time by calling setReturnCode().
*
* @param message the entire message content of the event
*/
protected void processOtherMessage(String message) throws ActivityException {
}
protected void updateOwningTransition(Long taskInstanceId) throws DataAccessException {
Map changes = new HashMap();
changes.put("TASK_INSTANCE_OWNER", OwnerType.PROCESS_INSTANCE);
changes.put("TASK_INSTANCE_OWNER_ID", getProcessInstanceId());
changes.put("TASK_INST_SECONDARY_OWNER", OwnerType.WORK_TRANSITION_INSTANCE);
changes.put("TASK_INST_SECONDARY_OWNER_ID", getWorkTransitionInstanceId());
new TaskDataAccess().updateTaskInstance(taskInstanceId, changes, false);
}
protected TaskInstance getTaskInstance(Long taskInstanceId) throws DataAccessException {
return new TaskDataAccess().getTaskInstance(taskInstanceId);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy