Ejemplo n.º 1
0
        public virtual object Execute(ICommandContext commandContext)
        {
            lock (syncRoot)
            {
                ProcessEngineConfigurationImpl processEngineConfiguration = commandContext.ProcessEngineConfiguration;
                Interceptor.ICommandExecutor   commandExecutor            = processEngineConfiguration.CommandExecutor;

                ITaskEntity task = commandExecutor.Execute(new GetTaskByIdCmd(currentTaskId)) as ITaskEntity;
                if (task is null)
                {
                    throw new ActivitiObjectNotFoundException(string.Concat("No task found for id '", currentTaskId));
                }

                string           currentExecutionId = task.ExecutionId;
                IExecutionEntity execution          = task.Execution;
                if (execution is null)
                {
                    throw new ActivitiObjectNotFoundException(string.Concat("No execution found for id '", currentExecutionId));
                }

                var flowElement = ProcessDefinitionUtil.GetFlowElement(execution.ProcessDefinitionId, returnToActivityId);
                if (flowElement is null)
                {
                    throw new ActivitiObjectNotFoundException(string.Concat("No execution found for id '", currentExecutionId, "'"));
                }

                IHistoricActivityInstanceEntity hisInst = processEngineConfiguration.HistoryService.CreateHistoricActivityInstanceQuery()
                                                          .SetProcessInstanceId(execution.ProcessInstanceId)
                                                          .SetActivityId(returnToActivityId)
                                                          .OrderByHistoricActivityInstanceStartTime()
                                                          .Desc()
                                                          .List()
                                                          .FirstOrDefault() as IHistoricActivityInstanceEntity;

                IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager;

                IExecutionEntity returnToExec = executionEntityManager.CreateChildExecution(execution.ProcessInstance);
                returnToExec.CurrentFlowElement = flowElement;
                foreach (var key in variables.Keys)
                {
                    returnToExec.SetVariable(key, variables[key]);
                }

                executionEntityManager.Insert(returnToExec);

                commandContext.Agenda.PlanContinueProcessOperation(returnToExec);

                IExecutionEntity miRoot = commandExecutor.Execute(new GetMultiInstanceRootExecutionCmd(execution));

                List <ITask> tasks = new List <ITask>();
                if (miRoot != null)
                {
                    ITaskQuery query = commandContext.ProcessEngineConfiguration.TaskService.CreateTaskQuery();

                    IEnumerable <IExecutionEntity> childExecutions = commandExecutor.Execute(new GetChildExecutionsCmd(miRoot));

                    query.SetExecutionIdIn(childExecutions.Select(x => x.Id).ToArray());

                    tasks.AddRange(query.List());
                }
                else
                {
                    tasks.Add(task);
                }

                DeleteTasks(commandContext, commandExecutor, miRoot != null ? miRoot : execution, executionEntityManager, tasks);

                return(null);
            }
        }
        /// <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);
                }
            }
        }