Search in sources :

Example 6 with Connection

use of org.kie.api.definition.process.Connection in project jbpm by kiegroup.

the class JoinInstance method internalTrigger.

public void internalTrigger(final NodeInstance from, String type) {
    if (!org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
        throw new IllegalArgumentException("An ActionNode only accepts default incoming connections!");
    }
    final Join join = getJoin();
    switch(join.getType()) {
        case Join.TYPE_XOR:
            triggerCompleted();
            break;
        case Join.TYPE_AND:
            Integer count = (Integer) this.triggers.get(from.getNodeId());
            if (count == null) {
                this.triggers.put(from.getNodeId(), 1);
            } else {
                this.triggers.put(from.getNodeId(), count.intValue() + 1);
            }
            if (checkAllActivated()) {
                decreaseAllTriggers();
                triggerCompleted();
            }
            break;
        case Join.TYPE_DISCRIMINATOR:
            boolean triggerCompleted = triggers.isEmpty();
            triggers.put(from.getNodeId(), new Integer(1));
            if (checkAllActivated()) {
                resetAllTriggers();
            }
            if (triggerCompleted) {
                triggerCompleted();
            }
            break;
        case Join.TYPE_N_OF_M:
            count = (Integer) this.triggers.get(from.getNodeId());
            if (count == null) {
                this.triggers.put(from.getNodeId(), 1);
            } else {
                this.triggers.put(from.getNodeId(), count.intValue() + 1);
            }
            int counter = 0;
            for (final Connection connection : getJoin().getDefaultIncomingConnections()) {
                if (this.triggers.get(connection.getFrom().getId()) != null) {
                    counter++;
                }
            }
            String n = join.getN();
            Integer number = null;
            if (n.startsWith("#{") && n.endsWith("}")) {
                n = n.substring(2, n.length() - 1);
                VariableScopeInstance variableScopeInstance = (VariableScopeInstance) resolveContextInstance(VariableScope.VARIABLE_SCOPE, n);
                if (variableScopeInstance == null) {
                    throw new IllegalArgumentException("Could not find variable " + n + " when executing join.");
                }
                Object value = variableScopeInstance.getVariable(n);
                if (value instanceof Number) {
                    number = ((Number) value).intValue();
                } else {
                    throw new IllegalArgumentException("Variable " + n + " did not return a number when executing join: " + value);
                }
            } else {
                number = new Integer(n);
            }
            if (counter >= number) {
                resetAllTriggers();
                triggerCompleted();
            }
            break;
        case Join.TYPE_OR:
            NodeInstanceContainer nodeInstanceContainer = (NodeInstanceContainer) getNodeInstanceContainer();
            boolean activePathExists = existsActiveDirectFlow(nodeInstanceContainer, getJoin());
            if (!activePathExists) {
                triggerCompleted();
            }
            break;
        default:
            throw new IllegalArgumentException("Illegal join type " + join.getType());
    }
}
Also used : NodeInstanceContainer(org.kie.api.runtime.process.NodeInstanceContainer) VariableScopeInstance(org.jbpm.process.instance.context.variable.VariableScopeInstance) Connection(org.kie.api.definition.process.Connection) Join(org.jbpm.workflow.core.node.Join)

Example 7 with Connection

use of org.kie.api.definition.process.Connection in project jbpm by kiegroup.

the class JoinInstance method checkNodes.

