/**
* Copyright 2005 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.workflow.instance.impl;
import static org.jbpm.workflow.instance.impl.DummyEventListener.EMPTY_EVENT_LISTENER;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
import org.drools.core.common.InternalKnowledgeRuntime;
import org.drools.core.util.MVELSafeHelper;
import org.jbpm.process.core.ContextContainer;
import org.jbpm.process.core.context.variable.VariableScope;
import org.jbpm.process.core.timer.Timer;
import org.jbpm.process.instance.ContextInstance;
import org.jbpm.process.instance.InternalProcessRuntime;
import org.jbpm.process.instance.ProcessInstance;
import org.jbpm.process.instance.context.variable.VariableScopeInstance;
import org.jbpm.process.instance.impl.ProcessInstanceImpl;
import org.jbpm.workflow.core.DroolsAction;
import org.jbpm.workflow.core.impl.NodeImpl;
import org.jbpm.workflow.core.node.AsyncEventNode;
import org.jbpm.workflow.core.node.EventNode;
import org.jbpm.workflow.core.node.EventNodeInterface;
import org.jbpm.workflow.core.node.EventSubProcessNode;
import org.jbpm.workflow.core.node.StartNode;
import org.jbpm.workflow.instance.NodeInstance;
import org.jbpm.workflow.instance.WorkflowProcessInstance;
import org.jbpm.workflow.instance.node.CompositeNodeInstance;
import org.jbpm.workflow.instance.node.EndNodeInstance;
import org.jbpm.workflow.instance.node.EventBasedNodeInstanceInterface;
import org.jbpm.workflow.instance.node.EventNodeInstance;
import org.jbpm.workflow.instance.node.EventNodeInstanceInterface;
import org.jbpm.workflow.instance.node.EventSubProcessNodeInstance;
import org.kie.api.definition.process.Node;
import org.kie.api.definition.process.NodeContainer;
import org.kie.api.definition.process.WorkflowProcess;
import org.kie.api.runtime.EnvironmentName;
import org.kie.api.runtime.manager.RuntimeEngine;
import org.kie.api.runtime.manager.RuntimeManager;
import org.kie.api.runtime.process.EventListener;
import org.kie.api.runtime.process.NodeInstanceContainer;
import org.kie.internal.process.CorrelationKey;
import org.kie.internal.runtime.KnowledgeRuntime;
import org.kie.internal.runtime.manager.InternalRuntimeManager;
import org.kie.internal.runtime.manager.SessionNotFoundException;
import org.kie.internal.runtime.manager.context.CaseContext;
import org.kie.internal.runtime.manager.context.ProcessInstanceIdContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Default implementation of a RuleFlow process instance.
*
*/
public abstract class WorkflowProcessInstanceImpl extends ProcessInstanceImpl
implements WorkflowProcessInstance,
org.jbpm.workflow.instance.NodeInstanceContainer {
private static final long serialVersionUID = 510l;
private static final Logger logger = LoggerFactory.getLogger(WorkflowProcessInstanceImpl.class);
private final List<NodeInstance> nodeInstances = new ArrayList<NodeInstance>();;
private AtomicLong singleNodeInstanceCounter = new AtomicLong(0);
private Map<String, List<EventListener>> eventListeners = new HashMap<String, List<EventListener>>();
private Map<String, List<EventListener>> externalEventListeners = new HashMap<String, List<EventListener>>();
private List<String> completedNodeIds = new ArrayList<String>();
private List<String> activatingNodeIds;
private Map<String, Integer> iterationLevels = new HashMap<String, Integer>();
private int currentLevel;
private boolean persisted = false;
private Object faultData;
private boolean signalCompletion = true;
private String deploymentId;
private String correlationKey;
public NodeContainer getNodeContainer() {
return getWorkflowProcess();
}
public void addNodeInstance(final NodeInstance nodeInstance) {
if (nodeInstance.getId() == -1) {
// assign new id only if it does not exist as it might already be set by marshalling
// it's important to keep same ids of node instances as they might be references e.g. exclusive group
long id = singleNodeInstanceCounter.getAndIncrement();
((NodeInstanceImpl) nodeInstance).setId(id);
}
this.nodeInstances.add(nodeInstance);
}
@Override
public int getLevelForNode(String uniqueID) {
if ("true".equalsIgnoreCase(System.getProperty("jbpm.loop.level.disabled"))) {
return 1;
}
Integer value = iterationLevels.get(uniqueID);
if (value == null && currentLevel == 0) {
value = new Integer(1);
} else if ((value == null && currentLevel > 0) || (value != null && currentLevel > 0 && value > currentLevel)) {
value = new Integer(currentLevel);
} else {
value++;
}
iterationLevels.put(uniqueID, value);
return value;
}
public void removeNodeInstance(final NodeInstance nodeInstance) {
if (((NodeInstanceImpl) nodeInstance).isInversionOfControl()) {
getKnowledgeRuntime().delete(
getKnowledgeRuntime().getFactHandle(nodeInstance));
}
this.nodeInstances.remove(nodeInstance);
}
public Collection<org.kie.api.runtime.process.NodeInstance> getNodeInstances() {
return new ArrayList<org.kie.api.runtime.process.NodeInstance>(getNodeInstances(false));
}
public Collection<NodeInstance> getNodeInstances(boolean recursive) {
Collection<NodeInstance> result = nodeInstances;
if (recursive) {
result = new ArrayList<NodeInstance>(result);
for (Iterator<NodeInstance> iterator = nodeInstances.iterator(); iterator
.hasNext();) {
NodeInstance nodeInstance = iterator.next();
if (nodeInstance instanceof NodeInstanceContainer) {
result
.addAll(((org.jbpm.workflow.instance.NodeInstanceContainer) nodeInstance)
.getNodeInstances(true));
}
}
}
return Collections.unmodifiableCollection(result);
}
public NodeInstance getNodeInstance(long nodeInstanceId) {
for (NodeInstance nodeInstance: nodeInstances) {
if (nodeInstance.getId() == nodeInstanceId) {
return nodeInstance;
}
}
return null;
}
public NodeInstance getNodeInstance(long nodeInstanceId, boolean recursive) {
for (NodeInstance nodeInstance: getNodeInstances(recursive)) {
if (nodeInstance.getId() == nodeInstanceId) {
return nodeInstance;
}
}
return null;
}
public List<String> getActiveNodeIds() {
List<String> result = new ArrayList<String>();
addActiveNodeIds(this, result);
return result;
}
private void addActiveNodeIds(NodeInstanceContainer container, List<String> result) {
for (org.kie.api.runtime.process.NodeInstance nodeInstance: container.getNodeInstances()) {
result.add(((NodeImpl) ((NodeInstanceImpl) nodeInstance).getNode()).getUniqueId());
if (nodeInstance instanceof NodeInstanceContainer) {
addActiveNodeIds((NodeInstanceContainer) nodeInstance, result);
}
}
}
public NodeInstance getFirstNodeInstance(final long nodeId) {
for (final Iterator<NodeInstance> iterator = this.nodeInstances
.iterator(); iterator.hasNext();) {
final NodeInstance nodeInstance = iterator.next();
if (nodeInstance.getNodeId() == nodeId && nodeInstance.getLevel() == getCurrentLevel()) {
return nodeInstance;
}
}
return null;
}
public List<NodeInstance> getNodeInstances(final long nodeId) {
List<NodeInstance> result = new ArrayList<NodeInstance>();
for (final Iterator<NodeInstance> iterator = this.nodeInstances
.iterator(); iterator.hasNext();) {
final NodeInstance nodeInstance = iterator.next();
if (nodeInstance.getNodeId() == nodeId) {
result.add(nodeInstance);
}
}
return result;
}
public List<NodeInstance> getNodeInstances(final long nodeId, final List<NodeInstance> currentView) {
List<NodeInstance> result = new ArrayList<NodeInstance>();
for (final Iterator<NodeInstance> iterator = currentView.iterator(); iterator.hasNext();) {
final NodeInstance nodeInstance = iterator.next();
if (nodeInstance.getNodeId() == nodeId) {
result.add(nodeInstance);
}
}
return result;
}
public NodeInstance getNodeInstance(final Node node) {
Node actualNode = node;
// async continuation handling
if (node instanceof AsyncEventNode) {
actualNode = ((AsyncEventNode) node).getActualNode();
} else if (useAsync(node)) {
actualNode = new AsyncEventNode(node);
}
NodeInstanceFactory conf = NodeInstanceFactoryRegistry.getInstance(getKnowledgeRuntime().getEnvironment()).getProcessNodeInstanceFactory(actualNode);
if (conf == null) {
throw new IllegalArgumentException("Illegal node type: "
+ node.getClass());
}
NodeInstanceImpl nodeInstance = (NodeInstanceImpl) conf.getNodeInstance(actualNode, this, this);
if (nodeInstance == null) {
throw new IllegalArgumentException("Illegal node type: "
+ node.getClass());
}
if (((NodeInstanceImpl) nodeInstance).isInversionOfControl()) {
getKnowledgeRuntime().insert(nodeInstance);
}
return nodeInstance;
}
public long getNodeInstanceCounter() {
return singleNodeInstanceCounter.get();
}
public void internalSetNodeInstanceCounter(long nodeInstanceCounter) {
this.singleNodeInstanceCounter = new AtomicLong(nodeInstanceCounter);
}
public AtomicLong internalGetNodeInstanceCounter() {
return this.singleNodeInstanceCounter;
}
public WorkflowProcess getWorkflowProcess() {
return (WorkflowProcess) getProcess();
}
public Object getVariable(String name) {
// for disconnected process instances, try going through the variable scope instances
// (as the default variable scope cannot be retrieved as the link to the process could
// be null and the associated working memory is no longer accessible)
if (getKnowledgeRuntime() == null) {
List<ContextInstance> variableScopeInstances =
getContextInstances(VariableScope.VARIABLE_SCOPE);
if (variableScopeInstances != null && variableScopeInstances.size() == 1) {
for (ContextInstance contextInstance: variableScopeInstances) {
Object value = ((VariableScopeInstance) contextInstance).getVariable(name);
if (value != null) {
return value;
}
}
}
return null;
}
// else retrieve the variable scope
VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
getContextInstance(VariableScope.VARIABLE_SCOPE);
if (variableScopeInstance == null) {
return null;
}
return variableScopeInstance.getVariable(name);
}
public Map<String, Object> getVariables() {
// for disconnected process instances, try going through the variable scope instances
// (as the default variable scope cannot be retrieved as the link to the process could
// be null and the associated working memory is no longer accessible)
if (getKnowledgeRuntime() == null) {
List<ContextInstance> variableScopeInstances =
getContextInstances(VariableScope.VARIABLE_SCOPE);
if (variableScopeInstances == null) {
return null;
}
Map<String, Object> result = new HashMap<String, Object>();
for (ContextInstance contextInstance: variableScopeInstances) {
Map<String, Object> variables =
((VariableScopeInstance) contextInstance).getVariables();
result.putAll(variables);
}
return result;
}
// else retrieve the variable scope
VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
getContextInstance(VariableScope.VARIABLE_SCOPE);
if (variableScopeInstance == null) {
return null;
}
return variableScopeInstance.getVariables();
}
public void setVariable(String name, Object value) {
VariableScope variableScope = (VariableScope) ((ContextContainer) getProcess()).getDefaultContext( VariableScope.VARIABLE_SCOPE );
VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
getContextInstance(VariableScope.VARIABLE_SCOPE);
if (variableScopeInstance == null) {
throw new IllegalArgumentException("No variable scope found.");
}
variableScope.validateVariable(getProcessName(), name, value);
variableScopeInstance.setVariable(name, value);
}
public void setState(final int state, String outcome, Object faultData) {
this.faultData = faultData;
setState(state, outcome);
}
public void setState(final int state, String outcome) {
super.setState(state, outcome);
// TODO move most of this to ProcessInstanceImpl
if (state == ProcessInstance.STATE_COMPLETED
|| state == ProcessInstance.STATE_ABORTED) {
InternalKnowledgeRuntime kruntime = getKnowledgeRuntime();
InternalProcessRuntime processRuntime = (InternalProcessRuntime) kruntime.getProcessRuntime();
processRuntime.getProcessEventSupport().fireBeforeProcessCompleted(this, kruntime);
// deactivate all node instances of this process instance
while (!nodeInstances.isEmpty()) {
NodeInstance nodeInstance = nodeInstances.get(0);
((org.jbpm.workflow.instance.NodeInstance) nodeInstance)
.cancel();
}
removeEventListeners();
processRuntime.getProcessInstanceManager().removeProcessInstance(this);
processRuntime.getProcessEventSupport().fireAfterProcessCompleted(this, kruntime);
if (isSignalCompletion()) {
RuntimeManager manager = (RuntimeManager) kruntime.getEnvironment().get(EnvironmentName.RUNTIME_MANAGER);
if (getParentProcessInstanceId() > 0 && manager != null) {
try {
org.kie.api.runtime.manager.Context<?> context = ProcessInstanceIdContext.get(getParentProcessInstanceId());
String caseId = (String) kruntime.getEnvironment().get(EnvironmentName.CASE_ID);
if (caseId != null) {
context = CaseContext.get(caseId);
}
RuntimeEngine runtime = manager.getRuntimeEngine(context);
KnowledgeRuntime managedkruntime = (KnowledgeRuntime) runtime.getKieSession();
managedkruntime.signalEvent("processInstanceCompleted:" + getId(), this);
} catch (SessionNotFoundException e) {
// in case no session is found for parent process let's skip signal for process instance completion
}
} else {
processRuntime.getSignalManager().signalEvent("processInstanceCompleted:" + getId(), this);
}
}
}
}
public void setState(final int state) {
setState(state, null);
}
public void disconnect() {
removeEventListeners();
unregisterExternalEventNodeListeners();
for (NodeInstance nodeInstance : nodeInstances) {
if (nodeInstance instanceof EventBasedNodeInstanceInterface) {
((EventBasedNodeInstanceInterface) nodeInstance).removeEventListeners();
}
}
super.disconnect();
}
public void reconnect() {
super.reconnect();
for (NodeInstance nodeInstance : nodeInstances) {
if (nodeInstance instanceof EventBasedNodeInstanceInterface) {
((EventBasedNodeInstanceInterface) nodeInstance)
.addEventListeners();
}
}
registerExternalEventNodeListeners();
}
public String toString() {
final StringBuilder sb = new StringBuilder("WorkflowProcessInstance");
sb.append(getId());
sb.append(" [processId=");
sb.append(getProcessId());
sb.append(",state=");
sb.append(getState());
sb.append("]");
return sb.toString();
}
public void start() {
start(null);
}
public void start(String trigger) {
synchronized (this) {
registerExternalEventNodeListeners();
// activate timer event sub processes
Node[] nodes = getNodeContainer().getNodes();
for (Node node : nodes) {
if (node instanceof EventSubProcessNode) {
Map<Timer, DroolsAction> timers = ((EventSubProcessNode) node).getTimers();
if (timers != null && !timers.isEmpty()) {
EventSubProcessNodeInstance eventSubprocess = (EventSubProcessNodeInstance) getNodeInstance(node);
eventSubprocess.trigger(null, org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE);
}
}
}
super.start(trigger);
}
}
private void registerExternalEventNodeListeners() {
for (Node node : getWorkflowProcess().getNodes()) {
if (node instanceof EventNode) {
if ("external".equals(((EventNode) node).getScope())) {
addEventListener(((EventNode) node).getType(), EMPTY_EVENT_LISTENER, true);
}
} else if (node instanceof EventSubProcessNode) {
List<String> events = ((EventSubProcessNode) node).getEvents();
for (String type : events) {
addEventListener(type, EMPTY_EVENT_LISTENER, true);
}
}
}
if( getWorkflowProcess().getMetaData().containsKey("Compensation") ) {
addEventListener("Compensation", new CompensationEventListener(this), true);
}
}
private void unregisterExternalEventNodeListeners() {
for (Node node : getWorkflowProcess().getNodes()) {
if (node instanceof EventNode) {
if ("external".equals(((EventNode) node).getScope())) {
externalEventListeners.remove(((EventNode) node).getType());
}
}
}
}
@SuppressWarnings("unchecked")
public void signalEvent(String type, Object event) {
synchronized (this) {
if (getState() != ProcessInstance.STATE_ACTIVE) {
return;
}
InternalRuntimeManager manager = (InternalRuntimeManager) getKnowledgeRuntime().getEnvironment().get("RuntimeManager");
if (manager != null) {
// check if process instance is owned by the same manager as the one owning ksession
if (hasDeploymentId() && !manager.getIdentifier().equals(getDeploymentId())) {
logger.debug("Skipping signal on process instance " + getId() + " as it's owned by another deployment " +
getDeploymentId() + " != " + manager.getIdentifier());
return;
}
}
List<NodeInstance> currentView = new ArrayList<NodeInstance>(this.nodeInstances);
try {
this.activatingNodeIds = new ArrayList<String>();
List<EventListener> listeners = eventListeners.get(type);
if (listeners != null) {
for (EventListener listener : listeners) {
listener.signalEvent(type, event);
}
}
listeners = externalEventListeners.get(type);
if (listeners != null) {
for (EventListener listener : listeners) {
listener.signalEvent(type, event);
}
}
for (Node node : getWorkflowProcess().getNodes()) {
if (node instanceof EventNodeInterface) {
if (((EventNodeInterface) node).acceptsEvent(type, event, (e) -> resolveVariable(e) )) {
if (node instanceof EventNode && ((EventNode) node).getFrom() == null) {
EventNodeInstance eventNodeInstance = (EventNodeInstance) getNodeInstance(node);
eventNodeInstance.signalEvent(type, event);
} else {
if (node instanceof EventSubProcessNode && ((resolveVariables(((EventSubProcessNode) node).getEvents()).contains(type)))) {
EventSubProcessNodeInstance eventNodeInstance = (EventSubProcessNodeInstance) getNodeInstance(node);
eventNodeInstance.signalEvent(type, event);
} else {
List<NodeInstance> nodeInstances = getNodeInstances(node.getId(), currentView);
if (nodeInstances != null && !nodeInstances.isEmpty()) {
for (NodeInstance nodeInstance : nodeInstances) {
((EventNodeInstanceInterface) nodeInstance).signalEvent(type, event);
}
}
}
}
}
}
}
if (((org.jbpm.workflow.core.WorkflowProcess) getWorkflowProcess()).isDynamic()) {
for (Node node : getWorkflowProcess().getNodes()) {
if (type.equals(node.getName()) && node.getIncomingConnections().isEmpty()) {
NodeInstance nodeInstance = getNodeInstance(node);
if (event != null) {
Map<String, Object> dynamicParams = new HashMap<>();
if (event instanceof Map) {
dynamicParams.putAll((Map<String, Object>) event);
} else {
dynamicParams.put("Data", event);
}
((org.jbpm.workflow.instance.NodeInstance) nodeInstance).setDynamicParameters(dynamicParams);
}
((org.jbpm.workflow.instance.NodeInstance) nodeInstance).trigger(null, NodeImpl.CONNECTION_DEFAULT_TYPE);
}
}
}
} finally {
if (this.activatingNodeIds != null) {
this.activatingNodeIds.clear();
this.activatingNodeIds = null;
}
}
}
}
protected List<String> resolveVariables(List<String> events) {
return events.stream().map( event -> resolveVariable(event)).collect(Collectors.toList());
}
private String resolveVariable(String s) {
Map<String, String> replacements = new HashMap<String, String>();
Matcher matcher = PARAMETER_MATCHER.matcher(s);
while (matcher.find()) {
String paramName = matcher.group(1);
if (replacements.get(paramName) == null) {
Object variableValue = getVariable(paramName);
if (variableValue != null) {
String variableValueString = variableValue == null ? "" : variableValue.toString();
replacements.put(paramName, variableValueString);
} else {
try {
variableValue = MVELSafeHelper.getEvaluator().eval(paramName, new ProcessInstanceResolverFactory(this));
String variableValueString = variableValue == null ? "" : variableValue.toString();
replacements.put(paramName, variableValueString);
} catch (Throwable t) {
logger.error("Could not find variable scope for variable {}", paramName);
}
}
}
}
for (Map.Entry<String, String> replacement: replacements.entrySet()) {
s = s.replace("#{" + replacement.getKey() + "}", replacement.getValue());
}
return s;
}
public void addEventListener(String type, EventListener listener, boolean external) {
Map<String, List<EventListener>> eventListeners = external ? this.externalEventListeners : this.eventListeners;
List<EventListener> listeners = eventListeners.get(type);
if (listeners == null) {
listeners = new CopyOnWriteArrayList<EventListener>();
eventListeners.put(type, listeners);
if (external) {
((InternalProcessRuntime) getKnowledgeRuntime().getProcessRuntime())
.getSignalManager().addEventListener(type, this);
}
}
listeners.add(listener);
}
public void removeEventListener(String type, EventListener listener, boolean external) {
Map<String, List<EventListener>> eventListeners = external ? this.externalEventListeners : this.eventListeners;
List<EventListener> listeners = eventListeners.get(type);
if (listeners != null) {
listeners.remove(listener);
if (listeners.isEmpty()) {
eventListeners.remove(type);
if (external) {
((InternalProcessRuntime) getKnowledgeRuntime().getProcessRuntime())
.getSignalManager().removeEventListener(type, this);
}
}
} else {
eventListeners.remove(type);
}
}
private void removeEventListeners() {
for (String type : externalEventListeners.keySet()) {
((InternalProcessRuntime) getKnowledgeRuntime().getProcessRuntime())
.getSignalManager().removeEventListener(type, this);
}
}
public String[] getEventTypes() {
return externalEventListeners.keySet().toArray(new String[externalEventListeners.size()]);
}
public void nodeInstanceCompleted(NodeInstance nodeInstance, String outType) {
Node nodeInstanceNode = nodeInstance.getNode();
if( nodeInstanceNode != null ) {
Object compensationBoolObj = nodeInstanceNode.getMetaData().get("isForCompensation");
boolean isForCompensation = compensationBoolObj == null ? false : ((Boolean) compensationBoolObj);
if( isForCompensation ) {
return;
}
}
if (nodeInstance instanceof EndNodeInstance ||
((org.jbpm.workflow.core.WorkflowProcess) getWorkflowProcess()).isDynamic()
|| nodeInstance instanceof CompositeNodeInstance) {
if (((org.jbpm.workflow.core.WorkflowProcess) getProcess()).isAutoComplete()) {
if (canComplete()) {
setState(ProcessInstance.STATE_COMPLETED);
}
}
} else {
throw new IllegalArgumentException(
"Completing a node instance that has no outgoing connection is not supported.");
}
}
private boolean canComplete() {
if (nodeInstances.isEmpty()) {
return true;
} else {
int eventSubprocessCounter = 0;
for (NodeInstance nodeInstance : nodeInstances) {
Node node = nodeInstance.getNode();
if (node instanceof EventSubProcessNode) {
if (((EventSubProcessNodeInstance) nodeInstance).getNodeInstances().isEmpty()) {
eventSubprocessCounter++;
}
} else {
return false;
}
}
return eventSubprocessCounter == nodeInstances.size();
}
}
public void addCompletedNodeId(String uniqueId) {
this.completedNodeIds.add(uniqueId.intern());
}
public List<String> getCompletedNodeIds() {
return new ArrayList<String>(this.completedNodeIds);
}
public int getCurrentLevel() {
return currentLevel;
}
public void setCurrentLevel(int currentLevel) {
this.currentLevel = currentLevel;
}
public Map<String, Integer> getIterationLevels() {
return iterationLevels;
}
public boolean isPersisted() {
return persisted;
}
public void setPersisted(boolean persisted) {
this.persisted = persisted;
}
public void addActivatingNodeId(String uniqueId) {
if (this.activatingNodeIds == null) {
return;
}
this.activatingNodeIds.add(uniqueId.intern());
}
public List<String> getActivatingNodeIds() {
if (this.activatingNodeIds == null) {
return Collections.emptyList();
}
return new ArrayList<String>(this.activatingNodeIds);
}
public Object getFaultData() {
return faultData;
}
public boolean isSignalCompletion() {
return signalCompletion;
}
public void setSignalCompletion(boolean signalCompletion) {
this.signalCompletion = signalCompletion;
}
public String getDeploymentId() {
return deploymentId;
}
public void setDeploymentId(String deploymentId) {
this.deploymentId = deploymentId;
}
public String getCorrelationKey() {
if (correlationKey == null && getMetaData().get("CorrelationKey") != null) {
this.correlationKey = ((CorrelationKey) getMetaData().get("CorrelationKey")).toExternalForm();
}
return correlationKey;
}
public void setCorrelationKey(String correlationKey) {
this.correlationKey = correlationKey;
}
protected boolean hasDeploymentId() {
if (this.deploymentId == null || this.deploymentId.isEmpty()) {
return false;
}
return true;
}
protected boolean useAsync(final Node node) {
if (node instanceof StartNode) {
return false;
}
boolean asyncMode = Boolean.parseBoolean((String)node.getMetaData().get("customAsync"));
if (asyncMode) {
return asyncMode;
}
return Boolean.parseBoolean((String)getKnowledgeRuntime().getEnvironment().get("AsyncMode"));
}
}