protected internal virtual void DeleteOtherEventsRelatedToEventBasedGateway(IExecutionEntity execution, EventGateway eventGateway)
        {
            // To clean up the other events behind the event based gateway, we must gather the
            // activity ids of said events and check the _sibling_ executions of the incoming execution.
            // Note that it can happen that there are multiple such execution in those activity ids,
            // (for example a parallel gw going twice to the event based gateway, kinda silly, but valid)
            // so we only take _one_ result of such a query for deletion.

            // Gather all activity ids for the events after the event based gateway that need to be destroyed
            IList <SequenceFlow> outgoingSequenceFlows = eventGateway.OutgoingFlows;
            ISet <string>        eventActivityIds      = new HashSet <string>();//outgoingSequenceFlows.Count - 1); // -1, the event being triggered does not need to be deleted

            foreach (SequenceFlow outgoingSequenceFlow in outgoingSequenceFlows)
            {
                if (outgoingSequenceFlow.TargetFlowElement != null && !outgoingSequenceFlow.TargetFlowElement.Id.Equals(execution.CurrentActivityId))
                {
                    eventActivityIds.Add(outgoingSequenceFlow.TargetFlowElement.Id);
                }
            }

            ICommandContext         commandContext         = Context.CommandContext;
            IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager;

            // Find the executions
            IList <IExecutionEntity> executionEntities = executionEntityManager.FindExecutionsByParentExecutionAndActivityIds(execution.ParentId, eventActivityIds);

            // Execute the cancel behaviour of the IntermediateCatchEvent
            foreach (IExecutionEntity executionEntity in executionEntities)
            {
                if (eventActivityIds.Contains(executionEntity.ActivityId) && execution.CurrentFlowElement is IntermediateCatchEvent)
                {
                    IntermediateCatchEvent intermediateCatchEvent = (IntermediateCatchEvent)execution.CurrentFlowElement;
                    if (intermediateCatchEvent.Behavior is IntermediateCatchEventActivityBehavior)
                    {
                        ((IntermediateCatchEventActivityBehavior)intermediateCatchEvent.Behavior).EventCancelledByEventGateway(executionEntity);
                        eventActivityIds.Remove(executionEntity.ActivityId); // We only need to delete ONE execution at the event.
                    }
                }
            }
        }
Ejemplo n.º 2
0
        public override void Execute(IExecutionEntity execution)
        {
            ICommandContext         commandContext         = Context.CommandContext;
            IExecutionEntityManager executionEntityManager = commandContext.ExecutionEntityManager;

            // find cancel boundary event:
            IExecutionEntity parentScopeExecution       = null;
            IExecutionEntity currentlyExaminedExecution = executionEntityManager.FindById <IExecutionEntity>(execution.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 " + execution.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 " + execution.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, execution, commandContext, History.DeleteReasonFields.TRANSACTION_CANCELED);
                        }
                    }

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

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

                // TODO: 先删除已生成的边界取消执行实例
                var cancelBoundaryEventExecution = executionEntityManager.FindExecutionsByParentExecutionAndActivityIds(parentScopeExecution.Id, new string[] { cancelBoundaryEvent.Id }).FirstOrDefault();
                executionEntityManager.Delete(cancelBoundaryEventExecution);

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

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

                Context.Agenda.PlanTriggerExecutionOperation(execution);
            }
        }