Search in sources :

Example 11 with NodeInstance

use of io.automatiko.engine.api.runtime.process.NodeInstance in project automatiko-engine by automatiko-io.

the class NodeInstanceImpl method trigger.

public final void trigger(NodeInstance from, String type) {
    io.automatiko.engine.workflow.process.core.Node currentNode = (io.automatiko.engine.workflow.process.core.Node) getNode();
    // function flow check
    if (getProcessInstance().isFunctionFlow(this) && getProcessInstance().isExecutionNode(currentNode)) {
        Integer functionFlowCounter = (Integer) getProcessInstance().getMetaData("ATK_FUNC_FLOW_COUNTER");
        if (functionFlowCounter == null) {
            functionFlowCounter = 1;
            getProcessInstance().getMetaData().put("ATK_FUNC_FLOW_COUNTER", functionFlowCounter);
        } else {
            // function flow already called function
            getProcessInstance().getMetaData().compute("ATK_FUNC_FLOW_NEXT", (k, v) -> {
                if (v == null) {
                    v = new ArrayList<String>();
                }
                Process process = getProcessInstance().getProcess();
                String version = "";
                if (process.getVersion() != null && !process.getVersion().trim().isEmpty()) {
                    version = ".v" + process.getVersion().replaceAll("\\.", "_");
                }
                String defaultNextNode = process.getPackageName() + "." + process.getId() + version + "." + getNodeName().toLowerCase();
                ((List<String>) v).add((String) getNode().getMetaData().getOrDefault("functionType", defaultNextNode));
                return v;
            });
            nodeInstanceContainer.removeNodeInstance(this);
            return;
        }
    }
    // check activation condition if this can be invoked
    if (currentNode.getActivationCheck().isPresent()) {
        if (!currentNode.getActivationCheck().get().isValid(getProcessInstance().getVariables())) {
            nodeInstanceContainer.removeNodeInstance(this);
            return;
        }
    }
    internalChangeState(NodeInstanceState.Active);
    boolean hidden = false;
    if (getNode().getMetaData().get(HIDDEN) != null) {
        hidden = true;
    }
    if (from != null) {
        int level = ((io.automatiko.engine.workflow.process.instance.NodeInstance) from).getLevel();
        ((io.automatiko.engine.workflow.process.instance.NodeInstanceContainer) getNodeInstanceContainer()).setCurrentLevel(level);
        Collection<Connection> incoming = getNode().getIncomingConnections(type);
        for (Connection conn : incoming) {
            if (conn.getFrom().getId() == from.getNodeId()) {
                this.metaData.put(INCOMING_CONNECTION, conn.getMetaData().get(UNIQUE_ID));
                break;
            }
        }
    }
    if (dynamicParameters != null) {
        for (Entry<String, Object> entry : dynamicParameters.entrySet()) {
            setVariable(entry.getKey(), entry.getValue());
        }
    }
    configureSla();
    InternalProcessRuntime runtime = getProcessInstance().getProcessRuntime();
    if (!hidden) {
        runtime.getProcessEventSupport().fireBeforeNodeTriggered(this, runtime);
    }
    try {
        internalTrigger(from, type);
    } catch (Exception e) {
        String errorId = captureError(e);
        internalChangeState(NodeInstanceState.Failed);
        runtime.getProcessEventSupport().fireAfterNodeInstanceFailed(getProcessInstance(), this, errorId, getRootException(e).getMessage(), e, runtime);
        // stop after capturing error
        return;
    }
    if (!hidden) {
        runtime.getProcessEventSupport().fireAfterNodeTriggered(this, runtime);
    }
}
Also used : NodeInstanceContainer(io.automatiko.engine.api.runtime.process.NodeInstanceContainer) Node(io.automatiko.engine.api.definition.process.Node) Connection(io.automatiko.engine.api.definition.process.Connection) Process(io.automatiko.engine.api.definition.process.Process) WorkflowRuntimeException(io.automatiko.engine.workflow.process.instance.WorkflowRuntimeException) ArrayList(java.util.ArrayList) List(java.util.List) InternalProcessRuntime(io.automatiko.engine.workflow.base.instance.InternalProcessRuntime) ActionNodeInstance(io.automatiko.engine.workflow.process.instance.node.ActionNodeInstance) NodeInstance(io.automatiko.engine.api.runtime.process.NodeInstance) CompositeNodeInstance(io.automatiko.engine.workflow.process.instance.node.CompositeNodeInstance)

Example 12 with NodeInstance

use of io.automatiko.engine.api.runtime.process.NodeInstance in project automatiko-engine by automatiko-io.

