端到端功能部分代码提交

This commit is contained in:
qinoy 2023-05-18 17:45:19 +08:00
parent 6ca569f7c0
commit 057c4762b8
11 changed files with 222 additions and 153 deletions

View File

@ -25,6 +25,6 @@
<requires/>
<palMethodIcon>{"process.epc":{"code": "&amp;#xe605;","color": "#4E7FF9"}}</palMethodIcon>
<properties>
<property action="disabled" group="功能入口相关" name="SUB_PROCESS_MODEL_LOCATION" title="端到端模型存放目录" type="input" isSystem="false" desc="指定生成的端到端模型存放的根目录&lt;br&gt;{资产库名称}/{根目录}/{一级目录} " ref="">伊利/流程制度/专门存放端到端总图</property>
<property action="disabled" group="功能入口相关" name="SUB_PROCESS_MODEL_LOCATION" title="端到端模型存放目录" type="input" isSystem="false" desc="指定生成的端到端模型存放的根目录&lt;br&gt;{资产库名称}/{根目录}/{一级目录} " ref="">伊利/流程制度/端到端流程</property>
</properties>
</app>

View File

@ -8,6 +8,7 @@ import com.actionsoft.bpms.server.bind.annotation.Controller;
import com.actionsoft.bpms.server.bind.annotation.Mapping;
import com.actionsoft.exception.AWSException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.List;
@ -103,9 +104,9 @@ public class SubProcessController {
public String vertexPreHandleIndependentNode(UserContext uc, String processIdJsonArr){
try {
SubProcessWeb processWeb = new SubProcessWeb(uc);
List<IndependentNodeVo> independentNodeVos = processWeb.vertexPreHandleIndependentNode(processIdJsonArr);
JSONObject data = processWeb.vertexPreHandleIndependentNode(processIdJsonArr);
ResponseObject ro = ResponseObject.newOkResponse();
ro.put("independentNodeVos",independentNodeVos);
ro.setData(data);
return ro.toString();
} catch (AWSException e) {
return ResponseObject.newErrResponse(e.getMessage()).toString();
@ -136,9 +137,9 @@ public class SubProcessController {
* @return
*/
@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){
public String generatorEndToEndModel(UserContext uc, String processIdJsonArr, String locationId, String direction, String modelName, String excludeProcessIdArr){
SubProcessWeb processWeb = new SubProcessWeb(uc);
processWeb.generatorEndToEndModel(processIdJsonArr, locationId, direction, modelName);
processWeb.generatorEndToEndModel(processIdJsonArr, locationId, direction, modelName, excludeProcessIdArr);
return ResponseObject.newOkResponse().toString();
}

View File

@ -75,23 +75,22 @@ public class GraphAdjMatrix {
/**
* 构建邻接矩阵
* @param nodeIndexMap 索引映射 节点ID与节点在列表中索引的映射关系
*/
public void buildAdjMatrix(Map<String, Integer> nodeIndexMap){
public void buildAdjMatrix(){
for (int i = 0; i < vertexList.size(); i++) {
Node currentNode = vertexList.get(i);
// 处理当前节点到后置节点的边
if (currentNode.getRearModeList() != null && currentNode.getRearModeList().size() > 0){
List<DesignerShapeRelationModel> rearModeList = currentNode.getRearModeList();
for (DesignerShapeRelationModel rearModel : rearModeList) {
addEdge(i, nodeIndexMap.get(rearModel.getRelationFileId()).intValue());
if (currentNode.getRearNodeList() != null && currentNode.getRearNodeList().size() > 0){
List<Node> rearNodeList = currentNode.getRearNodeList();
for (Node rearNode : rearNodeList) {
addEdge(i, vertexList.indexOf(rearNode));
}
}
// 处理当前节点与前置节点的边
if (currentNode.getLearModeList() != null && currentNode.getLearModeList().size() > 0){
List<DesignerShapeRelationModel> learModeList = currentNode.getLearModeList();
for (DesignerShapeRelationModel learModel : learModeList) {
addEdge(nodeIndexMap.get(learModel.getRelationFileId()).intValue(), i);
if (currentNode.getLeadNodeList() != null && currentNode.getLeadNodeList().size() > 0){
List<Node> leadNodeList = currentNode.getLeadNodeList();
for (Node leadNode : leadNodeList) {
addEdge(vertexList.indexOf(leadNode), i);
}
}
}

View File

@ -96,32 +96,32 @@ public class GraphLayout {
* 节点布局
*/
public double[][] layOut(){
double tempY = 0.0; // 记录第一列的高度
double realTimeY = 0.0; // 实时记录图形最高的Y
for (int i = 0; i < nodeList.size(); i++) {
// 第一个节点直接放到画布的左上角
if (i == 0) {
position[i][0] = 100.0;
position[i][1] = 100.0;
tempY = 100.0; // 更新第一列的高度
realTimeY = 100.0;
isPosition[i] = true;
if (existOutLink(i)){ // 如果存在后置节点 并且后置节点还未渲染
calculationRearNodePosition(i);
realTimeY = calculationRearNodePosition(i, realTimeY);
}
continue;
}
if (!isPosition[i]){
position[i][0] = 100.0;
position[i][1] = tempY + shapeH + vertInterval;
tempY = position[i][1]; // 更新第一列的高度
position[i][1] = realTimeY + shapeH + vertInterval;
realTimeY = position[i][1];
// 存在后置节点
if (existOutLink(i)){
calculationRearNodePosition(i);
realTimeY = calculationRearNodePosition(i, realTimeY);
}
}
}
// 确定画布的宽度与高度
double w = Arrays.stream(position).mapToDouble(position -> position[0]).max().getAsDouble();
double h = Arrays.stream(position).mapToDouble(position -> position[1]).max().getAsDouble();
double w = Arrays.stream(position).mapToDouble(position -> position[0]).max().orElse(0.0);
double h = Arrays.stream(position).mapToDouble(position -> position[1]).max().orElse(0.0);
this.canvasWidth = w + 200.0;
this.canvasHeight = h + 200.0;
@ -139,7 +139,7 @@ public class GraphLayout {
* 计算当前节点所有后置节点的位置
* @param nodeIndex
*/
private void calculationRearNodePosition(int nodeIndex){
private double calculationRearNodePosition(int nodeIndex, double realTimeY){
// 获取后置节点的索引
List<Integer> rearNodeIndexSet = getRearNodeIndex(nodeIndex);
for (int i = 0; i < rearNodeIndexSet.size(); i++) {
@ -149,15 +149,17 @@ public class GraphLayout {
if (i == 0) {
position[rearNodeIndex][1] = position[nodeIndex][1]; // 上一个节点的y坐标 第一个后置节点的y坐标一致
}else {
position[rearNodeIndex][1] = position[nodeIndex][1] + shapeH + i * vertInterval; // 非第一个后置节点的y坐标 = 上一个节点的y坐标 + 后置节点索引 * 垂直间隔
position[rearNodeIndex][1] = realTimeY + shapeH + i * vertInterval; // 非第一个后置节点的y坐标 = 上一个节点的y坐标 + 图形高度 + 后置节点索引 * 垂直间隔
realTimeY = position[rearNodeIndex][1];
}
isPosition[rearNodeIndex] = true;
if (existOutLink(rearNodeIndex)) {
calculationRearNodePosition(rearNodeIndex);
realTimeY = calculationRearNodePosition(rearNodeIndex, realTimeY);
}
}
}
return realTimeY;
}

View File

@ -0,0 +1,38 @@
package com.actionsoft.apps.coe.method.process.subprocess.graph;
import com.actionsoft.apps.coe.method.process.subprocess.mode.Node;
/**
* 图形节点连线渲染
*/
public class GraphLinkerRender {
private String linkerId;
private Node fromNode;
private Node toNode;
private double[] fromPoi;
private double[] toPoi;
private double[][] vertexPosition; // 所有节点的坐标
private String linkerDefine;
public GraphLinkerRender(double[][] vertexPosition) {
this.vertexPosition = vertexPosition;
}
/**
* 计算两个坐标之间的折点
* @param fromPoi
* @param toPoi
* @return
*/
private double[][] calculationTurningPoint(double[] fromPoi, double[] toPoi){
double fromX = fromPoi[0];
double fromY = fromPoi[1];
double toX = toPoi[0];
double toY = toPoi[1];
return new double[2][2];
}
}

View File

@ -11,9 +11,8 @@ import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.model.Design
import com.actionsoft.apps.coe.pal.pal.repository.model.PALRepositoryModel;
import com.actionsoft.exception.AWSException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
* 模型节点预处理
@ -31,78 +30,124 @@ public class VertexPreHandle {
/**
* 收集独立子流程
* 既没有前置也没有后置 同时也未被引用
* @param processIdList
* @return
* @throws AWSException
*/
public List<IndependentNodeVo> collectIndependentNode(List<String> processIdList) throws AWSException{
public Map<String, List<IndependentNodeVo>> collectIndependentNode(List<String> processIdList) throws AWSException{
List<IndependentNodeVo> independentNodeVos = new ArrayList<>();
List<IndependentNodeVo> nodeVoList = new ArrayList<>();
List<String> attrIdList = new ArrayList<>();
attrIdList.add(SubProcessConst.LEAD_PROCESS_ATTR_ID);
attrIdList.add(SubProcessConst.REAR_PROCESS_ATTR_ID);
for (String processId : processIdList) {
PALRepositoryModel repositoryModel = PALRepositoryCache.getCache().get(processId);
IndependentNodeVo independentNodeVo = new IndependentNodeVo(processId, repositoryModel.getName(), false);
// 1. 该子流程是否存在前置或后置流程
List<DesignerShapeRelationModel> leadProcessList = DesignerShapeRelationCache.getByFileId(processId, SubProcessConst.LEAD_PROCESS_ATTR_ID);
if (leadProcessList != null && leadProcessList.size() > 0) continue;
if (leadProcessList != null && leadProcessList.size() > 0) {
List<IndependentNodeVo> nodeVos = leadProcessList.stream().map(relationModel -> {
PALRepositoryModel model = PALRepositoryCache.getCache().get(relationModel.getRelationFileId());
IndependentNodeVo nodeVo = new IndependentNodeVo(relationModel.getRelationFileId(), model.getName());
return nodeVo;
}).collect(Collectors.toList());
independentNodeVo.setLeadNodeVo(nodeVos);
};
List<DesignerShapeRelationModel> rearProcessList = DesignerShapeRelationCache.getByFileId(processId, SubProcessConst.REAR_PROCESS_ATTR_ID);
if (rearProcessList != null && rearProcessList.size() > 0) continue;
if (rearProcessList != null && rearProcessList.size() > 0) {
List<IndependentNodeVo> nodeVos = rearProcessList.stream().map(relationModel -> {
PALRepositoryModel model = PALRepositoryCache.getCache().get(relationModel.getRelationFileId());
IndependentNodeVo nodeVo = new IndependentNodeVo(relationModel.getRelationFileId(), model.getName());
return nodeVo;
}).collect(Collectors.toList());
independentNodeVo.setRearNodeVo(nodeVos);
};
// 2. 该节点是否被别的节点
DesignerShapeRelationDao relationDao = new DesignerShapeRelationDao();
List<DesignerShapeRelationModel> relationModels = relationDao.getModelListByRelationFileIdAndAttrIds(processId, attrIdList);
if (relationModels != null && relationModels.size() > 0) continue;
if (relationModels != null && relationModels.size() > 0) {
independentNodeVo.setBeReference(true);
};
// 3. 收集独立节点信息返回给前台
PALRepositoryModel repositoryModel = PALRepositoryCache.getCache().get(processId);
IndependentNodeVo independentNodeVo = new IndependentNodeVo(processId, repositoryModel.getName());
independentNodeVos.add(independentNodeVo);
nodeVoList.add(independentNodeVo);
}
return independentNodeVos;
Map<String, List<IndependentNodeVo>> map = new HashMap<>();
List<IndependentNodeVo> independentNodeVos = new ArrayList<>();
List<IndependentNodeVo> leadAndRearNotInRange = new ArrayList<>();
for (IndependentNodeVo nodeVo : nodeVoList) {
if (nodeVo.isBeReference()) continue; // 被引用了 不管有没有前置或后置 都保留
if (nodeVo.getLeadNodeVo() == null && nodeVo.getRearNodeVo() == null && !nodeVo.isBeReference()){ // 完全独立
independentNodeVos.add(nodeVo);
continue;
}
List<IndependentNodeVo> leadNodeVos = nodeVo.getLeadNodeVo();
if (leadNodeVos != null && leadNodeVos.size() > 0){
List<String> nodeIds = leadNodeVos.stream().map(leadNodeVo -> leadNodeVo.getId()).collect(Collectors.toList());
if (!processIdList.containsAll(nodeIds)){
leadAndRearNotInRange.add(nodeVo);
continue;
}
}
List<IndependentNodeVo> rearNodeVos = nodeVo.getRearNodeVo();
if (rearNodeVos != null && rearNodeVos.size() > 0){
List<String> nodeIds = rearNodeVos.stream().map(rearNodeVo -> rearNodeVo.getId()).collect(Collectors.toList());
if (!processIdList.containsAll(nodeIds)){
leadAndRearNotInRange.add(nodeVo);
continue;
}
}
}
map.put("independentNodeVos", independentNodeVos);
map.put("leadAndRearNotInRange", leadAndRearNotInRange);
return map;
}
/**
* 包含进总图中
* @param processIdList 选择的若干子流程ID
* @param nodeIndexMap 存放子流程在集合中的索引
* @return
* 对于节点的前置或者后置流程
* 如果未在选择的范围内 则忽略
*
* 同时处理节点的前后置关系
* @param processIdList
* @param nodeIndexMap
* @return 按照节点前置流程数量 从小到大排序
* @throws AWSException
*/
public List<Node> includeLearAndRearNode(List<String> processIdList, Map<String, Integer> nodeIndexMap) throws AWSException {
public List<Node> excludeLearAndRearNode(List<String> processIdList, Map<String, Integer> nodeIndexMap) throws AWSException {
List<Node> nodeList = new ArrayList<>();
for (int i = 0; i < processIdList.size(); i++) {
Node node = new Node(processIdList.get(i));
// 前置流程
List<DesignerShapeRelationModel> 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);
List<DesignerShapeRelationModel> leadProcessList = DesignerShapeRelationCache.getByFileId(processIdList.get(i), SubProcessConst.LEAD_PROCESS_ATTR_ID);
List<Node> leadNodeList = new ArrayList<>();
leadProcessList.stream().forEach(model -> {
if (processIdList.contains(model.getRelationFileId())){
Node leadNode = new Node(model.getRelationFileId());
leadNodeList.add(leadNode);
}
});
node.setLearModeList(learProcessList);
node.setLeadNodeList(leadNodeList);
// 后置流程
List<DesignerShapeRelationModel> rearProcessList = DesignerShapeRelationCache.getByFileId(processIdList.get(i), SubProcessConst.REAR_PROCESS_ATTR_ID);
List<Node> rearNodeList = new ArrayList<>();
rearProcessList.stream().forEach(model -> {
if (!processIdList.contains(model.getRelationFileId())){
if (processIdList.contains(model.getRelationFileId())){
Node rearNode = new Node(model.getRelationFileId());
nodeList.add(rearNode);
nodeIndexMap.put(model.getRelationFileId(), nodeList.size() - 1);
rearNodeList.add(rearNode);
}
});
node.setRearModeList(rearProcessList);
node.setRearNodeList(rearNodeList);
nodeList.add(node);
nodeIndexMap.put(node.getId(), nodeList.size() - 1);
}
Collections.sort(nodeList);
return nodeList;
}
@Deprecated
public void excludeLearAndRearNode(List<String> processIdList) throws AWSException {
}
}

View File

@ -1,42 +1,23 @@
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;
import java.util.Objects;
/**
* @author oYang
* @create 2023-05-11 17:21
*/
public class Node {
public class Node implements Comparable<Node> {
private String id;
private double x;
private double y;
private double vx;
private double vy;
private List<DesignerShapeRelationModel> learModeList;
private List<DesignerShapeRelationModel> rearModeList;
private List<Node> leadNodeList;
private List<Node> rearNodeList;
public Node(String id) {
this.id = id;
}
public Node(String id, double x, double y) {
this.id = id;
this.x = x;
this.y = y;
}
public Node(String id, double x, double y, double vx, double vy) {
this.id = id;
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
}
public String getId() {
return id;
}
@ -45,61 +26,37 @@ public class Node {
this.id = id;
}
public double getX() {
return x;
public List<Node> getLeadNodeList() {
return leadNodeList;
}
public void setX(double x) {
this.x = x;
public void setLeadNodeList(List<Node> leadNodeList) {
this.leadNodeList = leadNodeList;
}
public double getY() {
return y;
public List<Node> getRearNodeList() {
return rearNodeList;
}
public void setY(double y) {
this.y = y;
}
public List<DesignerShapeRelationModel> getLearModeList() {
return learModeList;
}
public void setLearModeList(List<DesignerShapeRelationModel> learModeList) {
this.learModeList = learModeList;
}
public List<DesignerShapeRelationModel> getRearModeList() {
return rearModeList;
}
public void setRearModeList(List<DesignerShapeRelationModel> rearModeList) {
this.rearModeList = rearModeList;
}
public double getVx() {
return vx;
}
public void setVx(double vx) {
this.vx = vx;
}
public double getVy() {
return vy;
}
public void setVy(double vy) {
this.vy = vy;
public void setRearNodeList(List<Node> rearNodeList) {
this.rearNodeList = rearNodeList;
}
@Override
public String toString() {
return "Node{" +
"id='" + id + '\'' +
", x=" + x +
", y=" + y +
'}';
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node node = (Node) o;
return Objects.equals(id, node.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public int compareTo(Node node) {
return Integer.compare(this.leadNodeList.size(), node.getLeadNodeList().size());
}
}

View File

@ -1,5 +1,7 @@
package com.actionsoft.apps.coe.method.process.subprocess.mode.vo;
import java.util.List;
/**
* @author oYang
* @create 2023-05-17 15:13
@ -8,12 +10,23 @@ public class IndependentNodeVo {
private String id;
private String name;
private List<IndependentNodeVo> leadNodeVo;
private List<IndependentNodeVo> rearNodeVo;
private boolean isBeReference;
private String leadNodeNames;
private String rearNodeNames;
public IndependentNodeVo(String id, String name) {
this.id = id;
this.name = name;
}
public IndependentNodeVo(String id, String name, boolean isBeReference) {
this.id = id;
this.name = name;
this.isBeReference = isBeReference;
}
public String getId() {
return id;
}
@ -29,4 +42,28 @@ public class IndependentNodeVo {
public void setName(String name) {
this.name = name;
}
public List<IndependentNodeVo> getLeadNodeVo() {
return leadNodeVo;
}
public void setLeadNodeVo(List<IndependentNodeVo> leadNodeVo) {
this.leadNodeVo = leadNodeVo;
}
public List<IndependentNodeVo> getRearNodeVo() {
return rearNodeVo;
}
public void setRearNodeVo(List<IndependentNodeVo> rearNodeVo) {
this.rearNodeVo = rearNodeVo;
}
public boolean isBeReference() {
return isBeReference;
}
public void setBeReference(boolean beReference) {
isBeReference = beReference;
}
}

View File

@ -31,6 +31,7 @@ import com.actionsoft.bpms.util.UtilString;
import com.actionsoft.exception.AWSException;
import com.actionsoft.i18n.I18nRes;
import com.actionsoft.sdk.local.SDK;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections4.IteratorUtils;
@ -234,44 +235,32 @@ public class SubProcessWeb extends ActionWeb {
* @param processIdJsonArr
* @return
*/
public List<IndependentNodeVo> vertexPreHandleIndependentNode(String processIdJsonArr) throws AWSException{
public JSONObject vertexPreHandleIndependentNode(String processIdJsonArr) throws AWSException{
List<String> processIdList = JSONArray.parseArray(processIdJsonArr, String.class);
// 节点预处理
VertexPreHandle vertexPreHandle = new VertexPreHandle();
return vertexPreHandle.collectIndependentNode(processIdList);
return (JSONObject) JSON.toJSON(vertexPreHandle.collectIndependentNode(processIdList));
}
/**
* 生成图->前置处理
* 前置流程或后置流程是否在所选的范围内
* @param uc
* @param processIdJsonArr
* @param excludeProcessIdJsonArr
* @return
*/
public void vertexPreHandle2(String processIdJsonArr, String excludeProcessIdJsonArr){
public void generatorEndToEndModel(String processIdJsonArr, String locationId, String direction, String modelName, String excludeProcessIdArr) throws AWSException{
// 忽略独立的节点
List<String> processIdList = JSONArray.parseArray(processIdJsonArr, String.class);
List<String> excludeProcessIdList = JSONArray.parseArray(excludeProcessIdJsonArr, String.class);
List<String> excludeProcessIdList = JSONArray.parseArray(excludeProcessIdArr, String.class);
if (excludeProcessIdList != null && excludeProcessIdList.size() > 0) {
processIdList = processIdList.stream().filter(id -> !excludeProcessIdList.contains(id)).collect(Collectors.toList());
}
public void generatorEndToEndModel(String processIdJsonArr, String locationId, String direction, String modelName) throws AWSException{
List<String> processIdList = JSONArray.parseArray(processIdJsonArr, String.class);
// 节点预处理
VertexPreHandle vertexPreHandle = new VertexPreHandle();
Map<String, Integer> nodeIndexMap = new HashMap<>();
List<Node> nodeList = vertexPreHandle.includeLearAndRearNode(processIdList, nodeIndexMap);
List<Node> nodeList = vertexPreHandle.excludeLearAndRearNode(processIdList, nodeIndexMap);
// 构建有向图邻接矩阵
GraphAdjMatrix graphAdjMatrix = new GraphAdjMatrix(nodeList);
graphAdjMatrix.buildAdjMatrix(nodeIndexMap);
graphAdjMatrix.buildAdjMatrix();
graphAdjMatrix.printAdjMatrix();
// 获取节点分布

View File

@ -25,5 +25,6 @@
<param name="locationId"/>
<param name="direction"/>
<param name="modelName"/>
<param name="excludeProcessIdArr"/>
</cmd-bean>
</aws-actions>