示例#1
0
        /// <summary>
        ///
        /// </summary>
        protected override void RunOperation()
        {
            try
            {
                // Find the actual scope that needs to be destroyed.
                // This could be the incoming execution, or the first parent execution where isScope = true

                // Find parent scope execution
                IExecutionEntity scopeExecution = execution.IsScope ? execution : FindFirstParentScopeExecution(execution);

                if (scopeExecution == null)
                {
                    throw new ActivitiException("Programmatic error: no parent scope execution found for boundary event");
                }

                IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager;
                DeleteAllChildExecutions(executionEntityManager, scopeExecution);

                // Delete all scope tasks
                ITaskEntityManager taskEntityManager = commandContext.TaskEntityManager;
                DeleteAllScopeTasks(scopeExecution, taskEntityManager);

                // Delete all scope jobs
                ITimerJobEntityManager timerJobEntityManager = commandContext.TimerJobEntityManager;
                DeleteAllScopeJobs(scopeExecution, timerJobEntityManager);

                // Remove variables associated with this scope
                IVariableInstanceEntityManager variableInstanceEntityManager = commandContext.VariableInstanceEntityManager;
                RemoveAllVariablesFromScope(scopeExecution, variableInstanceEntityManager);

                commandContext.HistoryManager.RecordActivityEnd(scopeExecution, scopeExecution.DeleteReason);
                executionEntityManager.Delete(scopeExecution);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, ex.Message);
                throw;
            }
        }
        public override void Trigger(IExecutionEntity execution, string triggerName, object triggerData, bool throwError = true)
        {
            ICommandContext         commandContext         = Context.CommandContext;
            IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager;

            StartEvent startEvent = (StartEvent)execution.CurrentFlowElement;

            if (startEvent.Interrupting)
            {
                IList <IExecutionEntity> childExecutions = executionEntityManager.FindChildExecutionsByParentExecutionId(execution.ParentId);
                foreach (IExecutionEntity childExecution in childExecutions)
                {
                    if (!childExecution.Id.Equals(execution.Id))
                    {
                        executionEntityManager.DeleteExecutionAndRelatedData(childExecution, History.DeleteReasonFields.EVENT_SUBPROCESS_INTERRUPTING + "(" + startEvent.Id + ")", false);
                    }
                }
            }

            IEventSubscriptionEntityManager  eventSubscriptionEntityManager = Context.CommandContext.EventSubscriptionEntityManager;
            IList <IEventSubscriptionEntity> eventSubscriptions             = execution.EventSubscriptions;

            foreach (IEventSubscriptionEntity eventSubscription in eventSubscriptions)
            {
                if (eventSubscription.EventType == MessageEventSubscriptionEntityFields.EVENT_TYPE && eventSubscription.EventName.Equals(messageEventDefinition.MessageRef))
                {
                    eventSubscriptionEntityManager.Delete(eventSubscription);
                }
            }

            execution.CurrentFlowElement = (SubProcess)execution.CurrentFlowElement.ParentContainer;
            execution.IsScope            = true;

            IExecutionEntity outgoingFlowExecution = executionEntityManager.CreateChildExecution(execution);

            outgoingFlowExecution.CurrentFlowElement = startEvent;

            Leave(outgoingFlowExecution);
        }
示例#3
0
        public virtual object Execute(ICommandContext commandContext)
        {
            // check that the new process definition is just another version of the same
            // process definition that the process instance is using
            IExecutionEntityManager executionManager = commandContext.ExecutionEntityManager;
            IExecutionEntity        processInstance  = executionManager.FindById <IExecutionEntity>(new KeyValuePair <string, object>("id", processInstanceId));

            if (processInstance == null)
            {
                throw new ActivitiObjectNotFoundException("No process instance found for id = '" + processInstanceId + "'.", typeof(IProcessInstance));
            }
            else if (!processInstance.ProcessInstanceType)
            {
                throw new ActivitiIllegalArgumentException("A process instance id is required, but the provided id " + "'" + processInstanceId + "' " + "points to a child execution of process instance " + "'" + processInstance.ProcessInstanceId + "'. " + "Please invoke the " + this.GetType().Name + " with a root execution id.");
            }

            DeploymentManager  deploymentCache          = commandContext.ProcessEngineConfiguration.DeploymentManager;
            IProcessDefinition currentProcessDefinition = deploymentCache.FindDeployedProcessDefinitionById(processInstance.ProcessDefinitionId);

            IProcessDefinition newProcessDefinition = deploymentCache.FindDeployedProcessDefinitionByKeyAndVersionAndTenantId(currentProcessDefinition.Key, processDefinitionVersion, currentProcessDefinition.TenantId);

            ValidateAndSwitchVersionOfExecution(commandContext, processInstance, newProcessDefinition);

            // switch the historic process instance to the new process definition version
            commandContext.HistoryManager.RecordProcessDefinitionChange(processInstanceId, newProcessDefinition.Id);

            // switch all sub-executions of the process instance to the new process definition version
            ICollection <IExecutionEntity> childExecutions = executionManager.FindChildExecutionsByProcessInstanceId(processInstanceId);

            foreach (IExecutionEntity executionEntity in childExecutions)
            {
                ValidateAndSwitchVersionOfExecution(commandContext, executionEntity, newProcessDefinition);
            }

            return(null);
        }
