Search in sources :

Example 46 with SequenceFlow

use of org.activiti.bpmn.model.SequenceFlow in project Activiti by Activiti.

the class UserTaskConverterTest method validateModel.

private void validateModel(BpmnModel model) {
    FlowElement flowElement = model.getMainProcess().getFlowElement("usertask", true);
    assertThat(flowElement).isNotNull();
    assertThat(flowElement).isInstanceOf(UserTask.class);
    assertThat(flowElement.getId()).isEqualTo("usertask");
    UserTask userTask = (UserTask) flowElement;
    assertThat(userTask.getId()).isEqualTo("usertask");
    assertThat(userTask.getName()).isEqualTo("User task");
    assertThat(userTask.getFormKey()).isEqualTo("testKey");
    assertThat(userTask.getPriority()).isEqualTo("40");
    assertThat(userTask.getDueDate()).isEqualTo("2012-11-01");
    assertThat(userTask.getCategory()).isEqualTo("defaultCategory");
    assertThat(userTask.getAssignee()).isEqualTo("kermit");
    assertThat(userTask.getCandidateUsers()).hasSize(2);
    assertThat(userTask.getCandidateUsers().contains("kermit")).isTrue();
    assertThat(userTask.getCandidateUsers().contains("fozzie")).isTrue();
    assertThat(userTask.getCandidateGroups()).hasSize(2);
    assertThat(userTask.getCandidateGroups().contains("management")).isTrue();
    assertThat(userTask.getCandidateGroups().contains("sales")).isTrue();
    List<FormProperty> formProperties = userTask.getFormProperties();
    assertThat(formProperties).hasSize(2);
    FormProperty formProperty = formProperties.get(0);
    assertThat(formProperty.getId()).isEqualTo("formId");
    assertThat(formProperty.getName()).isEqualTo("formName");
    assertThat(formProperty.getType()).isEqualTo("string");
    assertThat(formProperty.getVariable()).isEqualTo("variable");
    assertThat(formProperty.getExpression()).isEqualTo("${expression}");
    formProperty = formProperties.get(1);
    assertThat(formProperty.getId()).isEqualTo("formId2");
    assertThat(formProperty.getName()).isEqualTo("anotherName");
    assertThat(formProperty.getType()).isEqualTo("long");
    assertThat(StringUtils.isEmpty(formProperty.getVariable())).isTrue();
    assertThat(StringUtils.isEmpty(formProperty.getExpression())).isTrue();
    List<ActivitiListener> listeners = userTask.getTaskListeners();
    assertThat(listeners).hasSize(3);
    ActivitiListener listener = (ActivitiListener) listeners.get(0);
    assertThat(ImplementationType.IMPLEMENTATION_TYPE_CLASS.equals(listener.getImplementationType())).isTrue();
    assertThat(listener.getImplementation()).isEqualTo("org.test.TestClass");
    assertThat(listener.getEvent()).isEqualTo("create");
    assertThat(listener.getFieldExtensions()).hasSize(2);
    assertThat(listener.getFieldExtensions().get(0).getFieldName()).isEqualTo("testField");
    assertThat(listener.getFieldExtensions().get(0).getStringValue()).isEqualTo("test");
    listener = (ActivitiListener) listeners.get(1);
    assertThat(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION.equals(listener.getImplementationType())).isTrue();
    assertThat(listener.getImplementation()).isEqualTo("${someExpression}");
    assertThat(listener.getEvent()).isEqualTo("assignment");
    listener = (ActivitiListener) listeners.get(2);
    assertThat(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equals(listener.getImplementationType())).isTrue();
    assertThat(listener.getImplementation()).isEqualTo("${someDelegateExpression}");
    assertThat(listener.getEvent()).isEqualTo("complete");
    flowElement = model.getMainProcess().getFlowElement("start", true);
    assertThat(flowElement).isInstanceOf(StartEvent.class);
    StartEvent startEvent = (StartEvent) flowElement;
    assertThat(startEvent.getOutgoingFlows().size() == 1).isTrue();
    flowElement = model.getMainProcess().getFlowElement("flow1", true);
    assertThat(flowElement).isInstanceOf(SequenceFlow.class);
    SequenceFlow flow = (SequenceFlow) flowElement;
    assertThat(flow.getId()).isEqualTo("flow1");
    assertThat(flow.getSourceRef()).isNotNull();
    assertThat(flow.getTargetRef()).isNotNull();
}
Also used : FormProperty(org.activiti.bpmn.model.FormProperty) FlowElement(org.activiti.bpmn.model.FlowElement) SequenceFlow(org.activiti.bpmn.model.SequenceFlow) UserTask(org.activiti.bpmn.model.UserTask) StartEvent(org.activiti.bpmn.model.StartEvent) ActivitiListener(org.activiti.bpmn.model.ActivitiListener)

