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)); } }
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 }); }
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)); }
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); }
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)); }