public override void Trigger(IExecutionEntity execution, string triggerName, object triggerData, bool throwError = true)
        {
            IExecutionEntity executionEntity = execution;
            BoundaryEvent    boundaryEvent   = (BoundaryEvent)execution.CurrentFlowElement;

            if (boundaryEvent.CancelActivity)
            {
                string eventName;
                if (signal != null)
                {
                    eventName = signal.Name;
                }
                else
                {
                    eventName = signalEventDefinition.SignalRef;
                }

                IEventSubscriptionEntityManager  eventSubscriptionEntityManager = Context.CommandContext.EventSubscriptionEntityManager;
                IList <IEventSubscriptionEntity> eventSubscriptions             = executionEntity.EventSubscriptions;
                foreach (IEventSubscriptionEntity eventSubscription in eventSubscriptions)
                {
                    if (eventSubscription.EventType == SignalEventSubscriptionEntityFields.EVENT_TYPE && eventSubscription.EventName.Equals(eventName))
                    {
                        eventSubscriptionEntityManager.Delete(eventSubscription);
                    }
                }
            }

            base.Trigger(executionEntity, triggerName, triggerData, throwError);
        }
        public override BaseFlowNode Build()
        {
            var result = new BoundaryEvent();

            FeedCatchEvt(result);
            return(result);
        }
        protected internal override BaseElement ConvertXMLToElement(XMLStreamReader xtr, BpmnModel model)
        {
            BoundaryEvent boundaryEvent = new BoundaryEvent();

            BpmnXMLUtil.AddXMLLocation(boundaryEvent, xtr);
            if (!string.IsNullOrWhiteSpace(xtr.GetAttributeValue(BpmnXMLConstants.ATTRIBUTE_BOUNDARY_CANCELACTIVITY)))
            {
                string cancelActivity = xtr.GetAttributeValue(BpmnXMLConstants.ATTRIBUTE_BOUNDARY_CANCELACTIVITY);
                if (BpmnXMLConstants.ATTRIBUTE_VALUE_FALSE.Equals(cancelActivity, StringComparison.CurrentCultureIgnoreCase))
                {
                    boundaryEvent.CancelActivity = false;
                }
            }
            boundaryEvent.AttachedToRefId = xtr.GetAttributeValue(BpmnXMLConstants.ATTRIBUTE_BOUNDARY_ATTACHEDTOREF);
            ParseChildElements(XMLElementName, boundaryEvent, model, xtr);

            // Explicitly set cancel activity to false for error boundary events
            if (boundaryEvent.EventDefinitions.Count == 1)
            {
                EventDefinition eventDef = boundaryEvent.EventDefinitions[0];

                if (eventDef is ErrorEventDefinition)
                {
                    boundaryEvent.CancelActivity = false;
                }
            }

            return(boundaryEvent);
        }
예제 #4
0
        public override void Execute(IExecutionEntity execution)
        {
            IExecutionEntity executionEntity = execution;
            BoundaryEvent    boundaryEvent   = (BoundaryEvent)execution.CurrentFlowElement;

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

            if (process == null)
            {
                throw new ActivitiException("Process model (id = " + execution.Id + ") could not be found");
            }

            Activity            compensationActivity = null;
            IList <Association> associations         = process.FindAssociationsWithSourceRefRecursive(boundaryEvent.Id);

            foreach (Association association in associations)
            {
                FlowElement targetElement = process.GetFlowElement(association.TargetRef, true);
                if (targetElement is Activity activity)
                {
                    if (activity.ForCompensation)
                    {
                        compensationActivity = activity;
                        break;
                    }
                }
            }

            if (compensationActivity == null)
            {
                throw new ActivitiException("Compensation activity could not be found (or it is missing 'isForCompensation=\"true\"'");
            }

            // find SubProcess or Process instance execution
            IExecutionEntity scopeExecution  = null;
            IExecutionEntity parentExecution = executionEntity.Parent;

            while (scopeExecution == null && parentExecution != null)
            {
                if (parentExecution.CurrentFlowElement is SubProcess)
                {
                    scopeExecution = parentExecution;
                }
                else if (parentExecution.ProcessInstanceType)
                {
                    scopeExecution = parentExecution;
                }
                else
                {
                    parentExecution = parentExecution.Parent;
                }
            }

            if (scopeExecution == null)
            {
                throw new ActivitiException("Could not find a scope execution for compensation boundary event " + boundaryEvent.Id);
            }

            Context.CommandContext.EventSubscriptionEntityManager.InsertCompensationEvent(scopeExecution, compensationActivity.Id);
        }