Example 47 with SequenceFlow

use of org.activiti.bpmn.model.SequenceFlow in project Activiti by Activiti.

the class IntermediateCatchEventActivityBehavior method getPrecedingEventBasedGateway.

protected EventGateway getPrecedingEventBasedGateway(DelegateExecution execution) {
    FlowElement currentFlowElement = execution.getCurrentFlowElement();
    if (currentFlowElement instanceof IntermediateCatchEvent) {
        IntermediateCatchEvent intermediateCatchEvent = (IntermediateCatchEvent) currentFlowElement;
        List<SequenceFlow> incomingSequenceFlow = intermediateCatchEvent.getIncomingFlows();
        // If behind an event based gateway, there is only one incoming sequence flow that originates from said gateway
        if (incomingSequenceFlow != null && incomingSequenceFlow.size() == 1) {
            SequenceFlow sequenceFlow = incomingSequenceFlow.get(0);
            FlowElement sourceFlowElement = sequenceFlow.getSourceFlowElement();
            if (sourceFlowElement instanceof EventGateway) {
                return (EventGateway) sourceFlowElement;
            }
        }
    }
    return null;
}
Also used : EventGateway(org.activiti.bpmn.model.EventGateway) FlowElement(org.activiti.bpmn.model.FlowElement) SequenceFlow(org.activiti.bpmn.model.SequenceFlow) IntermediateCatchEvent(org.activiti.bpmn.model.IntermediateCatchEvent)

Example 48 with SequenceFlow

use of org.activiti.bpmn.model.SequenceFlow in project Activiti by Activiti.

the class IntermediateCatchEventActivityBehavior method deleteOtherEventsRelatedToEventBasedGateway.

protected void deleteOtherEventsRelatedToEventBasedGateway(DelegateExecution execution, EventGateway eventGateway) {
    // To clean up the other events behind the event based gateway, we must gather the
    // activity ids of said events and check the _sibling_ executions of the incoming execution.
    // Note that it can happen that there are multiple such execution in those activity ids,
    // (for example a parallel gw going twice to the event based gateway, kinda silly, but valid)
    // so we only take _one_ result of such a query for deletion.
    // Gather all activity ids for the events after the event based gateway that need to be destroyed
    List<SequenceFlow> outgoingSequenceFlows = eventGateway.getOutgoingFlows();
    // -1, the event being triggered does not need to be deleted
    Set<String> eventActivityIds = new HashSet<String>(outgoingSequenceFlows.size() - 1);
    for (SequenceFlow outgoingSequenceFlow : outgoingSequenceFlows) {
        if (outgoingSequenceFlow.getTargetFlowElement() != null && !outgoingSequenceFlow.getTargetFlowElement().getId().equals(execution.getCurrentActivityId())) {
            eventActivityIds.add(outgoingSequenceFlow.getTargetFlowElement().getId());
        }
    }
    CommandContext commandContext = Context.getCommandContext();
    ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
    // Find the executions
    List<ExecutionEntity> executionEntities = executionEntityManager.findExecutionsByParentExecutionAndActivityIds(execution.getParentId(), eventActivityIds);
    // Execute the cancel behaviour of the IntermediateCatchEvent
    for (ExecutionEntity executionEntity : executionEntities) {
        if (eventActivityIds.contains(executionEntity.getActivityId()) && execution.getCurrentFlowElement() instanceof IntermediateCatchEvent) {
            IntermediateCatchEvent intermediateCatchEvent = (IntermediateCatchEvent) execution.getCurrentFlowElement();
            if (intermediateCatchEvent.getBehavior() instanceof IntermediateCatchEventActivityBehavior) {
                ((IntermediateCatchEventActivityBehavior) intermediateCatchEvent.getBehavior()).eventCancelledByEventGateway(executionEntity);
                // We only need to delete ONE execution at the event.
                eventActivityIds.remove(executionEntity.getActivityId());
            }
        }
    }
}
Also used : CommandContext(org.activiti.engine.impl.interceptor.CommandContext) ExecutionEntity(org.activiti.engine.impl.persistence.entity.ExecutionEntity) SequenceFlow(org.activiti.bpmn.model.SequenceFlow) IntermediateCatchEvent(org.activiti.bpmn.model.IntermediateCatchEvent) ExecutionEntityManager(org.activiti.engine.impl.persistence.entity.ExecutionEntityManager) HashSet(java.util.HashSet)

Example 49 with SequenceFlow

use of org.activiti.bpmn.model.SequenceFlow in project Activiti by Activiti.

the class TakeOutgoingSequenceFlowsOperation method leaveFlowNode.

