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();
}
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;
}
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());
}
}
}
}
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);
}
}
}
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);
}
Aggregations