예제 #5
0
        public override object Clone()
        {
            var result = new BoundaryEvent();

            FeedCatchEvent(result);
            result.AttachedToRef = AttachedToRef;
            return(result);
        }
예제 #6
0
        public override void Trigger(IExecutionEntity execution, string triggerName, object triggerData, bool throwError = true)
        {
            BoundaryEvent boundaryEvent = (BoundaryEvent)execution.CurrentFlowElement;

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

            IExecutionEntity subProcessExecution = null;
            // TODO: this can be optimized. A full search in the all executions shouldn't be needed
            IList <IExecutionEntity> processInstanceExecutions = executionEntityManager.FindChildExecutionsByProcessInstanceId(execution.ProcessInstanceId);

            foreach (IExecutionEntity childExecution in processInstanceExecutions)
            {
                if (childExecution.CurrentFlowElement != null && childExecution.CurrentFlowElement.Id.Equals(boundaryEvent.AttachedToRefId))
                {
                    subProcessExecution = childExecution;
                    break;
                }
            }

            if (subProcessExecution == null)
            {
                throw new ActivitiException("No execution found for sub process of boundary cancel event " + boundaryEvent.Id);
            }

            IEventSubscriptionEntityManager            eventSubscriptionEntityManager = commandContext.EventSubscriptionEntityManager;
            IList <ICompensateEventSubscriptionEntity> eventSubscriptions             = eventSubscriptionEntityManager.FindCompensateEventSubscriptionsByExecutionId(subProcessExecution.ParentId);

            if (eventSubscriptions.Count == 0)
            {
                Leave(execution);
            }
            else
            {
                Leave(execution);

                string deleteReason = History.DeleteReasonFields.BOUNDARY_EVENT_INTERRUPTING + "(" + boundaryEvent.Id + ")";

                // cancel boundary is always sync
                ScopeUtil.ThrowCompensationEvent(eventSubscriptions, execution, false);
                executionEntityManager.DeleteExecutionAndRelatedData(subProcessExecution, deleteReason, false);
                if (subProcessExecution.CurrentFlowElement is Activity activity)
                {
                    if (activity.LoopCharacteristics != null)
                    {
                        IExecutionEntity         miExecution       = subProcessExecution.Parent;
                        IList <IExecutionEntity> miChildExecutions = executionEntityManager.FindChildExecutionsByParentExecutionId(miExecution.Id);
                        foreach (IExecutionEntity miChildExecution in miChildExecutions)
                        {
                            if (subProcessExecution.Id.Equals(miChildExecution.Id) == false && activity.Id.Equals(miChildExecution.CurrentActivityId))
                            {
                                executionEntityManager.DeleteExecutionAndRelatedData(miChildExecution, deleteReason, false);
                            }
                        }
                    }
                }
            }
        }
예제 #7
0
        public virtual BoundaryEventBuilder boundaryEvent(string id)
        {
            BoundaryEvent boundaryEvent = createSibling(typeof(BoundaryEvent), id);

            boundaryEvent.AttachedTo = element;

            BpmnShape boundaryEventBpmnShape = createBpmnShape(boundaryEvent);

            BoundaryEventCoordinates = boundaryEventBpmnShape;

            return(boundaryEvent.builder());
        }
예제 #8
0
        protected internal virtual double calculateXCoordinate(Bounds boundaryEventBounds)
        {
            BpmnShape attachedToElement = findBpmnShape(element);

            double x = 0;

            if (attachedToElement != null)
            {
                Bounds attachedToBounds = attachedToElement.Bounds;

                ICollection <BoundaryEvent> boundaryEvents         = element.ParentElement.getChildElementsByType(typeof(BoundaryEvent));
                ICollection <BoundaryEvent> attachedBoundaryEvents = new List <BoundaryEvent>();

                IEnumerator <BoundaryEvent> iterator = boundaryEvents.GetEnumerator();
                while (iterator.MoveNext())
                {
                    BoundaryEvent tmp = iterator.Current;
                    if (tmp.AttachedTo.Equals(element))
                    {
                        attachedBoundaryEvents.Add(tmp);
                    }
                }

                double attachedToX     = attachedToBounds.getX().Value;
                double attachedToWidth = attachedToBounds.getWidth().Value;
                double boundaryWidth   = boundaryEventBounds.getWidth().Value;

                switch (attachedBoundaryEvents.Count)
                {
                case 2:
                {
                    x = attachedToX + attachedToWidth / 2 + boundaryWidth / 2;
                    break;
                }

                case 3:
                {
                    x = attachedToX + attachedToWidth / 2 - 1.5 * boundaryWidth;
                    break;
                }

                default:
                {
                    x = attachedToX + attachedToWidth / 2 - boundaryWidth / 2;
                    break;
                }
                }
            }

            return(x);
        }
        protected internal override void WriteAdditionalAttributes(BaseElement element, BpmnModel model, XMLStreamWriter xtw)
        {
            BoundaryEvent boundaryEvent = (BoundaryEvent)element;

            if (boundaryEvent.AttachedToRef != null)
            {
                WriteDefaultAttribute(BpmnXMLConstants.ATTRIBUTE_BOUNDARY_ATTACHEDTOREF, boundaryEvent.AttachedToRef.Id, xtw);
            }

            if (boundaryEvent.EventDefinitions.Count == 1)
            {
                EventDefinition eventDef = boundaryEvent.EventDefinitions[0];

                if (eventDef is ErrorEventDefinition == false)
                {
                    WriteDefaultAttribute(BpmnXMLConstants.ATTRIBUTE_BOUNDARY_CANCELACTIVITY, boundaryEvent.CancelActivity ? "true" : "false", xtw);
                }
            }
        }