protected void leaveFlowNode(FlowNode flowNode) {
    logger.debug("Leaving flow node {} with id '{}' by following it's {} outgoing sequenceflow", flowNode.getClass(), flowNode.getId(), flowNode.getOutgoingFlows().size());
    // Get default sequence flow (if set)
    String defaultSequenceFlowId = null;
    if (flowNode instanceof Activity) {
        defaultSequenceFlowId = ((Activity) flowNode).getDefaultFlow();
    } else if (flowNode instanceof Gateway) {
        defaultSequenceFlowId = ((Gateway) flowNode).getDefaultFlow();
    }
    // Determine which sequence flows can be used for leaving
    List<SequenceFlow> outgoingSequenceFlows = new ArrayList<SequenceFlow>();
    for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
        String skipExpressionString = sequenceFlow.getSkipExpression();
        if (!SkipExpressionUtil.isSkipExpressionEnabled(execution, skipExpressionString)) {
            if (!evaluateConditions || (evaluateConditions && ConditionUtil.hasTrueCondition(sequenceFlow, execution) && (defaultSequenceFlowId == null || !defaultSequenceFlowId.equals(sequenceFlow.getId())))) {
                outgoingSequenceFlows.add(sequenceFlow);
            }
        } else if (flowNode.getOutgoingFlows().size() == 1 || SkipExpressionUtil.shouldSkipFlowElement(commandContext, execution, skipExpressionString)) {
            // The 'skip' for a sequence flow means that we skip the condition, not the sequence flow.
            outgoingSequenceFlows.add(sequenceFlow);
        }
    }
    // Check if there is a default sequence flow
    if (outgoingSequenceFlows.size() == 0 && evaluateConditions) {
        // The elements that set this to false also have no support for default sequence flow
        if (defaultSequenceFlowId != null) {
            for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
                if (defaultSequenceFlowId.equals(sequenceFlow.getId())) {
                    outgoingSequenceFlows.add(sequenceFlow);
                    break;
                }
            }
        }
    }
    // No outgoing found. Ending the execution
    if (outgoingSequenceFlows.size() == 0) {
        if (flowNode.getOutgoingFlows() == null || flowNode.getOutgoingFlows().size() == 0) {
            logger.debug("No outgoing sequence flow found for flow node '{}'.", flowNode.getId());
            Context.getAgenda().planEndExecutionOperation(execution);
        } else {
            throw new ActivitiException("No outgoing sequence flow of element '" + flowNode.getId() + "' could be selected for continuing the process");
        }
    } else {
        // Leave, and reuse the incoming sequence flow, make executions for all the others (if applicable)
        ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
        List<ExecutionEntity> outgoingExecutions = new ArrayList<ExecutionEntity>(flowNode.getOutgoingFlows().size());
        SequenceFlow sequenceFlow = outgoingSequenceFlows.get(0);
        // Reuse existing one
        execution.setCurrentFlowElement(sequenceFlow);
        execution.setActive(true);
        outgoingExecutions.add((ExecutionEntity) execution);
        // Executions for all the other one
        if (outgoingSequenceFlows.size() > 1) {
            for (int i = 1; i < outgoingSequenceFlows.size(); i++) {
                ExecutionEntity parent = execution.getParentId() != null ? execution.getParent() : execution;
                ExecutionEntity outgoingExecutionEntity = commandContext.getExecutionEntityManager().createChildExecution(parent);
                SequenceFlow outgoingSequenceFlow = outgoingSequenceFlows.get(i);
                outgoingExecutionEntity.setCurrentFlowElement(outgoingSequenceFlow);
                executionEntityManager.insert(outgoingExecutionEntity);
                outgoingExecutions.add(outgoingExecutionEntity);
            }
        }
        // Leave (only done when all executions have been made, since some queries depend on this)
        for (ExecutionEntity outgoingExecution : outgoingExecutions) {
            Context.getAgenda().planContinueProcessOperation(outgoingExecution);
        }
    }
}
Also used : ActivitiException(org.activiti.engine.ActivitiException) ExecutionEntity(org.activiti.engine.impl.persistence.entity.ExecutionEntity) Gateway(org.activiti.bpmn.model.Gateway) SequenceFlow(org.activiti.bpmn.model.SequenceFlow) ArrayList(java.util.ArrayList) Activity(org.activiti.bpmn.model.Activity) ExecutionEntityManager(org.activiti.engine.impl.persistence.entity.ExecutionEntityManager)

Example 50 with SequenceFlow

use of org.activiti.bpmn.model.SequenceFlow in project Activiti by Activiti.

the class ExclusiveGatewayActivityBehavior method leave.

/**
 * The default behaviour of BPMN, taking every outgoing sequence flow (where the condition evaluates to true), is not valid for an exclusive gateway.
 *
 * Hence, this behaviour is overridden and replaced by the correct behavior: selecting the first sequence flow which condition evaluates to true (or which hasn't got a condition) and leaving the
 * activity through that sequence flow.
 *
 * If no sequence flow is selected (ie all conditions evaluate to false), then the default sequence flow is taken (if defined).
 */