the class SplitInstance method executeStrategy.

protected void executeStrategy(Split split, String type) {
    // TODO make different strategies for each type
    String uniqueId = (String) getNode().getMetaData().get(UNIQUE_ID);
    if (uniqueId == null) {
        uniqueId = ((NodeImpl) getNode()).getUniqueId();
    }
    switch(split.getType()) {
        case Split.TYPE_AND:
            triggerCompleted(io.automatiko.engine.workflow.process.core.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);
            ((WorkflowProcessInstanceImpl) getProcessInstance()).addCompletedNodeId(uniqueId);
            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() == STATE_COMPLETED || getProcessInstance().getState() == STATE_ABORTED) {
                    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());
            }
            ((WorkflowProcessInstanceImpl) getProcessInstance()).addCompletedNodeId(uniqueId);
            break;
        case Split.TYPE_XAND:
            ((io.automatiko.engine.workflow.process.instance.NodeInstanceContainer) getNodeInstanceContainer()).removeNodeInstance(this);
            Node node = getNode();
            List<Connection> connections = null;
            if (node != null) {
                connections = node.getOutgoingConnections(type);
            }
            if (connections == null || connections.isEmpty()) {
                ((io.automatiko.engine.workflow.process.instance.NodeInstanceContainer) getNodeInstanceContainer()).nodeInstanceCompleted(this, type);
            } else {
                ExclusiveGroupInstance groupInstance = new ExclusiveGroupInstance();
                io.automatiko.engine.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<io.automatiko.engine.workflow.process.instance.NodeInstance, String> nodeInstancesMap = new HashMap<io.automatiko.engine.workflow.process.instance.NodeInstance, String>();
                for (Connection connection : connections) {
                    nodeInstancesMap.put(followConnection(connection), connection.getToType());
                }
                for (NodeInstance nodeInstance : nodeInstancesMap.keySet()) {
                    groupInstance.addNodeInstance(nodeInstance);
                }
                for (Map.Entry<io.automatiko.engine.workflow.process.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;
                    }
                    InternalProcessRuntime runtime = getProcessInstance().getProcessRuntime();
                    if (!hidden) {
                        runtime.getProcessEventSupport().fireBeforeNodeLeft(this, runtime);
                    }
                    ((io.automatiko.engine.workflow.process.instance.NodeInstance) entry.getKey()).trigger(this, entry.getValue());
                    if (!hidden) {
                        runtime.getProcessEventSupport().fireAfterNodeLeft(this, runtime);
                    }
                }
            }
            ((WorkflowProcessInstanceImpl) getProcessInstance()).addCompletedNodeId(uniqueId);
            break;
        default:
            throw new IllegalArgumentException("Illegal split type " + split.getType());
    }
}
Also used : NodeInstanceContainer(io.automatiko.engine.workflow.process.instance.NodeInstanceContainer) HashMap(java.util.HashMap) Node(io.automatiko.engine.api.definition.process.Node) WorkflowProcessInstanceImpl(io.automatiko.engine.workflow.process.instance.impl.WorkflowProcessInstanceImpl) ArrayList(java.util.ArrayList) ConstraintEvaluator(io.automatiko.engine.workflow.base.instance.impl.ConstraintEvaluator) WorkflowRuntimeException(io.automatiko.engine.workflow.process.instance.WorkflowRuntimeException) ContextInstanceContainer(io.automatiko.engine.workflow.base.instance.ContextInstanceContainer) ExclusiveGroupInstance(io.automatiko.engine.workflow.base.instance.context.exclusive.ExclusiveGroupInstance) Connection(io.automatiko.engine.api.definition.process.Connection) InternalProcessRuntime(io.automatiko.engine.workflow.base.instance.InternalProcessRuntime) NodeInstance(io.automatiko.engine.api.runtime.process.NodeInstance) HashMap(java.util.HashMap) Map(java.util.Map)

Example 13 with NodeInstance

use of io.automatiko.engine.api.runtime.process.NodeInstance in project automatiko-engine by automatiko-io.

the class JoinInstance method cancelRemainingDirectFlows.

