package com.supervision.handler.graph; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import com.supervision.ngbatis.dao.CommonQueryDao; import com.supervision.ngbatis.domain.tag.Condition; import com.supervision.ngbatis.domain.tag.ProcessCondition; import lombok.extern.slf4j.Slf4j; import org.jgrapht.Graph; import org.jgrapht.GraphPath; import org.jgrapht.alg.shortestpath.AllDirectedPaths; import org.jgrapht.graph.DefaultEdge; import org.jgrapht.graph.builder.GraphTypeBuilder; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** * 寻找判断节点的链条 */ @Slf4j @Component public class FindConditionPathHandler { @Resource private CommonQueryDao commonQueryDao; /** * 根据某个办理条件节点,寻找所有路径,以用来判断是否符合 * @param itemLeafId 叶子节点的ID * @return 所有路径 */ public List> findConditionPath(String itemLeafId) { // 首先根据叶子节点,找到条件节点 ProcessCondition conditionVertexByLeafVertex = commonQueryDao.findConditionVertexByLeafVertex(itemLeafId); if (ObjUtil.isEmpty(conditionVertexByLeafVertex)){ return new ArrayList<>(); } // 构建一个图,用这个图来找属性结构 Graph jGraph = buildJGraph(); // 定位终点的vertexId Set finalVertexSet = new HashSet<>(); // 从条件节点processConditionVid开始探索下一级节点列表,使用GO语句 List sourceConditionList = commonQueryDao.findNextConditionByConditionEdge(conditionVertexByLeafVertex.getId()); // 如果没有任何绑定的条件节点, if (CollUtil.isEmpty(sourceConditionList)) { // TODO 如果没有任何绑定的条件节点,这里咋整?暂定返回一个空的集合 return new ArrayList<>(); } for (Condition sourceVertex : sourceConditionList) { jGraph.addVertex(sourceVertex); } // 下面开始使用递归,开始持续的找下级节点(递归增加次数限制,最多100次) int recursionCount = 0; recursionFindNext(sourceConditionList, jGraph, finalVertexSet, recursionCount); // 根据图去找所有的路径 return findAllPath(jGraph, new HashSet<>(sourceConditionList), finalVertexSet); } private void recursionFindNext(List sourceIdList, Graph jGraph, Set finalVertexSet, int recursionCount) { // 防止死循环出现无限递归 if (recursionCount > 100) { return; } recursionCount++; for (Condition source : sourceIdList) { List nextVertxList = commonQueryDao.findNextConditionByConditionEdge(source.getId()); if (CollUtil.isNotEmpty(nextVertxList)) { for (Condition nextVertex : nextVertxList) { jGraph.addVertex(nextVertex); jGraph.addEdge(source, nextVertex); } recursionFindNext(nextVertxList, jGraph, finalVertexSet, recursionCount); } else { finalVertexSet.add(source); } } } private Graph buildJGraph() { // 创建一个树形结构 return GraphTypeBuilder .directed() .allowingMultipleEdges(false) .allowingSelfLoops(false) .edgeClass(DefaultEdge.class) .vertexClass(Condition.class) .weighted(false) .buildGraph(); } private List> findAllPath(Graph graph, Set sourceSet, Set targetIdSet) { // 使用深度优先遍历来获取所有路径 AllDirectedPaths directedPaths = new AllDirectedPaths<>(graph); // 根据一个起始点和终止节点,开始找所有的路径 List> allPaths = directedPaths.getAllPaths(sourceSet, targetIdSet, true, 100); // 将所有判断的路径汇聚起来 List> paths = new ArrayList<>(); for (GraphPath path : allPaths) { List vertexList = path.getVertexList(); if (CollUtil.isNotEmpty(vertexList)) { paths.add(vertexList); } } return paths; } }