diff --git a/com.actionsoft.apps.coe.method.process.subprocess/lib/com.actionsoft.apps.coe.method.process.subprocess.jar b/com.actionsoft.apps.coe.method.process.subprocess/lib/com.actionsoft.apps.coe.method.process.subprocess.jar index 4b5db017..f19625b6 100644 Binary files a/com.actionsoft.apps.coe.method.process.subprocess/lib/com.actionsoft.apps.coe.method.process.subprocess.jar and b/com.actionsoft.apps.coe.method.process.subprocess/lib/com.actionsoft.apps.coe.method.process.subprocess.jar differ diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/SubProcessController.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/SubProcessController.java index 6377716c..7e6bc0fc 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/SubProcessController.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/SubProcessController.java @@ -90,6 +90,11 @@ public class SubProcessController { } } - + @Mapping("com.actionsoft.apps.coe.method.process.subprocess.generator_end_to_end_model") + public String generatorEndToEndModel(UserContext uc, String processIdJsonArr, String locationId, String direction, String modelName){ + SubProcessWeb processWeb = new SubProcessWeb(uc); + processWeb.generatorEndToEndModel(processIdJsonArr, locationId, direction, modelName); + return ResponseObject.newOkResponse().toString(); + } } diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/constant/SubProcessConst.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/constant/SubProcessConst.java index 7093a8ad..8e3b5288 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/constant/SubProcessConst.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/constant/SubProcessConst.java @@ -9,6 +9,9 @@ public interface SubProcessConst { // 应用ID String APP_ID = "com.actionsoft.apps.coe.method.process.subprocess"; + String SUB_PROCESS_CATEGORY = "process"; + String SUB_PROCESS_METHOD_ID = "process.subprocess"; + // 端到端流程存放父节点 参数名 String SUB_PROCESS_MODEL_LOCATION = "SUB_PROCESS_MODEL_LOCATION"; diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/ForceDirectedGraphLayout.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/ForceDirectedGraphLayout.java new file mode 100644 index 00000000..f4150842 --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/ForceDirectedGraphLayout.java @@ -0,0 +1,131 @@ +package com.actionsoft.apps.coe.method.process.subprocess.graph; + +import java.util.Random; + +/** + * 图模型节点布局 + * 采用力导向算法 + * @author oYang + * @create 2023-05-12 14:58 + */ +public class ForceDirectedGraphLayout { + + private final int n; // 节点数 + private final int[][] adjacency; // 邻接矩阵 + private final double[][] position; // 节点位置 + private final double[] charge; // 节点电荷 + private final double[] forceX; // 节点受到的x方向力 + private final double[] forceY; // 节点受到的y方向力 + private final double[] displacementX; // 节点位移的x方向补偿 + private final double[] displacementY; // 节点位移的y方向补偿 + private double temperature = 100.0; // 温度 + private double temperatureDecay = 0.1; // 温度衰减率 + private final double maxDisplacement = 50.0; // 最大位移量 + private final Random random = new Random(); + private final double width; // 画布宽度 + private final double height; // 画布高度 + private final double shapeInterval = 80.0; // 图形节点在画布上的间隔 + private final double nodeW = 100.0; // 图形节点默认宽度 + private final double nodeH = 70.0; // 图形节点默认高度 + + public ForceDirectedGraphLayout(int[][] adjacency) { + this.n = adjacency.length; + this.adjacency = adjacency; + this.position = new double[n][2]; + this.charge = new double[n]; + this.forceX = new double[n]; + this.forceY = new double[n]; + this.displacementX = new double[n]; + this.displacementY = new double[n]; + this.width = n * (shapeInterval + nodeW); + this.height = n * (shapeInterval + nodeH); + + // 初始化节点位置,随机分布在一个2000x2000的矩形内 + for (int i = 0; i < n; i++) { + position[i][0] = random.nextDouble() * width; + position[i][1] = random.nextDouble() * height; + charge[i] = 1.0; // 电荷为1 + } + } + + public void run() { + for (int i = 0; i < 1000; i++) { // 迭代1000次 + calculateForces(); + moveNodes(); + cool(); // 降温 + } + } + + private void calculateForces() { + // 清空所有节点受到的力 + for (int i = 0; i < n; i++) { + forceX[i] = 0; + forceY[i] = 0; + } + + // 计算节点间的斥力 + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i != j) { + double dx = position[j][0] - position[i][0]; + double dy = position[j][1] - position[i][1]; + double distance = Math.sqrt(dx * dx + dy * dy); + double repulsiveForce = charge[i] * charge[j] / distance * distance; + forceX[i] -= repulsiveForce * dx / distance; + forceY[i] -= repulsiveForce * dy / distance; + } + } + } + + // 计算节点所在边的吸引力 + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (adjacency[i][j] != 0) { // 代表节点i和节点j之间存在一条边 + double dx = position[j][0] - position[i][0]; + double dy = position[j][1] - position[i][1]; + double distance = Math.sqrt(dx * dx + dy * dy); + double attractiveForce = distance * distance / charge[i]; + forceX[i] += attractiveForce * dx / distance; + forceY[i] += attractiveForce * dy / distance; + } + } + } + } + + private void moveNodes() { + for (int i = 0; i < n; i++) { + double displacement = Math.sqrt(forceX[i] * forceX[i] + forceY[i] * forceY[i]); + if (displacement == 0) { // 如果节点受到的力为0,就加一点随机扰动,防止节点过于静止 + displacementX[i] = random.nextDouble() * maxDisplacement * 2 - maxDisplacement; + displacementY[i] = random.nextDouble() * maxDisplacement * 2 - maxDisplacement; + } else { + displacementX[i] = forceX[i] / displacement * Math.min(displacement, maxDisplacement); // 获得x方向的位移补偿 + displacementY[i] = forceY[i] / displacement * Math.min(displacement, maxDisplacement); // 获得y方向的位移补偿 + } + } + for (int i = 0; i < n; i++) { + position[i][0] += displacementX[i]; // 更新节点的x坐标 + position[i][1] += displacementY[i]; // 更新节点的y坐标 + } + } + + private void cool() { + temperature *= 1 - temperatureDecay; // 温度指数级下降,达到类似于“退火”的贪心优化效果 + } + + public double[][] getPosition() { + return position; + } + + public static void main(String[] args) { + int[][] adjacency = new int[][]{{0, 1, 1, 0}, {0, 0, 1, 1}, {1, 0, 0, 1}, {1, 1, 0, 0}}; // 代表四个节点的有向图 + + ForceDirectedGraphLayout fdl = new ForceDirectedGraphLayout(adjacency); + fdl.run(); + + double[][] position = fdl.getPosition(); + for (int i = 0; i < position.length; i++) { + System.out.println("Node " + i + ": (" + position[i][0] + ", " + position[i][1] + ")"); + } + } +} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphAdjMatrix.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphAdjMatrix.java index 2a96ccbc..88709782 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphAdjMatrix.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphAdjMatrix.java @@ -1,9 +1,12 @@ package com.actionsoft.apps.coe.method.process.subprocess.graph; import com.actionsoft.apps.coe.method.process.subprocess.mode.Node; +import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.model.DesignerShapeRelationModel; +import com.actionsoft.bpms.util.ConsolePrinter; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * 用邻接矩阵表示图模型 并实现相关的操作 @@ -18,11 +21,11 @@ public class GraphAdjMatrix { /** * 构造函数 初始化邻接矩阵 - * @param numVertices + * @param nodeList */ - public GraphAdjMatrix(int numVertices) { - adjMatrix = new int[numVertices][numVertices]; - vertexList = new ArrayList<>(numVertices); + public GraphAdjMatrix(List nodeList) { + adjMatrix = new int[nodeList.size()][nodeList.size()]; + vertexList = nodeList; numEdges = 0; } @@ -53,4 +56,56 @@ public class GraphAdjMatrix { public boolean hasEdge(int u, int v) { return adjMatrix[u][v] == 1; } + + /** + * 获取边的树目 + * @return + */ + public int getNumEdges(){ + return numEdges; + } + + /** + * 获取邻接矩阵 + * @return + */ + public int[][] getAdjMatrix(){ + return adjMatrix; + } + + /** + * 构建邻接矩阵 + * @param nodeIndexMap 索引映射 节点ID与节点在列表中索引的映射关系 + */ + public void buildAdjMatrix(Map nodeIndexMap){ + for (int i = 0; i < vertexList.size(); i++) { + Node currentNode = vertexList.get(i); + // 处理当前节点到后置节点的边 + if (currentNode.getRearModeList() != null && currentNode.getRearModeList().size() > 0){ + List rearModeList = currentNode.getRearModeList(); + for (DesignerShapeRelationModel rearModel : rearModeList) { + addEdge(i, nodeIndexMap.get(rearModel.getRelationFileId()).intValue()); + } + } + // 处理当前节点与前置节点的边 + if (currentNode.getLearModeList() != null && currentNode.getLearModeList().size() > 0){ + List learModeList = currentNode.getLearModeList(); + for (DesignerShapeRelationModel learModel : learModeList) { + addEdge(nodeIndexMap.get(learModel.getRelationFileId()).intValue(), i); + } + } + } + } + + // 输出邻接矩阵 + public void printAdjMatrix() { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < vertexList.size(); i++) { + for (int j = 0; j < vertexList.size(); j++) { + sb.append(adjMatrix[i][j]).append(" "); + } + sb.append("\n"); + } + System.out.println(sb.toString()); + } } diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphRender.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphRender.java new file mode 100644 index 00000000..216d5495 --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphRender.java @@ -0,0 +1,55 @@ +package com.actionsoft.apps.coe.method.process.subprocess.graph; + +import com.actionsoft.apps.coe.method.process.subprocess.constant.SubProcessConst; +import com.actionsoft.apps.coe.pal.pal.repository.designer.manage.CoeDesignerAPIManager; +import com.actionsoft.apps.coe.pal.pal.repository.designer.model.BaseModel; +import com.actionsoft.apps.coe.pal.pal.repository.designer.util.CoeDesignerUtil; +import com.actionsoft.apps.coe.pal.pal.repository.designer.util.ShapeUtil; +import com.actionsoft.bpms.util.UUIDGener; +import com.alibaba.fastjson.JSONObject; + +public class GraphRender { + + private final int numVertex; + private final double width; // 画布宽度 + private final double height; // 画布高度 + private final double shapeInterval = 80.0; // 图形节点在画布上的间隔 + private final double nodeW = 100.0; // 图形节点默认宽度 + private final double nodeH = 70.0; // 图形节点默认高度 + private final String definition; + private final String modelId; + + + public GraphRender(int numVertex, String modelId, String definition) { + this.numVertex = numVertex; + this.width = numVertex * (shapeInterval + nodeW); + this.height = numVertex * (shapeInterval + nodeH); + + this.definition = definition; + this.modelId = modelId; + } + + public void handleShapeNodeRender(double[][] position) { + JSONObject defineJsonObj = JSONObject.parseObject(definition); + JSONObject page = defineJsonObj.getJSONObject("page"); + page.put("width", width); + page.put("height", height); + JSONObject elements = defineJsonObj.getJSONObject("elements"); + for (int i = 0; i < numVertex; i++) { + JSONObject subProcessNode = ShapeUtil.getProcessShapeDefinition(SubProcessConst.SUB_PROCESS_METHOD_ID, "子流程"); + String nodeId = UUIDGener.getObjectId(); + subProcessNode.put("id", nodeId); + JSONObject subProcessNodeProps = subProcessNode.getJSONObject("props"); + subProcessNodeProps.put("x", position[i][0]); + subProcessNodeProps.put("y", position[i][1]); + elements.put(nodeId, subProcessNode); + } + defineJsonObj.put("elements",elements); + BaseModel model = CoeDesignerAPIManager.getInstance().getDefinition(modelId, 0); + if (model == null) { + model = CoeDesignerUtil.createModel(modelId, 0); + } + model.setDefinition(JSONObject.toJSONString(defineJsonObj)); + CoeDesignerAPIManager.getInstance().storeDefinition(model); + } +} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/VertexPreHandle.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/VertexPreHandle.java new file mode 100644 index 00000000..47ce10a5 --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/VertexPreHandle.java @@ -0,0 +1,65 @@ +package com.actionsoft.apps.coe.method.process.subprocess.graph; + +import com.actionsoft.apps.coe.method.process.subprocess.constant.SubProcessConst; +import com.actionsoft.apps.coe.method.process.subprocess.mode.Node; +import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.cache.DesignerShapeRelationCache; +import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.model.DesignerShapeRelationModel; +import com.actionsoft.exception.AWSException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 图模型节点预处理 + * 选择的若干子流程 其中某些子流程配置的上下游流程并不在所选的若干子流程中 + * 那么这些配置上的上下游流程怎么归属 + * 是包含进总图中还是排除掉 + * @author oYang + * @create 2023-05-12 15:30 + */ +public class VertexPreHandle { + + /** + * 包含进总图中 + * @param processIdList 选择的若干子流程ID + * @param nodeIndexMap 存放子流程在集合中的索引 + * @return + * @throws AWSException + */ + public List includeLearAndRearNode(List processIdList, Map nodeIndexMap) throws AWSException { + List nodeList = new ArrayList<>(); + + for (int i = 0; i < processIdList.size(); i++) { + Node node = new Node(processIdList.get(i)); + // 前置流程 + List learProcessList = DesignerShapeRelationCache.getByFileId(processIdList.get(i), SubProcessConst.LEAD_PROCESS_ATTR_ID); + learProcessList.stream().forEach(model -> { + if (!processIdList.contains(model.getRelationFileId())){ + Node learNode = new Node(model.getRelationFileId()); + nodeList.add(learNode); + nodeIndexMap.put(model.getRelationFileId(), nodeList.size() - 1); + } + }); + node.setLearModeList(learProcessList); + // 后置流程 + List rearProcessList = DesignerShapeRelationCache.getByFileId(processIdList.get(i), SubProcessConst.REAR_PROCESS_ATTR_ID); + rearProcessList.stream().forEach(model -> { + if (!processIdList.contains(model.getRelationFileId())){ + Node rearNode = new Node(model.getRelationFileId()); + nodeList.add(rearNode); + nodeIndexMap.put(model.getRelationFileId(), nodeList.size() - 1); + } + }); + node.setRearModeList(rearProcessList); + nodeList.add(node); + nodeIndexMap.put(node.getId(), nodeList.size() - 1); + } + return nodeList; + } + + @Deprecated + public void excludeLearAndRearNode(List processIdList) throws AWSException { + + } +} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/Node.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/Node.java index aae7675a..31820ea4 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/Node.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/Node.java @@ -1,5 +1,9 @@ package com.actionsoft.apps.coe.method.process.subprocess.mode; +import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.model.DesignerShapeRelationModel; + +import java.util.List; + /** * @author oYang * @create 2023-05-11 17:21 @@ -9,8 +13,10 @@ public class Node { private String id; private double x; private double y; - public double displaceX; // x方向移动位移 - public double displaceY; // y方向移动位移 + + private List learModeList; + private List rearModeList; + public Node(String id) { this.id = id; @@ -46,6 +52,23 @@ public class Node { this.y = y; } + public List getLearModeList() { + return learModeList; + } + + public void setLearModeList(List learModeList) { + this.learModeList = learModeList; + } + + public List getRearModeList() { + return rearModeList; + } + + public void setRearModeList(List rearModeList) { + this.rearModeList = rearModeList; + } + + @Override public String toString() { return "Node{" + diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/model/vo/SubProcessTagVo.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/vo/SubProcessTagVo.java similarity index 91% rename from com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/model/vo/SubProcessTagVo.java rename to com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/vo/SubProcessTagVo.java index e2373791..cd8ca501 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/model/vo/SubProcessTagVo.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/vo/SubProcessTagVo.java @@ -1,4 +1,4 @@ -package com.actionsoft.apps.coe.method.process.subprocess.model.vo; +package com.actionsoft.apps.coe.method.process.subprocess.mode.vo; /** * @author oYang diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/web/SubProcessWeb.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/web/SubProcessWeb.java index 5166f571..471c79b1 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/web/SubProcessWeb.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/web/SubProcessWeb.java @@ -1,19 +1,31 @@ package com.actionsoft.apps.coe.method.process.subprocess.web; import com.actionsoft.apps.coe.method.process.subprocess.constant.SubProcessConst; +import com.actionsoft.apps.coe.method.process.subprocess.graph.ForceDirectedGraphLayout; import com.actionsoft.apps.coe.method.process.subprocess.graph.GraphAdjMatrix; +import com.actionsoft.apps.coe.method.process.subprocess.graph.GraphRender; +import com.actionsoft.apps.coe.method.process.subprocess.graph.VertexPreHandle; import com.actionsoft.apps.coe.method.process.subprocess.mode.Node; -import com.actionsoft.apps.coe.method.process.subprocess.model.vo.SubProcessTagVo; +import com.actionsoft.apps.coe.method.process.subprocess.mode.vo.SubProcessTagVo; import com.actionsoft.apps.coe.pal.constant.CoEConstant; import com.actionsoft.apps.coe.pal.pal.repository.PALRepositoryQueryAPIManager; import com.actionsoft.apps.coe.pal.pal.repository.cache.PALRepositoryCache; +import com.actionsoft.apps.coe.pal.pal.repository.dao.CoeProcessLevelDaoFacotory; +import com.actionsoft.apps.coe.pal.pal.repository.dao.PALRepository; +import com.actionsoft.apps.coe.pal.pal.repository.designer.CoeDesignerShapeAPIManager; +import com.actionsoft.apps.coe.pal.pal.repository.designer.manage.CoeDesignerAPIManager; +import com.actionsoft.apps.coe.pal.pal.repository.designer.model.BaseModel; import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.cache.DesignerShapeRelationCache; import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.model.DesignerShapeRelationModel; +import com.actionsoft.apps.coe.pal.pal.repository.designer.util.CoeDesignerUtil; import com.actionsoft.apps.coe.pal.pal.repository.model.PALRepositoryModel; +import com.actionsoft.apps.coe.pal.pal.repository.model.impl.PALRepositoryModelImpl; +import com.actionsoft.apps.coe.pal.pal.repository.util.CoeProcessLevelUtil; import com.actionsoft.apps.coe.pal.pal.repository.web.CoeProcessLevelWeb; import com.actionsoft.bpms.commons.mvc.view.ActionWeb; import com.actionsoft.bpms.commons.mvc.view.ResponseObject; import com.actionsoft.bpms.server.UserContext; +import com.actionsoft.bpms.util.UUIDGener; import com.actionsoft.bpms.util.UtilString; import com.actionsoft.exception.AWSException; import com.actionsoft.i18n.I18nRes; @@ -22,6 +34,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import org.apache.commons.collections4.IteratorUtils; +import java.sql.Timestamp; import java.util.*; import java.util.stream.Collectors; @@ -46,11 +59,10 @@ public class SubProcessWeb extends ActionWeb { String[] locationIds = property.split("/"); StringBuffer dirName = new StringBuffer(I18nRes.findValue(CoEConstant.APP_ID, locationIds[0]) + "/"); - for (int i = 1; i < locationIds.length; i++) { - PALRepositoryModel model = PALRepositoryCache.getCache().get(locationIds[i]); - dirName.append(model.getName()).append("/"); - } - + PALRepositoryModel model = PALRepositoryCache.getCache().get(locationIds[1]); + if (model == null) + throw new AWSException("应用参数【" + SubProcessConst.SUB_PROCESS_MODEL_LOCATION + "】中配置的一级目录在当前资产库中不存在"); + dirName.append(model.getName()).append("/"); ResponseObject ro = ResponseObject.newOkResponse(); ro.put("dirRootName", dirName.toString()); ro.put("dirRootPath", property); @@ -198,35 +210,57 @@ public class SubProcessWeb extends ActionWeb { .filter(item -> { boolean flag = false; JSONObject model = (JSONObject) item; - return flag = "default".equals(model.getString("plMethodId")) || "".equals(model.getString("plMethodId")); + return flag = "default".equals(model.getString("plMethodId")) || "process.framework".equals(model.getString("plMethodId")); }).collect(Collectors.toCollection(JSONArray :: new)); return result; } - public void generatorEndToEndModel(String processIdJsonArr){ + public void generatorEndToEndModel(String processIdJsonArr, String locationId, String direction, String modelName) throws AWSException{ + if (UtilString.isEmpty(processIdJsonArr)) + throw new AWSException("参数异常"); List processIdList = JSONArray.parseArray(processIdJsonArr, String.class); - // 1.校验 - // 2.根据文件中前游流程与后游流程来确定关联关系 - GraphAdjMatrix graphAdjMatrix = new GraphAdjMatrix(processIdList.size()); - List nodeList = new ArrayList<>(); - for (String processId : processIdList) { - Node node = new Node(processId); - // 前置流程 - List learProcessList = DesignerShapeRelationCache.getByFileId(processId, SubProcessConst.LEAD_PROCESS_ATTR_ID); - // 后置流程 - List rearProcessList = DesignerShapeRelationCache.getByFileId(processId, SubProcessConst.REAR_PROCESS_ATTR_ID); + // 节点预处理 + Map nodeIndexMap = new HashMap<>(); + VertexPreHandle vertexPreHandle = new VertexPreHandle(); + List nodeList = vertexPreHandle.includeLearAndRearNode(processIdList, nodeIndexMap); - } + // 构建有向图邻接矩阵 + GraphAdjMatrix graphAdjMatrix = new GraphAdjMatrix(nodeList); + graphAdjMatrix.buildAdjMatrix(nodeIndexMap); + // graphAdjMatrix.printAdjMatrix(); - // 3.根据关联关系数据模型来决定分布位置 + // 获取节点分布 + ForceDirectedGraphLayout graphLayout = new ForceDirectedGraphLayout(graphAdjMatrix.getAdjMatrix()); + graphLayout.run(); + double[][] position = graphLayout.getPosition(); - // 3.1 每个子流程模型有一个 【子流程模型】的图形属性处理 + // 新建模型 + PALRepositoryModel parentModel = PALRepositoryCache.getCache().get(locationId); + PALRepository coeProcessLevel = CoeProcessLevelDaoFacotory.createCoeProcessLevel(); + Timestamp nowTime = new Timestamp(System.currentTimeMillis()); + String plRid = UUIDGener.getUUID(); + String id = UUIDGener.getUUID(); + int orderIndex = coeProcessLevel.getChildrenMaxOrderIndexByPidAndWsId(parentModel.getId(), parentModel.getWsId()) + 1; + PALRepositoryModelImpl model = CoeProcessLevelUtil.createPALRepositoryModel(id, plRid, parentModel.getWsId(), modelName, "", orderIndex, parentModel.getVersionId(), + SubProcessConst.SUB_PROCESS_CATEGORY, true, 1, id, false, SubProcessConst.SUB_PROCESS_METHOD_ID, "0", parentModel.getLevel() + 1, null, null, + uc.getUID(), uc.getUID(), nowTime, null, null, null, null, null, null, null, null, null,0); - // 4.在分布好的位置上根据关联关系数据模型连线 + CoeProcessLevelDaoFacotory.createCoeProcessLevel().insert(model); + BaseModel baseModel = CoeDesignerAPIManager.getInstance().getDefinition(model.getId(), 0); + if (baseModel == null) baseModel = CoeDesignerUtil.createModel(model.getId(), 0); + //获取流程定义和排序 + CoeDesignerShapeAPIManager manager = CoeDesignerShapeAPIManager.getInstance(); + JSONObject object = manager.getCoeDefinitionAndSort(baseModel.getDefinition(), parentModel.getWsId(), SubProcessConst.SUB_PROCESS_METHOD_ID); + //处理流程节点形状的通用配置 + JSONObject obj = manager.getCoeProcessShapeConfig(object.getString("define"), parentModel.getWsId(), SubProcessConst.SUB_PROCESS_METHOD_ID, model.getId()); + baseModel.setDefinition(obj.getString("define")); + // 节点渲染 + GraphRender graphRender = new GraphRender(nodeList.size(), model.getId(), baseModel.getDefinition()); + graphRender.handleShapeNodeRender(position); } } diff --git a/com.actionsoft.apps.coe.method.process.subprocess/web/com.actionsoft.apps.coe.method.process.subprocess/action.xml b/com.actionsoft.apps.coe.method.process.subprocess/web/com.actionsoft.apps.coe.method.process.subprocess/action.xml index 46184d28..61d310ce 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/web/com.actionsoft.apps.coe.method.process.subprocess/action.xml +++ b/com.actionsoft.apps.coe.method.process.subprocess/web/com.actionsoft.apps.coe.method.process.subprocess/action.xml @@ -17,4 +17,10 @@ + + + + + + \ No newline at end of file