activiti获取可回退的节点

news/2023/6/5 21:10:38

    在处理流程回退时,需要获取某个节点当前可以回退到的节点,简单分析下:

1. 只支持回退到userTask。

2. 如果流程流转过某节点时生成了多个任务,从其中某一个任务回退到该节点后,不处理另外的任务。

3. 只能回退到当前节点前已经处理过的节点。

 

    基于这个考虑,获取哪些节点可以回退按如下处理:

1. 从历史任务表查当前节点所在流程实例已经完成过的所有任务,有可能包括当前节点以后的任务(比如当前节点本来就是由后面节点回退的)

2. 判断任务是不是当前节点以前的userTask节点任务,如果是,加入返回列表。

3. 同一个节点只返回一次。

 

    在这种处理前提下,需要获取流程中所有userTask节点的前后关系。我用深度优先的方式对流程的所有节点进行了一个遍历,把所有节点的前后关系保存在一个map里,map的内容为:

    key: 前面的节点编号#后面的节点编号

    value:从前面节点到后面节点中间要经过几个节点。

    如果一个节点前有多个节点,比如 流程是 A-->B-->C-->D,那么 map的数据类似:

   {A#B:1,A#C:2,A#D:3,B#C:1,B#D:2,C#D:1}

   在这种情况下,所有的可能性都存储了一份,但是在后面判断节点的前后关系时相对比较容易,只要把要判断的节点和当前节点编号拼接在一起,判断 要判断的节点#当前节点 是不是在map里存在就好了。

   一般来说,流程的节点数不会太多,这样已经够用了。

 

  由于回退不是在流程上通过划线处理的,所以一般不会出现环状的流程图,因此用深度优先方式遍历也适用,感觉上应该用广度优先的方式遍历更合适一点。

 

  附部分代码:

private static Map<String,Map<String,Object>> PROCESS_NODE_MAP = null;
private Map getFlowNodeRel(String processDefKey){if (null == PROCESS_NODE_MAP){PROCESS_NODE_MAP = new HashMap<String, Map<String, Object>>();}if(null == PROCESS_NODE_MAP.get(processDefKey)){ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();List<Process> processList = engine.getRepositoryService().getBpmnModel(processDefKey).getProcesses();Process process = null;if(processList.size()>0){process = processList.get(0);Map relationMap = new HashMap<String,Integer>();setFlowNodeRel(process,relationMap);PROCESS_NODE_MAP.put(processDefKey, relationMap);}}return PROCESS_NODE_MAP.get(processDefKey);}//根据process往relationMap里写入UserTask之间的前后关系,从start开始遍历节点,不循环private void setFlowNodeRel(Process process,Map relationMap){Iterator<FlowElement> iterator = process.getFlowElements().iterator();HashMap nodeMap = new HashMap<String,FlowElement>();setFlowNodeMap(process,nodeMap);//获取start节点StartEvent startEvent = (StartEvent) nodeMap.get("startEvent");//处理节点关系setFlowNodeRel("","startEvent",nodeMap,relationMap,1);}//根据节点ID设置关系private void setFlowNodeRel(String parentKey,String nodeId,Map<String,FlowElement> nodeMap,Map relationMap,int level){FlowElement element = nodeMap.get(nodeId);if(element instanceof UserTask){relationMap.put(nodeId, element);}if(!(element  instanceof FlowNode)){return;}List<SequenceFlow> outFlows = ((FlowNode)element).getOutgoingFlows(); if(outFlows.size() == 0){return;}//采用深度遍历for(int index=0;index < outFlows.size();index++){SequenceFlow tmpSequence = outFlows.get(index);String target = tmpSequence.getTargetRef();String key = nodeId + "#" + target;String loopKey = target + "#" + nodeId;FlowElement tmpElement = nodeMap.get(target);//只是源和目标都是 用户任务 才写入if(relationMap.containsKey(loopKey) || relationMap.containsKey(key)){continue;}if(tmpElement instanceof UserTask && element instanceof UserTask){setRelMapValue(relationMap,parentKey,target, level);}//递归找下一个任务的关系setFlowNodeRel(parentKey+"#"+target,target,nodeMap,relationMap,level+1);}}private void setRelMapValue(Map relationMap,String parentKey,String nodeKey,int level){if(parentKey.length() > 0){String[] parentArr = parentKey.split("#");for(String parent:parentArr){if(StringUtils.isNotEmpty(parent)){String key = parent + "#" + nodeKey;String loopKey = nodeKey + "#" + parent;if(relationMap.containsKey(loopKey) || relationMap.containsKey(key)){continue;}else{relationMap.put(key, level);}}}}}//把流程节点设置到map属性里private void setFlowNodeMap(Process process,Map<String,FlowElement> nodeMap){Iterator<FlowElement> iterator = process.getFlowElements().iterator();while(iterator.hasNext()){FlowElement element = iterator.next();                    if(element instanceof StartEvent){nodeMap.put("startEvent", element);}else{nodeMap.put(element.getId(),element);}}}
View Code

 

 

 

 

 

 

转载于:https://www.cnblogs.com/kevinYX/p/3480125.html


https://dhexx.cn/news/show-17886.html

相关文章

Android之NDK开发环境r9

需要的软件&#xff1a; android-ndk-r9-windows-x86_64.zip&#xff08;我的系统是64位的&#xff0c;所以下载的是64的&#xff09;下载地址&#xff1a;http://developer.android.com/tools/sdk/ndk/index.html#Downloadsadt-bundle-windows-x86_64-20130917&#xff08;这个…

被大厂废掉的年轻人

作者| Mr.K 编辑| Emma来源| 技术领导力(ID&#xff1a;jishulingdaoli)朋友M总的公司招人&#xff0c;有两个候选人&#xff0c;一个是有大厂经验的“毕业生”&#xff0c;另一个曾在某腰部企业工做过团队主管。M总有点拿不准&#xff0c;问K哥的意见。对比两人的简历后&…

工作这几年

11年年初来北京找工作&#xff0c;转眼已经8个年头了&#xff0c;经验丰富了&#xff0c;技术更广泛了&#xff0c;也结婚了&#xff0c;孩子也有了&#xff0c;几乎身边所有的地方都在悄悄的发生变化。可是&#xff0c;唯一不变的&#xff0c;确实这身材&#xff08;175cm,60公…

主流浏览器CSS3和HTML5兼容性详细清单

各大主流浏览器对 CSS3 和 HTML5 的支持越来越完善&#xff0c;曾经让多少前端开发人员心碎的IE系也开始拥抱标准。就在前几天&#xff0c;W3C的 HTML5 社区领袖 Shelley 宣布&#xff0c;HTML5的开发工作已经接近完成&#xff0c;如果进展顺利&#xff0c;HTML5 将在 2012 年正…

tomcat性能优化,内存优化和并发线程连接优化

今天被一同事问到tomcat和内存优化的问题&#xff0c;而网上的资料基本都是来回copy&#xff0c;所以抽时间随便写点。文章中设置的参数都是一个随便写的&#xff0c;具体的还要根据自己的情况来定。 1.内存优化&#xff1a; 说到tomcat不得不提的是jvm&#xff0c;想让tomca…

微软BI 之SSAS 系列 - 基于雪花模型的维度设计

基于雪花模型的维度以下面的 Product 产品与产品子类别&#xff0c;产品类别为例。 DimProduct 表和 DimProductSubcategory 表有外键关系&#xff0c;而 DimProductSubcategory 表和 DimProductCategory 表存在外键关系。 测试的维度表与数据 - USE BIWORK_SSIS GOIF OBJECT_…

HIVE-row_number() OVER(PARTITION BY)函数-先分组,取每个分组的前几个

OVER(PARTITION BY order by)函数更详细的使用&#xff0c;可查看博文https://blog.csdn.net/qq_41712271/article/details/109224538 select row_number() over (partition by month order by ref_host_cnts desc) partition&#xff1a;按照month分成区块 order by &#x…

Lr监控linux系统资源方法

1.监控linux系统需要开启rstatd和xinetd两个服务&#xff0c;查看系统是否配置rstatd、xinetd守护进程&#xff1a; 输入命令&#xff1a;rpcinfo -p查看rstatd服务 输入命令&#xff1a;rpm -q xinetd查看xinetd服务 2. 监控linux系统需要安装下载4个服务包&#xff1a;&a…

Windows Phone 8初学者开发—第22部分:用演示图板创建卷盘的动画

第22部分: 用演示图板创建卷盘的动画 原文地址&#xff1a;http://channel9.msdn.com/Series/Windows-Phone-8-Development-for-Absolute-Beginners/Part-22-Animating-the-Reel-Grid-with-a-Storyboard 系列地址&#xff1a;http://channel9.msdn.com/Series/Windows-Phone-8-…

在Ubuntu 13.10(64位)安装Oracle 11g(32+64位)成功----有图!

先上一张图片&#xff0c;安装了两个晚上&#xff0c;漫长的等待&#xff0c;主要是一些欺骗oracle安装程序的设置&#xff08;oracle安装程序默认不支持ubuntu的&#xff0c;需要更改里面的一些设置&#xff09;&#xff01;&#xff08;由于我第一学的是mysql&#xff0c;然后…