Example #1
0
        /// <summary>
        ///     Actual implementation of leaving an activity.
        /// </summary>
        /// <param name="execution">
        ///     The current execution context
        /// </param>
        /// <param name="checkConditions">
        ///     Whether or not to check conditions before determining whether or
        ///     not to take a transition.
        /// </param>
        /// <param name="throwExceptionIfExecutionStuck">
        ///     If true, an <seealso cref="ProcessEngineException" /> will be thrown in case no
        ///     transition could be found to leave the activity.
        /// </param>
        protected internal virtual void PerformOutgoingBehavior(IActivityExecution execution, bool checkConditions,
                                                                bool throwExceptionIfExecutionStuck, IList <IActivityExecution> reusableExecutions)
        {
            Log.LeavingActivity(execution.Activity.Id);

            var defaultSequenceFlow = (string)execution.Activity.GetProperty("default");
            IList <IPvmTransition> transitionsToTake = new List <IPvmTransition>();

            IList <IPvmTransition> outgoingTransitions = execution.Activity.OutgoingTransitions;

            foreach (IPvmTransition outgoingTransition in outgoingTransitions)
            {
                if (defaultSequenceFlow == null || outgoingTransition.Id != defaultSequenceFlow)
                {
                    var condition = (ICondition)outgoingTransition.GetProperty(BpmnParse.PropertynameCondition);
                    if ((condition == null) || !checkConditions || condition.Evaluate(execution))
                    {
                        transitionsToTake.Add(outgoingTransition);
                    }
                }
            }

            if (transitionsToTake.Count == 1)
            {
                execution.LeaveActivityViaTransition(transitionsToTake.ElementAt(0));
            }
            else if (transitionsToTake.Count >= 1)
            {
                if (reusableExecutions == null || reusableExecutions.Count == 0)
                {
                    execution.LeaveActivityViaTransitions(transitionsToTake, new List <IActivityExecution>()
                    {
                        execution
                    });
                }
                else
                {
                    execution.LeaveActivityViaTransitions(transitionsToTake, reusableExecutions);
                }
            }
            else
            {
                //if (!ReferenceEquals(defaultSequenceFlow, null))
                if (!string.IsNullOrEmpty(defaultSequenceFlow))
                {
                    var defaultTransition = execution.Activity.FindOutgoingTransition(defaultSequenceFlow);
                    if (defaultTransition != null)
                    {
                        execution.LeaveActivityViaTransition(defaultTransition);
                    }
                    else
                    {
                        throw Log.MissingDefaultFlowException(execution.Activity.Id, defaultSequenceFlow);
                    }
                }
                else if (outgoingTransitions.Count > 0)
                {
                    throw Log.MissingConditionalFlowException(execution.Activity.Id);
                }
                else
                {
                    if (((ActivityImpl)execution.Activity).CompensationHandler &&
                        IsAncestorCompensationThrowing(execution))
                    {
                        execution.EndCompensation();
                    }
                    else
                    {
                        Log.MissingOutgoingSequenceFlow(execution.Activity.Id);
                        execution.End(true);

                        if (throwExceptionIfExecutionStuck)
                        {
                            throw Log.StuckExecutionException(execution.Activity.Id);
                        }
                    }
                }
            }
        }