Example #1
0
        public override void Execute(IExecutionEntity execution)
        {
            try
            {
                bool isSkipExpressionEnabled = SkipExpressionUtil.IsSkipExpressionEnabled(execution, skipExpression);
                if (!isSkipExpressionEnabled || (isSkipExpressionEnabled && !SkipExpressionUtil.ShouldSkipFlowElement(execution, skipExpression)))
                {
                    if (Context.ProcessEngineConfiguration.EnableProcessDefinitionInfoCache)
                    {
                        JToken taskElementProperties = Context.GetBpmnOverrideElementProperties(serviceTaskId, execution.ProcessDefinitionId);
                        if (taskElementProperties != null && taskElementProperties[DynamicBpmnConstants.SERVICE_TASK_EXPRESSION] != null)
                        {
                            string overrideExpression = taskElementProperties[DynamicBpmnConstants.SERVICE_TASK_EXPRESSION].ToString();
                            if (!string.IsNullOrWhiteSpace(overrideExpression) && !overrideExpression.Equals(expression.ExpressionText))
                            {
                                expression = Context.ProcessEngineConfiguration.ExpressionManager.CreateExpression(overrideExpression);
                            }
                        }
                    }

                    object value = expression.GetValue(execution);
                    if (!(resultVariable is null))
                    {
                        execution.SetVariable(resultVariable, value);
                    }
                }

                Leave(execution);
            }
            catch (Exception exc)
            {
                Exception cause = exc;
                BpmnError error = null;
                while (cause != null)
                {
                    if (cause is BpmnError)
                    {
                        error = (BpmnError)cause;
                        break;
                    }
                    cause = cause.InnerException;
                }

                if (error != null)
                {
                    ErrorPropagation.PropagateError(error, execution);
                }
                else
                {
                    throw new ActivitiException("Could not execute service task expression", exc);
                }
            }
        }
        // private static Logger log = LoggerFactory.getLogger(typeof(ExclusiveGatewayActivityBehavior));

        /// <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 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).
        /// </summary>
        public override void Leave(IExecutionEntity execution)
        {
            if (log.IsEnabled(LogLevel.Debug))
            {
                log.LogDebug($"Leaving exclusive gateway '{execution.CurrentActivityId}'");
            }

            ExclusiveGateway exclusiveGateway = (ExclusiveGateway)execution.CurrentFlowElement;

            ProcessEngineConfigurationImpl processEngineConfiguration = Context.ProcessEngineConfiguration;

            if (processEngineConfiguration is object && processEngineConfiguration.EventDispatcher.Enabled)
            {
                processEngineConfiguration.EventDispatcher.DispatchEvent(ActivitiEventBuilder.CreateActivityEvent(ActivitiEventType.ACTIVITY_COMPLETED, exclusiveGateway.Id, exclusiveGateway.Name, execution.Id, execution.ProcessInstanceId, execution.ProcessDefinitionId, exclusiveGateway));
            }

            SequenceFlow outgoingSequenceFlow  = null;
            SequenceFlow defaultSequenceFlow   = null;
            string       defaultSequenceFlowId = exclusiveGateway.DefaultFlow;

            // Determine sequence flow to take
            foreach (SequenceFlow sequenceFlow in exclusiveGateway.OutgoingFlows)
            {
                string skipExpressionString = sequenceFlow.SkipExpression;
                if (!SkipExpressionUtil.IsSkipExpressionEnabled(execution, skipExpressionString))
                {
                    bool conditionEvaluatesToTrue = ConditionUtil.HasTrueCondition(sequenceFlow, execution);
                    if (conditionEvaluatesToTrue && (defaultSequenceFlowId is null || !defaultSequenceFlowId.Equals(sequenceFlow.Id)))
                    {
                        if (log.IsEnabled(LogLevel.Debug))
                        {
                            log.LogDebug($"Sequence flow '{sequenceFlow.Id}'selected as outgoing sequence flow.");
                        }
                        outgoingSequenceFlow = sequenceFlow;
                        break;
                    }
                }
                else if (SkipExpressionUtil.ShouldSkipFlowElement(Context.CommandContext, execution, skipExpressionString))
                {
                    outgoingSequenceFlow = sequenceFlow;
                    break;
                }

                // Already store it, if we would need it later. Saves one for loop.
                if (defaultSequenceFlowId is object && defaultSequenceFlowId.Equals(sequenceFlow.Id))
                {
                    defaultSequenceFlow = sequenceFlow;
                }
            }

            // We have to record the end here, or else we're already past it
            Context.CommandContext.HistoryManager.RecordActivityEnd(execution, null);

            // Leave the gateway
            if (outgoingSequenceFlow != null)
            {
                execution.CurrentFlowElement = outgoingSequenceFlow;

                log.LogInformation($"条件表达式:id={outgoingSequenceFlow.Id} expression={outgoingSequenceFlow.ConditionExpression}");
            }
            else
            {
                if (defaultSequenceFlow != null)
                {
                    execution.CurrentFlowElement = defaultSequenceFlow;

                    log.LogInformation($"条件表达式:id={defaultSequenceFlow.Id} expression={defaultSequenceFlow.ConditionExpression}");
                }
                else
                {
                    // No sequence flow could be found, not even a default one
                    throw new ActivitiException("No outgoing sequence flow of the exclusive gateway '" + exclusiveGateway.Id + "' could be selected for continuing the process");
                }
            }

            base.Leave(execution);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="flowNode"></param>
        protected internal virtual void LeaveFlowNode(FlowNode flowNode)
        {
            log.LogDebug($"Leaving flow node {flowNode.GetType()} with id '{flowNode.Id}' by following it's {flowNode.OutgoingFlows.Count} outgoing sequenceflow");

            // Get default sequence flow (if set)
            string defaultSequenceFlowId = null;

            if (flowNode is Activity)
            {
                defaultSequenceFlowId = ((Activity)flowNode).DefaultFlow;
            }
            else if (flowNode is Gateway)
            {
                defaultSequenceFlowId = ((Gateway)flowNode).DefaultFlow;
            }

            // Determine which sequence flows can be used for leaving
            IList <SequenceFlow> outgoingSequenceFlows = new List <SequenceFlow>();

            foreach (SequenceFlow sequenceFlow in flowNode.OutgoingFlows)
            {
                string skipExpressionString = sequenceFlow.SkipExpression;
                if (!SkipExpressionUtil.IsSkipExpressionEnabled(execution, skipExpressionString))
                {
                    if (!evaluateConditions || (evaluateConditions && ConditionUtil.HasTrueCondition(sequenceFlow, execution) && (defaultSequenceFlowId is null || !defaultSequenceFlowId.Equals(sequenceFlow.Id))))
                    {
                        outgoingSequenceFlows.Add(sequenceFlow);
                    }
                }
                else if (flowNode.OutgoingFlows.Count == 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.Count == 0 && evaluateConditions)
            { // The elements that set this to false also have no support for default sequence flow
                if (defaultSequenceFlowId is object)
                {
                    foreach (SequenceFlow sequenceFlow in flowNode.OutgoingFlows)
                    {
                        if (defaultSequenceFlowId.Equals(sequenceFlow.Id))
                        {
                            outgoingSequenceFlows.Add(sequenceFlow);
                            break;
                        }
                    }
                }
            }

            // No outgoing found. Ending the execution
            if (outgoingSequenceFlows.Count == 0)
            {
                if (flowNode.OutgoingFlows == null || flowNode.OutgoingFlows.Count == 0)
                {
                    log.LogDebug($"No outgoing sequence flow found for flow node '{flowNode.Id}'.");
                    Context.Agenda.PlanEndExecutionOperation(execution);
                }
                else
                {
                    throw new ActivitiException("No outgoing sequence flow of element '" + flowNode.Id + "' could be selected for continuing the process");
                }
            }
            else
            {
                // Leave, and reuse the incoming sequence flow, make executions for all the others (if applicable)

                IExecutionEntityManager  executionEntityManager = commandContext.ExecutionEntityManager;
                IList <IExecutionEntity> outgoingExecutions     = new List <IExecutionEntity>(flowNode.OutgoingFlows.Count);

                SequenceFlow sequenceFlow = outgoingSequenceFlows[0];

                // Reuse existing one
                execution.CurrentFlowElement = sequenceFlow;
                execution.IsActive           = true;
                outgoingExecutions.Add(execution);

                // Executions for all the other one
                if (outgoingSequenceFlows.Count > 1)
                {
                    for (int i = 1; i < outgoingSequenceFlows.Count; i++)
                    {
                        IExecutionEntity parent = execution.ParentId is object?execution.Parent : execution;
                        IExecutionEntity outgoingExecutionEntity = commandContext.ExecutionEntityManager.CreateChildExecution(parent);

                        SequenceFlow outgoingSequenceFlow = outgoingSequenceFlows[i];
                        outgoingExecutionEntity.CurrentFlowElement = outgoingSequenceFlow;

                        executionEntityManager.Insert(outgoingExecutionEntity);
                        outgoingExecutions.Add(outgoingExecutionEntity);
                    }
                }

                // Leave (only done when all executions have been made, since some queries depend on this)
                foreach (IExecutionEntity outgoingExecution in outgoingExecutions)
                {
                    Context.Agenda.PlanContinueProcessOperation(outgoingExecution);
                }
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="execution"></param>
        public override void Execute(IExecutionEntity execution)
        {
            ICommandContext    commandContext    = Context.CommandContext;
            ITaskEntityManager taskEntityManager = commandContext.TaskEntityManager;

            //如果当前任务为补偿任务,则修改任务的父级为流程实例
            if ((execution.CurrentFlowElement as UserTask).ForCompensation)
            {
                execution.Parent = execution.ProcessInstance;
            }

            ITaskEntity task = taskEntityManager.Create();

            task.Execution         = execution;
            task.TaskDefinitionKey = userTask.Id;
            task.IsRuntimeAssignee();

            task.CanTransfer  = userTask.CanTransfer;
            task.OnlyAssignee = task.OnlyAssignee;

            ProcessEngineConfigurationImpl processEngineConfiguration = Context.ProcessEngineConfiguration;
            ExpressionManager expressionManager = processEngineConfiguration.ExpressionManager;

            string         activeTaskName;
            string         activeTaskDescription;
            string         activeTaskDueDate;
            string         activeTaskCategory;
            string         activeTaskSkipExpression;
            string         activeTaskPriority;
            string         activeTaskFormKey;
            string         activeTaskAssignee;
            string         activeTaskOwner;
            IList <string> activeTaskCandidateUsers;
            IList <string> activeTaskCandidateGroups;

            if (Context.ProcessEngineConfiguration.EnableProcessDefinitionInfoCache)
            {
                JToken taskElementProperties = Context.GetBpmnOverrideElementProperties(userTask.Id, execution.ProcessDefinitionId);
                activeTaskName            = GetActiveValue(userTask.Name, DynamicBpmnConstants.USER_TASK_NAME, taskElementProperties);
                activeTaskDescription     = GetActiveValue(userTask.Documentation, DynamicBpmnConstants.USER_TASK_DESCRIPTION, taskElementProperties);
                activeTaskDueDate         = GetActiveValue(userTask.DueDate, DynamicBpmnConstants.USER_TASK_DUEDATE, taskElementProperties);
                activeTaskPriority        = GetActiveValue(userTask.Priority, DynamicBpmnConstants.USER_TASK_PRIORITY, taskElementProperties);
                activeTaskCategory        = GetActiveValue(userTask.Category, DynamicBpmnConstants.USER_TASK_CATEGORY, taskElementProperties);
                activeTaskFormKey         = GetActiveValue(userTask.FormKey, DynamicBpmnConstants.USER_TASK_FORM_KEY, taskElementProperties);
                activeTaskSkipExpression  = GetActiveValue(userTask.SkipExpression, DynamicBpmnConstants.TASK_SKIP_EXPRESSION, taskElementProperties);
                activeTaskAssignee        = GetActiveValue(userTask.Assignee, DynamicBpmnConstants.USER_TASK_ASSIGNEE, taskElementProperties);
                activeTaskOwner           = GetActiveValue(userTask.Owner, DynamicBpmnConstants.USER_TASK_OWNER, taskElementProperties);
                activeTaskCandidateUsers  = GetActiveValueList(userTask.CandidateUsers, DynamicBpmnConstants.USER_TASK_CANDIDATE_USERS, taskElementProperties);
                activeTaskCandidateGroups = GetActiveValueList(userTask.CandidateGroups, DynamicBpmnConstants.USER_TASK_CANDIDATE_GROUPS, taskElementProperties);
            }
            else
            {
                activeTaskName            = userTask.Name;
                activeTaskDescription     = userTask.Documentation;
                activeTaskDueDate         = userTask.DueDate;
                activeTaskPriority        = userTask.Priority;
                activeTaskCategory        = userTask.Category;
                activeTaskFormKey         = userTask.FormKey;
                activeTaskSkipExpression  = userTask.SkipExpression;
                activeTaskAssignee        = userTask.Assignee;
                activeTaskOwner           = userTask.Owner;
                activeTaskCandidateUsers  = userTask.CandidateUsers;
                activeTaskCandidateGroups = userTask.CandidateGroups;
            }

            if (!string.IsNullOrWhiteSpace(activeTaskName))
            {
                string name;
                try
                {
                    name = (string)expressionManager.CreateExpression(activeTaskName).GetValue(execution);
                }
                catch (ActivitiException e)
                {
                    name = activeTaskName;
                    log.LogWarning("property not found in task name expression " + e.Message);
                }
                task.Name = name;
            }

            if (!string.IsNullOrWhiteSpace(activeTaskDescription))
            {
                string description;
                try
                {
                    description = (string)expressionManager.CreateExpression(activeTaskDescription).GetValue(execution);
                }
                catch (ActivitiException e)
                {
                    description = activeTaskDescription;
                    log.LogWarning("property not found in task description expression " + e.Message);
                }
                task.Description = description;
            }

            if (!string.IsNullOrWhiteSpace(activeTaskDueDate))
            {
                object dueDate = expressionManager.CreateExpression(activeTaskDueDate).GetValue(execution);
                if (dueDate != null)
                {
                    if (dueDate is DateTime time)
                    {
                        task.DueDate = time;
                    }
                    else if (dueDate is string @string)
                    {
                        string businessCalendarName;
                        if (!string.IsNullOrWhiteSpace(userTask.BusinessCalendarName))
                        {
                            businessCalendarName = expressionManager.CreateExpression(userTask.BusinessCalendarName).GetValue(execution).ToString();
                        }
                        else
                        {
                            businessCalendarName = DueDateBusinessCalendar.NAME;
                        }

                        IBusinessCalendar businessCalendar = Context.ProcessEngineConfiguration.BusinessCalendarManager.GetBusinessCalendar(businessCalendarName);
                        task.DueDate = businessCalendar.ResolveDuedate(@string);
                    }
                    else
                    {
                        throw new ActivitiIllegalArgumentException("Due date expression does not resolve to a Date or Date string: " + activeTaskDueDate);
                    }
                }
            }

            if (!string.IsNullOrWhiteSpace(activeTaskPriority))
            {
                object priority = expressionManager.CreateExpression(activeTaskPriority).GetValue(execution);
                if (priority != null)
                {
                    if (priority is string @string)
                    {
                        try
                        {
                            task.Priority = Convert.ToInt32(@string);
                        }
                        catch (FormatException e)
                        {
                            throw new ActivitiIllegalArgumentException("Priority does not resolve to a number: " + priority, e);
                        }
                    }
                    else if (priority is int || priority is long)
                    {
                        task.Priority = (int)priority;
                    }
                    else
                    {
                        throw new ActivitiIllegalArgumentException("Priority expression does not resolve to a number: " + activeTaskPriority);
                    }
                }
            }

            if (!string.IsNullOrWhiteSpace(activeTaskCategory))
            {
                object category = expressionManager.CreateExpression(activeTaskCategory).GetValue(execution);
                if (category != null)
                {
                    if (category is string)
                    {
                        task.Category = category.ToString();
                    }
                    else
                    {
                        throw new ActivitiIllegalArgumentException("Category expression does not resolve to a string: " + activeTaskCategory);
                    }
                }
            }

            if (!string.IsNullOrWhiteSpace(activeTaskFormKey))
            {
                object formKey = expressionManager.CreateExpression(activeTaskFormKey).GetValue(execution);
                if (formKey != null)
                {
                    if (formKey is string)
                    {
                        task.FormKey = formKey.ToString();
                    }
                    else
                    {
                        throw new ActivitiIllegalArgumentException("FormKey expression does not resolve to a string: " + activeTaskFormKey);
                    }
                }
            }

            taskEntityManager.Insert(task, execution);

            bool skipUserTask = false;

            if (!string.IsNullOrWhiteSpace(activeTaskSkipExpression))
            {
                IExpression skipExpression = expressionManager.CreateExpression(activeTaskSkipExpression);
                skipUserTask = SkipExpressionUtil.IsSkipExpressionEnabled(execution, skipExpression) && SkipExpressionUtil.ShouldSkipFlowElement(execution, skipExpression);
            }

            // Handling assignments need to be done after the task is inserted, to have an id
            if (!skipUserTask)
            {
                HandleAssignments(taskEntityManager, activeTaskAssignee, activeTaskOwner, activeTaskCandidateUsers, activeTaskCandidateGroups, task, expressionManager, execution);
            }

            processEngineConfiguration.ListenerNotificationHelper.ExecuteTaskListeners(task, BaseTaskListenerFields.EVENTNAME_CREATE);

            // All properties set, now fire events
            if (Context.ProcessEngineConfiguration.EventDispatcher.Enabled)
            {
                IActivitiEventDispatcher eventDispatcher = Context.ProcessEngineConfiguration.EventDispatcher;
                eventDispatcher.DispatchEvent(ActivitiEventBuilder.CreateEntityEvent(ActivitiEventType.TASK_CREATED, task));
                if (string.IsNullOrWhiteSpace(task.Assignee) == false)
                {
                    eventDispatcher.DispatchEvent(ActivitiEventBuilder.CreateEntityEvent(ActivitiEventType.TASK_ASSIGNED, task));
                }
            }

            if (skipUserTask)
            {
                taskEntityManager.DeleteTask(task, null, false, false);
                Leave(execution);
            }
        }
        public override void Execute(IExecutionEntity execution)
        {
            try
            {
                bool isSkipExpressionEnabled = SkipExpressionUtil.IsSkipExpressionEnabled(execution, skipExpression);
                if (!isSkipExpressionEnabled || (isSkipExpressionEnabled && !SkipExpressionUtil.ShouldSkipFlowElement(execution, skipExpression)))
                {
                    if (Context.ProcessEngineConfiguration.EnableProcessDefinitionInfoCache)
                    {
                        JToken taskElementProperties = Context.GetBpmnOverrideElementProperties(serviceTaskId, execution.ProcessDefinitionId);
                        if (taskElementProperties != null && taskElementProperties[DynamicBpmnConstants.SERVICE_TASK_DELEGATE_EXPRESSION] != null)
                        {
                            string overrideExpression = taskElementProperties[DynamicBpmnConstants.SERVICE_TASK_DELEGATE_EXPRESSION].ToString();
                            if (!string.IsNullOrWhiteSpace(overrideExpression) && !overrideExpression.Equals(expression.ExpressionText))
                            {
                                expression = Context.ProcessEngineConfiguration.ExpressionManager.CreateExpression(overrideExpression);
                            }
                        }
                    }

                    object @delegate = DelegateExpressionUtil.ResolveDelegateExpression(expression, execution, fieldDeclarations);
                    if (@delegate is IActivityBehavior)
                    {
                        if (@delegate is AbstractBpmnActivityBehavior)
                        {
                            ((AbstractBpmnActivityBehavior)@delegate).MultiInstanceActivityBehavior = MultiInstanceActivityBehavior;
                        }

                        Context.ProcessEngineConfiguration.DelegateInterceptor.HandleInvocation(new ActivityBehaviorInvocation((IActivityBehavior)@delegate, execution));
                    }
                    else if (@delegate is ICSharpDelegate)
                    {
                        Context.ProcessEngineConfiguration.DelegateInterceptor.HandleInvocation(new CSharpDelegateInvocation((ICSharpDelegate)@delegate, execution));
                        Leave(execution);
                    }
                    else
                    {
                        throw new ActivitiIllegalArgumentException("Delegate expression " + expression + " did neither resolve to an implementation of " + typeof(IActivityBehavior) + " nor " + typeof(ICSharpDelegate));
                    }
                }
                else
                {
                    Leave(execution);
                }
            }
            catch (Exception exc)
            {
                Exception cause = exc;
                BpmnError error = null;
                while (cause != null)
                {
                    if (cause is BpmnError)
                    {
                        error = (BpmnError)cause;
                        break;
                    }
                    cause = cause.InnerException;
                }

                if (error != null)
                {
                    ErrorPropagation.PropagateError(error, execution);
                }
                else
                {
                    throw new ActivitiException(exc.Message, exc);
                }
            }
        }