private void cancelRemainingDirectFlows(NodeInstanceContainer nodeInstanceContainer, final Node lookFor) {
    Collection<NodeInstance> activeNodeInstancesOrig = nodeInstanceContainer.getNodeInstances();
    List<NodeInstance> activeNodeInstances = new ArrayList<NodeInstance>(activeNodeInstancesOrig);
    // sort active instances in the way that lookFor nodeInstance will be last to
    // not finish too early
    Collections.sort(activeNodeInstances, new Comparator<NodeInstance>() {

        @Override
        public int compare(NodeInstance o1, NodeInstance o2) {
            if (o1.getNodeId() == lookFor.getId()) {
                return 1;
            } else if (o2.getNodeId() == lookFor.getId()) {
                return -1;
            }
            return 0;
        }
    });
    for (NodeInstance nodeInstance : activeNodeInstances) {
        // black box
        if (((io.automatiko.engine.workflow.process.instance.NodeInstance) nodeInstance).getLevel() != getLevel()) {
            continue;
        }
        Node node = nodeInstance.getNode();
        Set<Long> vistedNodes = new HashSet<Long>();
        checkNodes(vistedNodes, node, node, lookFor);
        if (vistedNodes.contains(lookFor.getId()) && !vistedNodes.contains(node.getId())) {
            ((NodeInstanceImpl) nodeInstance).cancel();
        }
    }
}
Also used : NodeInstanceImpl(io.automatiko.engine.workflow.process.instance.impl.NodeInstanceImpl) Node(io.automatiko.engine.api.definition.process.Node) ArrayList(java.util.ArrayList) NodeInstance(io.automatiko.engine.api.runtime.process.NodeInstance) HashSet(java.util.HashSet)

Example 14 with NodeInstance

use of io.automatiko.engine.api.runtime.process.NodeInstance in project automatiko-engine by automatiko-io.

the class EventSubProcessNodeInstance method signalEvent.

@Override
public void signalEvent(String type, Object event) {
    if (triggerTime == null) {
        // started by signal
        triggerTime = new Date();
    }
    if ("variableChanged".equals(type)) {
        ProcessContext context = new ProcessContext(getProcessInstance().getProcessRuntime());
        context.setProcessInstance(getProcessInstance());
        context.setNodeInstance(this);
        StartNode startNode = getCompositeNode().findStartNode();
        if (startNode.hasCondition()) {
            if (startNode.isMet(context)) {
                signalEvent(getCompositeNode().getEvents().get(0), null);
            } else {
                removeNodeInstance(this);
                return;
            }
        }
    }
    if (getNodeInstanceContainer().getNodeInstances().contains(this) || type.startsWith("Error-") || type.equals("timerTriggered")) {
        // instances
        if (this.getNodeInstances().isEmpty()) {
            StartNode startNode = getCompositeNode().findStartNode();
            if (resolveVariables(((EventSubProcessNode) getEventBasedNode()).getEvents()).contains(type) || type.equals("timerTriggered")) {
                NodeInstance nodeInstance = getNodeInstance(startNode);
                ((StartNodeInstance) nodeInstance).signalEvent(type, event);
                return;
            }
        }
    }
    super.signalEvent(type, event);
}
Also used : StartNode(io.automatiko.engine.workflow.process.core.node.StartNode) NodeInstance(io.automatiko.engine.api.runtime.process.NodeInstance) Date(java.util.Date) ProcessContext(io.automatiko.engine.workflow.base.core.context.ProcessContext)

Example 15 with NodeInstance

use of io.automatiko.engine.api.runtime.process.NodeInstance in project automatiko-engine by automatiko-io.

the class FaultNodeInstance method internalTrigger.