@Override
public void leave(DelegateExecution execution) {
    if (log.isDebugEnabled()) {
        log.debug("Leaving exclusive gateway '{}'", execution.getCurrentActivityId());
    }
    ExclusiveGateway exclusiveGateway = (ExclusiveGateway) execution.getCurrentFlowElement();
    if (Context.getProcessEngineConfiguration() != null && Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
        Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(ActivitiEventBuilder.createActivityEvent(ActivitiEventType.ACTIVITY_COMPLETED, exclusiveGateway.getId(), exclusiveGateway.getName(), execution.getId(), execution.getProcessInstanceId(), execution.getProcessDefinitionId(), exclusiveGateway));
    }
    SequenceFlow outgoingSequenceFlow = null;
    SequenceFlow defaultSequenceFlow = null;
    String defaultSequenceFlowId = exclusiveGateway.getDefaultFlow();
    // Determine sequence flow to take
    Iterator<SequenceFlow> sequenceFlowIterator = exclusiveGateway.getOutgoingFlows().iterator();
    while (outgoingSequenceFlow == null && sequenceFlowIterator.hasNext()) {
        SequenceFlow sequenceFlow = sequenceFlowIterator.next();
        String skipExpressionString = sequenceFlow.getSkipExpression();
        if (!SkipExpressionUtil.isSkipExpressionEnabled(execution, skipExpressionString)) {
            boolean conditionEvaluatesToTrue = ConditionUtil.hasTrueCondition(sequenceFlow, execution);
            if (conditionEvaluatesToTrue && (defaultSequenceFlowId == null || !defaultSequenceFlowId.equals(sequenceFlow.getId()))) {
                if (log.isDebugEnabled()) {
                    log.debug("Sequence flow '{}'selected as outgoing sequence flow.", sequenceFlow.getId());
                }
                outgoingSequenceFlow = sequenceFlow;
            }
        } else if (SkipExpressionUtil.shouldSkipFlowElement(Context.getCommandContext(), execution, skipExpressionString)) {
            outgoingSequenceFlow = sequenceFlow;
        }
        // Already store it, if we would need it later. Saves one for loop.
        if (defaultSequenceFlowId != null && defaultSequenceFlowId.equals(sequenceFlow.getId())) {
            defaultSequenceFlow = sequenceFlow;
        }
    }
    // We have to record the end here, or else we're already past it
    Context.getCommandContext().getHistoryManager().recordActivityEnd((ExecutionEntity) execution, null);
    // Leave the gateway
    if (outgoingSequenceFlow != null) {
        execution.setCurrentFlowElement(outgoingSequenceFlow);
    } else {
        if (defaultSequenceFlow != null) {
            execution.setCurrentFlowElement(defaultSequenceFlow);
        } else {
            // No sequence flow could be found, not even a default one
            throw new ActivitiException("No outgoing sequence flow of the exclusive gateway '" + exclusiveGateway.getId() + "' could be selected for continuing the process");
        }
    }
    super.leave(execution);
}
Also used : ExclusiveGateway(org.activiti.bpmn.model.ExclusiveGateway) ActivitiException(org.activiti.engine.ActivitiException) SequenceFlow(org.activiti.bpmn.model.SequenceFlow)

Aggregations

SequenceFlow (org.activiti.bpmn.model.SequenceFlow)63 FlowElement (org.activiti.bpmn.model.FlowElement)34 Process (org.activiti.bpmn.model.Process)23 SubProcess (org.activiti.bpmn.model.SubProcess)19 BpmnModel (org.activiti.bpmn.model.BpmnModel)16 StartEvent (org.activiti.bpmn.model.StartEvent)15 EndEvent (org.activiti.bpmn.model.EndEvent)14 ArrayList (java.util.ArrayList)12 FlowNode (org.activiti.bpmn.model.FlowNode)12 GraphicInfo (org.activiti.bpmn.model.GraphicInfo)11 UserTask (org.activiti.bpmn.model.UserTask)11 Activity (org.activiti.bpmn.model.Activity)10 Gateway (org.activiti.bpmn.model.Gateway)9 HashMap (java.util.HashMap)7 Lane (org.activiti.bpmn.model.Lane)7 JsonNode (com.fasterxml.jackson.databind.JsonNode)6 ArrayNode (com.fasterxml.jackson.databind.node.ArrayNode)6 BoundaryEvent (org.activiti.bpmn.model.BoundaryEvent)6 ExclusiveGateway (org.activiti.bpmn.model.ExclusiveGateway)6 Pool (org.activiti.bpmn.model.Pool)6