コード例 #1
0
        private void AppendHumanActivity(Client.AppendHumanMode mode, bool flag)
        {
            //流程:节点1(单人任务节点)->节点2
            var process = this.CreateProcess(this.CreateProcessType(UnitTestType + "Dynamic"
                                                                    , Resource.AppendHumanActivity_Workflow
                                                                    , Resource.AppendHumanActivity_Settings));

            //调度后进入节点1
            this.SyncScheduleUntil(process);
            Assert.AreEqual(_activityName1, TestHelper.GetCurrentActivityName(process));

            //人工单人任务节点允许
            Assert.IsTrue(this._clientApi.CanAppendHumanActivity(process.ID, mode, _dynamicActivityName).Result);

            //避免出现相同版本的流程类型
            Thread.Sleep(1000);

            //追加
            this._clientApi.AppendHumanActivity(process.ID, mode, this.CreateAppendHumanSetting(mode));
            //执行任务
            var w = this._workItemService.GetWorkItems(process).First();

            this._workItemService.Execute(w.ID, w.Actioner, this._enterAction, null);

            //调度后进入动态节点
            this.SyncScheduleUntil(process);
            Assert.AreEqual(this._dynamicActivityName, TestHelper.GetCurrentActivityName(process));
            //将动态节点任务全部执行完
            this._workItemService.GetWorkItems(process).ToList().ForEach(o =>
            {
                Assert.AreEqual(this._dynamicActivityName, o.ActivityName);
                this._workItemService.Execute(o.ID
                                              , o.Actioner
                                              //根据flag决定是否激活完成规则
                                              , flag ? this._action1 : this._action2
                                              , null);
            });

            this.SyncScheduleUntil(process);

            //流程结束
            if (!flag)
            {
                Assert.AreEqual(ProcessStatus.Completed, process.Status);
                return;
            }
            //调度后返回节点1
            if (mode == Client.AppendHumanMode.Wait)
            {
                Assert.AreEqual(_activityName1, TestHelper.GetCurrentActivityName(process));
            }
            //调度后进入节点2
            if (mode == Client.AppendHumanMode.Continues)
            {
                Assert.AreEqual(_activityName2, TestHelper.GetCurrentActivityName(process));
            }
        }
コード例 #2
0
        public Client.BooleanResult CanAppendHumanActivity(Guid processId, Client.AppendHumanMode mode, string appendActivityName)
        {
            string reason; HumanSetting setting;
            var    result = this.CanAppendHumanActivity(processId, mode, appendActivityName, out setting, out reason);

            if (!result && this._log.IsDebugEnabled)
            {
                this._log.Debug(reason);
            }
            return(new Client.BooleanResult()
            {
                Result = result, Reason = reason
            });
        }
コード例 #3
0
        private bool CanAppendHumanActivity(Guid processId
                                            , Client.AppendHumanMode mode
                                            , string appendActivityName
                                            , out HumanSetting currentHumanSetting
                                            , out string reason)
        {
            if (string.IsNullOrWhiteSpace(appendActivityName))
            {
                throw new InvalidOperationException("appendActivityName不能为空");
            }

            reason = string.Empty;
            var process     = this.GetProcessById(processId);
            var processType = process.ProcessType;
            var workItems   = this._workItemService.GetWorkItems(process);

            if (workItems.Count() != 1)
            {
                reason = "当前节点可能不是人工节点";
            }

            var human = workItems.First().ActivityInstance;

            currentHumanSetting = processType.GetHumanSetting(human.ActivityName);

            if (currentHumanSetting.ActivityName == appendActivityName)
            {
                reason = "当前节点与期望新增的节点同名";
            }
            else if (currentHumanSetting.IsChildOfActivity)
            {
                reason = "当前节点是子节点不支持";
            }
            else if (human.Actioners.Length > 1)
            {
                reason = "当前节点是多人任务节点";
            }
            else if (mode == Client.AppendHumanMode.Continues &&//HACK:AppendHumanMode.Continues模式下不支持多分支的节点,无法选取
                     currentHumanSetting.FinishRule != null &&
                     currentHumanSetting.FinishRule.Scripts != null &&
                     currentHumanSetting.FinishRule.Scripts.Count > 1)
            {
                reason = "当前节点存在多分支";
            }

            return(string.IsNullOrWhiteSpace(reason));
        }
コード例 #4
0
        private Client.AppendHumanSetting CreateAppendHumanSetting(Client.AppendHumanMode mode)
        {
            var setting = new Client.AppendHumanSetting();

            setting.ActionerRule        = new string[] { "'houkun'", "'xuanfang'" };
            setting.Actions             = new string[] { this._action1, this._action2 };
            setting.ActivityName        = this._dynamicActivityName;
            setting.EnterAction         = this._enterAction;
            setting.EnterFinishRuleName = this._enterAction;
            if (mode == Client.AppendHumanMode.Continues)
            {
                setting.FinishRuleName = "动态节点执行完成";
                setting.FinishRuleBody = string.Format("all('{0}')", _action1);
            }
            setting.Url = "aspx";
            return(setting);
        }
