/// <summary> /// 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 overriden 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). /// </summary> public override void doLeave(ActivityExecution execution) { LOG.leavingActivity(execution.Activity.Id); PvmTransition outgoingSeqFlow = null; string defaultSequenceFlow = (string)execution.Activity.getProperty("default"); IEnumerator <PvmTransition> transitionIterator = execution.Activity.OutgoingTransitions.GetEnumerator(); while (outgoingSeqFlow == null && transitionIterator.MoveNext()) { PvmTransition seqFlow = transitionIterator.Current; Condition condition = (Condition)seqFlow.getProperty(BpmnParse.PROPERTYNAME_CONDITION); if ((condition == null && (string.ReferenceEquals(defaultSequenceFlow, null) || !defaultSequenceFlow.Equals(seqFlow.Id))) || (condition != null && condition.evaluate(execution))) { LOG.outgoingSequenceFlowSelected(seqFlow.Id); outgoingSeqFlow = seqFlow; } } if (outgoingSeqFlow != null) { execution.leaveActivityViaTransition(outgoingSeqFlow); } else { if (!string.ReferenceEquals(defaultSequenceFlow, null)) { PvmTransition defaultTransition = execution.Activity.findOutgoingTransition(defaultSequenceFlow); if (defaultTransition != null) { execution.leaveActivityViaTransition(defaultTransition); } else { throw LOG.missingDefaultFlowException(execution.Activity.Id, defaultSequenceFlow); } } else { //No sequence flow could be found, not even a default one throw LOG.stuckExecutionException(execution.Activity.Id); } } }