Ejemplo n.º 1
0
        public virtual IProcessInstanceWithVariables Execute(CommandContext commandContext)
        {
            var processDefinition =
                new GetDeployedProcessDefinitionCmd(InstantiationBuilder, false).Execute(commandContext);

            foreach (var checker in commandContext.ProcessEngineConfiguration.CommandCheckers)
            {
                checker.CheckCreateProcessInstance(processDefinition);
            }

            var modificationBuilder = InstantiationBuilder.ModificationBuilder;

            EnsureUtil.EnsureNotEmpty(
                @"At least one instantiation instruction required (e.g. by invoking startBefore(..), startAfter(..) or startTransition(..))", "instructions", ListExt.ConvertToIlist(modificationBuilder.ModificationOperations));

            // instantiate the process
            var initialActivity = DetermineFirstActivity(processDefinition, modificationBuilder);

            ExecutionEntity processInstance = (ExecutionEntity)processDefinition.CreateProcessInstance(InstantiationBuilder.BusinessKey,
                                                                                                       InstantiationBuilder.CaseInstanceId, initialActivity);

            processInstance.SkipCustomListeners = modificationBuilder.SkipCustomListeners;
            var variables = modificationBuilder.ProcessVariables;

            ExecutionVariableSnapshotObserver variablesListener = new ExecutionVariableSnapshotObserver(processInstance);

            processInstance.StartWithoutExecuting(variables);

            // prevent ending of the process instance between instructions
            processInstance.PreserveScope = true;

            // apply modifications
            var instructions = modificationBuilder.ModificationOperations;

            for (var i = 0; i < instructions.Count; i++)
            {
                var instruction = instructions[i];
                Log.DebugStartingInstruction(processInstance.Id, i, instruction.Describe());

                instruction.ProcessInstanceId   = processInstance.Id;
                instruction.SkipCustomListeners = modificationBuilder.SkipCustomListeners;
                instruction.SkipIoMappings      = modificationBuilder.SkipIoMappings;
                instruction.Execute(commandContext);
            }

            if (!processInstance.HasChildren() && processInstance.IsEnded)
            {
                // process instance has ended regularly but this has not been propagated yet
                // due to preserveScope setting
                processInstance.PropagateEnd();
            }

            return(new ProcessInstanceWithVariablesImpl(processInstance, variablesListener.Variables));
        }
Ejemplo n.º 2
0
        public virtual object Execute(CommandContext commandContext)
        {
            var processInstanceId = Builder.ProcessInstanceId;

            IExecutionManager executionManager = commandContext.ExecutionManager;
            ExecutionEntity   processInstance  = executionManager.FindExecutionById(processInstanceId);


            CheckUpdateProcessInstance(processInstance, commandContext);

            processInstance.PreserveScope = true;

            var instructions = Builder.ModificationOperations;

            for (var i = 0; i < instructions.Count; i++)
            {
                var instruction = instructions[i];
                Log.DebugModificationInstruction(processInstanceId, i + 1, instruction.Describe());

                instruction.SkipCustomListeners = Builder.SkipCustomListeners;
                instruction.SkipIoMappings      = Builder.SkipIoMappings;
                instruction.Execute(commandContext);
            }

            processInstance = executionManager.FindExecutionById(processInstanceId);

            if (!processInstance.HasChildren())
            {
                if (processInstance.Activity == null)
                {
                    // process instance was cancelled
                    CheckDeleteProcessInstance(processInstance, commandContext);
                    DeletePropagate(processInstance, "Cancellation due to process instance modification",
                                    Builder.SkipCustomListeners, Builder.SkipIoMappings);
                }
                else if (processInstance.IsEnded)
                {
                    // process instance has ended regularly
                    processInstance.PropagateEnd();
                }
            }

            commandContext.OperationLogManager.LogProcessInstanceOperation(LogEntryOperation, processInstanceId, null,
                                                                           null, new List <PropertyChange>()
            {
                PropertyChange.EmptyChange
            });
            return(null);
        }