예제 #10
0
        public override void Trigger(IExecutionEntity execution, string triggerName, object triggerData, bool throwError = true)
        {
            BoundaryEvent boundaryEvent = (BoundaryEvent)execution.CurrentFlowElement;

            if (boundaryEvent.CancelActivity)
            {
                IEventSubscriptionEntityManager  eventSubscriptionEntityManager = Context.CommandContext.EventSubscriptionEntityManager;
                IList <IEventSubscriptionEntity> eventSubscriptions             = execution.EventSubscriptions;
                foreach (IEventSubscriptionEntity eventSubscription in eventSubscriptions)
                {
                    if (eventSubscription.EventType == CompensateEventSubscriptionEntityFields.EVENT_TYPE && eventSubscription.ActivityId.Equals(compensateEventDefinition.ActivityRef))
                    {
                        eventSubscriptionEntityManager.Delete(eventSubscription);
                    }
                }
            }

            base.Trigger(execution, triggerName, triggerData, throwError);
        }
예제 #11
0
        private void addServiceTaskCompensationHandler(BpmnModelInstance modelInstance, string boundaryEventId, string compensationHandlerId)
        {
            BoundaryEvent boundaryEvent = modelInstance.getModelElementById(boundaryEventId);
            BaseElement   scope         = (BaseElement)boundaryEvent.ParentElement;

            ServiceTask compensationHandler = modelInstance.newInstance(typeof(ServiceTask));

            compensationHandler.Id = compensationHandlerId;
            compensationHandler.ForCompensation = true;
//JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method:
            compensationHandler.CamundaClass = typeof(IncreaseCurrentTimeServiceTask).FullName;
            scope.addChildElement(compensationHandler);

            Association association = modelInstance.newInstance(typeof(Association));

            association.AssociationDirection = AssociationDirection.One;
            association.Source = boundaryEvent;
            association.Target = compensationHandler;
            scope.addChildElement(association);
        }
예제 #12
0
        public virtual B compensationStart()
        {
            if (element is BoundaryEvent)
            {
                BoundaryEvent boundaryEvent = (BoundaryEvent)element;
                foreach (EventDefinition eventDefinition in boundaryEvent.EventDefinitions)
                {
                    if (eventDefinition is CompensateEventDefinition)
                    {
                        // if the boundary event contains a compensate event definition then
                        // save the boundary event to later return to it and start a compensation

                        compensateBoundaryEvent = boundaryEvent;
                        compensationStarted     = true;

                        return(myself);
                    }
                }
            }

            throw new BpmnModelException("Compensation can only be started on a boundary event with a compensation event definition");
        }
