需求说明
根据流程设计,统计该流程的所有节点的完成数量,超时数量等数据,统计结果按照流程节点顺序排序。
如果从历史审批记录中获取流程节点,那么会出现两个问题
1.如果还未发起流程,那么是获取不到任何节点数据的。
2.如果流程设计频繁改动,那么获取到的历史节点数据,又可能是错误的。
所以有了如下代码,从流程设计中顺序读取节点。
开发思路
获取所有的流程节点(开始节点以及任务节点),然后获取所有的连接线,根据连接线的连接顺序,将流程节点串起来。
1.获取所有的流程节点
/**
* 获取流程设计的所有节点
* @param e
* @return
*/
public static HashMap<String,String> getNode(DomElement e){
HashMap<String,String> nodeMap = new HashMap<>();
e.getChildElements().stream()
.filter(it -> "startEvent".equals(it.getLocalName()) || "userTask".equals(it.getLocalName()) || "subProcess".equals(it.getLocalName()))
.forEach(item ->{
switch (item.getLocalName()){
case "userTask":
nodeMap.put(item.getAttribute("id"),item.getAttribute("name"));
break;
case "startEvent":
nodeMap.put(item.getAttribute("id"),item.getAttribute("name"));
break;
case "subProcess":
nodeMap.putAll(getNode(item));
break;
}
});
return nodeMap;
}
**2.获取所有的流程连接线**
/**
* 获取流程设计的所有连接线
* @param e
* @return
*/
public static HashMap<String,String> getSequenceFlow(DomElement e){
HashMap<String,String> sequenceFlow = new HashMap<>();
e.getChildElements().stream()
.filter(it -> "sequenceFlow".equals(it.getLocalName()))
.forEach(item ->{
if (sequenceFlow.get(item.getAttribute("sourceRef")) == null){
String sourceRef = item.getAttribute("sourceRef");
if (sourceRef.startsWith("StartEvent")){
sequenceFlow.put("StartEvent",item.getAttribute("sourceRef"));
}
sequenceFlow.put(sourceRef,item.getAttribute("targetRef"));
}else{
sequenceFlow.put(item.getAttribute("sourceRef"),sequenceFlow.get(item.getAttribute("sourceRef"))+","+item.getAttribute("targetRef"));
}
});
return sequenceFlow;
}
3.根据连接线将流程节点组装成有序的List
/**
* 获取有序的流程节点
* @param bpmnModelInstance
* @return
*/
public static ArrayList<HashMap<String,String>> getBpmNodeList(BpmnModelInstance bpmnModelInstance ){
if(ObjectUtils.isEmpty(bpmnModelInstance)){
return null;
}
List<DomElement> domElementList = bpmnModelInstance.getDocument().getRootElement().getChildElements();
if(ObjectUtils.isEmpty(domElementList)){
return new ArrayList<>();
}
DomElement domElement = domElementList.stream().filter(it -> "process".equals(it.getLocalName())).findFirst().orElse(null);
ArrayList<HashMap<String,String>> nodeList = new ArrayList<>();
HashMap<String,String> seqMap = BpmUtils.getSequenceFlow(domElement);
HashMap<String,String> nodeMao = BpmUtils.getNode(domElement);
String start = seqMap.get("StartEvent");
nodeList(nodeList,start,seqMap,nodeMao);
return nodeList;
}
/**
* 循环获取流程节点信息(非通用)
* @param nodeList 流程节点列表
* @param seqKey 流程节点key
* @param seqMap 流程连接线
* @param nodeMao 流程节点
*/
private static void nodeList(ArrayList<HashMap<String,String>> nodeList,String seqKey,HashMap<String,String> seqMap,HashMap<String,String> nodeMao){
if (seqKey.contains(",")){
String[] keyArr = seqKey.split(",");
for (int i = 0; i < keyArr.length; i++) {
nodeList(nodeList,keyArr[i],seqMap,nodeMao);
}
return;
}
if(seqMap.get(seqKey) == null){
return;
}
if (seqKey.startsWith("Task") || seqKey.startsWith("StartEvent")) {
HashMap<String, String> node = new HashMap<>();
node.put("code", seqKey);
node.put("name", nodeMao.get(seqKey));
nodeList.add(node);
}
String req = seqMap.get(seqKey);
seqMap.remove(seqKey);
nodeMao.remove(seqKey);
seqKey = req;
nodeList(nodeList,seqKey,seqMap,nodeMao);
}
4.方法调用
BpmnModelInstance bpmnModelInstance = repositoryService.getBpmnModelInstance("lhltest_sub:202:d15b24e2-4b8c-11ee-b735-c20b58b0bcdb");
ArrayList nodeList = BpmUtils.getBpmNodeList(bpmnModelInstance);
效果展示