private boolean checkNodes(Set<Long> vistedNodes, Node startAt, Node currentNode, Node lookFor) {
    if (currentNode == null) {
        // for dynamic/ad hoc task there is no node
        return false;
    }
    List<Connection> connections = currentNode.getOutgoingConnections(org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE);
    // special handling for XOR split as it usually is used for arbitrary loops
    if (currentNode instanceof Split && ((Split) currentNode).getType() == Split.TYPE_XOR) {
        if (vistedNodes.contains(startAt.getId())) {
            return false;
        }
        for (Connection conn : connections) {
            Set<Long> xorCopy = new HashSet<Long>(vistedNodes);
            Node nextNode = conn.getTo();
            if (nextNode == null) {
                continue;
            } else {
                xorCopy.add(nextNode.getId());
                if (nextNode.getId() != lookFor.getId()) {
                    checkNodes(xorCopy, currentNode, nextNode, lookFor);
                }
            }
            if (xorCopy.contains(lookFor.getId())) {
                vistedNodes.addAll(xorCopy);
                return true;
            }
        }
    } else {
        for (Connection conn : connections) {
            Node nextNode = conn.getTo();
            if (nextNode == null) {
                continue;
            } else {
                if (vistedNodes.contains(nextNode.getId())) {
                    // we have already been here so let's continue
                    continue;
                }
                if (nextNode.getId() == lookFor.getId()) {
                    // we found the node that we are looking for, add it and continue to find out other parts
                    // as it could be part of a loop
                    vistedNodes.add(nextNode.getId());
                    continue;
                }
                vistedNodes.add(nextNode.getId());
                if (startAt.getId() == nextNode.getId()) {
                    return true;
                } else {
                    boolean nestedCheck = checkNodes(vistedNodes, startAt, nextNode, lookFor);
                    if (nestedCheck) {
                        return true;
                    }
                }
            }
        }
    }
    return false;
}
Also used : Node(org.kie.api.definition.process.Node) Connection(org.kie.api.definition.process.Connection) Split(org.jbpm.workflow.core.node.Split) HashSet(java.util.HashSet)

Example 8 with Connection

use of org.kie.api.definition.process.Connection in project jbpm 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(org.jbpm.workflow.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);
            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);
            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 (NodeInstance 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());
    }
}
Also used : NodeInstanceContainer(org.jbpm.workflow.instance.NodeInstanceContainer) HashMap(java.util.HashMap) Node(org.kie.api.definition.process.Node) ArrayList(java.util.ArrayList) ConstraintEvaluator(org.jbpm.process.instance.impl.ConstraintEvaluator) InternalKnowledgeRuntime(org.drools.core.common.InternalKnowledgeRuntime) WorkflowRuntimeException(org.jbpm.workflow.instance.WorkflowRuntimeException) ContextInstanceContainer(org.jbpm.process.instance.ContextInstanceContainer) ExclusiveGroupInstance(org.jbpm.process.instance.context.exclusive.ExclusiveGroupInstance) Connection(org.kie.api.definition.process.Connection) NodeInstance(org.kie.api.runtime.process.NodeInstance) HashMap(java.util.HashMap) Map(java.util.Map)

Example 9 with Connection

use of org.kie.api.definition.process.Connection in project jbpm by kiegroup.

the class CompositeNodeInstance method internalTrigger.

public void internalTrigger(final org.kie.api.runtime.process.NodeInstance from, String type) {
    super.internalTrigger(from, type);
    // if node instance was cancelled, abort
    if (getNodeInstanceContainer().getNodeInstance(getId()) == null) {
        return;
    }
    CompositeNode.NodeAndType nodeAndType = getCompositeNode().internalGetLinkedIncomingNode(type);
    if (nodeAndType != null) {
        List<Connection> connections = nodeAndType.getNode().getIncomingConnections(nodeAndType.getType());
        for (Iterator<Connection> iterator = connections.iterator(); iterator.hasNext(); ) {
            Connection connection = iterator.next();
            if ((connection.getFrom() instanceof CompositeNode.CompositeNodeStart) && (from == null || ((CompositeNode.CompositeNodeStart) connection.getFrom()).getInNode().getId() == from.getNodeId())) {
                NodeInstance nodeInstance = getNodeInstance(connection.getFrom());
                ((org.jbpm.workflow.instance.NodeInstance) nodeInstance).trigger(null, nodeAndType.getType());
                return;
            }
        }
    } else {
        // try to search for start nodes
        boolean found = false;
        for (Node node : getCompositeNode().getNodes()) {
            if (node instanceof StartNode) {
                StartNode startNode = (StartNode) node;
                if (startNode.getTriggers() == null || startNode.getTriggers().isEmpty()) {
                    NodeInstance nodeInstance = getNodeInstance(startNode);
                    ((org.jbpm.workflow.instance.NodeInstance) nodeInstance).trigger(null, null);
                    found = true;
                }
            }
        }
        if (found) {
            return;
        }
    }
    if (isLinkedIncomingNodeRequired()) {
        throw new IllegalArgumentException("Could not find start for composite node: " + type);
    }
}
Also used : StartNode(org.jbpm.workflow.core.node.StartNode) StateBasedNode(org.jbpm.workflow.core.node.StateBasedNode) StartNode(org.jbpm.workflow.core.node.StartNode) CompositeNode(org.jbpm.workflow.core.node.CompositeNode) EventSubProcessNode(org.jbpm.workflow.core.node.EventSubProcessNode) AsyncEventNode(org.jbpm.workflow.core.node.AsyncEventNode) ActionNode(org.jbpm.workflow.core.node.ActionNode) EndNode(org.jbpm.workflow.core.node.EndNode) EventNode(org.jbpm.workflow.core.node.EventNode) Node(org.kie.api.definition.process.Node) Connection(org.kie.api.definition.process.Connection) CompositeNode(org.jbpm.workflow.core.node.CompositeNode) NodeInstance(org.jbpm.workflow.instance.NodeInstance)