예제 #13
0
        protected internal override void ExecuteValidation(BpmnModel bpmnModel, Process process, IList <ValidationError> errors)
        {
            IList <BoundaryEvent> boundaryEvents = process.FindFlowElementsOfType <BoundaryEvent>();

            // Only one boundary event of type 'cancel' can be attached to the same
            // element, so we store the count temporarily here
            Dictionary <string, int> cancelBoundaryEventsCounts = new Dictionary <string, int>();

            // Only one boundary event of type 'compensate' can be attached to the
            // same element, so we store the count temporarily here
            Dictionary <string, int> compensateBoundaryEventsCounts = new Dictionary <string, int>();

            for (int i = 0; i < boundaryEvents.Count; i++)
            {
                BoundaryEvent boundaryEvent = boundaryEvents[i];

                if (boundaryEvent.EventDefinitions != null && boundaryEvent.EventDefinitions.Count > 0)
                {
                    EventDefinition eventDefinition = boundaryEvent.EventDefinitions[0];
                    if (!(eventDefinition is TimerEventDefinition) && !(eventDefinition is ErrorEventDefinition) && !(eventDefinition is SignalEventDefinition) && !(eventDefinition is CancelEventDefinition) && !(eventDefinition is MessageEventDefinition) && !(eventDefinition is CompensateEventDefinition))
                    {
                        AddError(errors, ProblemsConstants.BOUNDARY_EVENT_INVALID_EVENT_DEFINITION, process, boundaryEvent, ProcessValidatorResource.BOUNDARY_EVENT_INVALID_EVENT_DEFINITION);
                    }

                    if (eventDefinition is CancelEventDefinition)
                    {
                        FlowElement attachedToFlowElement = bpmnModel.GetFlowElement(boundaryEvent.AttachedToRefId);
                        if (!(attachedToFlowElement is Transaction))
                        {
                            AddError(errors, ProblemsConstants.BOUNDARY_EVENT_CANCEL_ONLY_ON_TRANSACTION, process, boundaryEvent, ProcessValidatorResource.BOUNDARY_EVENT_CANCEL_ONLY_ON_TRANSACTION);
                        }
                        else
                        {
                            if (!cancelBoundaryEventsCounts.ContainsKey(attachedToFlowElement.Id))
                            {
                                cancelBoundaryEventsCounts[attachedToFlowElement.Id] = 0;
                            }
                            cancelBoundaryEventsCounts[attachedToFlowElement.Id] = cancelBoundaryEventsCounts[attachedToFlowElement.Id] + 1;
                        }
                    }
                    else if (eventDefinition is CompensateEventDefinition)
                    {
                        if (!compensateBoundaryEventsCounts.ContainsKey(boundaryEvent.AttachedToRefId))
                        {
                            compensateBoundaryEventsCounts[boundaryEvent.AttachedToRefId] = 0;
                        }
                        compensateBoundaryEventsCounts[boundaryEvent.AttachedToRefId] = compensateBoundaryEventsCounts[boundaryEvent.AttachedToRefId] + 1;
                    }
                    else if (eventDefinition is MessageEventDefinition)
                    {
                        // Check if other message boundary events with same message
                        // id
                        for (int j = 0; j < boundaryEvents.Count; j++)
                        {
                            if (j != i)
                            {
                                BoundaryEvent otherBoundaryEvent = boundaryEvents[j];
                                if (otherBoundaryEvent.AttachedToRefId is object && otherBoundaryEvent.AttachedToRefId.Equals(boundaryEvent.AttachedToRefId))
                                {
                                    if (otherBoundaryEvent.EventDefinitions != null && otherBoundaryEvent.EventDefinitions.Count > 0)
                                    {
                                        EventDefinition otherEventDefinition = otherBoundaryEvent.EventDefinitions[0];
                                        if (otherEventDefinition is MessageEventDefinition)
                                        {
                                            MessageEventDefinition currentMessageEventDefinition = (MessageEventDefinition)eventDefinition;
                                            MessageEventDefinition otherMessageEventDefinition   = (MessageEventDefinition)otherEventDefinition;
                                            if (otherMessageEventDefinition.MessageRef is object && otherMessageEventDefinition.MessageRef.Equals(currentMessageEventDefinition.MessageRef))
                                            {
                                                AddError(errors, ProblemsConstants.MESSAGE_EVENT_MULTIPLE_ON_BOUNDARY_SAME_MESSAGE_ID, process, boundaryEvent, ProcessValidatorResource.MESSAGE_EVENT_MULTIPLE_ON_BOUNDARY_SAME_MESSAGE_ID);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    AddError(errors, ProblemsConstants.BOUNDARY_EVENT_NO_EVENT_DEFINITION, process, boundaryEvent, "Event definition is missing from boundary event");
                }
            }

            foreach (string elementId in cancelBoundaryEventsCounts.Keys)
            {
                if (cancelBoundaryEventsCounts[elementId] > 1)
                {
                    AddError(errors, ProblemsConstants.BOUNDARY_EVENT_MULTIPLE_CANCEL_ON_TRANSACTION, process, bpmnModel.GetFlowElement(elementId), "multiple boundary events with cancelEventDefinition not supported on same transaction subprocess.");
                }
            }

            foreach (string elementId in compensateBoundaryEventsCounts.Keys)
            {
                if (compensateBoundaryEventsCounts[elementId] > 1)
                {
                    AddError(errors, ProblemsConstants.COMPENSATE_EVENT_MULTIPLE_ON_BOUNDARY, process, bpmnModel.GetFlowElement(elementId), "Multiple boundary events of type 'compensate' is invalid");
                }
            }
        }
 public virtual BoundaryMessageEventActivityBehavior CreateBoundaryMessageEventActivityBehavior(BoundaryEvent boundaryEvent, MessageEventDefinition messageEventDefinition, bool interrupting)
 {
     return(new BoundaryMessageEventActivityBehavior(messageEventDefinition, interrupting));
 }
 public virtual BoundarySignalEventActivityBehavior CreateBoundarySignalEventActivityBehavior(BoundaryEvent boundaryEvent, SignalEventDefinition signalEventDefinition, Signal signal, bool interrupting)
 {
     return(new BoundarySignalEventActivityBehavior(signalEventDefinition, signal, interrupting));
 }
 public virtual BoundaryTimerEventActivityBehavior CreateBoundaryTimerEventActivityBehavior(BoundaryEvent boundaryEvent, TimerEventDefinition timerEventDefinition, bool interrupting)
 {
     return(new BoundaryTimerEventActivityBehavior(timerEventDefinition, interrupting));
 }
 public virtual BoundaryCompensateEventActivityBehavior CreateBoundaryCompensateEventActivityBehavior(BoundaryEvent boundaryEvent, CompensateEventDefinition compensateEventDefinition, bool interrupting)
 {
     return(new BoundaryCompensateEventActivityBehavior(compensateEventDefinition, interrupting));
 }
        // Boundary Events

        public virtual BoundaryEventActivityBehavior CreateBoundaryEventActivityBehavior(BoundaryEvent boundaryEvent, bool interrupting)
        {
            return(new BoundaryEventActivityBehavior(interrupting));
        }
        protected internal override void WriteAdditionalChildElements(BaseElement element, BpmnModel model, XMLStreamWriter xtw)
        {
            BoundaryEvent boundaryEvent = (BoundaryEvent)element;

            WriteEventDefinitions(boundaryEvent, boundaryEvent.EventDefinitions, model, xtw);
        }
예제 #20
0
 protected internal AbstractBoundaryEventBuilder(BpmnModelInstance modelInstance, BoundaryEvent element, Type selfType) : base(modelInstance, element, selfType)
 {
 }
        protected internal virtual void DispatchExecutionTimeOut(IJobEntity timerEntity, IExecutionEntity execution, IList <string> processedElements, ICommandContext commandContext)
        {
            FlowElement currentElement = execution.CurrentFlowElement;

            if (currentElement is BoundaryEvent)
            {
                BoundaryEvent boundaryEvent = (BoundaryEvent)execution.CurrentFlowElement;
                if (boundaryEvent.CancelActivity && boundaryEvent.AttachedToRef != null)
                {
                    if (!processedElements.Contains(boundaryEvent.Id))
                    {
                        processedElements.Add(boundaryEvent.Id);
                        IExecutionEntity parentExecution = execution.Parent;
                        DispatchExecutionTimeOut(timerEntity, parentExecution, processedElements, commandContext);
                    }
                }
            }
            else
            {
                // flow nodes
                if (execution.CurrentFlowElement is FlowNode)
                {
                    processedElements.Add(execution.CurrentActivityId);
                    DispatchActivityTimeOut(timerEntity, (FlowNode)execution.CurrentFlowElement, execution, commandContext);
                    if (execution.CurrentFlowElement is UserTask && !execution.IsMultiInstanceRoot)
                    {
                        IList <ITaskEntity> tasks = execution.Tasks;
                        if (tasks.Count > 0)
                        {
                            tasks[0].Canceled = true;
                        }
                    }
                }

                // subprocesses
                if (execution.CurrentFlowElement is SubProcess)
                {
                    foreach (IExecutionEntity subExecution in execution.Executions)
                    {
                        if (!processedElements.Contains(subExecution.CurrentActivityId))
                        {
                            DispatchExecutionTimeOut(timerEntity, subExecution, processedElements, commandContext);
                        }
                    }

                    // call activities
                }
                else if (execution.CurrentFlowElement is CallActivity)
                {
                    IExecutionEntity subProcessInstance = commandContext.ExecutionEntityManager.FindSubProcessInstanceBySuperExecutionId(execution.Id);
                    if (subProcessInstance != null)
                    {
                        IList <IExecutionEntity> childExecutions = subProcessInstance.Executions;
                        foreach (IExecutionEntity subExecution in childExecutions)
                        {
                            if (!processedElements.Contains(subExecution.CurrentActivityId))
                            {
                                DispatchExecutionTimeOut(timerEntity, subExecution, processedElements, commandContext);
                            }
                        }
                    }
                }
            }
        }
예제 #22
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);
            }
        }