public void internalTrigger(final NodeInstance from, String type) {
    if (!io.automatiko.engine.workflow.process.core.Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
        throw new IllegalArgumentException("A FaultNode only accepts default incoming connections!");
    }
    triggerTime = new Date();
    if (getProcessInstance().isFunctionFlow(this) && getNodeInstanceContainer() instanceof ProcessInstance) {
        // only when running as function flow and node is in the top level node container meaning process instance
        // and not subprocesses
        getProcessInstance().getMetaData().compute("ATK_FUNC_FLOW_NEXT", (k, v) -> {
            if (v == null) {
                v = new ArrayList<String>();
            }
            Process process = getProcessInstance().getProcess();
            String version = "";
            if (process.getVersion() != null && !process.getVersion().trim().isEmpty()) {
                version = ".v" + process.getVersion().replaceAll("\\.", "_");
            }
            String defaultNextNode = process.getPackageName() + "." + process.getId() + version + "." + getNodeName().toLowerCase();
            ((List<String>) v).add((String) getNode().getMetaData().getOrDefault("functionType", defaultNextNode));
            return v;
        });
    }
    String faultName = getFaultName();
    ExceptionScopeInstance exceptionScopeInstance = getExceptionScopeInstance(faultName);
    NodeInstanceContainer nodeInstanceContainer = (NodeInstanceContainer) getNodeInstanceContainer();
    nodeInstanceContainer.removeNodeInstance(this);
    boolean exceptionHandled = false;
    if (getFaultNode().isTerminateParent()) {
        // 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) {
                ((io.automatiko.engine.workflow.process.instance.NodeInstance) nodeInstance).cancel();
            }
        }
    }
    String uniqueId = (String) getNode().getMetaData().get(UNIQUE_ID);
    if (uniqueId == null) {
        uniqueId = ((NodeImpl) getNode()).getUniqueId();
    }
    ((WorkflowProcessInstanceImpl) getProcessInstance()).addCompletedNodeId(uniqueId);
    if (exceptionScopeInstance != null) {
        if (!exceptionHandled) {
            handleException(faultName, exceptionScopeInstance);
        }
        boolean hidden = false;
        if (getNode().getMetaData().get("hidden") != null) {
            hidden = true;
        }
        if (!hidden) {
            InternalProcessRuntime runtime = getProcessInstance().getProcessRuntime();
            runtime.getProcessEventSupport().fireBeforeNodeLeft(this, runtime);
        }
        ((NodeInstanceContainer) getNodeInstanceContainer()).nodeInstanceCompleted(this, null);
        if (!hidden) {
            InternalProcessRuntime runtime = getProcessInstance().getProcessRuntime();
            runtime.getProcessEventSupport().fireAfterNodeLeft(this, runtime);
        }
    } else {
        ((ProcessInstance) getProcessInstance()).setState(ProcessInstance.STATE_ABORTED, faultName, getFaultData());
    }
}
Also used : NodeInstanceContainer(io.automatiko.engine.workflow.process.instance.NodeInstanceContainer) WorkflowProcessInstanceImpl(io.automatiko.engine.workflow.process.instance.impl.WorkflowProcessInstanceImpl) Process(io.automatiko.engine.api.definition.process.Process) Date(java.util.Date) Collection(java.util.Collection) WorkflowProcessInstance(io.automatiko.engine.api.runtime.process.WorkflowProcessInstance) ProcessInstance(io.automatiko.engine.workflow.base.instance.ProcessInstance) ArrayList(java.util.ArrayList) List(java.util.List) InternalProcessRuntime(io.automatiko.engine.workflow.base.instance.InternalProcessRuntime) NodeInstance(io.automatiko.engine.api.runtime.process.NodeInstance) WorkflowProcessInstance(io.automatiko.engine.api.runtime.process.WorkflowProcessInstance) ExceptionScopeInstance(io.automatiko.engine.workflow.base.instance.context.exception.ExceptionScopeInstance)

Aggregations

NodeInstance (io.automatiko.engine.api.runtime.process.NodeInstance)26 ArrayList (java.util.ArrayList)20 List (java.util.List)15 ProcessInstance (io.automatiko.engine.api.runtime.process.ProcessInstance)14 DelayedExecution (io.automatiko.engine.api.event.process.DelayedExecution)9 ProcessCompletedEvent (io.automatiko.engine.api.event.process.ProcessCompletedEvent)9 ProcessEventListener (io.automatiko.engine.api.event.process.ProcessEventListener)9 ProcessNodeInstanceFailedEvent (io.automatiko.engine.api.event.process.ProcessNodeInstanceFailedEvent)9 ProcessNodeLeftEvent (io.automatiko.engine.api.event.process.ProcessNodeLeftEvent)9 ProcessNodeTriggeredEvent (io.automatiko.engine.api.event.process.ProcessNodeTriggeredEvent)9 ProcessSignaledEvent (io.automatiko.engine.api.event.process.ProcessSignaledEvent)9 ProcessStartedEvent (io.automatiko.engine.api.event.process.ProcessStartedEvent)9 ProcessVariableChangedEvent (io.automatiko.engine.api.event.process.ProcessVariableChangedEvent)9 ProcessWorkItemTransitionEvent (io.automatiko.engine.api.event.process.ProcessWorkItemTransitionEvent)9 SLAViolatedEvent (io.automatiko.engine.api.event.process.SLAViolatedEvent)9 ProcessRuntime (io.automatiko.engine.api.runtime.process.ProcessRuntime)9 WorkItem (io.automatiko.engine.api.runtime.process.WorkItem)9 UnitOfWorkManager (io.automatiko.engine.api.uow.UnitOfWorkManager)9 WorkUnit (io.automatiko.engine.api.uow.WorkUnit)9 Transition (io.automatiko.engine.api.workflow.workitem.Transition)9