示例#4
0
        protected internal virtual void ExecuteInterruptingBehavior(IExecutionEntity executionEntity, ICommandContext commandContext)
        {
            // The destroy scope operation will look for the parent execution and
            // destroy the whole scope, and leave the boundary event using this parent execution.
            //
            // The take outgoing seq flows operation below (the non-interrupting else clause) on the other hand uses the
            // child execution to leave, which keeps the scope alive.
            // Which is what we need here.

            IExecutionEntityManager executionEntityManager    = commandContext.ExecutionEntityManager;
            IExecutionEntity        attachedRefScopeExecution = executionEntityManager.FindById <IExecutionEntity>(executionEntity.ParentId);

            IExecutionEntity scopeExecution             = null;
            IExecutionEntity currentlyExaminedExecution = executionEntityManager.FindById <IExecutionEntity>(attachedRefScopeExecution.ParentId);

            GetScopeExecution(executionEntityManager, ref scopeExecution, ref currentlyExaminedExecution);

            DeleteChildExecutions(attachedRefScopeExecution, executionEntity, commandContext);

            // set new parent for boundary event execution
            executionEntity.Parent = scopeExecution ?? throw new ActivitiException("Programmatic error: no parent scope execution found for boundary event");

            Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(executionEntity, true);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="executionEntityManager"></param>
        /// <param name="processInstanceId"></param>
        /// <returns></returns>
        protected internal virtual int GetNumberOfActiveChildExecutionsForProcessInstance(IExecutionEntityManager executionEntityManager, string processInstanceId, IExecutionEntity endingExecution)
        {
            ICollection <IExecutionEntity> executions = executionEntityManager.FindChildExecutionsByProcessInstanceId(processInstanceId);
            int activeExecutions = 0;

            foreach (IExecutionEntity execution in executions)
            {
                if (endingExecution is object && endingExecution.Id == execution.Id)
                {
                    continue;
                }

                if (execution.IsActive && !processInstanceId.Equals(execution.Id))
                {
                    activeExecutions++;
                }
            }
            return(activeExecutions);
        }
        /// <summary>
        ///
        /// </summary>
        protected internal virtual void HandleRegularExecution()
        {
            IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager;

            // There will be a parent execution (or else we would be in the process instance handling method)
            IExecutionEntity parentExecution = executionEntityManager.FindById <IExecutionEntity>(execution.ParentId);

            // If the execution is a scope, all the child executions must be deleted first.
            if (execution.IsScope)
            {
                executionEntityManager.DeleteChildExecutions(execution, null, false);
            }

            // Delete current execution
            logger.LogDebug($"Ending execution {execution.Id}");
            executionEntityManager.DeleteExecutionAndRelatedData(execution, null, false);

            logger.LogDebug($"Parent execution found. Continuing process using execution {parentExecution.Id}");

            // When ending an execution in a multi instance subprocess , special care is needed
            if (IsEndEventInMultiInstanceSubprocess(execution))
            {
                HandleMultiInstanceSubProcess(executionEntityManager, parentExecution);
                return;
            }

            SubProcess subProcess = execution.CurrentFlowElement.SubProcess;

            // If there are no more active child executions, the process can be continued
            // If not (eg an embedded subprocess still has active elements, we cannot continue)
            if (GetNumberOfActiveChildExecutionsForExecution(executionEntityManager, parentExecution.Id) == 0 || IsAllEventScopeExecutions(executionEntityManager, parentExecution))
            {
                IExecutionEntity executionToContinue = null;

                if (subProcess != null)
                {
                    // In case of ending a subprocess: go up in the scopes and continue via the parent scope
                    // unless its a compensation, then we don't need to do anything and can just end it

                    if (subProcess.ForCompensation)
                    {
                        Context.Agenda.PlanEndExecutionOperation(parentExecution);
                    }
                    else
                    {
                        executionToContinue = HandleSubProcessEnd(executionEntityManager, parentExecution, subProcess);
                    }
                }
                else
                {
                    // In the 'regular' case (not being in a subprocess), we use the parent execution to
                    // continue process instance execution

                    executionToContinue = HandleRegularExecutionEnd(executionEntityManager, parentExecution);
                }

                if (executionToContinue != null)
                {
                    // only continue with outgoing sequence flows if the execution is
                    // not the process instance root execution (otherwise the process instance is finished)
                    if (executionToContinue.ProcessInstanceType)
                    {
                        HandleProcessInstanceExecution(executionToContinue);
                    }
                    else
                    {
                        Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(executionToContinue, true);
                    }
                }
            }
        }
        protected internal virtual void DefaultTerminateEndEventBehaviour(IExecutionEntity execution, ICommandContext commandContext, IExecutionEntityManager executionEntityManager)
        {
            IExecutionEntity scopeExecutionEntity = executionEntityManager.FindFirstScope(execution);

            SendProcessInstanceCancelledEvent(scopeExecutionEntity, execution.CurrentFlowElement);

            // If the scope is the process instance, we can just terminate it all
            // Special treatment is needed when the terminated activity is a subprocess (embedded/callactivity/..)
            // The subprocess is destroyed, but the execution calling it, continues further on.
            // In case of a multi-instance subprocess, only one instance is terminated, the other instances continue to exist.

            string deleteReason = CreateDeleteReason(execution.CurrentActivityId);

            if (scopeExecutionEntity.ProcessInstanceType && scopeExecutionEntity.SuperExecutionId is null)
            {
                EndAllHistoricActivities(scopeExecutionEntity.Id, deleteReason);
                DeleteExecutionEntities(executionEntityManager, scopeExecutionEntity, deleteReason);
                commandContext.HistoryManager.RecordProcessInstanceEnd(scopeExecutionEntity.Id, deleteReason, execution.CurrentActivityId);
            }
            else if (scopeExecutionEntity.CurrentFlowElement != null && scopeExecutionEntity.CurrentFlowElement is SubProcess)
            { // SubProcess
                SubProcess subProcess = (SubProcess)scopeExecutionEntity.CurrentFlowElement;

                scopeExecutionEntity.DeleteReason = deleteReason;
                if (subProcess.HasMultiInstanceLoopCharacteristics())
                {
                    Context.Agenda.PlanDestroyScopeOperation(scopeExecutionEntity);
                    MultiInstanceActivityBehavior multiInstanceBehavior = (MultiInstanceActivityBehavior)subProcess.Behavior;
                    multiInstanceBehavior.Leave(scopeExecutionEntity);
                }
                else
                {
                    Context.Agenda.PlanDestroyScopeOperation(scopeExecutionEntity);
                    IExecutionEntity outgoingFlowExecution = executionEntityManager.CreateChildExecution(scopeExecutionEntity.Parent);
                    outgoingFlowExecution.CurrentFlowElement = scopeExecutionEntity.CurrentFlowElement;
                    Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(outgoingFlowExecution, true);
                }
            }
            else if (scopeExecutionEntity.ParentId is null && scopeExecutionEntity.SuperExecutionId is object)
            { // CallActivity
                IExecutionEntity callActivityExecution = scopeExecutionEntity.SuperExecution;
                CallActivity     callActivity          = (CallActivity)callActivityExecution.CurrentFlowElement;

                if (callActivity.HasMultiInstanceLoopCharacteristics())
                {
                    MultiInstanceActivityBehavior multiInstanceBehavior = (MultiInstanceActivityBehavior)callActivity.Behavior;
                    multiInstanceBehavior.Leave(callActivityExecution);
                    executionEntityManager.DeleteProcessInstanceExecutionEntity(scopeExecutionEntity.Id, execution.CurrentFlowElement.Id, "terminate end event", false, false);
                }
                else
                {
                    executionEntityManager.DeleteProcessInstanceExecutionEntity(scopeExecutionEntity.Id, execution.CurrentFlowElement.Id, "terminate end event", false, false);
                    IExecutionEntity superExecutionEntity = executionEntityManager.FindById <IExecutionEntity>(scopeExecutionEntity.SuperExecutionId);
                    Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(superExecutionEntity, true);
                }
            }
        }
        protected internal virtual void TerminateAllBehaviour(IExecutionEntity execution, ICommandContext commandContext, IExecutionEntityManager executionEntityManager)
        {
            IExecutionEntity rootExecutionEntity = executionEntityManager.FindByRootProcessInstanceId(execution.RootProcessInstanceId);
            string           deleteReason        = CreateDeleteReason(execution.CurrentActivityId);

            DeleteExecutionEntities(executionEntityManager, rootExecutionEntity, deleteReason);
            EndAllHistoricActivities(rootExecutionEntity.Id, deleteReason);
            commandContext.HistoryManager.RecordProcessInstanceEnd(rootExecutionEntity.Id, deleteReason, execution.CurrentActivityId);
        }
        protected internal virtual void TerminateMultiInstanceRoot(IExecutionEntity execution, ICommandContext commandContext, IExecutionEntityManager executionEntityManager)
        {
            // When terminateMultiInstance is 'true', we look for the multi instance root and delete it from there.
            IExecutionEntity miRootExecutionEntity = executionEntityManager.FindFirstMultiInstanceRoot(execution);

            if (miRootExecutionEntity != null)
            {
                // Create sibling execution to continue process instance execution before deletion
                IExecutionEntity siblingExecution = executionEntityManager.CreateChildExecution(miRootExecutionEntity.Parent);
                siblingExecution.CurrentFlowElement = miRootExecutionEntity.CurrentFlowElement;

                DeleteExecutionEntities(executionEntityManager, miRootExecutionEntity, CreateDeleteReason(miRootExecutionEntity.ActivityId));

                Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(siblingExecution, true);
            }
            else
            {
                DefaultTerminateEndEventBehaviour(execution, commandContext, executionEntityManager);
            }
        }
示例#10
0
        public override void Execute(IExecutionEntity execution)
        {
            IExecutionEntity        executionEntity        = execution;
            ICommandContext         commandContext         = Context.CommandContext;
            IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager;

            // find cancel boundary event:
            IExecutionEntity parentScopeExecution       = null;
            IExecutionEntity currentlyExaminedExecution = executionEntityManager.FindById <IExecutionEntity>(executionEntity.ParentId);

            while (currentlyExaminedExecution != null && parentScopeExecution == null)
            {
                if (currentlyExaminedExecution.CurrentFlowElement is SubProcess)
                {
                    parentScopeExecution = currentlyExaminedExecution;
                    SubProcess subProcess = (SubProcess)currentlyExaminedExecution.CurrentFlowElement;
                    if (subProcess.LoopCharacteristics != null)
                    {
                        IExecutionEntity miExecution = parentScopeExecution.Parent;
                        FlowElement      miElement   = miExecution.CurrentFlowElement;
                        if (miElement != null && miElement.Id.Equals(subProcess.Id))
                        {
                            parentScopeExecution = miExecution;
                        }
                    }
                }
                else
                {
                    currentlyExaminedExecution = executionEntityManager.FindById <IExecutionEntity>(currentlyExaminedExecution.ParentId);
                }
            }

            if (parentScopeExecution == null)
            {
                throw new ActivitiException("No sub process execution found for cancel end event " + executionEntity.CurrentActivityId);
            }

            {
                SubProcess    subProcess          = (SubProcess)parentScopeExecution.CurrentFlowElement;
                BoundaryEvent cancelBoundaryEvent = null;
                if (CollectionUtil.IsNotEmpty(subProcess.BoundaryEvents))
                {
                    foreach (BoundaryEvent boundaryEvent in subProcess.BoundaryEvents)
                    {
                        if (CollectionUtil.IsNotEmpty(boundaryEvent.EventDefinitions) && boundaryEvent.EventDefinitions[0] is CancelEventDefinition)
                        {
                            cancelBoundaryEvent = boundaryEvent;
                            break;
                        }
                    }
                }

                if (cancelBoundaryEvent == null)
                {
                    throw new ActivitiException("Could not find cancel boundary event for cancel end event " + executionEntity.CurrentActivityId);
                }

                IExecutionEntity newParentScopeExecution = null;
                currentlyExaminedExecution = executionEntityManager.FindById <IExecutionEntity>(parentScopeExecution.ParentId);
                while (currentlyExaminedExecution != null && newParentScopeExecution == null)
                {
                    if (currentlyExaminedExecution.IsScope)
                    {
                        newParentScopeExecution = currentlyExaminedExecution;
                    }
                    else
                    {
                        currentlyExaminedExecution = executionEntityManager.FindById <IExecutionEntity>(currentlyExaminedExecution.ParentId);
                    }
                }

                ScopeUtil.CreateCopyOfSubProcessExecutionForCompensation(parentScopeExecution);

                if (subProcess.LoopCharacteristics != null)
                {
                    IList <IExecutionEntity> multiInstanceExecutions = parentScopeExecution.Executions;
                    IList <IExecutionEntity> executionsToDelete      = new List <IExecutionEntity>();
                    foreach (IExecutionEntity multiInstanceExecution in multiInstanceExecutions)
                    {
                        if (!multiInstanceExecution.Id.Equals(parentScopeExecution.Id))
                        {
                            ScopeUtil.CreateCopyOfSubProcessExecutionForCompensation(multiInstanceExecution);

                            // end all executions in the scope of the transaction
                            executionsToDelete.Add(multiInstanceExecution);
                            DeleteChildExecutions(multiInstanceExecution, executionEntity, commandContext, History.DeleteReasonFields.TRANSACTION_CANCELED);
                        }
                    }

                    foreach (IExecutionEntity executionEntityToDelete in executionsToDelete)
                    {
                        DeleteChildExecutions(executionEntityToDelete, executionEntity, commandContext, History.DeleteReasonFields.TRANSACTION_CANCELED);
                    }
                }

                // The current activity is finished (and will not be ended in the deleteChildExecutions)
                commandContext.HistoryManager.RecordActivityEnd(executionEntity, null);

                // set new parent for boundary event execution
                executionEntity.Parent             = newParentScopeExecution ?? throw new ActivitiException("Programmatic error: no parent scope execution found for boundary event " + cancelBoundaryEvent.Id);
                executionEntity.CurrentFlowElement = cancelBoundaryEvent;

                // end all executions in the scope of the transaction
                DeleteChildExecutions(parentScopeExecution, executionEntity, commandContext, History.DeleteReasonFields.TRANSACTION_CANCELED);
                commandContext.HistoryManager.RecordActivityEnd(parentScopeExecution, History.DeleteReasonFields.TRANSACTION_CANCELED);

                Context.Agenda.PlanTriggerExecutionOperation(executionEntity);
            }
        }
        private void DeleteTasks(ICommandContext commandContext, Interceptor.ICommandExecutor commandExecutor, IExecutionEntity execution, IExecutionEntityManager executionEntityManager, List <ITask> tasks)
        {
            foreach (ITaskEntity delTask in tasks)
            {
                commandExecutor.Execute(new AddCommentCmd(delTask.Id, delTask.ProcessInstanceId, returnToReason));

                commandContext.TaskEntityManager.DeleteTask(delTask, returnToReason, false, false);
            }

            DeleteExecutions(execution, true, returnToReason, commandContext);
        }
示例#12
0
        private void ReturnToTasks(ICommandContext commandContext, Interceptor.ICommandExecutor commandExecutor, IExecutionEntity execution, IExecutionEntityManager executionEntityManager, List <ITask> tasks)
        {
            foreach (ITaskEntity delTask in tasks)
            {
                IActivitiEventDispatcher eventDispatcher = commandContext.ProcessEngineConfiguration.EventDispatcher;
                if (eventDispatcher.Enabled)
                {
                    eventDispatcher.DispatchEvent(ActivitiEventBuilder.CreateTaskReturnEntityEvent(delTask, returnToActivityId));
                }

                commandExecutor.Execute(new AddCommentCmd(delTask.Id, delTask.ProcessInstanceId, returnToReason));

                commandContext.TaskEntityManager.DeleteTask(delTask, returnToReason, false, false);
            }

            DeleteExecutions(execution, true, returnToReason, commandContext);
        }
示例#13
0
        public override void Execute(IExecutionEntity execution)
        {
            string finalProcessDefinitonKey;

            if (processDefinitionExpression != null)
            {
                finalProcessDefinitonKey = (string)processDefinitionExpression.GetValue(execution);
            }
            else
            {
                finalProcessDefinitonKey = processDefinitonKey;
            }

            IProcessDefinition processDefinition = FindProcessDefinition(finalProcessDefinitonKey, execution.TenantId);

            // Get model from cache
            Process subProcess = ProcessDefinitionUtil.GetProcess(processDefinition.Id);

            if (subProcess == null)
            {
                throw new ActivitiException("Cannot start a sub process instance. Process model " + processDefinition.Name + " (id = " + processDefinition.Id + ") could not be found");
            }

            FlowElement initialFlowElement = subProcess.InitialFlowElement;

            if (initialFlowElement == null)
            {
                throw new ActivitiException("No start element found for process definition " + processDefinition.Id);
            }

            // Do not start a process instance if the process definition is suspended
            if (ProcessDefinitionUtil.IsProcessDefinitionSuspended(processDefinition.Id))
            {
                throw new ActivitiException("Cannot start process instance. Process definition " + processDefinition.Name + " (id = " + processDefinition.Id + ") is suspended");
            }

            ProcessEngineConfigurationImpl processEngineConfiguration = Context.ProcessEngineConfiguration;
            IExecutionEntityManager        executionEntityManager     = Context.CommandContext.ExecutionEntityManager;
            ExpressionManager expressionManager = processEngineConfiguration.ExpressionManager;

            CallActivity callActivity = (CallActivity)execution.CurrentFlowElement;

            string businessKey = null;

            if (!string.IsNullOrWhiteSpace(callActivity.BusinessKey))
            {
                IExpression expression = expressionManager.CreateExpression(callActivity.BusinessKey);
                businessKey = expression.GetValue(execution).ToString();
            }
            else if (callActivity.InheritBusinessKey)
            {
                IExecutionEntity processInstance = executionEntityManager.FindById <IExecutionEntity>(execution.ProcessInstanceId);
                businessKey = processInstance.BusinessKey;
            }

            IExecutionEntity subProcessInstance = Context.CommandContext.ExecutionEntityManager.CreateSubprocessInstance(processDefinition, execution, businessKey);

            Context.CommandContext.HistoryManager.RecordSubProcessInstanceStart(execution, subProcessInstance, initialFlowElement);

            // process template-defined data objects
            IDictionary <string, object> variables = ProcessDataObjects(subProcess.DataObjects);

            if (callActivity.InheritVariables)
            {
                IDictionary <string, object> executionVariables = execution.Variables;
                foreach (KeyValuePair <string, object> entry in executionVariables.SetOfKeyValuePairs())
                {
                    variables[entry.Key] = entry.Value;
                }
            }

            // copy process variables
            foreach (IOParameter ioParameter in callActivity.InParameters)
            {
                object value = null;
                if (!string.IsNullOrWhiteSpace(ioParameter.SourceExpression))
                {
                    IExpression expression = expressionManager.CreateExpression(ioParameter.SourceExpression.Trim());
                    value = expression.GetValue(execution);
                }
                else
                {
                    value = execution.GetVariable(ioParameter.Source);
                }
                variables[ioParameter.Target] = value;
            }

            if (variables.Count > 0)
            {
                InitializeVariables(subProcessInstance, variables);
            }

            // Create the first execution that will visit all the process definition elements
            IExecutionEntity subProcessInitialExecution = executionEntityManager.CreateChildExecution(subProcessInstance);

            subProcessInitialExecution.CurrentFlowElement = initialFlowElement;

            Context.Agenda.PlanContinueProcessOperation(subProcessInitialExecution);

            Context.ProcessEngineConfiguration.EventDispatcher.DispatchEvent(ActivitiEventBuilder.CreateProcessStartedEvent(subProcessInitialExecution, variables, false));
        }
        /// <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);
                }
            }
        }
        public override void Execute(IExecutionEntity execution)
        {
            // First off all, deactivate the execution
            execution.Inactivate();

            // Join
            FlowElement     flowElement = execution.CurrentFlowElement;
            ParallelGateway parallelGateway;

            if (flowElement is ParallelGateway)
            {
                parallelGateway = (ParallelGateway)flowElement;
            }
            else
            {
                throw new ActivitiException("Programmatic error: parallel gateway behaviour can only be applied" + " to a ParallelGateway instance, but got an instance of " + flowElement);
            }

            LockFirstParentScope(execution);

            IExecutionEntity multiInstanceExecution = null;

            if (HasMultiInstanceParent(parallelGateway))
            {
                multiInstanceExecution = FindMultiInstanceParentExecution(execution);
            }

            IExecutionEntityManager        executionEntityManager = Context.CommandContext.ExecutionEntityManager;
            ICollection <IExecutionEntity> joinedExecutions       = executionEntityManager.FindInactiveExecutionsByActivityIdAndProcessInstanceId(execution.CurrentActivityId, execution.ProcessInstanceId);

            if (multiInstanceExecution != null)
            {
                joinedExecutions = CleanJoinedExecutions(joinedExecutions, multiInstanceExecution);
            }

            int nbrOfExecutionsToJoin          = parallelGateway.IncomingFlows.Count;
            int nbrOfExecutionsCurrentlyJoined = joinedExecutions.Count;

            // Fork

            // Is needed to set the endTime for all historic activity joins
            Context.CommandContext.HistoryManager.RecordActivityEnd(execution, null);

            if (nbrOfExecutionsCurrentlyJoined == nbrOfExecutionsToJoin)
            {
                // Fork
                if (log.IsEnabled(LogLevel.Debug))
                {
                    log.LogDebug($"parallel gateway '{execution.CurrentActivityId}' activates: {nbrOfExecutionsCurrentlyJoined} of {nbrOfExecutionsToJoin} joined");
                }

                if (parallelGateway.IncomingFlows.Count > 1)
                {
                    // All (now inactive) children are deleted.
                    foreach (IExecutionEntity joinedExecution in joinedExecutions)
                    {
                        // The current execution will be reused and not deleted
                        if (!joinedExecution.Id.Equals(execution.Id))
                        {
                            executionEntityManager.DeleteExecutionAndRelatedData(joinedExecution, null, false);
                        }
                    }
                }

                // TODO: potential optimization here: reuse more then 1 execution, only 1 currently
                Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(execution, false); // false -> ignoring conditions on parallel gw
            }
            else if (log.IsEnabled(LogLevel.Debug))
            {
                log.LogDebug($"parallel gateway '{execution.CurrentActivityId}' does not activate: {nbrOfExecutionsCurrentlyJoined} of {nbrOfExecutionsToJoin} joined");
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="executionEntityManager"></param>
        /// <param name="executionId"></param>
        /// <returns></returns>
        protected internal virtual IList <IExecutionEntity> GetActiveChildExecutionsForExecution(IExecutionEntityManager executionEntityManager, string executionId)
        {
            IList <IExecutionEntity> activeChildExecutions = new List <IExecutionEntity>();
            IList <IExecutionEntity> executions            = executionEntityManager.FindChildExecutionsByParentExecutionId(executionId);

            foreach (IExecutionEntity activeExecution in executions)
            {
                if (!(activeExecution.CurrentFlowElement is BoundaryEvent))
                {
                    activeChildExecutions.Add(activeExecution);
                }
            }

            return(activeChildExecutions);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="processInstanceExecution"></param>
        protected internal virtual void HandleProcessInstanceExecution(IExecutionEntity processInstanceExecution)
        {
            IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager;

            string processInstanceId = processInstanceExecution.Id;

            // No parent execution == process instance id
            logger.LogDebug($"No parent execution found. Verifying if process instance {processInstanceId} can be stopped.");

            IExecutionEntity            superExecution             = processInstanceExecution.SuperExecution;
            ISubProcessActivityBehavior subProcessActivityBehavior = null;

            // copy variables before destroying the ended sub process instance (call activity)
            if (superExecution != null)
            {
                FlowNode superExecutionElement = (FlowNode)superExecution.CurrentFlowElement;
                subProcessActivityBehavior = (ISubProcessActivityBehavior)superExecutionElement.Behavior;
                try
                {
                    subProcessActivityBehavior.Completing(superExecution, processInstanceExecution);
                }
                //catch (Exception e)
                //{
                //    //logger.error("Error while completing sub process of execution {}", processInstanceExecution, e);
                //    throw e;
                //}
                catch (Exception e)
                {
                    logger.LogError($"Error while completing sub process of execution {processInstanceExecution}.Exception Message: {e.Message}");
                    throw new ActivitiException("Error while completing sub process of execution " + processInstanceExecution, e);
                }
            }

            int activeExecutions = GetNumberOfActiveChildExecutionsForProcessInstance(executionEntityManager, processInstanceId, superExecution);

            if (activeExecutions == 0)
            {
                logger.LogDebug($"No active executions found. Ending process instance {processInstanceId} ");

                // note the use of execution here vs processinstance execution for getting the flowelement
                executionEntityManager.DeleteProcessInstanceExecutionEntity(processInstanceId, execution.CurrentFlowElement?.Id, null, false, false);
            }
            else
            {
                logger.LogDebug($"Active executions found. Process instance {processInstanceId} will not be ended.");
            }

            Process process = ProcessDefinitionUtil.GetProcess(processInstanceExecution.ProcessDefinitionId);

            // Execute execution listeners for process end.
            if (CollectionUtil.IsNotEmpty(process.ExecutionListeners))
            {
                ExecuteExecutionListeners(process, processInstanceExecution, BaseExecutionListenerFields.EVENTNAME_END);
            }

            // and trigger execution afterwards if doing a call activity
            if (superExecution != null)
            {
                superExecution.SubProcessInstance = null;
                try
                {
                    subProcessActivityBehavior.Completed(superExecution);
                }
                //catch (Exception e)
                //{
                //    logger.error("Error while completing sub process of execution {}", processInstanceExecution, e);
                //    throw e;
                //}
                catch (Exception e)
                {
                    logger.LogError($"Error while completing sub process of execution {processInstanceExecution}. Exception Messgae: {e.Message}.");
                    throw new ActivitiException("Error while completing sub process of execution " + processInstanceExecution, e);
                }
            }
        }
示例#18
0
        public static void PropagateError(string errorCode, IExecutionEntity execution)
        {
            IDictionary <string, IList <Event> > eventMap = FindCatchingEventsForProcess(execution.ProcessDefinitionId, errorCode);

            if (eventMap.Count > 0)
            {
                ExecuteCatch(eventMap, execution, errorCode);
            }
            else if (!execution.ProcessInstanceId.Equals(execution.RootProcessInstanceId))
            { // Call activity
                IExecutionEntityManager executionEntityManager   = Context.CommandContext.ExecutionEntityManager;
                IExecutionEntity        processInstanceExecution = executionEntityManager.FindById <IExecutionEntity>(execution.ProcessInstanceId);
                if (processInstanceExecution != null)
                {
                    IExecutionEntity parentExecution = processInstanceExecution.SuperExecution;

                    IList <string> toDeleteProcessInstanceIds = new List <string>
                    {
                        execution.ProcessInstanceId
                    };

                    while (parentExecution != null && eventMap.Count == 0)
                    {
                        eventMap = FindCatchingEventsForProcess(parentExecution.ProcessDefinitionId, errorCode);
                        if (eventMap.Count > 0)
                        {
                            foreach (string processInstanceId in toDeleteProcessInstanceIds)
                            {
                                IExecutionEntity processInstanceEntity = executionEntityManager.FindById <IExecutionEntity>(processInstanceId);

                                // Delete
                                executionEntityManager.DeleteProcessInstanceExecutionEntity(processInstanceEntity.Id, execution.CurrentFlowElement?.Id, "ERROR_EVENT " + errorCode, false, false);

                                // Event
                                ProcessEngineConfigurationImpl processEngineConfiguration = Context.ProcessEngineConfiguration;
                                if (!(processEngineConfiguration is null) && Context.ProcessEngineConfiguration.EventDispatcher.Enabled)
                                {
                                    processEngineConfiguration.EventDispatcher.DispatchEvent(ActivitiEventBuilder.CreateEntityEvent(ActivitiEventType.PROCESS_COMPLETED_WITH_ERROR_END_EVENT, processInstanceEntity));
                                }
                            }
                            ExecuteCatch(eventMap, parentExecution, errorCode);
                        }
                        else
                        {
                            toDeleteProcessInstanceIds.Add(parentExecution.ProcessInstanceId);
                            IExecutionEntity superExecution = parentExecution.SuperExecution;
                            if (superExecution != null)
                            {
                                parentExecution = superExecution;
                            }
                            else if (!parentExecution.Id.Equals(parentExecution.RootProcessInstanceId))
                            { // stop at the root
                                parentExecution = parentExecution.ProcessInstance;
                            }
                            else
                            {
                                parentExecution = null;
                            }
                        }
                    }
                }
            }

            if (eventMap.Count == 0)
            {
                throw new BpmnError(errorCode, "No catching boundary event found for error with errorCode '" + errorCode + "', neither in same process nor in parent process");
            }
        }
        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);
            }
        }