Ejemplo n.º 3
0
        protected internal virtual ExecutionEntity GetScopeExecutionForActivityInstance(ExecutionEntity processInstance,
                                                                                        ActivityExecutionTreeMapping mapping, IActivityInstance activityInstance)
        {
            EnsureUtil.EnsureNotNull("activityInstance", activityInstance);

            ProcessDefinitionImpl processDefinition = processInstance.ProcessDefinition;
            ScopeImpl             scope             = GetScopeForActivityInstance(processDefinition, activityInstance);

            ISet <ExecutionEntity> executions = mapping.GetExecutions(scope);
            ISet <string>          activityInstanceExecutions = new HashSet <string>(activityInstance.ExecutionIds);

            // TODO: this is a hack around the activity instance tree
            // remove with fix of CAM-3574
            foreach (var activityInstanceExecutionId in activityInstance.ExecutionIds)
            {
                ExecutionEntity execution = context.Impl.Context.CommandContext.ExecutionManager.FindExecutionById(activityInstanceExecutionId);
                if (execution.IsConcurrent && execution.HasChildren())
                {
                    // concurrent executions have at most one child
                    IActivityExecution child = execution.executions.First();//.Executions[0];
                    activityInstanceExecutions.Add(child.Id);
                }
            }

            // find the scope execution for the given activity instance
            ISet <ExecutionEntity> retainedExecutionsForInstance = new HashSet <ExecutionEntity>();

            foreach (ExecutionEntity execution in executions)
            {
                if (activityInstanceExecutions.Contains(execution.Id))
                {
                    retainedExecutionsForInstance.Add(execution);
                }
            }

            if (retainedExecutionsForInstance.Count != 1)
            {
                throw new ProcessEngineException("There are " + retainedExecutionsForInstance.Count +
                                                 " (!= 1) executions for activity instance " + activityInstance.Id);
            }

            return(retainedExecutionsForInstance.GetEnumerator().Current);
        }