コード例 #5
0
        public void AppendHumanActivity(Guid processId, Client.AppendHumanMode mode, Client.AppendHumanSetting appendHumanSetting)
        {
            //HACK:动态节点出于重复考虑,总是会先移除重名的节点,此设计会存在意外的情况

            string       reason;
            HumanSetting currentHumanSetting;

            if (!this.CanAppendHumanActivity(processId, mode, appendHumanSetting.ActivityName, out currentHumanSetting, out reason))
            {
                throw new InvalidOperationException(reason);
            }
            if (appendHumanSetting == null)
            {
                throw new ArgumentNullException("humanSetting");
            }

            var process            = this.GetProcessById(processId);
            var currentProcessType = process.ProcessType;
            //获取所有节点设置的副本
            var clonedSettings             = new List <ActivitySetting>(currentProcessType.ActivitySettings.Select(o => o.Clone()));
            var workflow                   = this._workflowParser.Parse(currentProcessType.Workflow.Serialized, clonedSettings);
            var originalWorkflowDefinition = currentProcessType.Workflow.Serialized;

            #region 查找节点信息
            var currentNode    = this.GetFlowStep(workflow, currentHumanSetting.ActivityName);
            var currentSetting = clonedSettings.FirstOrDefault(o => o.ActivityName == currentNode.Action.DisplayName) as HumanSetting;
            var nextNode       = this.GetNextFlowStep(workflow, currentNode);
            if (currentNode == null || currentSetting == null)
            {
                throw new InvalidOperationException(string.Format(
                                                        "没有在流程中找到节点“{0}”的定义", currentHumanSetting.ActivityName));
            }
            #endregion

            #region 修改当前节点
            clonedSettings.Remove(currentSetting);
            var finishRule = currentSetting.FinishRule.Scripts;
            //总是先移除避免多次重复追加
            finishRule.Remove(appendHumanSetting.EnterFinishRuleName);
            //新增完成规则用于满足后进入新节点
            //必须将新规则插入在第一个规则位置,避免原有规则的影响 用atMostOf?该细节不能出现在Model层
            finishRule = new Dictionary <string, string>()
            {
                { appendHumanSetting.EnterFinishRuleName, string.Format("all('{0}')", appendHumanSetting.EnterAction) }
            }
            .Concat(finishRule)
            .ToDictionary(o => o.Key, o => o.Value);
            currentSetting = new HumanSetting(currentSetting.FlowNodeIndex
                                              , currentSetting.ActivityName
                                              , currentSetting.Actions
                                              , currentSetting.SlotCount
                                              , currentSetting.SlotMode
                                              , currentSetting.Url
                                              , currentSetting.StartRule
                                              , currentSetting.ActionerRule
                                              , new FinishRule(finishRule)
                                              , currentSetting.EscalationRule
                                              , currentSetting.IsChildOfActivity);
            clonedSettings.Add(currentSetting);
            #endregion

            #region 新增节点设置
            var newHumanSetting = new HumanSetting(0//此时无需设置实际值,最终创建流程类型时会由转换器填充实际值
                                                   , appendHumanSetting.ActivityName
                                                   , appendHumanSetting.Actions
                                                   , appendHumanSetting.SlotCount
                                                   , (HumanSetting.SlotDistributionMode)(int) appendHumanSetting.SlotMode
                                                   , appendHumanSetting.Url
                                                   , null
                                                   , new HumanActionerRule(appendHumanSetting.ActionerRule)
                                                   , this.GetFinishRule(appendHumanSetting)
                                                   , null
                                                   , false);
            clonedSettings.Add(newHumanSetting);
            #endregion

            #region 将新节点与左右节点连接
            FlowStep newNode = null;
            if (mode == Client.AppendHumanMode.Wait)
            {
                newNode = WorkflowBuilder.CreateHuman(newHumanSetting
                                                      , newHumanSetting.ActivityName
                                                      , new GetUsers(appendHumanSetting.ActionerRule)
                                                      , null
                                                      , null
                                                      , currentNode);//总是返回当前节点
            }
            else if (mode == Client.AppendHumanMode.Continues)
            {
                newNode = WorkflowBuilder.CreateHuman(newHumanSetting
                                                      , newHumanSetting.ActivityName
                                                      , new GetUsers(appendHumanSetting.ActionerRule)
                                                      , workflow.CustomActivityResult
                                                      , nextNode == null
                    ? null
                                                      //HACK:下一节点的进入与否将根据新节点的完成规则而定,若满足则继续,若不满足则流程结束,常见于加签的情况
                    : new Dictionary <string, FlowNode>()
                {
                    { appendHumanSetting.FinishRuleName, nextNode }
                }
                                                      , null);
            }
            //总是先移除避免多次重复追加
            (currentNode.Next as FlowSwitch <string>).Cases.Remove(appendHumanSetting.EnterFinishRuleName);
            (currentNode.Next as FlowSwitch <string>).Cases.Add(appendHumanSetting.EnterFinishRuleName, newNode);
            //总是先移除避免多次重复追加
            workflow.Body.Nodes.Remove(this.GetFlowStep(workflow, newHumanSetting.ActivityName));
            //由于解析需要应同时补充此元数据
            workflow.Body.Nodes.Add(newNode);
            #endregion

            //创建新流程定义,动态变更
            this._processService.DynamicChangeProcessType(process
                                                          , this.CreateProcessType(currentProcessType.Name
                                                                                   , this._workflowParser.Parse(workflow, originalWorkflowDefinition)
                                                                                   , this._workflowParser.Parse(clonedSettings)
                                                                                   , currentProcessType.Description
                                                                                   , currentProcessType.Group
                                                                                   , false));
        }