use of org.kie.kogito.internal.process.runtime.KogitoNodeInstance in project kogito-runtimes by kiegroup.
the class SplitInstance method executeStrategy.
protected void executeStrategy(Split split, String type) {
// TODO make different strategies for each type
switch(split.getType()) {
case Split.TYPE_AND:
triggerCompleted(Node.CONNECTION_DEFAULT_TYPE, true);
break;
case Split.TYPE_XOR:
List<Connection> outgoing = split.getDefaultOutgoingConnections();
int priority = Integer.MAX_VALUE;
Connection selected = null;
for (final Iterator<Connection> iterator = outgoing.iterator(); iterator.hasNext(); ) {
final Connection connection = (Connection) iterator.next();
ConstraintEvaluator constraint = (ConstraintEvaluator) split.getConstraint(connection);
if (constraint != null && constraint.getPriority() < priority && !constraint.isDefault()) {
try {
if (constraint.evaluate(this, connection, constraint)) {
selected = connection;
priority = constraint.getPriority();
}
} catch (RuntimeException e) {
throw new RuntimeException("Exception when trying to evaluate constraint " + constraint.getName() + " in split " + split.getName(), e);
}
}
}
((NodeInstanceContainer) getNodeInstanceContainer()).removeNodeInstance(this);
if (selected == null) {
for (final Iterator<Connection> iterator = outgoing.iterator(); iterator.hasNext(); ) {
final Connection connection = (Connection) iterator.next();
if (split.isDefault(connection)) {
selected = connection;
break;
}
}
}
if (selected == null) {
throw new IllegalArgumentException("XOR split could not find at least one valid outgoing connection for split " + getSplit().getName());
}
if (!hasLoop(selected.getTo(), split)) {
setLevel(1);
((NodeInstanceContainer) getNodeInstanceContainer()).setCurrentLevel(1);
}
triggerConnection(selected);
break;
case Split.TYPE_OR:
((NodeInstanceContainer) getNodeInstanceContainer()).removeNodeInstance(this);
outgoing = split.getDefaultOutgoingConnections();
boolean found = false;
List<NodeInstanceTrigger> nodeInstances = new ArrayList<NodeInstanceTrigger>();
List<Connection> outgoingCopy = new ArrayList<Connection>(outgoing);
while (!outgoingCopy.isEmpty()) {
priority = Integer.MAX_VALUE;
Connection selectedConnection = null;
ConstraintEvaluator selectedConstraint = null;
for (final Iterator<Connection> iterator = outgoingCopy.iterator(); iterator.hasNext(); ) {
final Connection connection = (Connection) iterator.next();
ConstraintEvaluator constraint = (ConstraintEvaluator) split.getConstraint(connection);
if (constraint != null && constraint.getPriority() < priority && !constraint.isDefault()) {
priority = constraint.getPriority();
selectedConnection = connection;
selectedConstraint = constraint;
}
}
if (selectedConstraint == null) {
break;
}
if (selectedConstraint.evaluate(this, selectedConnection, selectedConstraint)) {
nodeInstances.add(new NodeInstanceTrigger(followConnection(selectedConnection), selectedConnection.getToType()));
found = true;
}
outgoingCopy.remove(selectedConnection);
}
for (NodeInstanceTrigger nodeInstance : nodeInstances) {
// stop if this process instance has been aborted / completed
if (getProcessInstance().getState() != ProcessInstance.STATE_ACTIVE) {
return;
}
triggerNodeInstance(nodeInstance.getNodeInstance(), nodeInstance.getToType());
}
if (!found) {
for (final Iterator<Connection> iterator = outgoing.iterator(); iterator.hasNext(); ) {
final Connection connection = (Connection) iterator.next();
ConstraintEvaluator constraint = (ConstraintEvaluator) split.getConstraint(connection);
if (constraint != null && constraint.isDefault() || split.isDefault(connection)) {
triggerConnection(connection);
found = true;
break;
}
}
}
if (!found) {
throw new IllegalArgumentException("OR split could not find at least one valid outgoing connection for split " + getSplit().getName());
}
break;
case Split.TYPE_XAND:
((org.jbpm.workflow.instance.NodeInstanceContainer) getNodeInstanceContainer()).removeNodeInstance(this);
org.kie.api.definition.process.Node node = getNode();
List<Connection> connections = null;
if (node != null) {
connections = node.getOutgoingConnections(type);
}
if (connections == null || connections.isEmpty()) {
((org.jbpm.workflow.instance.NodeInstanceContainer) getNodeInstanceContainer()).nodeInstanceCompleted(this, type);
} else {
ExclusiveGroupInstance groupInstance = new ExclusiveGroupInstance();
org.kie.api.runtime.process.NodeInstanceContainer parent = getNodeInstanceContainer();
if (parent instanceof ContextInstanceContainer) {
((ContextInstanceContainer) parent).addContextInstance(ExclusiveGroup.EXCLUSIVE_GROUP, groupInstance);
} else {
throw new IllegalArgumentException("An Exclusive AND is only possible if the parent is a context instance container");
}
Map<org.jbpm.workflow.instance.NodeInstance, String> nodeInstancesMap = new HashMap<org.jbpm.workflow.instance.NodeInstance, String>();
for (Connection connection : connections) {
nodeInstancesMap.put(followConnection(connection), connection.getToType());
}
for (KogitoNodeInstance nodeInstance : nodeInstancesMap.keySet()) {
groupInstance.addNodeInstance(nodeInstance);
}
for (Map.Entry<org.jbpm.workflow.instance.NodeInstance, String> entry : nodeInstancesMap.entrySet()) {
// stop if this process instance has been aborted / completed
if (getProcessInstance().getState() != ProcessInstance.STATE_ACTIVE) {
return;
}
boolean hidden = false;
if (getNode().getMetaData().get("hidden") != null) {
hidden = true;
}
InternalKnowledgeRuntime kruntime = getProcessInstance().getKnowledgeRuntime();
if (!hidden) {
((InternalProcessRuntime) kruntime.getProcessRuntime()).getProcessEventSupport().fireBeforeNodeLeft(this, kruntime);
}
((org.jbpm.workflow.instance.NodeInstance) entry.getKey()).trigger(this, entry.getValue());
if (!hidden) {
((InternalProcessRuntime) kruntime.getProcessRuntime()).getProcessEventSupport().fireAfterNodeLeft(this, kruntime);
}
}
}
break;
default:
throw new IllegalArgumentException("Illegal split type " + split.getType());
}
}
use of org.kie.kogito.internal.process.runtime.KogitoNodeInstance in project kogito-runtimes by kiegroup.
the class StateBasedNodeInstance method internalTrigger.
@Override
public void internalTrigger(KogitoNodeInstance from, String type) {
super.internalTrigger(from, type);
// if node instance was cancelled, abort
if (getNodeInstanceContainer().getNodeInstance(getStringId()) == null) {
return;
}
// activate timers
Map<Timer, DroolsAction> timers = getEventBasedNode().getTimers();
if (timers != null) {
addTimerListener();
timerInstances = new ArrayList<>(timers.size());
JobsService jobService = ((KogitoProcessRuntime.Provider) getProcessInstance().getKnowledgeRuntime().getProcessRuntime()).getKogitoProcessRuntime().getJobsService();
for (Timer timer : timers.keySet()) {
ProcessInstanceJobDescription jobDescription = ProcessInstanceJobDescription.of(new TimerJobId(timer.getId()), createTimerInstance(timer), getProcessInstance().getStringId(), getProcessInstance().getRootProcessInstanceId(), getProcessInstance().getProcessId(), getProcessInstance().getRootProcessId(), Optional.ofNullable(from).map(KogitoNodeInstance::getStringId).orElse(null));
timerInstances.add(jobService.scheduleProcessInstanceJob(jobDescription));
}
}
if (getEventBasedNode().getBoundaryEvents() != null) {
for (String name : getEventBasedNode().getBoundaryEvents()) {
boolean isActive = ((InternalAgenda) getProcessInstance().getKnowledgeRuntime().getAgenda()).isRuleActiveInRuleFlowGroup("DROOLS_SYSTEM", name, getProcessInstance().getId());
if (isActive) {
getProcessInstance().getKnowledgeRuntime().signalEvent(name, null);
} else {
addActivationListener();
}
}
}
((WorkflowProcessInstanceImpl) getProcessInstance()).addActivatingNodeId((String) getNode().getMetaData().get("UniqueId"));
}
use of org.kie.kogito.internal.process.runtime.KogitoNodeInstance in project kogito-runtimes by kiegroup.
the class CompositeNodeInstance method internalTrigger.
@Override
public void internalTrigger(KogitoNodeInstance from, String type) {
super.internalTrigger(from, type);
// if node instance was cancelled, abort
if (getNodeInstanceContainer().getNodeInstance(getStringId()) == null) {
return;
}
CompositeNode.NodeAndType nodeAndType = getCompositeNode().internalGetLinkedIncomingNode(type);
if (nodeAndType != null) {
List<Connection> connections = nodeAndType.getNode().getIncomingConnections(nodeAndType.getType());
for (Connection connection : connections) {
if ((connection.getFrom() instanceof CompositeNode.CompositeNodeStart) && (from == null || ((CompositeNode.CompositeNodeStart) connection.getFrom()).getInNode().getId() == from.getNodeId())) {
NodeInstance nodeInstance = getNodeInstance(connection.getFrom());
nodeInstance.trigger(null, nodeAndType.getType());
return;
}
}
} else {
// try to search for start nodes
boolean found = false;
for (org.kie.api.definition.process.Node node : getCompositeNode().getNodes()) {
if (node instanceof StartNode) {
StartNode startNode = (StartNode) node;
if (startNode.getTriggers() == null || startNode.getTriggers().isEmpty()) {
NodeInstance nodeInstance = getNodeInstance(startNode);
nodeInstance.trigger(null, null);
found = true;
}
}
}
if (found) {
return;
}
}
if (isLinkedIncomingNodeRequired()) {
throw new IllegalArgumentException("Could not find start for composite node: " + type);
}
}
use of org.kie.kogito.internal.process.runtime.KogitoNodeInstance in project kogito-runtimes by kiegroup.
the class EndNodeInstance method internalTrigger.
@Override
public void internalTrigger(KogitoNodeInstance from, String type) {
super.internalTrigger(from, type);
if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
throw new IllegalArgumentException("An EndNode only accepts default incoming connections!");
}
leaveTime = new Date();
boolean hidden = false;
if (getNode().getMetaData().get(HIDDEN) != null) {
hidden = true;
}
InternalKnowledgeRuntime kruntime = getProcessInstance().getKnowledgeRuntime();
if (!hidden) {
((InternalProcessRuntime) kruntime.getProcessRuntime()).getProcessEventSupport().fireBeforeNodeLeft(this, kruntime);
}
((NodeInstanceContainer) getNodeInstanceContainer()).removeNodeInstance(this);
if (getEndNode().isTerminate()) {
if (getNodeInstanceContainer() instanceof CompositeNodeInstance) {
if (getEndNode().getScope() == PROCESS_SCOPE) {
getProcessInstance().setState(KogitoProcessInstance.STATE_COMPLETED);
} else {
while (!getNodeInstanceContainer().getNodeInstances().isEmpty()) {
((org.jbpm.workflow.instance.NodeInstance) getNodeInstanceContainer().getNodeInstances().iterator().next()).cancel();
}
((NodeInstanceContainer) getNodeInstanceContainer()).nodeInstanceCompleted(this, null);
}
} else {
((NodeInstanceContainer) getNodeInstanceContainer()).setState(KogitoProcessInstance.STATE_COMPLETED);
}
} else {
((NodeInstanceContainer) getNodeInstanceContainer()).nodeInstanceCompleted(this, null);
}
if (!hidden) {
((InternalProcessRuntime) kruntime.getProcessRuntime()).getProcessEventSupport().fireAfterNodeLeft(this, kruntime);
}
}
use of org.kie.kogito.internal.process.runtime.KogitoNodeInstance in project kogito-runtimes by kiegroup.
the class FaultNodeInstance method internalTrigger.
public void internalTrigger(KogitoNodeInstance from, String type) {
if (!Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
throw new IllegalArgumentException("A FaultNode only accepts default incoming connections!");
}
triggerTime = new Date();
String faultName = getFaultName();
ExceptionScopeInstance exceptionScopeInstance = getExceptionScopeInstance(faultName);
NodeInstanceContainer nodeInstanceContainer = (NodeInstanceContainer) getNodeInstanceContainer();
nodeInstanceContainer.removeNodeInstance(this);
boolean exceptionHandled = false;
if (getFaultNode().isTerminateParent()) {
// handle exception before canceling nodes to allow boundary event to catch the events
if (exceptionScopeInstance != null) {
exceptionHandled = true;
handleException(faultName, exceptionScopeInstance);
}
if (nodeInstanceContainer instanceof CompositeNodeInstance) {
((CompositeNodeInstance) nodeInstanceContainer).cancel();
} else if (nodeInstanceContainer instanceof WorkflowProcessInstance) {
Collection<NodeInstance> nodeInstances = ((WorkflowProcessInstance) nodeInstanceContainer).getNodeInstances();
for (NodeInstance nodeInstance : nodeInstances) {
((org.jbpm.workflow.instance.NodeInstance) nodeInstance).cancel();
}
}
}
if (exceptionScopeInstance != null) {
if (!exceptionHandled) {
handleException(faultName, exceptionScopeInstance);
}
boolean hidden = false;
if (getNode().getMetaData().get("hidden") != null) {
hidden = true;
}
if (!hidden) {
InternalKnowledgeRuntime kruntime = getProcessInstance().getKnowledgeRuntime();
((InternalProcessRuntime) kruntime.getProcessRuntime()).getProcessEventSupport().fireBeforeNodeLeft(this, kruntime);
}
((NodeInstanceContainer) getNodeInstanceContainer()).nodeInstanceCompleted(this, null);
if (!hidden) {
InternalKnowledgeRuntime kruntime = getProcessInstance().getKnowledgeRuntime();
((InternalProcessRuntime) kruntime.getProcessRuntime()).getProcessEventSupport().fireAfterNodeLeft(this, kruntime);
}
} else {
((ProcessInstance) getProcessInstance()).setState(ProcessInstance.STATE_ABORTED, faultName, getFaultData());
}
}
Aggregations