Ejemplo n.º 4
0
        public override object Execute(CommandContext commandContext)
        {
            ExecutionEntity processInstance = commandContext.ExecutionManager.FindExecutionById(processInstanceId);

            ProcessDefinitionImpl processDefinition = processInstance.GetProcessDefinition();

            CoreModelElement elementToInstantiate = GetTargetElement(processDefinition);

            EnsureUtil.EnsureNotNull(typeof(NotValidException), DescribeFailure("Element '" + TargetElementId + "' does not exist in process '" + processDefinition.Id + "'"), "element", elementToInstantiate);

            // rebuild the mapping because the execution tree changes with every iteration
            var mapping = new ActivityExecutionTreeMapping(commandContext, processInstanceId);

            // before instantiating an activity, two things have to be determined:
            //
            // activityStack:
            // For the activity to instantiate, we build a stack of parent flow scopes
            // for which no executions exist yet and that have to be instantiated
            //
            // scopeExecution:
            // This is typically the execution under which a new sub tree has to be created.
            // if an explicit ancestor activity instance is set:
            //   - this is the scope execution for that ancestor activity instance
            //   - throws exception if that scope execution is not in the parent hierarchy
            //     of the activity to be started
            // if no explicit ancestor activity instance is set:
            //   - this is the execution of the first parent/ancestor flow scope that has an execution
            //   - throws an exception if there is more than one such execution

            var targetFlowScope = GetTargetFlowScope(processDefinition);

            // prepare to walk up the flow scope hierarchy and collect the flow scope activities
            var stackCollector = new ActivityStackCollector();
            var walker         = new FlowScopeWalker(targetFlowScope);

            walker.AddPreVisitor(stackCollector);

            ExecutionEntity scopeExecution = null;

            // if no explicit ancestor activity instance is set
            if (ReferenceEquals(AncestorActivityInstanceId, null))
            {
                // walk until a scope is reached for which executions exist
                walker.WalkWhile((element) => mapping.GetExecutions(element)
                                 .Count > 0 || element == processDefinition);

                var flowScopeExecutions = mapping.GetExecutions(walker.CurrentElement);

                if (flowScopeExecutions.Count > 1)
                {
                    throw new ProcessEngineException("Ancestor activity execution is ambiguous for activity " +
                                                     targetFlowScope);
                }

                //scopeExecution = flowScopeExecutions.GetEnumerator().Next();
                scopeExecution = flowScopeExecutions.First();
            }

            var activitiesToInstantiate = stackCollector.ActivityStack;

            activitiesToInstantiate.Reverse();

            // We have to make a distinction between
            // - "regular" activities for which the activity stack can be instantiated and started
            //   right away
            // - interrupting or cancelling activities for which we have to ensure that
            //   the interruption and cancellation takes place before we instantiate the activity stack
            ActivityImpl topMostActivity = null;
            ScopeImpl    flowScope       = null;

            if (activitiesToInstantiate.Count > 0)
            {
                topMostActivity = (ActivityImpl)activitiesToInstantiate[0];
                flowScope       = topMostActivity.FlowScope;
            }
            else if (elementToInstantiate is ActivityImpl)
            {
                topMostActivity = (ActivityImpl)elementToInstantiate;
                flowScope       = topMostActivity.FlowScope;
            }
            else if (elementToInstantiate is TransitionImpl)
            {
                var transitionToInstantiate = (TransitionImpl)elementToInstantiate;
                flowScope = transitionToInstantiate.Source.FlowScope;
            }

            if (!SupportsConcurrentChildInstantiation(flowScope))
            {
                throw new ProcessEngineException("Concurrent instantiation not possible for " + "activities in scope " +
                                                 flowScope.Id);
            }

            var startBehavior = ActivityStartBehavior.ConcurrentInFlowScope;

            if (topMostActivity != null)
            {
                startBehavior = topMostActivity.ActivityStartBehavior;

                if (activitiesToInstantiate.Count > 0)
                {
                    // this is in BPMN relevant if there is an interrupting event sub process.
                    // we have to distinguish between instantiation of the start event and any other activity.
                    // instantiation of the start event means interrupting behavior; instantiation
                    // of any other ITask means no interruption.
                    IPvmActivity initialActivity       = topMostActivity.Properties.Get(BpmnProperties.InitialActivity);
                    IPvmActivity secondTopMostActivity = null;
                    if (activitiesToInstantiate.Count > 1)
                    {
                        secondTopMostActivity = activitiesToInstantiate[1];
                    }
                    else if (elementToInstantiate.GetType().IsSubclassOf(typeof(ActivityImpl)))
                    {
                        secondTopMostActivity = (IPvmActivity)elementToInstantiate;
                    }

                    if (initialActivity != secondTopMostActivity)
                    {
                        startBehavior = ActivityStartBehavior.ConcurrentInFlowScope;
                    }
                }
            }
            //throw new Exception("startBehavior值:"+(int)startBehavior);//2
            switch (startBehavior)
            {
            case ActivityStartBehavior.CancelEventScope:
            {
                ScopeImpl scopeToCancel     = (ScopeImpl)topMostActivity.EventScope;
                var       executionToCancel = GetSingleExecutionForScope(mapping, scopeToCancel);
                if (executionToCancel != null)
                {
                    executionToCancel.DeleteCascade("Cancelling activity " + topMostActivity + " executed.",
                                                    skipCustomListeners, skipIoMappings);
                    Instantiate(executionToCancel.Parent, activitiesToInstantiate, elementToInstantiate);
                }
                else
                {
                    var flowScopeExecution = GetSingleExecutionForScope(mapping, topMostActivity.FlowScope);
                    InstantiateConcurrent(flowScopeExecution, activitiesToInstantiate, elementToInstantiate);
                }
                break;
            }

            case ActivityStartBehavior.InterruptEventScope:
            {
                ScopeImpl scopeToCancel     = (ScopeImpl)topMostActivity.EventScope;
                var       executionToCancel = GetSingleExecutionForScope(mapping, scopeToCancel);
                executionToCancel.Interrupt("Interrupting activity " + topMostActivity + " executed.",
                                            skipCustomListeners, skipIoMappings);
                executionToCancel.SetActivity(null);
                executionToCancel.LeaveActivityInstance();
                Instantiate(executionToCancel, activitiesToInstantiate, elementToInstantiate);
                break;
            }

            case ActivityStartBehavior.InterruptFlowScope:
            {
                var scopeToCancel     = topMostActivity.FlowScope;
                var executionToCancel = GetSingleExecutionForScope(mapping, scopeToCancel);
                executionToCancel.Interrupt("Interrupting activity " + topMostActivity + " executed.",
                                            skipCustomListeners, skipIoMappings);
                executionToCancel.SetActivity(null);
                executionToCancel.LeaveActivityInstance();
                Instantiate(executionToCancel, activitiesToInstantiate, elementToInstantiate);
                break;
            }

            default:
            {
                // if all child executions have been cancelled
                // or this execution has ended executing its scope, it can be reused
                if (!scopeExecution.HasChildren() && (scopeExecution.GetActivity() == null || scopeExecution.IsEnded))
                {
                    // reuse the scope execution
                    Instantiate(scopeExecution, activitiesToInstantiate, elementToInstantiate);
                }
                else
                {
                    // if the activity is not cancelling/interrupting, it can simply be instantiated as
                    // a concurrent child of the scopeExecution
                    InstantiateConcurrent(scopeExecution, activitiesToInstantiate, elementToInstantiate);
                }
                break;
            }
            }

            return(null);
        }