示例#20
0
        public override void Leave(IExecutionEntity execution, object signalData)
        {
            lock (syncRoot)
            {
                ICommandContext commandContext = Context.CommandContext;
                if (commandContext == null)
                {
                    throw new ActivitiException("lazy loading outside command context");
                }

                completedPolicy.LeaveExection = execution;

                bool zeroNrOfInstances = false;
                if (ResolveNrOfInstances(execution) == 0)
                {
                    // Empty collection, just leave.
                    zeroNrOfInstances = true;
                    RemoveLocalLoopVariable(execution, CollectionElementIndexVariable);
                    base.Leave(execution, signalData); // Plan the default leave
                    execution.IsMultiInstanceRoot = false;
                }

                int loopCounter            = GetLoopVariable(execution, CollectionElementIndexVariable).GetValueOrDefault(0);
                int nrOfInstances          = GetLoopVariable(execution, NUMBER_OF_INSTANCES).GetValueOrDefault(0);
                int nrOfCompletedInstances = GetLoopVariable(execution, NUMBER_OF_COMPLETED_INSTANCES).GetValueOrDefault(0) + 1;
                int nrOfActiveInstances    = GetLoopVariable(execution, NUMBER_OF_ACTIVE_INSTANCES).GetValueOrDefault(0) - 1;

                Context.CommandContext.HistoryManager.RecordActivityEnd(execution, null);
                CallActivityEndListeners(execution);

                if (zeroNrOfInstances)
                {
                    return;
                }

                IExecutionEntity miRootExecution = GetMultiInstanceRootExecution(execution);
                if (miRootExecution != null)
                { // will be null in case of empty collection
                    SetLoopVariable(miRootExecution, NUMBER_OF_COMPLETED_INSTANCES, nrOfCompletedInstances);
                    SetLoopVariable(miRootExecution, NUMBER_OF_ACTIVE_INSTANCES, nrOfActiveInstances < 0 ? 0 : nrOfActiveInstances);
                }

                //ExecuteCompensationBoundaryEvents(execution.CurrentFlowElement, execution);

                LogLoopDetails(execution, "instance completed", loopCounter, nrOfCompletedInstances, nrOfActiveInstances, nrOfActiveInstances < 0 ? 0 : nrOfActiveInstances);

                if (execution.Parent != null)
                {
                    execution.Inactivate();
                    LockFirstParentScope(execution);

                    if (CompletionConditionSatisfied(execution.Parent, signalData) || nrOfCompletedInstances >= nrOfInstances)
                    {
                        IExecutionEntity executionToUse;
                        if (nrOfInstances > 0)
                        {
                            executionToUse = execution.Parent;
                        }
                        else
                        {
                            executionToUse = execution;
                        }

                        bool     hasCompensation = false;
                        Activity activity        = (Activity)execution.CurrentFlowElement;
                        if (activity is Transaction)
                        {
                            hasCompensation = true;
                        }
                        else if (activity is SubProcess subProcess)
                        {
                            foreach (FlowElement subElement in subProcess.FlowElements)
                            {
                                if (subElement is Activity subActivity)
                                {
                                    if (CollectionUtil.IsNotEmpty(subActivity.BoundaryEvents))
                                    {
                                        foreach (BoundaryEvent boundaryEvent in subActivity.BoundaryEvents)
                                        {
                                            if (CollectionUtil.IsNotEmpty(boundaryEvent.EventDefinitions) && boundaryEvent.EventDefinitions[0] is CompensateEventDefinition)
                                            {
                                                hasCompensation = true;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        if (hasCompensation)
                        {
                            ScopeUtil.CreateCopyOfSubProcessExecutionForCompensation(executionToUse);
                        }

                        if (activity is CallActivity)
                        {
                            IExecutionEntityManager executionEntityManager = Context.CommandContext.ExecutionEntityManager;
                            if (executionToUse != null)
                            {
                                IList <string> callActivityExecutionIds = new List <string>();

                                // Find all execution entities that are at the call activity
                                IList <IExecutionEntity> childExecutions = executionEntityManager.CollectChildren(executionToUse);
                                if (childExecutions != null)
                                {
                                    foreach (IExecutionEntity childExecution in childExecutions)
                                    {
                                        if (activity.Id.Equals(childExecution.CurrentActivityId))
                                        {
                                            callActivityExecutionIds.Add(childExecution.Id);
                                        }
                                    }

                                    // Now all call activity executions have been collected, loop again and check which should be removed
                                    for (int i = childExecutions.Count - 1; i >= 0; i--)
                                    {
                                        IExecutionEntity childExecution = childExecutions[i];
                                        if (!string.IsNullOrWhiteSpace(childExecution.SuperExecutionId) && callActivityExecutionIds.Contains(childExecution.SuperExecutionId))
                                        {
                                            executionEntityManager.DeleteProcessInstanceExecutionEntity(childExecution.Id, activity.Id, "call activity completion condition met", true, false);
                                        }
                                    }
                                }
                            }
                        }

                        DeleteChildExecutions(executionToUse, false, Context.CommandContext);
                        RemoveLocalLoopVariable(executionToUse, CollectionElementIndexVariable);
                        executionToUse.IsScope             = false;
                        executionToUse.IsMultiInstanceRoot = false;
                        Context.Agenda.PlanTakeOutgoingSequenceFlowsOperation(executionToUse, true);
                    }
                }
                else
                {
                    RemoveLocalLoopVariable(execution, CollectionElementIndexVariable);
                    execution.IsMultiInstanceRoot = false;
                    base.Leave(execution, signalData);
                }
            }
        }