浏览代码

fix:修复相同节点多次抛异常后回退流程节点数据紊乱bug

韩帛霖 1 年之前
父节点
当前提交
ec47f23f3c

+ 68 - 59
zkqy-common/src/main/java/com/zkqy/common/utils/bpm/XmlDataParserUtils.java

@@ -3,6 +3,7 @@ package com.zkqy.common.utils.bpm;
 import cn.hutool.core.util.XmlUtil;
 import com.zkqy.common.utils.uuid.IdUtils;
 import org.w3c.dom.*;
+
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
@@ -27,23 +28,23 @@ public class XmlDataParserUtils {
      * @param xmlData xml内容
      * @return
      */
-    public static Map<String,String> getStartNodeAndNextNode(String xmlData){
+    public static Map<String, String> getStartNodeAndNextNode(String xmlData) {
         Map<String, String> map = new HashMap<>();
-        Document document= XmlUtil.parseXml(xmlData);
+        Document document = XmlUtil.parseXml(xmlData);
         //获得XML文档根节点
-        Element elementG=XmlUtil.getRootElement(document);
+        Element elementG = XmlUtil.getRootElement(document);
         //获取bpmn:process节点
-        Element bpmnProcessEvent = XmlUtil.getElement(elementG,"bpmn:process");
+        Element bpmnProcessEvent = XmlUtil.getElement(elementG, "bpmn:process");
         //获取开始节点并得到开始节点ID
-        Element bpmnStartEvent=XmlUtil.getElement(bpmnProcessEvent,"bpmn:startEvent");
+        Element bpmnStartEvent = XmlUtil.getElement(bpmnProcessEvent, "bpmn:startEvent");
         String startNode = bpmnStartEvent.getAttribute("id");
-        map.put("startNode",startNode);
+        map.put("startNode", startNode);
 
         //获取所有序列流(顺序),循环得到开始节点的下一个节点
         NodeList elementsByTagName = elementG.getElementsByTagName("bpmn:sequenceFlow");
         for (int i = 0; i < elementsByTagName.getLength(); i++) {
             if (startNode.equals(elementsByTagName.item(i).getAttributes().getNamedItem("sourceRef").getNodeValue())) {
-                map.put("nextNode",elementsByTagName.item(i).getAttributes().getNamedItem("targetRef").getNodeValue());
+                map.put("nextNode", elementsByTagName.item(i).getAttributes().getNamedItem("targetRef").getNodeValue());
                 break;
             }
         }
@@ -52,11 +53,12 @@ public class XmlDataParserUtils {
 
     /**
      * 新增用户异常节点
+     *
      * @param userTaskTagName 新增节点名称
-     * @param nextTagId 新增节点下一节点ID
+     * @param nextTagId       新增节点下一节点ID
      * @return
      */
-    public static String addUserTaskTag(String xmlData,String newUserTaskTagId,String userTaskTagName,String nextTagId) throws Exception {
+    public static String addUserTaskTag(String xmlData, String newUserTaskTagId, String userTaskTagName, String nextTagId) throws Exception {
         //新增节点标签ID
 //        String newUserTaskTagId = "Flow_" + IdUtils.fastSimpleUUID().substring(0,7);
         //新增序列流ID
@@ -66,9 +68,9 @@ public class XmlDataParserUtils {
         //上一节点标签ID
         String previousId = null;
         //将xml文件内容转成Document对象
-        Document document= XmlUtil.parseXml(xmlData);
+        Document document = XmlUtil.parseXml(xmlData);
         //获得XML文档根节点
-        Element elementG=XmlUtil.getRootElement(document);
+        Element elementG = XmlUtil.getRootElement(document);
         //获取所有序列流(顺序),循环得到新增节点下一节点序列流ID、上一节点标签ID,修改新增节点下一节点序列流sourceRef为新增节点标签ID
         NodeList elementsByTagName = elementG.getElementsByTagName("bpmn:sequenceFlow");
         for (int i = 0; i < elementsByTagName.getLength(); i++) {
@@ -86,8 +88,8 @@ public class XmlDataParserUtils {
         }
         //创建异常任务节点标签
         Element userTaskTag = document.createElement("bpmn:exceptionTask");
-        userTaskTag.setAttribute("id",newUserTaskTagId);
-        userTaskTag.setAttribute("name",userTaskTagName);
+        userTaskTag.setAttribute("id", newUserTaskTagId);
+        userTaskTag.setAttribute("name", userTaskTagName);
         userTaskTag.appendChild(document.createTextNode("\n\t\t"));
         Element userTaskTagChild1 = document.createElement("bpmn:incoming");
         userTaskTagChild1.setTextContent(newSequenceFlowId);
@@ -99,12 +101,12 @@ public class XmlDataParserUtils {
         userTaskTag.appendChild(document.createTextNode("\n\t"));
         //创建新序列流标签
         Element sequenceFlowTag = document.createElement("bpmn:sequenceFlow");
-        sequenceFlowTag.setAttribute("id",newSequenceFlowId);
-        sequenceFlowTag.setAttribute("sourceRef",previousId);
-        sequenceFlowTag.setAttribute("targetRef",newUserTaskTagId);
+        sequenceFlowTag.setAttribute("id", newSequenceFlowId);
+        sequenceFlowTag.setAttribute("sourceRef", previousId);
+        sequenceFlowTag.setAttribute("targetRef", newUserTaskTagId);
         //修改上一节点bpmn:outgoing和下一节点bpmn:incoming
         //获取bpmn:process节点
-        Element bpmnProcessEvent = XmlUtil.getElement(elementG,"bpmn:process");
+        Element bpmnProcessEvent = XmlUtil.getElement(elementG, "bpmn:process");
         NodeList bpmnProcessNextLevelEventList = bpmnProcessEvent.getChildNodes();
         for (int i = 0; i < bpmnProcessNextLevelEventList.getLength(); i++) {
             Node node = bpmnProcessNextLevelEventList.item(i);
@@ -112,18 +114,18 @@ public class XmlDataParserUtils {
             if (node.getNodeType() == Node.ELEMENT_NODE && node instanceof Element) {
                 Element element = (Element) node;
                 String id = element.getAttribute("id");
-                if(id.equals(previousId)){
-                    Element elementOutgoing = XmlUtil.getElement(element,"bpmn:outgoing");
+                if (id.equals(previousId)) {
+                    Element elementOutgoing = XmlUtil.getElement(element, "bpmn:outgoing");
                     elementOutgoing.setTextContent(newSequenceFlowId);
                 }
-                if(id.equals(nextTagId)){
-                    Element elementOutgoing = XmlUtil.getElement(element,"bpmn:incoming");
+                if (id.equals(nextTagId)) {
+                    Element elementOutgoing = XmlUtil.getElement(element, "bpmn:incoming");
                     elementOutgoing.setTextContent(sequenceFlowId);
                     //插入标签
                     Node parentNode = element.getParentNode();
-                    parentNode.insertBefore(userTaskTag,element);
+                    parentNode.insertBefore(userTaskTag, element);
 
-                    parentNode.insertBefore(sequenceFlowTag,element);
+                    parentNode.insertBefore(sequenceFlowTag, element);
                 }
             }
         }
@@ -139,20 +141,21 @@ public class XmlDataParserUtils {
 
     /**
      * 获取下一节点key
-     * @param xmlData xml内容
+     *
+     * @param xmlData     xml内容
      * @param taskNodeKey 当前节点key
      * @return
      */
-    public static String getNextNodeKey(String xmlData, String taskNodeKey){
+    public static String getNextNodeKey(String xmlData, String taskNodeKey) {
         //下一节点key
         String nextTaskNodeKey = null;
-        Document document= XmlUtil.parseXml(xmlData);
+        Document document = XmlUtil.parseXml(xmlData);
         //获得XML文档根节点
-        Element elementG=XmlUtil.getRootElement(document);
+        Element elementG = XmlUtil.getRootElement(document);
         //获取所有序列流(顺序),循环得到开始节点的下一个节点
         NodeList elementsByTagName = elementG.getElementsByTagName("bpmn:sequenceFlow");
         for (int i = 0; i < elementsByTagName.getLength(); i++) {
-            if(taskNodeKey.equals(elementsByTagName.item(i).getAttributes().getNamedItem("sourceRef").getNodeValue())){
+            if (taskNodeKey.equals(elementsByTagName.item(i).getAttributes().getNamedItem("sourceRef").getNodeValue())) {
                 nextTaskNodeKey = elementsByTagName.item(i).getAttributes().getNamedItem("targetRef").getNodeValue();
             }
         }
@@ -161,33 +164,34 @@ public class XmlDataParserUtils {
 
     /**
      * 按顺序获取流程节点
+     *
      * @param xmlData xml内容
      * @return
      */
-    public static Map<String,Object> getAllNodeKey(String xmlData){
-        Map<String,Object> resultMap = new HashMap<>();
+    public static Map<String, Object> getAllNodeKey(String xmlData) {
+        Map<String, Object> resultMap = new HashMap<>();
         //将xml文件内容转成Document对象
-        Document document= XmlUtil.parseXml(xmlData);
+        Document document = XmlUtil.parseXml(xmlData);
         //获得XML文档根节点
-        Element elementG=XmlUtil.getRootElement(document);
+        Element elementG = XmlUtil.getRootElement(document);
         //获取bpmn:process节点
-        Element bpmnProcessEvent = XmlUtil.getElement(elementG,"bpmn:process");
+        Element bpmnProcessEvent = XmlUtil.getElement(elementG, "bpmn:process");
         //获取所有序列流(顺序)
         NodeList elementsByTagName = elementG.getElementsByTagName("bpmn:sequenceFlow");
         //获取开始节点并得到开始节点ID
-        Element bpmnStartEvent=XmlUtil.getElement(bpmnProcessEvent,"bpmn:startEvent");
+        Element bpmnStartEvent = XmlUtil.getElement(bpmnProcessEvent, "bpmn:startEvent");
         String startNode = bpmnStartEvent.getAttribute("id");
-        Map<String,Integer> map = new HashMap<>();
-        map.put(startNode,0);
+        Map<String, Integer> map = new HashMap<>();
+        map.put(startNode, 0);
         List<String> list = new ArrayList<>();
         list.add(startNode);
-        resultMap.put("nodeList",list);
-        resultMap.put("nodeMap",recursiveParse(elementsByTagName, startNode, map, list));
+        resultMap.put("nodeList", list);
+        resultMap.put("nodeMap", recursiveParse(elementsByTagName, startNode, map, list));
         return resultMap;
     }
 
     //递归查找下一节点
-    private static Map<String,Integer> recursiveParse(NodeList nodeList, String currentId ,Map<String,Integer> map, List<String> list) {
+    private static Map<String, Integer> recursiveParse(NodeList nodeList, String currentId, Map<String, Integer> map, List<String> list) {
         for (int i = 0; i < nodeList.getLength(); i++) {
             Node node = nodeList.item(i);
             if (node.getNodeType() == Node.ELEMENT_NODE) {
@@ -195,9 +199,9 @@ public class XmlDataParserUtils {
                 String sourceRef = element.getAttribute("sourceRef");
                 String targetRef = element.getAttribute("targetRef");
                 if (sourceRef.equals(currentId)) {
-                    map.put(targetRef, map.size()+1);
+                    map.put(targetRef, map.size() + 1);
                     list.add(targetRef);
-                    recursiveParse(nodeList, targetRef,map,list);
+                    recursiveParse(nodeList, targetRef, map, list);
                     break;
                 }
             }
@@ -207,46 +211,50 @@ public class XmlDataParserUtils {
 
     /**
      * 清空异常节点
-     * @param xmlData xml内容
+     *
+     * @param xmlData       xml内容
      * @param currentNodeId 当前节点ID
      * @return
      */
-    public static String clearExceptionTask(String xmlData,String currentNodeId) {
+    public static String clearExceptionTask(String xmlData, String currentNodeId) {
         //将xml文件内容转成Document对象
         Document document = XmlUtil.parseXml(xmlData);
         //得到当前所有节点ID
         Map<String, Object> allNodeKey = getAllNodeKey(xmlData);
         List<String> list = (List<String>) allNodeKey.get("nodeList");
         //截取当前节点后的所有ID
-        list = new ArrayList<>(list.subList(list.indexOf(currentNodeId),list.size()));
+        list = new ArrayList<>(list.subList(list.indexOf(currentNodeId), list.size()));
         //获取所有异常节点,筛选出正常节点和异常节点
         List<String> exceptionList = new ArrayList<>();
-        for (int i = 1; i < list.size(); i++){
-            Element node = getElement(document, list.get(i),"id");
+        List<String> endList = new ArrayList<>();
+        for (int i = 1; i < list.size(); i++) {
+            Element node = getElement(document, list.get(i), "id");
             String nodeTagName = node.getTagName();
-            if (nodeTagName.equals("bpmn:exceptionTask")){
+            if (nodeTagName.equals("bpmn:exceptionTask")) {
                 exceptionList.add(list.get(i));
-                list.remove(i);
+            } else {
+                endList.add(list.get(i));
             }
         }
+        endList.add(0, list.get(0));
         // 循环正常节点,修改下一个节点指向
-        for (int i = 0; i < list.size() - 1; i++ ) {
+        for (int i = 0; i < endList.size() - 1; i++) {
             //获取下一节点
-            Element nextNode = getElement(document, list.get(i + 1),"id");
+            Element nextNode = getElement(document, endList.get(i + 1), "id");
             //得到上一个正常节点得序列流元素,修改targetRef指向下一个节点ID
-            Element currentSequenceFlow = getElement(document,list.get(i),"sourceRef");
-            currentSequenceFlow.setAttribute("targetRef",list.get(i+1));
+            Element currentSequenceFlow = getElement(document, endList.get(i), "sourceRef");
+            currentSequenceFlow.setAttribute("targetRef", endList.get(i + 1));
             //修改下一个节点入口incoming指向上一个节点序列流ID
-            Element elementOutgoing = XmlUtil.getElement(nextNode,"bpmn:incoming");
+            Element elementOutgoing = XmlUtil.getElement(nextNode, "bpmn:incoming");
             elementOutgoing.setTextContent(currentSequenceFlow.getAttributes().getNamedItem("id").getNodeValue());
         }
         //删除异常节点及异常节点序列线
         for (int i = 0; i < exceptionList.size(); i++) {
             //获取异常节点-删除
-            Element node = getElement(document, exceptionList.get(i),"id");
+            Element node = getElement(document, exceptionList.get(i), "id");
             node.getParentNode().removeChild(node);
             //获取序列线-删除
-            Element nodeXian = getElement(document, exceptionList.get(i),"sourceRef");
+            Element nodeXian = getElement(document, exceptionList.get(i), "sourceRef");
             nodeXian.getParentNode().removeChild(nodeXian);
         }
         //将document对象转成字符串
@@ -257,7 +265,7 @@ public class XmlDataParserUtils {
             DOMSource source = new DOMSource(document);
             StreamResult result = new StreamResult(new StringWriter()); // 使用StringWriter来将结果输出为字符串
             transformer.transform(source, result);
-            data =  result.getWriter().toString();
+            data = result.getWriter().toString();
         } catch (Exception e) {
             e.printStackTrace();
         }
@@ -267,14 +275,15 @@ public class XmlDataParserUtils {
 
     /**
      * 获取元素
+     *
      * @param document
-     * @param nodeAttributeId 节点属性ID
+     * @param nodeAttributeId   节点属性ID
      * @param nodeAttributeName 节点属性名称
      * @return
      */
-    private static Element getElement(Document document,String nodeAttributeId,String nodeAttributeName){
+    private static Element getElement(Document document, String nodeAttributeId, String nodeAttributeName) {
         try {
-            String expression = "//*[namespace-uri()='http://www.omg.org/spec/BPMN/20100524/MODEL'][@"+nodeAttributeName+"='"+nodeAttributeId+"']";
+            String expression = "//*[namespace-uri()='http://www.omg.org/spec/BPMN/20100524/MODEL'][@" + nodeAttributeName + "='" + nodeAttributeId + "']";
             XPath xpath = XPathFactory.newInstance().newXPath();
             NodeList nodeList = (NodeList) xpath.compile(expression).evaluate(document, XPathConstants.NODESET);
             // 遍历节点列表并获取第一个匹配的元素

+ 20 - 9
zkqy-process-execution/src/main/java/com/zkqy/execution/produce/dispersed/entity/runbpm/BpmBackNodeVo.java

@@ -23,6 +23,26 @@ public class BpmBackNodeVo {
      */
     private String taskBackNodeKey;
 
+    /**
+     * 当前回退节点的类型
+     */
+    private String taskNodeType;
+
+    public BpmBackNodeVo(String taskProcessKey, String taskNodeKey, String taskBackNodeKey, String taskNodeType) {
+        this.taskProcessKey = taskProcessKey;
+        this.taskNodeKey = taskNodeKey;
+        this.taskBackNodeKey = taskBackNodeKey;
+        this.taskNodeType = taskNodeType;
+    }
+
+    public String getTaskNodeType() {
+        return taskNodeType;
+    }
+
+    public void setTaskNodeType(String taskNodeType) {
+        this.taskNodeType = taskNodeType;
+    }
+
     public BpmBackNodeVo() {
     }
 
@@ -56,13 +76,4 @@ public class BpmBackNodeVo {
         this.taskBackNodeKey = taskBackNodeKey;
     }
 
-    @Override
-    public String toString() {
-        final StringBuilder sb = new StringBuilder("BpmBackNodeVo{");
-        sb.append("taskProcessKey='").append(taskProcessKey).append('\'');
-        sb.append(", taskNodeKey='").append(taskNodeKey).append('\'');
-        sb.append(", taskBackNodeKey='").append(taskBackNodeKey).append('\'');
-        sb.append('}');
-        return sb.toString();
-    }
 }

+ 7 - 0
zkqy-process-execution/src/main/java/com/zkqy/execution/produce/dispersed/mapper/BpmExecuteNodeMapper.java

@@ -92,6 +92,13 @@ public interface BpmExecuteNodeMapper {
      */
     public int updateNodeStateByKeys(@Param("processKey") String processKey, @Param("nodeKeys") List<String> nodeKeys);
 
+    /**
+     * 回退流程之后删除被回退节点后的异常节点
+     *
+     * @param processKey 当前流程key
+     * @param nodeKeys
+     * @return
+     */
     public int deleteExceptionNodeByKeys(@Param("processKey") String processKey, @Param("nodeKeys") List<String> nodeKeys);
 
     /**

+ 20 - 2
zkqy-process-execution/src/main/java/com/zkqy/execution/produce/dispersed/runbpm/PreExecutionToolClass.java

@@ -524,14 +524,24 @@ public class PreExecutionToolClass<R> {
          *
          * 被回退的节点
          */
-        // 得到当前流程的详细信息
         BpmExecuteProcess bpmExecuteProcess = runBpmExecuteProcessMapper.selectBpmExecuteProcessByTaskKey(bpmBackNodeVo.getTaskProcessKey());
         bpmExecuteProcess.getTaskProcessXmlContent(); // 当前流程xml内容
         Map<String, Object> bpmInfoOrder = XmlDataParserUtils.getAllNodeKey(bpmExecuteProcess.getTaskProcessXmlContent());
         // 修改流程-> 流程执行的xml文件
-        bpmExecuteProcess.setTaskNodeNextKey(bpmBackNodeVo.getTaskBackNodeKey());
         bpmExecuteProcess.setTaskProcessXmlContent(XmlDataParserUtils.clearExceptionTask(bpmExecuteProcess.getTaskProcessXmlContent(), bpmBackNodeVo.getTaskBackNodeKey()));
+
+
+        // 如果触发回退操作的节点是一个异常节点(需要更改当前流程绑定的执行节点)
+//        if (bpmBackNodeVo.getTaskNodeType().equals("exceptionTask")) {
+//
+//
+//            bpmExecuteProcess.setTaskNodeNextKey(bpmBackNodeVo.getTaskBackNodeKey());
+//        } else if ((bpmBackNodeVo.getTaskNodeType().equals("userTask"))) {
+//            bpmExecuteProcess.setTaskNodeNextKey(bpmBackNodeVo.getTaskBackNodeKey());
+//        }
+        bpmExecuteProcess.setTaskNodeNextKey(bpmBackNodeVo.getTaskBackNodeKey());
         runBpmExecuteProcessMapper.updateBpmExecuteProcess(bpmExecuteProcess);
+        // 得到当前流程的详细信息
         Map<String, Object> nodeMap = (Map<String, Object>) bpmInfoOrder.get("nodeMap");
         List<String> nodeList = (List<String>) bpmInfoOrder.get("nodeList");
         int index = (int) nodeMap.get(bpmBackNodeVo.getTaskBackNodeKey()); // 得到被回退的节点下标
@@ -649,3 +659,11 @@ public class PreExecutionToolClass<R> {
 //        return mapList;
 //    }
 }
+/*
+
+
+
+
+
+
+ */

+ 4 - 2
zkqy-process-execution/src/main/java/com/zkqy/execution/produce/dispersed/service/impl/runbpm/hangye1/yichang/yichang1.java

@@ -1,7 +1,6 @@
 package com.zkqy.execution.produce.dispersed.service.impl.runbpm.hangye1.yichang;
 
 
-
 import com.zkqy.common.core.domain.AjaxResult;
 import com.zkqy.execution.produce.dispersed.entity.BpmExecuteNode;
 import com.zkqy.execution.produce.dispersed.entity.CommonEntity;
@@ -57,7 +56,10 @@ public class yichang1 implements IRunBPMService {
         BpmBackNodeVo bpmBackNodeVo = new BpmBackNodeVo(
                 iRunBPMEntity.getExecutionMap().get("taskProcessKey").toString(),
                 iRunBPMEntity.getExecutionMap().get("taskNodeKey").toString(),
-                iRunBPMEntity.getExecutionMap().get("taskBackNodeKey").toString());
+                iRunBPMEntity.getExecutionMap().get("taskBackNodeKey").toString()
+//                ,
+//                iRunBPMEntity.getExecutionMap().get("taskNodeType").toString()
+        );
         preExecutionToolClass.backProcessNode(bpmBackNodeVo);
         return AjaxResult.success();
     }