Example 10 with Connection

use of org.kie.api.definition.process.Connection in project jbpm by kiegroup.

the class NodeInstanceImpl method triggerNodeInstance.

protected void triggerNodeInstance(org.jbpm.workflow.instance.NodeInstance nodeInstance, String type) {
    boolean hidden = false;
    if (getNode().getMetaData().get("hidden") != null) {
        hidden = true;
    }
    InternalKnowledgeRuntime kruntime = getProcessInstance().getKnowledgeRuntime();
    if (!hidden) {
        ((InternalProcessRuntime) kruntime.getProcessRuntime()).getProcessEventSupport().fireBeforeNodeLeft(this, kruntime);
    }
    // trigger next node
    nodeInstance.trigger(this, type);
    Collection<Connection> outgoing = getNode().getOutgoingConnections(type);
    for (Connection conn : outgoing) {
        if (conn.getTo().getId() == nodeInstance.getNodeId()) {
            this.metaData.put("OutgoingConnection", conn.getMetaData().get("UniqueId"));
            break;
        }
    }
    if (!hidden) {
        ((InternalProcessRuntime) kruntime.getProcessRuntime()).getProcessEventSupport().fireAfterNodeLeft(this, kruntime);
    }
}
Also used : InternalKnowledgeRuntime(org.drools.core.common.InternalKnowledgeRuntime) Connection(org.kie.api.definition.process.Connection)

Aggregations

Connection (org.kie.api.definition.process.Connection)24 ArrayList (java.util.ArrayList)10 Node (org.kie.api.definition.process.Node)10 Map (java.util.Map)6 Constraint (org.jbpm.workflow.core.Constraint)6 HashMap (java.util.HashMap)5 ConnectionImpl (org.jbpm.workflow.core.impl.ConnectionImpl)5 CompositeNode (org.jbpm.workflow.core.node.CompositeNode)5 EventNode (org.jbpm.workflow.core.node.EventNode)5 Split (org.jbpm.workflow.core.node.Split)5 StartNode (org.jbpm.workflow.core.node.StartNode)5 InternalKnowledgeRuntime (org.drools.core.common.InternalKnowledgeRuntime)4 ActionNode (org.jbpm.workflow.core.node.ActionNode)4 EndNode (org.jbpm.workflow.core.node.EndNode)4 List (java.util.List)3 FaultNode (org.jbpm.workflow.core.node.FaultNode)3 ForEachNode (org.jbpm.workflow.core.node.ForEachNode)3 WorkItemNode (org.jbpm.workflow.core.node.WorkItemNode)3 NodeInstanceContainer (org.jbpm.workflow.instance.NodeInstanceContainer)3 NodeInstance (org.kie.api.runtime.process.NodeInstance)3