diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction b/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction new file mode 100644 index 0000000..e4cd427 --- /dev/null +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction @@ -0,0 +1,8 @@ +business:计量检定业务模块 +equipment:设备与装置模块 +resource:资源管理模块 +quality:质量活动模块 +data:数据管理模块 +system:系统管理模块 +sys:基础包系统管理扩展 +flowable:工作流操作相关 \ No newline at end of file diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction b/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction new file mode 100644 index 0000000..e4cd427 --- /dev/null +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction @@ -0,0 +1,8 @@ +business:计量检定业务模块 +equipment:设备与装置模块 +resource:资源管理模块 +quality:质量活动模块 +data:数据管理模块 +system:系统管理模块 +sys:基础包系统管理扩展 +flowable:工作流操作相关 \ No newline at end of file diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java deleted file mode 100644 index 26d7da4..0000000 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ /dev/null @@ -1,530 +0,0 @@ -package com.casic.missiles.controller.flowable; - -import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.dto.ReturnUtil; -import com.casic.missiles.utils.SnowflakeUtil; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import io.swagger.annotations.Api; -import org.apache.commons.lang3.StringUtils; -import org.flowable.bpmn.BpmnAutoLayout; -import org.flowable.bpmn.converter.BpmnXMLConverter; -import org.flowable.bpmn.model.Process; -import org.flowable.bpmn.model.*; -import org.springframework.util.CollectionUtils; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import java.lang.reflect.InvocationTargetException; -import java.util.*; -import java.util.stream.Collectors; - - -/** - * @Description: 此Controller已废弃,已整合到流程管理中,此处仅作参考 - * @Author: wangpeng - * @Date: 2022/12/4 16:28 - */ -@Api("此Controller已废弃") -@RestController -@RequestMapping("/vue3") -public class JsonToBpmnController { - - @Resource - private SnowflakeUtil snowflakeUtil; - - /** - * 保存流程定义,流程实例中才要传业务表id - */ - @PostMapping("/jsonToBpmn") - public Object saveForm(@RequestBody JSONObject jsonObject) throws InvocationTargetException, IllegalAccessException { - System.err.println(jsonObject.toJSONString()); - //bpmn对象(可与xml相互转化) - BpmnModel bpmnModel = new BpmnModel(); - //流程定义对象 - Process process = new Process(); - //添加流程定义到bpmn对象 - bpmnModel.addProcess(process); - //流程中连线 - List sequenceFlows = Lists.newArrayList(); - //流程定义-添加流程id - process.setId("flowableV2_" + snowflakeUtil.nextId()); - //启动事件 - StartEvent startEvent = createStartEvent(); - //流程定义-添加启动事件 - process.addFlowElement(startEvent); - //获取json实体 - JSONObject workFlowObj = jsonObject.getJSONObject("_value"); - String name = workFlowObj.getJSONObject("workFlowDef").getString("name"); - //流程定义-添加流程名称 - process.setName(name); - //流程定义-添加扩展属性 - ExtensionAttribute extensionAttribute = new ExtensionAttribute(); - extensionAttribute.setName("Casic"); - extensionAttribute.setNamespace("http://flowable.org/bpmn"); - extensionAttribute.setValue(jsonObject.toJSONString()); - process.addAttribute(extensionAttribute); - //流程定义-添加节点 - JSONObject processNodes = workFlowObj.getJSONObject("nodeConfig"); - String lastNode = create(startEvent.getId(), processNodes, bpmnModel, process, sequenceFlows); - EndEvent endEvent = createEndEvent(); - process.addFlowElement(endEvent); - process.addFlowElement(connect(lastNode, endEvent.getId(), sequenceFlows)); - - new BpmnAutoLayout(bpmnModel).execute(); - System.err.println(new String(new BpmnXMLConverter().convertToXML(bpmnModel))); - return ReturnUtil.success("保存成功"); - } - - /** - * 方法功能:根据上个节点id及本节点信息生成本节点 - * @param fromId:启动事件id - * @param flowNode:所有节点树形结构 - * @param model:bpmn对象(最终要得到的结果) - * @param process:流程定义 - * @param sequenceFlows:连线列表 - */ - private static String create(String fromId, JSONObject flowNode, BpmnModel model, Process process, List sequenceFlows) throws InvocationTargetException, IllegalAccessException { - //获取节点类型,0 发起人 1审批 2抄送 3条件 4路由 - Integer nodeType = flowNode.getInteger("type"); - //节点类型-并行网关 - if (Type.PARALLEL.type.equals(nodeType)) { - return createParallelGatewayBuilder(fromId, flowNode, model, process, sequenceFlows); - } - //节点类型-路由 - else if (Type.ROUTER.type.equals(nodeType)) { - return createExclusiveGatewayBuilder(fromId, flowNode, model, process, sequenceFlows); - } - //节点类型-发起人(根节点) - else if (Type.ROOT.type.equals(nodeType)) { - //添加incoming属性(表示进来的,即上面流程节点的id列表),值为仅一个启动事件id的列表 - flowNode.put("incoming", Collections.singletonList(fromId)); - String id = createTask(flowNode, process, sequenceFlows); - - // 如果当前任务还有后续任务,则遍历创建后续任务 - JSONObject nextNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(nextNode)) { - FlowElement flowElement = model.getFlowElement(id); - return create(id, nextNode, model, process, sequenceFlows); - } else { - return id; - } - } - //节点类型-抄送任务 - else if (Type.CC.type.equals(nodeType)) { - flowNode.put("incoming", Collections.singletonList(fromId)); - String id = createServiceTask(flowNode, process, sequenceFlows); - - // 如果当前任务还有后续任务,则遍历创建后续任务 - JSONObject nextNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(nextNode)) { - FlowElement flowElement = model.getFlowElement(id); - return create(id, nextNode, model, process, sequenceFlows); - } else { - return id; - } - } - //节点类型-用户审批任务 - else if (Type.USER_TASK.type.equals(nodeType)) { - flowNode.put("incoming", Collections.singletonList(fromId)); - String id = createTask(flowNode, process, sequenceFlows); - - // 如果当前任务还有后续任务,则遍历创建后续任务 - JSONObject nextNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(nextNode)) { - FlowElement flowElement = model.getFlowElement(id); - return create(id, nextNode, model, process, sequenceFlows); - } else { - return id; - } - } else { - throw new RuntimeException("未知节点类型: nodeType=" + nodeType); - } - } - - /** - * 排他网关分支上有条件设置 - * @param formId - * @param flowNode - * @param model - * @param process - * @param sequenceFlows - * @return 返回创建的节点的id标识 - */ - private static String createExclusiveGatewayBuilder(String formId, JSONObject flowNode, BpmnModel model, Process process, List sequenceFlows) throws InvocationTargetException, IllegalAccessException { - String name = flowNode.getString("nodeName"); - String exclusiveGatewayId = id("exclusiveGateway"); - ExclusiveGateway exclusiveGateway = new ExclusiveGateway(); - exclusiveGateway.setId(exclusiveGatewayId); - exclusiveGateway.setName(name); - process.addFlowElement(exclusiveGateway); - process.addFlowElement(connect(formId, exclusiveGatewayId, sequenceFlows)); - - if (Objects.isNull(flowNode.getJSONArray("conditionNodes")) && Objects.isNull(flowNode.getJSONObject("childNode"))) { - return exclusiveGatewayId; - } - List flowNodes = Optional.ofNullable(flowNode.getJSONArray("conditionNodes")).map(e -> e.toJavaList(JSONObject.class)).orElse(Collections.emptyList()); - List incoming = Lists.newArrayListWithCapacity(flowNodes.size()); - - List conditions = Lists.newCopyOnWriteArrayList(); - ///为每个排他网关的条件节点的子节点添加后续节点(相比于并行网关多了连线的条件表达式设置) - for (JSONObject element : flowNodes) { - //一个分支的子节点 - JSONObject childNode = element.getJSONObject("childNode"); - //一个分支的名字和表达式 - String nodeName = element.getString("nodeName"); - String expression = element.getString("conditionExpression"); - - if (Objects.isNull(childNode)) { - //条件节点下无子节点,设置后续节点的fromId为exclusiveGatewayId(即排他网关的id,多个分支的排他网关id相同,名字和表达式不同) - incoming.add(exclusiveGatewayId); - JSONObject condition = new JSONObject(); - condition.fluentPut("nodeName", nodeName) - .fluentPut("expression", expression); - conditions.add(condition); - continue; - } - // 只生成一个任务,同时设置当前任务的条件 - childNode.put("incoming", Collections.singletonList(exclusiveGatewayId)); - String identifier = create(exclusiveGatewayId, childNode, model, process, sequenceFlows); - //连线列表中前一个节点是exclusiveGatewayId的连线,给每个连线设置名称和表达式 - //使用forEach是因为前一个节点是exclusiveGatewayId的节点有很多,需要遍历为没赋值过的赋值 - List flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(exclusiveGatewayId, flow.getSourceRef())) - .collect(Collectors.toList()); - flows.stream().forEach( - e -> { - //设置连线名为条件节点名 - if (StringUtils.isBlank(e.getName()) && StringUtils.isNotBlank(nodeName)) { - e.setName(nodeName); - } - // 设置条件表达式 - if (Objects.isNull(e.getConditionExpression()) && StringUtils.isNotBlank(expression)) { - e.setConditionExpression(expression); - } - } - ); - if (Objects.nonNull(identifier)) { - incoming.add(identifier); - } - } - //当前网关节点的子节点(整个排他网关的子节点) - JSONObject childNode = flowNode.getJSONObject("childNode"); - - if (Objects.nonNull(childNode)) { - //有条件分支但无条件节点对应的子节点 - if (incoming == null || incoming.isEmpty()) { - return create(exclusiveGatewayId, childNode, model, process, sequenceFlows); - } else { - // 所有 service task 连接 end exclusive gateway - //条件分支汇合到下面的childNode节点 - childNode.put("incoming", incoming); - FlowElement flowElement = model.getFlowElement(incoming.get(0)); - // 1.0 先进行边连接, 暂存 nextNode - JSONObject nextNode = childNode.getJSONObject("childNode"); - String endExId = id("exclusiveGateway") + "end"; - process.addFlowElement(createExclusiveGateWayEnd(endExId)); - childNode.put("childNode", null); - String identifier = endExId; - for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 - // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId - process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); - } - - // 针对 gateway 空任务分支 添加条件表达式,即条件节点下无子节点的情况 - if (!conditions.isEmpty()) { - FlowElement flowElement1 = model.getFlowElement(identifier); - // 获取从 gateway 到目标节点 未设置条件表达式的节点 - List flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(flowElement1.getId(), flow.getTargetRef())) - .filter(flow -> StringUtils.equals(flow.getSourceRef(), exclusiveGatewayId)) - .collect(Collectors.toList()); - //顺序无所谓,都是分支上一个条件的分支 - flows.stream().forEach(sequenceFlow -> { - if (!conditions.isEmpty()) { - JSONObject condition = conditions.get(0); - String nodeName = condition.getString("nodeName"); - String expression = condition.getString("expression"); - - if (StringUtils.isBlank(sequenceFlow.getName()) && StringUtils.isNotBlank(nodeName)) { - sequenceFlow.setName(nodeName); - } - // 设置条件表达式 - if (Objects.isNull(sequenceFlow.getConditionExpression()) && StringUtils.isNotBlank(expression)) { - sequenceFlow.setConditionExpression(expression); - } - - conditions.remove(0); - } - }); - - } - - // 1.1 边连接完成后,在进行 nextNode 创建 - if (Objects.nonNull(childNode)) { - return create(endExId, childNode, model, process, sequenceFlows); - } else { - return endExId; - } - } - } else { - // 所有 service task 连接 end exclusive gateway - // 1.0 先进行边连接, 暂存 nextNode - String endExId = id("exclusiveGateway") + "end"; - process.addFlowElement(createExclusiveGateWayEnd(endExId)); - String identifier = endExId; - //其他条件分支和第一个条件分支连线的终点节点相同 - for (int i = 0; i < incoming.size(); i++) { - process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); - } - - // 针对 gateway 空任务分支 添加条件表达式,即条件节点下无子节点的情况 - if (!conditions.isEmpty()) { - FlowElement flowElement1 = model.getFlowElement(identifier); - // 获取从 gateway 到目标节点 未设置条件表达式的节点 - List flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(flowElement1.getId(), flow.getTargetRef())) - .filter(flow -> StringUtils.equals(flow.getSourceRef(), exclusiveGatewayId)) - .collect(Collectors.toList()); - flows.stream().forEach(sequenceFlow -> { - if (!conditions.isEmpty()) { - JSONObject condition = conditions.get(0); - String nodeName = condition.getString("nodeName"); - String expression = condition.getString("expression"); - - if (StringUtils.isBlank(sequenceFlow.getName()) && StringUtils.isNotBlank(nodeName)) { - sequenceFlow.setName(nodeName); - } - // 设置条件表达式 - if (Objects.isNull(sequenceFlow.getConditionExpression()) && StringUtils.isNotBlank(expression)) { - sequenceFlow.setConditionExpression(expression); - } - - conditions.remove(0); - } - }); - - } - return endExId; - } -// return exclusiveGatewayId; - } - - /** - * 并行网关分支上无条件设置 - * @param formId - * @param flowNode - * @param model - * @param process - * @param sequenceFlows - * @return 返回创建的节点的id标识 - */ - private static String createParallelGatewayBuilder(String formId, JSONObject flowNode, BpmnModel model, Process process, List sequenceFlows) throws InvocationTargetException, IllegalAccessException { - //并行网关节点名 - String name = flowNode.getString("nodeName"); - ParallelGateway parallelGateway = new ParallelGateway(); - String parallelGatewayId = id("parallelGateway"); - parallelGateway.setId(parallelGatewayId); - parallelGateway.setName(name); - process.addFlowElement(parallelGateway); - //与上个节点的连线 - process.addFlowElement(connect(formId, parallelGatewayId, sequenceFlows)); - //1、无条件节点和子节点 - if (Objects.isNull(flowNode.getJSONArray("conditionNodes")) && Objects.isNull(flowNode.getJSONObject("childNode"))) { - return parallelGatewayId; - } - //2、有条件节点或子节点 - //获取条件节点 - List flowNodes = Optional.ofNullable(flowNode.getJSONArray("conditionNodes")).map(e -> e.toJavaList(JSONObject.class)).orElse(Collections.emptyList()); - //每个分支上的最后节点的标识id,用于给整个并行网关的子节点提供fromId - List incoming = Lists.newArrayListWithCapacity(flowNodes.size()); - //为每个并行网关的条件节点的子节点添加后续节点 - for (JSONObject element : flowNodes) { - JSONObject childNode = element.getJSONObject("childNode"); - if (Objects.isNull(childNode)) { - incoming.add(parallelGatewayId); - continue; - } - String identifier = create(parallelGatewayId, childNode, model, process, sequenceFlows); - if (Objects.nonNull(identifier)) { - incoming.add(identifier); - } - } - //当前网关节点的子节点(整个并行网关的子节点) - JSONObject childNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(childNode)) { - // 普通结束网关 - //有并行分支但无条件节点对应的子节点 - if (CollectionUtils.isEmpty(incoming)) { - return create(parallelGatewayId, childNode, model, process, sequenceFlows); - } else { - // 所有 service task 连接 end parallel gateway - //并行分支汇合到下面的childNode节点 - childNode.put("incoming", incoming); - FlowElement flowElement = model.getFlowElement(incoming.get(0)); - // 1.0 先进行线连接, 暂存 nextNode - JSONObject nextNode = childNode.getJSONObject("childNode"); - childNode.put("childNode", null); - String identifier = create(incoming.get(0), childNode, model, process, sequenceFlows); - //其他并行分支和第一个并行分支连线的终点节点相同 - for (int i = 1; i < incoming.size(); i++) { - FlowElement flowElement1 = model.getFlowElement(incoming.get(i)); - process.addFlowElement(connect(flowElement1.getId(), identifier, sequenceFlows)); - } - // 1.1 线连接完成后,再进行 nextNode 创建 - if (Objects.nonNull(nextNode)) { - return create(identifier, nextNode, model, process, sequenceFlows); - } else { - return identifier; - } - } - } - return parallelGatewayId; - } - - //流转到服务任务(serviceTask)节点时会自动执行某些操作然后向下流转 - private static String createServiceTask(JSONObject flowNode, Process process, List sequenceFlows) { - List incoming = flowNode.getJSONArray("incoming").toJavaList(String.class); - // 自动生成id - String id = id("serviceTask"); - if (incoming != null && !incoming.isEmpty()) { - ServiceTask serviceTask = new ServiceTask(); - serviceTask.setName(flowNode.getString("nodeName")); - serviceTask.setId(id); - process.addFlowElement(serviceTask); - process.addFlowElement(connect(incoming.get(0), id, sequenceFlows)); - } - return id; - } - - private static String createTask(JSONObject flowNode, Process process, List sequenceFlows) { - List incoming = flowNode.getJSONArray("incoming").toJavaList(String.class); - // 自动生成id - String id = id("userTask"); - if (incoming != null && !incoming.isEmpty()) { - UserTask userTask = new UserTask(); - userTask.setName(flowNode.getString("nodeName")); - userTask.setId(id); - process.addFlowElement(userTask); - //根节点 - if (Type.ROOT.type.equals(flowNode.getInteger("type"))) { - - } - //用户审批任务节点 - else { - //多实例,在业务流程中,为特定步骤定义重复的方式 - MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics(); - String examineMode = flowNode.getString("examineMode"); - // 审批人集合参数 - multiInstanceLoopCharacteristics.setInputDataItem(userTask.getId() + "assigneeList"); - // 迭代集合 - multiInstanceLoopCharacteristics.setElementVariable("assigneeName"); - // 并行 - multiInstanceLoopCharacteristics.setSequential(false); - userTask.setAssignee("${assigneeName}"); - // 设置多实例属性 - userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics); - //多人审批时采用的审批方式 1依次会签 2并行会签 3或签 - //默认并行会签 - if ("1".equals(examineMode)) { - multiInstanceLoopCharacteristics.setSequential(true); - } else if ("3".equals(examineMode)) { - //或签,即设置完成条件nrOfCompletedInstances/nrOfInstances > 0 - //nrOfCompletedInstances:已完成的实例数量,nrOfInstances:实例总数 - multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances/nrOfInstances > 0}"); - } - } - process.addFlowElement(connect(incoming.get(0), id, sequenceFlows)); - } - return id; - } - - private enum Type { - //0 发起人 1审批 2抄送 3条件 4路由 - ROOT(0, UserTask.class), - ROUTER(4, ExclusiveGateway.class), - PARALLEL(5, ParallelGateway.class), - - /** - * 排他事件 - */ -// EXCLUSIVE(4, ExclusiveGateway.class), - - /** - * 任务 - */ - USER_TASK(1, UserTask.class), - CC(2, ServiceTask.class); - - private Integer type; - - private Class typeClass; - - Type(Integer type, Class typeClass) { - this.type = type; - this.typeClass = typeClass; - } - - public final static Map> TYPE_MAP = Maps.newHashMap(); - - static { - for (Type element : Type.values()) { - TYPE_MAP.put(element.type, element.typeClass); - } - } - - public boolean isEqual(String type) { - return this.type.equals(type); - } - - } - - - private static String id(String prefix) { - return prefix + "_" + UUID.randomUUID().toString().replace("-", "").toLowerCase(); - } - - private static ServiceTask serviceTask(String name) { - ServiceTask serviceTask = new ServiceTask(); - serviceTask.setName(name); - return serviceTask; - } - - /** - * 新建连线实体加入连线列表 - */ - protected static SequenceFlow connect(String from, String to, List sequenceFlows) { - SequenceFlow flow = new SequenceFlow(); - flow.setId(id("sequenceFlow")); - flow.setSourceRef(from); - flow.setTargetRef(to); - sequenceFlows.add(flow); - return flow; - } - - protected static StartEvent createStartEvent() { - StartEvent startEvent = new StartEvent(); - startEvent.setId(id("start")); - startEvent.setInitiator("applyUserId"); - return startEvent; - } - - protected static EndEvent createEndEvent() { - EndEvent endEvent = new EndEvent(); - endEvent.setId(id("end")); - return endEvent; - } - - public static ExclusiveGateway createExclusiveGateWayEnd(String id) { - ExclusiveGateway exclusiveGateway = new ExclusiveGateway(); - exclusiveGateway.setId(id); - return exclusiveGateway; - } - - private static ParallelGateway createParallelGateWayEnd(String id) { - ParallelGateway parallelGateway = new ParallelGateway(); - parallelGateway.setId(id); - return parallelGateway; - } -} diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction b/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction new file mode 100644 index 0000000..e4cd427 --- /dev/null +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction @@ -0,0 +1,8 @@ +business:计量检定业务模块 +equipment:设备与装置模块 +resource:资源管理模块 +quality:质量活动模块 +data:数据管理模块 +system:系统管理模块 +sys:基础包系统管理扩展 +flowable:工作流操作相关 \ No newline at end of file diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java deleted file mode 100644 index 26d7da4..0000000 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ /dev/null @@ -1,530 +0,0 @@ -package com.casic.missiles.controller.flowable; - -import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.dto.ReturnUtil; -import com.casic.missiles.utils.SnowflakeUtil; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import io.swagger.annotations.Api; -import org.apache.commons.lang3.StringUtils; -import org.flowable.bpmn.BpmnAutoLayout; -import org.flowable.bpmn.converter.BpmnXMLConverter; -import org.flowable.bpmn.model.Process; -import org.flowable.bpmn.model.*; -import org.springframework.util.CollectionUtils; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import java.lang.reflect.InvocationTargetException; -import java.util.*; -import java.util.stream.Collectors; - - -/** - * @Description: 此Controller已废弃,已整合到流程管理中,此处仅作参考 - * @Author: wangpeng - * @Date: 2022/12/4 16:28 - */ -@Api("此Controller已废弃") -@RestController -@RequestMapping("/vue3") -public class JsonToBpmnController { - - @Resource - private SnowflakeUtil snowflakeUtil; - - /** - * 保存流程定义,流程实例中才要传业务表id - */ - @PostMapping("/jsonToBpmn") - public Object saveForm(@RequestBody JSONObject jsonObject) throws InvocationTargetException, IllegalAccessException { - System.err.println(jsonObject.toJSONString()); - //bpmn对象(可与xml相互转化) - BpmnModel bpmnModel = new BpmnModel(); - //流程定义对象 - Process process = new Process(); - //添加流程定义到bpmn对象 - bpmnModel.addProcess(process); - //流程中连线 - List sequenceFlows = Lists.newArrayList(); - //流程定义-添加流程id - process.setId("flowableV2_" + snowflakeUtil.nextId()); - //启动事件 - StartEvent startEvent = createStartEvent(); - //流程定义-添加启动事件 - process.addFlowElement(startEvent); - //获取json实体 - JSONObject workFlowObj = jsonObject.getJSONObject("_value"); - String name = workFlowObj.getJSONObject("workFlowDef").getString("name"); - //流程定义-添加流程名称 - process.setName(name); - //流程定义-添加扩展属性 - ExtensionAttribute extensionAttribute = new ExtensionAttribute(); - extensionAttribute.setName("Casic"); - extensionAttribute.setNamespace("http://flowable.org/bpmn"); - extensionAttribute.setValue(jsonObject.toJSONString()); - process.addAttribute(extensionAttribute); - //流程定义-添加节点 - JSONObject processNodes = workFlowObj.getJSONObject("nodeConfig"); - String lastNode = create(startEvent.getId(), processNodes, bpmnModel, process, sequenceFlows); - EndEvent endEvent = createEndEvent(); - process.addFlowElement(endEvent); - process.addFlowElement(connect(lastNode, endEvent.getId(), sequenceFlows)); - - new BpmnAutoLayout(bpmnModel).execute(); - System.err.println(new String(new BpmnXMLConverter().convertToXML(bpmnModel))); - return ReturnUtil.success("保存成功"); - } - - /** - * 方法功能:根据上个节点id及本节点信息生成本节点 - * @param fromId:启动事件id - * @param flowNode:所有节点树形结构 - * @param model:bpmn对象(最终要得到的结果) - * @param process:流程定义 - * @param sequenceFlows:连线列表 - */ - private static String create(String fromId, JSONObject flowNode, BpmnModel model, Process process, List sequenceFlows) throws InvocationTargetException, IllegalAccessException { - //获取节点类型,0 发起人 1审批 2抄送 3条件 4路由 - Integer nodeType = flowNode.getInteger("type"); - //节点类型-并行网关 - if (Type.PARALLEL.type.equals(nodeType)) { - return createParallelGatewayBuilder(fromId, flowNode, model, process, sequenceFlows); - } - //节点类型-路由 - else if (Type.ROUTER.type.equals(nodeType)) { - return createExclusiveGatewayBuilder(fromId, flowNode, model, process, sequenceFlows); - } - //节点类型-发起人(根节点) - else if (Type.ROOT.type.equals(nodeType)) { - //添加incoming属性(表示进来的,即上面流程节点的id列表),值为仅一个启动事件id的列表 - flowNode.put("incoming", Collections.singletonList(fromId)); - String id = createTask(flowNode, process, sequenceFlows); - - // 如果当前任务还有后续任务,则遍历创建后续任务 - JSONObject nextNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(nextNode)) { - FlowElement flowElement = model.getFlowElement(id); - return create(id, nextNode, model, process, sequenceFlows); - } else { - return id; - } - } - //节点类型-抄送任务 - else if (Type.CC.type.equals(nodeType)) { - flowNode.put("incoming", Collections.singletonList(fromId)); - String id = createServiceTask(flowNode, process, sequenceFlows); - - // 如果当前任务还有后续任务,则遍历创建后续任务 - JSONObject nextNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(nextNode)) { - FlowElement flowElement = model.getFlowElement(id); - return create(id, nextNode, model, process, sequenceFlows); - } else { - return id; - } - } - //节点类型-用户审批任务 - else if (Type.USER_TASK.type.equals(nodeType)) { - flowNode.put("incoming", Collections.singletonList(fromId)); - String id = createTask(flowNode, process, sequenceFlows); - - // 如果当前任务还有后续任务,则遍历创建后续任务 - JSONObject nextNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(nextNode)) { - FlowElement flowElement = model.getFlowElement(id); - return create(id, nextNode, model, process, sequenceFlows); - } else { - return id; - } - } else { - throw new RuntimeException("未知节点类型: nodeType=" + nodeType); - } - } - - /** - * 排他网关分支上有条件设置 - * @param formId - * @param flowNode - * @param model - * @param process - * @param sequenceFlows - * @return 返回创建的节点的id标识 - */ - private static String createExclusiveGatewayBuilder(String formId, JSONObject flowNode, BpmnModel model, Process process, List sequenceFlows) throws InvocationTargetException, IllegalAccessException { - String name = flowNode.getString("nodeName"); - String exclusiveGatewayId = id("exclusiveGateway"); - ExclusiveGateway exclusiveGateway = new ExclusiveGateway(); - exclusiveGateway.setId(exclusiveGatewayId); - exclusiveGateway.setName(name); - process.addFlowElement(exclusiveGateway); - process.addFlowElement(connect(formId, exclusiveGatewayId, sequenceFlows)); - - if (Objects.isNull(flowNode.getJSONArray("conditionNodes")) && Objects.isNull(flowNode.getJSONObject("childNode"))) { - return exclusiveGatewayId; - } - List flowNodes = Optional.ofNullable(flowNode.getJSONArray("conditionNodes")).map(e -> e.toJavaList(JSONObject.class)).orElse(Collections.emptyList()); - List incoming = Lists.newArrayListWithCapacity(flowNodes.size()); - - List conditions = Lists.newCopyOnWriteArrayList(); - ///为每个排他网关的条件节点的子节点添加后续节点(相比于并行网关多了连线的条件表达式设置) - for (JSONObject element : flowNodes) { - //一个分支的子节点 - JSONObject childNode = element.getJSONObject("childNode"); - //一个分支的名字和表达式 - String nodeName = element.getString("nodeName"); - String expression = element.getString("conditionExpression"); - - if (Objects.isNull(childNode)) { - //条件节点下无子节点,设置后续节点的fromId为exclusiveGatewayId(即排他网关的id,多个分支的排他网关id相同,名字和表达式不同) - incoming.add(exclusiveGatewayId); - JSONObject condition = new JSONObject(); - condition.fluentPut("nodeName", nodeName) - .fluentPut("expression", expression); - conditions.add(condition); - continue; - } - // 只生成一个任务,同时设置当前任务的条件 - childNode.put("incoming", Collections.singletonList(exclusiveGatewayId)); - String identifier = create(exclusiveGatewayId, childNode, model, process, sequenceFlows); - //连线列表中前一个节点是exclusiveGatewayId的连线,给每个连线设置名称和表达式 - //使用forEach是因为前一个节点是exclusiveGatewayId的节点有很多,需要遍历为没赋值过的赋值 - List flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(exclusiveGatewayId, flow.getSourceRef())) - .collect(Collectors.toList()); - flows.stream().forEach( - e -> { - //设置连线名为条件节点名 - if (StringUtils.isBlank(e.getName()) && StringUtils.isNotBlank(nodeName)) { - e.setName(nodeName); - } - // 设置条件表达式 - if (Objects.isNull(e.getConditionExpression()) && StringUtils.isNotBlank(expression)) { - e.setConditionExpression(expression); - } - } - ); - if (Objects.nonNull(identifier)) { - incoming.add(identifier); - } - } - //当前网关节点的子节点(整个排他网关的子节点) - JSONObject childNode = flowNode.getJSONObject("childNode"); - - if (Objects.nonNull(childNode)) { - //有条件分支但无条件节点对应的子节点 - if (incoming == null || incoming.isEmpty()) { - return create(exclusiveGatewayId, childNode, model, process, sequenceFlows); - } else { - // 所有 service task 连接 end exclusive gateway - //条件分支汇合到下面的childNode节点 - childNode.put("incoming", incoming); - FlowElement flowElement = model.getFlowElement(incoming.get(0)); - // 1.0 先进行边连接, 暂存 nextNode - JSONObject nextNode = childNode.getJSONObject("childNode"); - String endExId = id("exclusiveGateway") + "end"; - process.addFlowElement(createExclusiveGateWayEnd(endExId)); - childNode.put("childNode", null); - String identifier = endExId; - for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 - // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId - process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); - } - - // 针对 gateway 空任务分支 添加条件表达式,即条件节点下无子节点的情况 - if (!conditions.isEmpty()) { - FlowElement flowElement1 = model.getFlowElement(identifier); - // 获取从 gateway 到目标节点 未设置条件表达式的节点 - List flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(flowElement1.getId(), flow.getTargetRef())) - .filter(flow -> StringUtils.equals(flow.getSourceRef(), exclusiveGatewayId)) - .collect(Collectors.toList()); - //顺序无所谓,都是分支上一个条件的分支 - flows.stream().forEach(sequenceFlow -> { - if (!conditions.isEmpty()) { - JSONObject condition = conditions.get(0); - String nodeName = condition.getString("nodeName"); - String expression = condition.getString("expression"); - - if (StringUtils.isBlank(sequenceFlow.getName()) && StringUtils.isNotBlank(nodeName)) { - sequenceFlow.setName(nodeName); - } - // 设置条件表达式 - if (Objects.isNull(sequenceFlow.getConditionExpression()) && StringUtils.isNotBlank(expression)) { - sequenceFlow.setConditionExpression(expression); - } - - conditions.remove(0); - } - }); - - } - - // 1.1 边连接完成后,在进行 nextNode 创建 - if (Objects.nonNull(childNode)) { - return create(endExId, childNode, model, process, sequenceFlows); - } else { - return endExId; - } - } - } else { - // 所有 service task 连接 end exclusive gateway - // 1.0 先进行边连接, 暂存 nextNode - String endExId = id("exclusiveGateway") + "end"; - process.addFlowElement(createExclusiveGateWayEnd(endExId)); - String identifier = endExId; - //其他条件分支和第一个条件分支连线的终点节点相同 - for (int i = 0; i < incoming.size(); i++) { - process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); - } - - // 针对 gateway 空任务分支 添加条件表达式,即条件节点下无子节点的情况 - if (!conditions.isEmpty()) { - FlowElement flowElement1 = model.getFlowElement(identifier); - // 获取从 gateway 到目标节点 未设置条件表达式的节点 - List flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(flowElement1.getId(), flow.getTargetRef())) - .filter(flow -> StringUtils.equals(flow.getSourceRef(), exclusiveGatewayId)) - .collect(Collectors.toList()); - flows.stream().forEach(sequenceFlow -> { - if (!conditions.isEmpty()) { - JSONObject condition = conditions.get(0); - String nodeName = condition.getString("nodeName"); - String expression = condition.getString("expression"); - - if (StringUtils.isBlank(sequenceFlow.getName()) && StringUtils.isNotBlank(nodeName)) { - sequenceFlow.setName(nodeName); - } - // 设置条件表达式 - if (Objects.isNull(sequenceFlow.getConditionExpression()) && StringUtils.isNotBlank(expression)) { - sequenceFlow.setConditionExpression(expression); - } - - conditions.remove(0); - } - }); - - } - return endExId; - } -// return exclusiveGatewayId; - } - - /** - * 并行网关分支上无条件设置 - * @param formId - * @param flowNode - * @param model - * @param process - * @param sequenceFlows - * @return 返回创建的节点的id标识 - */ - private static String createParallelGatewayBuilder(String formId, JSONObject flowNode, BpmnModel model, Process process, List sequenceFlows) throws InvocationTargetException, IllegalAccessException { - //并行网关节点名 - String name = flowNode.getString("nodeName"); - ParallelGateway parallelGateway = new ParallelGateway(); - String parallelGatewayId = id("parallelGateway"); - parallelGateway.setId(parallelGatewayId); - parallelGateway.setName(name); - process.addFlowElement(parallelGateway); - //与上个节点的连线 - process.addFlowElement(connect(formId, parallelGatewayId, sequenceFlows)); - //1、无条件节点和子节点 - if (Objects.isNull(flowNode.getJSONArray("conditionNodes")) && Objects.isNull(flowNode.getJSONObject("childNode"))) { - return parallelGatewayId; - } - //2、有条件节点或子节点 - //获取条件节点 - List flowNodes = Optional.ofNullable(flowNode.getJSONArray("conditionNodes")).map(e -> e.toJavaList(JSONObject.class)).orElse(Collections.emptyList()); - //每个分支上的最后节点的标识id,用于给整个并行网关的子节点提供fromId - List incoming = Lists.newArrayListWithCapacity(flowNodes.size()); - //为每个并行网关的条件节点的子节点添加后续节点 - for (JSONObject element : flowNodes) { - JSONObject childNode = element.getJSONObject("childNode"); - if (Objects.isNull(childNode)) { - incoming.add(parallelGatewayId); - continue; - } - String identifier = create(parallelGatewayId, childNode, model, process, sequenceFlows); - if (Objects.nonNull(identifier)) { - incoming.add(identifier); - } - } - //当前网关节点的子节点(整个并行网关的子节点) - JSONObject childNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(childNode)) { - // 普通结束网关 - //有并行分支但无条件节点对应的子节点 - if (CollectionUtils.isEmpty(incoming)) { - return create(parallelGatewayId, childNode, model, process, sequenceFlows); - } else { - // 所有 service task 连接 end parallel gateway - //并行分支汇合到下面的childNode节点 - childNode.put("incoming", incoming); - FlowElement flowElement = model.getFlowElement(incoming.get(0)); - // 1.0 先进行线连接, 暂存 nextNode - JSONObject nextNode = childNode.getJSONObject("childNode"); - childNode.put("childNode", null); - String identifier = create(incoming.get(0), childNode, model, process, sequenceFlows); - //其他并行分支和第一个并行分支连线的终点节点相同 - for (int i = 1; i < incoming.size(); i++) { - FlowElement flowElement1 = model.getFlowElement(incoming.get(i)); - process.addFlowElement(connect(flowElement1.getId(), identifier, sequenceFlows)); - } - // 1.1 线连接完成后,再进行 nextNode 创建 - if (Objects.nonNull(nextNode)) { - return create(identifier, nextNode, model, process, sequenceFlows); - } else { - return identifier; - } - } - } - return parallelGatewayId; - } - - //流转到服务任务(serviceTask)节点时会自动执行某些操作然后向下流转 - private static String createServiceTask(JSONObject flowNode, Process process, List sequenceFlows) { - List incoming = flowNode.getJSONArray("incoming").toJavaList(String.class); - // 自动生成id - String id = id("serviceTask"); - if (incoming != null && !incoming.isEmpty()) { - ServiceTask serviceTask = new ServiceTask(); - serviceTask.setName(flowNode.getString("nodeName")); - serviceTask.setId(id); - process.addFlowElement(serviceTask); - process.addFlowElement(connect(incoming.get(0), id, sequenceFlows)); - } - return id; - } - - private static String createTask(JSONObject flowNode, Process process, List sequenceFlows) { - List incoming = flowNode.getJSONArray("incoming").toJavaList(String.class); - // 自动生成id - String id = id("userTask"); - if (incoming != null && !incoming.isEmpty()) { - UserTask userTask = new UserTask(); - userTask.setName(flowNode.getString("nodeName")); - userTask.setId(id); - process.addFlowElement(userTask); - //根节点 - if (Type.ROOT.type.equals(flowNode.getInteger("type"))) { - - } - //用户审批任务节点 - else { - //多实例,在业务流程中,为特定步骤定义重复的方式 - MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics(); - String examineMode = flowNode.getString("examineMode"); - // 审批人集合参数 - multiInstanceLoopCharacteristics.setInputDataItem(userTask.getId() + "assigneeList"); - // 迭代集合 - multiInstanceLoopCharacteristics.setElementVariable("assigneeName"); - // 并行 - multiInstanceLoopCharacteristics.setSequential(false); - userTask.setAssignee("${assigneeName}"); - // 设置多实例属性 - userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics); - //多人审批时采用的审批方式 1依次会签 2并行会签 3或签 - //默认并行会签 - if ("1".equals(examineMode)) { - multiInstanceLoopCharacteristics.setSequential(true); - } else if ("3".equals(examineMode)) { - //或签,即设置完成条件nrOfCompletedInstances/nrOfInstances > 0 - //nrOfCompletedInstances:已完成的实例数量,nrOfInstances:实例总数 - multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances/nrOfInstances > 0}"); - } - } - process.addFlowElement(connect(incoming.get(0), id, sequenceFlows)); - } - return id; - } - - private enum Type { - //0 发起人 1审批 2抄送 3条件 4路由 - ROOT(0, UserTask.class), - ROUTER(4, ExclusiveGateway.class), - PARALLEL(5, ParallelGateway.class), - - /** - * 排他事件 - */ -// EXCLUSIVE(4, ExclusiveGateway.class), - - /** - * 任务 - */ - USER_TASK(1, UserTask.class), - CC(2, ServiceTask.class); - - private Integer type; - - private Class typeClass; - - Type(Integer type, Class typeClass) { - this.type = type; - this.typeClass = typeClass; - } - - public final static Map> TYPE_MAP = Maps.newHashMap(); - - static { - for (Type element : Type.values()) { - TYPE_MAP.put(element.type, element.typeClass); - } - } - - public boolean isEqual(String type) { - return this.type.equals(type); - } - - } - - - private static String id(String prefix) { - return prefix + "_" + UUID.randomUUID().toString().replace("-", "").toLowerCase(); - } - - private static ServiceTask serviceTask(String name) { - ServiceTask serviceTask = new ServiceTask(); - serviceTask.setName(name); - return serviceTask; - } - - /** - * 新建连线实体加入连线列表 - */ - protected static SequenceFlow connect(String from, String to, List sequenceFlows) { - SequenceFlow flow = new SequenceFlow(); - flow.setId(id("sequenceFlow")); - flow.setSourceRef(from); - flow.setTargetRef(to); - sequenceFlows.add(flow); - return flow; - } - - protected static StartEvent createStartEvent() { - StartEvent startEvent = new StartEvent(); - startEvent.setId(id("start")); - startEvent.setInitiator("applyUserId"); - return startEvent; - } - - protected static EndEvent createEndEvent() { - EndEvent endEvent = new EndEvent(); - endEvent.setId(id("end")); - return endEvent; - } - - public static ExclusiveGateway createExclusiveGateWayEnd(String id) { - ExclusiveGateway exclusiveGateway = new ExclusiveGateway(); - exclusiveGateway.setId(id); - return exclusiveGateway; - } - - private static ParallelGateway createParallelGateWayEnd(String id) { - ParallelGateway parallelGateway = new ParallelGateway(); - parallelGateway.setId(id); - return parallelGateway; - } -} diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index 45003a0..66f34c9 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -4,7 +4,7 @@ spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true + url: jdbc:mysql://111.198.10.15:11336/casic_metering_xichang?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 redis: diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction b/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction new file mode 100644 index 0000000..e4cd427 --- /dev/null +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction @@ -0,0 +1,8 @@ +business:计量检定业务模块 +equipment:设备与装置模块 +resource:资源管理模块 +quality:质量活动模块 +data:数据管理模块 +system:系统管理模块 +sys:基础包系统管理扩展 +flowable:工作流操作相关 \ No newline at end of file diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java deleted file mode 100644 index 26d7da4..0000000 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ /dev/null @@ -1,530 +0,0 @@ -package com.casic.missiles.controller.flowable; - -import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.dto.ReturnUtil; -import com.casic.missiles.utils.SnowflakeUtil; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import io.swagger.annotations.Api; -import org.apache.commons.lang3.StringUtils; -import org.flowable.bpmn.BpmnAutoLayout; -import org.flowable.bpmn.converter.BpmnXMLConverter; -import org.flowable.bpmn.model.Process; -import org.flowable.bpmn.model.*; -import org.springframework.util.CollectionUtils; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import java.lang.reflect.InvocationTargetException; -import java.util.*; -import java.util.stream.Collectors; - - -/** - * @Description: 此Controller已废弃,已整合到流程管理中,此处仅作参考 - * @Author: wangpeng - * @Date: 2022/12/4 16:28 - */ -@Api("此Controller已废弃") -@RestController -@RequestMapping("/vue3") -public class JsonToBpmnController { - - @Resource - private SnowflakeUtil snowflakeUtil; - - /** - * 保存流程定义,流程实例中才要传业务表id - */ - @PostMapping("/jsonToBpmn") - public Object saveForm(@RequestBody JSONObject jsonObject) throws InvocationTargetException, IllegalAccessException { - System.err.println(jsonObject.toJSONString()); - //bpmn对象(可与xml相互转化) - BpmnModel bpmnModel = new BpmnModel(); - //流程定义对象 - Process process = new Process(); - //添加流程定义到bpmn对象 - bpmnModel.addProcess(process); - //流程中连线 - List sequenceFlows = Lists.newArrayList(); - //流程定义-添加流程id - process.setId("flowableV2_" + snowflakeUtil.nextId()); - //启动事件 - StartEvent startEvent = createStartEvent(); - //流程定义-添加启动事件 - process.addFlowElement(startEvent); - //获取json实体 - JSONObject workFlowObj = jsonObject.getJSONObject("_value"); - String name = workFlowObj.getJSONObject("workFlowDef").getString("name"); - //流程定义-添加流程名称 - process.setName(name); - //流程定义-添加扩展属性 - ExtensionAttribute extensionAttribute = new ExtensionAttribute(); - extensionAttribute.setName("Casic"); - extensionAttribute.setNamespace("http://flowable.org/bpmn"); - extensionAttribute.setValue(jsonObject.toJSONString()); - process.addAttribute(extensionAttribute); - //流程定义-添加节点 - JSONObject processNodes = workFlowObj.getJSONObject("nodeConfig"); - String lastNode = create(startEvent.getId(), processNodes, bpmnModel, process, sequenceFlows); - EndEvent endEvent = createEndEvent(); - process.addFlowElement(endEvent); - process.addFlowElement(connect(lastNode, endEvent.getId(), sequenceFlows)); - - new BpmnAutoLayout(bpmnModel).execute(); - System.err.println(new String(new BpmnXMLConverter().convertToXML(bpmnModel))); - return ReturnUtil.success("保存成功"); - } - - /** - * 方法功能:根据上个节点id及本节点信息生成本节点 - * @param fromId:启动事件id - * @param flowNode:所有节点树形结构 - * @param model:bpmn对象(最终要得到的结果) - * @param process:流程定义 - * @param sequenceFlows:连线列表 - */ - private static String create(String fromId, JSONObject flowNode, BpmnModel model, Process process, List sequenceFlows) throws InvocationTargetException, IllegalAccessException { - //获取节点类型,0 发起人 1审批 2抄送 3条件 4路由 - Integer nodeType = flowNode.getInteger("type"); - //节点类型-并行网关 - if (Type.PARALLEL.type.equals(nodeType)) { - return createParallelGatewayBuilder(fromId, flowNode, model, process, sequenceFlows); - } - //节点类型-路由 - else if (Type.ROUTER.type.equals(nodeType)) { - return createExclusiveGatewayBuilder(fromId, flowNode, model, process, sequenceFlows); - } - //节点类型-发起人(根节点) - else if (Type.ROOT.type.equals(nodeType)) { - //添加incoming属性(表示进来的,即上面流程节点的id列表),值为仅一个启动事件id的列表 - flowNode.put("incoming", Collections.singletonList(fromId)); - String id = createTask(flowNode, process, sequenceFlows); - - // 如果当前任务还有后续任务,则遍历创建后续任务 - JSONObject nextNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(nextNode)) { - FlowElement flowElement = model.getFlowElement(id); - return create(id, nextNode, model, process, sequenceFlows); - } else { - return id; - } - } - //节点类型-抄送任务 - else if (Type.CC.type.equals(nodeType)) { - flowNode.put("incoming", Collections.singletonList(fromId)); - String id = createServiceTask(flowNode, process, sequenceFlows); - - // 如果当前任务还有后续任务,则遍历创建后续任务 - JSONObject nextNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(nextNode)) { - FlowElement flowElement = model.getFlowElement(id); - return create(id, nextNode, model, process, sequenceFlows); - } else { - return id; - } - } - //节点类型-用户审批任务 - else if (Type.USER_TASK.type.equals(nodeType)) { - flowNode.put("incoming", Collections.singletonList(fromId)); - String id = createTask(flowNode, process, sequenceFlows); - - // 如果当前任务还有后续任务,则遍历创建后续任务 - JSONObject nextNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(nextNode)) { - FlowElement flowElement = model.getFlowElement(id); - return create(id, nextNode, model, process, sequenceFlows); - } else { - return id; - } - } else { - throw new RuntimeException("未知节点类型: nodeType=" + nodeType); - } - } - - /** - * 排他网关分支上有条件设置 - * @param formId - * @param flowNode - * @param model - * @param process - * @param sequenceFlows - * @return 返回创建的节点的id标识 - */ - private static String createExclusiveGatewayBuilder(String formId, JSONObject flowNode, BpmnModel model, Process process, List sequenceFlows) throws InvocationTargetException, IllegalAccessException { - String name = flowNode.getString("nodeName"); - String exclusiveGatewayId = id("exclusiveGateway"); - ExclusiveGateway exclusiveGateway = new ExclusiveGateway(); - exclusiveGateway.setId(exclusiveGatewayId); - exclusiveGateway.setName(name); - process.addFlowElement(exclusiveGateway); - process.addFlowElement(connect(formId, exclusiveGatewayId, sequenceFlows)); - - if (Objects.isNull(flowNode.getJSONArray("conditionNodes")) && Objects.isNull(flowNode.getJSONObject("childNode"))) { - return exclusiveGatewayId; - } - List flowNodes = Optional.ofNullable(flowNode.getJSONArray("conditionNodes")).map(e -> e.toJavaList(JSONObject.class)).orElse(Collections.emptyList()); - List incoming = Lists.newArrayListWithCapacity(flowNodes.size()); - - List conditions = Lists.newCopyOnWriteArrayList(); - ///为每个排他网关的条件节点的子节点添加后续节点(相比于并行网关多了连线的条件表达式设置) - for (JSONObject element : flowNodes) { - //一个分支的子节点 - JSONObject childNode = element.getJSONObject("childNode"); - //一个分支的名字和表达式 - String nodeName = element.getString("nodeName"); - String expression = element.getString("conditionExpression"); - - if (Objects.isNull(childNode)) { - //条件节点下无子节点,设置后续节点的fromId为exclusiveGatewayId(即排他网关的id,多个分支的排他网关id相同,名字和表达式不同) - incoming.add(exclusiveGatewayId); - JSONObject condition = new JSONObject(); - condition.fluentPut("nodeName", nodeName) - .fluentPut("expression", expression); - conditions.add(condition); - continue; - } - // 只生成一个任务,同时设置当前任务的条件 - childNode.put("incoming", Collections.singletonList(exclusiveGatewayId)); - String identifier = create(exclusiveGatewayId, childNode, model, process, sequenceFlows); - //连线列表中前一个节点是exclusiveGatewayId的连线,给每个连线设置名称和表达式 - //使用forEach是因为前一个节点是exclusiveGatewayId的节点有很多,需要遍历为没赋值过的赋值 - List flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(exclusiveGatewayId, flow.getSourceRef())) - .collect(Collectors.toList()); - flows.stream().forEach( - e -> { - //设置连线名为条件节点名 - if (StringUtils.isBlank(e.getName()) && StringUtils.isNotBlank(nodeName)) { - e.setName(nodeName); - } - // 设置条件表达式 - if (Objects.isNull(e.getConditionExpression()) && StringUtils.isNotBlank(expression)) { - e.setConditionExpression(expression); - } - } - ); - if (Objects.nonNull(identifier)) { - incoming.add(identifier); - } - } - //当前网关节点的子节点(整个排他网关的子节点) - JSONObject childNode = flowNode.getJSONObject("childNode"); - - if (Objects.nonNull(childNode)) { - //有条件分支但无条件节点对应的子节点 - if (incoming == null || incoming.isEmpty()) { - return create(exclusiveGatewayId, childNode, model, process, sequenceFlows); - } else { - // 所有 service task 连接 end exclusive gateway - //条件分支汇合到下面的childNode节点 - childNode.put("incoming", incoming); - FlowElement flowElement = model.getFlowElement(incoming.get(0)); - // 1.0 先进行边连接, 暂存 nextNode - JSONObject nextNode = childNode.getJSONObject("childNode"); - String endExId = id("exclusiveGateway") + "end"; - process.addFlowElement(createExclusiveGateWayEnd(endExId)); - childNode.put("childNode", null); - String identifier = endExId; - for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 - // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId - process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); - } - - // 针对 gateway 空任务分支 添加条件表达式,即条件节点下无子节点的情况 - if (!conditions.isEmpty()) { - FlowElement flowElement1 = model.getFlowElement(identifier); - // 获取从 gateway 到目标节点 未设置条件表达式的节点 - List flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(flowElement1.getId(), flow.getTargetRef())) - .filter(flow -> StringUtils.equals(flow.getSourceRef(), exclusiveGatewayId)) - .collect(Collectors.toList()); - //顺序无所谓,都是分支上一个条件的分支 - flows.stream().forEach(sequenceFlow -> { - if (!conditions.isEmpty()) { - JSONObject condition = conditions.get(0); - String nodeName = condition.getString("nodeName"); - String expression = condition.getString("expression"); - - if (StringUtils.isBlank(sequenceFlow.getName()) && StringUtils.isNotBlank(nodeName)) { - sequenceFlow.setName(nodeName); - } - // 设置条件表达式 - if (Objects.isNull(sequenceFlow.getConditionExpression()) && StringUtils.isNotBlank(expression)) { - sequenceFlow.setConditionExpression(expression); - } - - conditions.remove(0); - } - }); - - } - - // 1.1 边连接完成后,在进行 nextNode 创建 - if (Objects.nonNull(childNode)) { - return create(endExId, childNode, model, process, sequenceFlows); - } else { - return endExId; - } - } - } else { - // 所有 service task 连接 end exclusive gateway - // 1.0 先进行边连接, 暂存 nextNode - String endExId = id("exclusiveGateway") + "end"; - process.addFlowElement(createExclusiveGateWayEnd(endExId)); - String identifier = endExId; - //其他条件分支和第一个条件分支连线的终点节点相同 - for (int i = 0; i < incoming.size(); i++) { - process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); - } - - // 针对 gateway 空任务分支 添加条件表达式,即条件节点下无子节点的情况 - if (!conditions.isEmpty()) { - FlowElement flowElement1 = model.getFlowElement(identifier); - // 获取从 gateway 到目标节点 未设置条件表达式的节点 - List flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(flowElement1.getId(), flow.getTargetRef())) - .filter(flow -> StringUtils.equals(flow.getSourceRef(), exclusiveGatewayId)) - .collect(Collectors.toList()); - flows.stream().forEach(sequenceFlow -> { - if (!conditions.isEmpty()) { - JSONObject condition = conditions.get(0); - String nodeName = condition.getString("nodeName"); - String expression = condition.getString("expression"); - - if (StringUtils.isBlank(sequenceFlow.getName()) && StringUtils.isNotBlank(nodeName)) { - sequenceFlow.setName(nodeName); - } - // 设置条件表达式 - if (Objects.isNull(sequenceFlow.getConditionExpression()) && StringUtils.isNotBlank(expression)) { - sequenceFlow.setConditionExpression(expression); - } - - conditions.remove(0); - } - }); - - } - return endExId; - } -// return exclusiveGatewayId; - } - - /** - * 并行网关分支上无条件设置 - * @param formId - * @param flowNode - * @param model - * @param process - * @param sequenceFlows - * @return 返回创建的节点的id标识 - */ - private static String createParallelGatewayBuilder(String formId, JSONObject flowNode, BpmnModel model, Process process, List sequenceFlows) throws InvocationTargetException, IllegalAccessException { - //并行网关节点名 - String name = flowNode.getString("nodeName"); - ParallelGateway parallelGateway = new ParallelGateway(); - String parallelGatewayId = id("parallelGateway"); - parallelGateway.setId(parallelGatewayId); - parallelGateway.setName(name); - process.addFlowElement(parallelGateway); - //与上个节点的连线 - process.addFlowElement(connect(formId, parallelGatewayId, sequenceFlows)); - //1、无条件节点和子节点 - if (Objects.isNull(flowNode.getJSONArray("conditionNodes")) && Objects.isNull(flowNode.getJSONObject("childNode"))) { - return parallelGatewayId; - } - //2、有条件节点或子节点 - //获取条件节点 - List flowNodes = Optional.ofNullable(flowNode.getJSONArray("conditionNodes")).map(e -> e.toJavaList(JSONObject.class)).orElse(Collections.emptyList()); - //每个分支上的最后节点的标识id,用于给整个并行网关的子节点提供fromId - List incoming = Lists.newArrayListWithCapacity(flowNodes.size()); - //为每个并行网关的条件节点的子节点添加后续节点 - for (JSONObject element : flowNodes) { - JSONObject childNode = element.getJSONObject("childNode"); - if (Objects.isNull(childNode)) { - incoming.add(parallelGatewayId); - continue; - } - String identifier = create(parallelGatewayId, childNode, model, process, sequenceFlows); - if (Objects.nonNull(identifier)) { - incoming.add(identifier); - } - } - //当前网关节点的子节点(整个并行网关的子节点) - JSONObject childNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(childNode)) { - // 普通结束网关 - //有并行分支但无条件节点对应的子节点 - if (CollectionUtils.isEmpty(incoming)) { - return create(parallelGatewayId, childNode, model, process, sequenceFlows); - } else { - // 所有 service task 连接 end parallel gateway - //并行分支汇合到下面的childNode节点 - childNode.put("incoming", incoming); - FlowElement flowElement = model.getFlowElement(incoming.get(0)); - // 1.0 先进行线连接, 暂存 nextNode - JSONObject nextNode = childNode.getJSONObject("childNode"); - childNode.put("childNode", null); - String identifier = create(incoming.get(0), childNode, model, process, sequenceFlows); - //其他并行分支和第一个并行分支连线的终点节点相同 - for (int i = 1; i < incoming.size(); i++) { - FlowElement flowElement1 = model.getFlowElement(incoming.get(i)); - process.addFlowElement(connect(flowElement1.getId(), identifier, sequenceFlows)); - } - // 1.1 线连接完成后,再进行 nextNode 创建 - if (Objects.nonNull(nextNode)) { - return create(identifier, nextNode, model, process, sequenceFlows); - } else { - return identifier; - } - } - } - return parallelGatewayId; - } - - //流转到服务任务(serviceTask)节点时会自动执行某些操作然后向下流转 - private static String createServiceTask(JSONObject flowNode, Process process, List sequenceFlows) { - List incoming = flowNode.getJSONArray("incoming").toJavaList(String.class); - // 自动生成id - String id = id("serviceTask"); - if (incoming != null && !incoming.isEmpty()) { - ServiceTask serviceTask = new ServiceTask(); - serviceTask.setName(flowNode.getString("nodeName")); - serviceTask.setId(id); - process.addFlowElement(serviceTask); - process.addFlowElement(connect(incoming.get(0), id, sequenceFlows)); - } - return id; - } - - private static String createTask(JSONObject flowNode, Process process, List sequenceFlows) { - List incoming = flowNode.getJSONArray("incoming").toJavaList(String.class); - // 自动生成id - String id = id("userTask"); - if (incoming != null && !incoming.isEmpty()) { - UserTask userTask = new UserTask(); - userTask.setName(flowNode.getString("nodeName")); - userTask.setId(id); - process.addFlowElement(userTask); - //根节点 - if (Type.ROOT.type.equals(flowNode.getInteger("type"))) { - - } - //用户审批任务节点 - else { - //多实例,在业务流程中,为特定步骤定义重复的方式 - MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics(); - String examineMode = flowNode.getString("examineMode"); - // 审批人集合参数 - multiInstanceLoopCharacteristics.setInputDataItem(userTask.getId() + "assigneeList"); - // 迭代集合 - multiInstanceLoopCharacteristics.setElementVariable("assigneeName"); - // 并行 - multiInstanceLoopCharacteristics.setSequential(false); - userTask.setAssignee("${assigneeName}"); - // 设置多实例属性 - userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics); - //多人审批时采用的审批方式 1依次会签 2并行会签 3或签 - //默认并行会签 - if ("1".equals(examineMode)) { - multiInstanceLoopCharacteristics.setSequential(true); - } else if ("3".equals(examineMode)) { - //或签,即设置完成条件nrOfCompletedInstances/nrOfInstances > 0 - //nrOfCompletedInstances:已完成的实例数量,nrOfInstances:实例总数 - multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances/nrOfInstances > 0}"); - } - } - process.addFlowElement(connect(incoming.get(0), id, sequenceFlows)); - } - return id; - } - - private enum Type { - //0 发起人 1审批 2抄送 3条件 4路由 - ROOT(0, UserTask.class), - ROUTER(4, ExclusiveGateway.class), - PARALLEL(5, ParallelGateway.class), - - /** - * 排他事件 - */ -// EXCLUSIVE(4, ExclusiveGateway.class), - - /** - * 任务 - */ - USER_TASK(1, UserTask.class), - CC(2, ServiceTask.class); - - private Integer type; - - private Class typeClass; - - Type(Integer type, Class typeClass) { - this.type = type; - this.typeClass = typeClass; - } - - public final static Map> TYPE_MAP = Maps.newHashMap(); - - static { - for (Type element : Type.values()) { - TYPE_MAP.put(element.type, element.typeClass); - } - } - - public boolean isEqual(String type) { - return this.type.equals(type); - } - - } - - - private static String id(String prefix) { - return prefix + "_" + UUID.randomUUID().toString().replace("-", "").toLowerCase(); - } - - private static ServiceTask serviceTask(String name) { - ServiceTask serviceTask = new ServiceTask(); - serviceTask.setName(name); - return serviceTask; - } - - /** - * 新建连线实体加入连线列表 - */ - protected static SequenceFlow connect(String from, String to, List sequenceFlows) { - SequenceFlow flow = new SequenceFlow(); - flow.setId(id("sequenceFlow")); - flow.setSourceRef(from); - flow.setTargetRef(to); - sequenceFlows.add(flow); - return flow; - } - - protected static StartEvent createStartEvent() { - StartEvent startEvent = new StartEvent(); - startEvent.setId(id("start")); - startEvent.setInitiator("applyUserId"); - return startEvent; - } - - protected static EndEvent createEndEvent() { - EndEvent endEvent = new EndEvent(); - endEvent.setId(id("end")); - return endEvent; - } - - public static ExclusiveGateway createExclusiveGateWayEnd(String id) { - ExclusiveGateway exclusiveGateway = new ExclusiveGateway(); - exclusiveGateway.setId(id); - return exclusiveGateway; - } - - private static ParallelGateway createParallelGateWayEnd(String id) { - ParallelGateway parallelGateway = new ParallelGateway(); - parallelGateway.setId(id); - return parallelGateway; - } -} diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index 45003a0..66f34c9 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -4,7 +4,7 @@ spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true + url: jdbc:mysql://111.198.10.15:11336/casic_metering_xichang?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 redis: diff --git a/casic-metering-api/src/main/resources/config/application-prod.yml b/casic-metering-api/src/main/resources/config/application-prod.yml index 5fe749d..ce49c66 100644 --- a/casic-metering-api/src/main/resources/config/application-prod.yml +++ b/casic-metering-api/src/main/resources/config/application-prod.yml @@ -4,7 +4,7 @@ ################### spring配置 ################### spring: datasource: - url: jdbc:mysql://111.198.10.15:11336/casic_metering?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&nullCatalogMeansCurrent=true + url: jdbc:mysql://111.198.10.15:11336/casic_metering_xichang?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&nullCatalogMeansCurrent=true username: root password: Casic203 initial-size: 2 diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction b/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction new file mode 100644 index 0000000..e4cd427 --- /dev/null +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/Structure Introduction @@ -0,0 +1,8 @@ +business:计量检定业务模块 +equipment:设备与装置模块 +resource:资源管理模块 +quality:质量活动模块 +data:数据管理模块 +system:系统管理模块 +sys:基础包系统管理扩展 +flowable:工作流操作相关 \ No newline at end of file diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java deleted file mode 100644 index 26d7da4..0000000 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ /dev/null @@ -1,530 +0,0 @@ -package com.casic.missiles.controller.flowable; - -import com.alibaba.fastjson.JSONObject; -import com.casic.missiles.dto.ReturnUtil; -import com.casic.missiles.utils.SnowflakeUtil; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import io.swagger.annotations.Api; -import org.apache.commons.lang3.StringUtils; -import org.flowable.bpmn.BpmnAutoLayout; -import org.flowable.bpmn.converter.BpmnXMLConverter; -import org.flowable.bpmn.model.Process; -import org.flowable.bpmn.model.*; -import org.springframework.util.CollectionUtils; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import java.lang.reflect.InvocationTargetException; -import java.util.*; -import java.util.stream.Collectors; - - -/** - * @Description: 此Controller已废弃,已整合到流程管理中,此处仅作参考 - * @Author: wangpeng - * @Date: 2022/12/4 16:28 - */ -@Api("此Controller已废弃") -@RestController -@RequestMapping("/vue3") -public class JsonToBpmnController { - - @Resource - private SnowflakeUtil snowflakeUtil; - - /** - * 保存流程定义,流程实例中才要传业务表id - */ - @PostMapping("/jsonToBpmn") - public Object saveForm(@RequestBody JSONObject jsonObject) throws InvocationTargetException, IllegalAccessException { - System.err.println(jsonObject.toJSONString()); - //bpmn对象(可与xml相互转化) - BpmnModel bpmnModel = new BpmnModel(); - //流程定义对象 - Process process = new Process(); - //添加流程定义到bpmn对象 - bpmnModel.addProcess(process); - //流程中连线 - List sequenceFlows = Lists.newArrayList(); - //流程定义-添加流程id - process.setId("flowableV2_" + snowflakeUtil.nextId()); - //启动事件 - StartEvent startEvent = createStartEvent(); - //流程定义-添加启动事件 - process.addFlowElement(startEvent); - //获取json实体 - JSONObject workFlowObj = jsonObject.getJSONObject("_value"); - String name = workFlowObj.getJSONObject("workFlowDef").getString("name"); - //流程定义-添加流程名称 - process.setName(name); - //流程定义-添加扩展属性 - ExtensionAttribute extensionAttribute = new ExtensionAttribute(); - extensionAttribute.setName("Casic"); - extensionAttribute.setNamespace("http://flowable.org/bpmn"); - extensionAttribute.setValue(jsonObject.toJSONString()); - process.addAttribute(extensionAttribute); - //流程定义-添加节点 - JSONObject processNodes = workFlowObj.getJSONObject("nodeConfig"); - String lastNode = create(startEvent.getId(), processNodes, bpmnModel, process, sequenceFlows); - EndEvent endEvent = createEndEvent(); - process.addFlowElement(endEvent); - process.addFlowElement(connect(lastNode, endEvent.getId(), sequenceFlows)); - - new BpmnAutoLayout(bpmnModel).execute(); - System.err.println(new String(new BpmnXMLConverter().convertToXML(bpmnModel))); - return ReturnUtil.success("保存成功"); - } - - /** - * 方法功能:根据上个节点id及本节点信息生成本节点 - * @param fromId:启动事件id - * @param flowNode:所有节点树形结构 - * @param model:bpmn对象(最终要得到的结果) - * @param process:流程定义 - * @param sequenceFlows:连线列表 - */ - private static String create(String fromId, JSONObject flowNode, BpmnModel model, Process process, List sequenceFlows) throws InvocationTargetException, IllegalAccessException { - //获取节点类型,0 发起人 1审批 2抄送 3条件 4路由 - Integer nodeType = flowNode.getInteger("type"); - //节点类型-并行网关 - if (Type.PARALLEL.type.equals(nodeType)) { - return createParallelGatewayBuilder(fromId, flowNode, model, process, sequenceFlows); - } - //节点类型-路由 - else if (Type.ROUTER.type.equals(nodeType)) { - return createExclusiveGatewayBuilder(fromId, flowNode, model, process, sequenceFlows); - } - //节点类型-发起人(根节点) - else if (Type.ROOT.type.equals(nodeType)) { - //添加incoming属性(表示进来的,即上面流程节点的id列表),值为仅一个启动事件id的列表 - flowNode.put("incoming", Collections.singletonList(fromId)); - String id = createTask(flowNode, process, sequenceFlows); - - // 如果当前任务还有后续任务,则遍历创建后续任务 - JSONObject nextNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(nextNode)) { - FlowElement flowElement = model.getFlowElement(id); - return create(id, nextNode, model, process, sequenceFlows); - } else { - return id; - } - } - //节点类型-抄送任务 - else if (Type.CC.type.equals(nodeType)) { - flowNode.put("incoming", Collections.singletonList(fromId)); - String id = createServiceTask(flowNode, process, sequenceFlows); - - // 如果当前任务还有后续任务,则遍历创建后续任务 - JSONObject nextNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(nextNode)) { - FlowElement flowElement = model.getFlowElement(id); - return create(id, nextNode, model, process, sequenceFlows); - } else { - return id; - } - } - //节点类型-用户审批任务 - else if (Type.USER_TASK.type.equals(nodeType)) { - flowNode.put("incoming", Collections.singletonList(fromId)); - String id = createTask(flowNode, process, sequenceFlows); - - // 如果当前任务还有后续任务,则遍历创建后续任务 - JSONObject nextNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(nextNode)) { - FlowElement flowElement = model.getFlowElement(id); - return create(id, nextNode, model, process, sequenceFlows); - } else { - return id; - } - } else { - throw new RuntimeException("未知节点类型: nodeType=" + nodeType); - } - } - - /** - * 排他网关分支上有条件设置 - * @param formId - * @param flowNode - * @param model - * @param process - * @param sequenceFlows - * @return 返回创建的节点的id标识 - */ - private static String createExclusiveGatewayBuilder(String formId, JSONObject flowNode, BpmnModel model, Process process, List sequenceFlows) throws InvocationTargetException, IllegalAccessException { - String name = flowNode.getString("nodeName"); - String exclusiveGatewayId = id("exclusiveGateway"); - ExclusiveGateway exclusiveGateway = new ExclusiveGateway(); - exclusiveGateway.setId(exclusiveGatewayId); - exclusiveGateway.setName(name); - process.addFlowElement(exclusiveGateway); - process.addFlowElement(connect(formId, exclusiveGatewayId, sequenceFlows)); - - if (Objects.isNull(flowNode.getJSONArray("conditionNodes")) && Objects.isNull(flowNode.getJSONObject("childNode"))) { - return exclusiveGatewayId; - } - List flowNodes = Optional.ofNullable(flowNode.getJSONArray("conditionNodes")).map(e -> e.toJavaList(JSONObject.class)).orElse(Collections.emptyList()); - List incoming = Lists.newArrayListWithCapacity(flowNodes.size()); - - List conditions = Lists.newCopyOnWriteArrayList(); - ///为每个排他网关的条件节点的子节点添加后续节点(相比于并行网关多了连线的条件表达式设置) - for (JSONObject element : flowNodes) { - //一个分支的子节点 - JSONObject childNode = element.getJSONObject("childNode"); - //一个分支的名字和表达式 - String nodeName = element.getString("nodeName"); - String expression = element.getString("conditionExpression"); - - if (Objects.isNull(childNode)) { - //条件节点下无子节点,设置后续节点的fromId为exclusiveGatewayId(即排他网关的id,多个分支的排他网关id相同,名字和表达式不同) - incoming.add(exclusiveGatewayId); - JSONObject condition = new JSONObject(); - condition.fluentPut("nodeName", nodeName) - .fluentPut("expression", expression); - conditions.add(condition); - continue; - } - // 只生成一个任务,同时设置当前任务的条件 - childNode.put("incoming", Collections.singletonList(exclusiveGatewayId)); - String identifier = create(exclusiveGatewayId, childNode, model, process, sequenceFlows); - //连线列表中前一个节点是exclusiveGatewayId的连线,给每个连线设置名称和表达式 - //使用forEach是因为前一个节点是exclusiveGatewayId的节点有很多,需要遍历为没赋值过的赋值 - List flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(exclusiveGatewayId, flow.getSourceRef())) - .collect(Collectors.toList()); - flows.stream().forEach( - e -> { - //设置连线名为条件节点名 - if (StringUtils.isBlank(e.getName()) && StringUtils.isNotBlank(nodeName)) { - e.setName(nodeName); - } - // 设置条件表达式 - if (Objects.isNull(e.getConditionExpression()) && StringUtils.isNotBlank(expression)) { - e.setConditionExpression(expression); - } - } - ); - if (Objects.nonNull(identifier)) { - incoming.add(identifier); - } - } - //当前网关节点的子节点(整个排他网关的子节点) - JSONObject childNode = flowNode.getJSONObject("childNode"); - - if (Objects.nonNull(childNode)) { - //有条件分支但无条件节点对应的子节点 - if (incoming == null || incoming.isEmpty()) { - return create(exclusiveGatewayId, childNode, model, process, sequenceFlows); - } else { - // 所有 service task 连接 end exclusive gateway - //条件分支汇合到下面的childNode节点 - childNode.put("incoming", incoming); - FlowElement flowElement = model.getFlowElement(incoming.get(0)); - // 1.0 先进行边连接, 暂存 nextNode - JSONObject nextNode = childNode.getJSONObject("childNode"); - String endExId = id("exclusiveGateway") + "end"; - process.addFlowElement(createExclusiveGateWayEnd(endExId)); - childNode.put("childNode", null); - String identifier = endExId; - for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 - // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId - process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); - } - - // 针对 gateway 空任务分支 添加条件表达式,即条件节点下无子节点的情况 - if (!conditions.isEmpty()) { - FlowElement flowElement1 = model.getFlowElement(identifier); - // 获取从 gateway 到目标节点 未设置条件表达式的节点 - List flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(flowElement1.getId(), flow.getTargetRef())) - .filter(flow -> StringUtils.equals(flow.getSourceRef(), exclusiveGatewayId)) - .collect(Collectors.toList()); - //顺序无所谓,都是分支上一个条件的分支 - flows.stream().forEach(sequenceFlow -> { - if (!conditions.isEmpty()) { - JSONObject condition = conditions.get(0); - String nodeName = condition.getString("nodeName"); - String expression = condition.getString("expression"); - - if (StringUtils.isBlank(sequenceFlow.getName()) && StringUtils.isNotBlank(nodeName)) { - sequenceFlow.setName(nodeName); - } - // 设置条件表达式 - if (Objects.isNull(sequenceFlow.getConditionExpression()) && StringUtils.isNotBlank(expression)) { - sequenceFlow.setConditionExpression(expression); - } - - conditions.remove(0); - } - }); - - } - - // 1.1 边连接完成后,在进行 nextNode 创建 - if (Objects.nonNull(childNode)) { - return create(endExId, childNode, model, process, sequenceFlows); - } else { - return endExId; - } - } - } else { - // 所有 service task 连接 end exclusive gateway - // 1.0 先进行边连接, 暂存 nextNode - String endExId = id("exclusiveGateway") + "end"; - process.addFlowElement(createExclusiveGateWayEnd(endExId)); - String identifier = endExId; - //其他条件分支和第一个条件分支连线的终点节点相同 - for (int i = 0; i < incoming.size(); i++) { - process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); - } - - // 针对 gateway 空任务分支 添加条件表达式,即条件节点下无子节点的情况 - if (!conditions.isEmpty()) { - FlowElement flowElement1 = model.getFlowElement(identifier); - // 获取从 gateway 到目标节点 未设置条件表达式的节点 - List flows = sequenceFlows.stream().filter(flow -> StringUtils.equals(flowElement1.getId(), flow.getTargetRef())) - .filter(flow -> StringUtils.equals(flow.getSourceRef(), exclusiveGatewayId)) - .collect(Collectors.toList()); - flows.stream().forEach(sequenceFlow -> { - if (!conditions.isEmpty()) { - JSONObject condition = conditions.get(0); - String nodeName = condition.getString("nodeName"); - String expression = condition.getString("expression"); - - if (StringUtils.isBlank(sequenceFlow.getName()) && StringUtils.isNotBlank(nodeName)) { - sequenceFlow.setName(nodeName); - } - // 设置条件表达式 - if (Objects.isNull(sequenceFlow.getConditionExpression()) && StringUtils.isNotBlank(expression)) { - sequenceFlow.setConditionExpression(expression); - } - - conditions.remove(0); - } - }); - - } - return endExId; - } -// return exclusiveGatewayId; - } - - /** - * 并行网关分支上无条件设置 - * @param formId - * @param flowNode - * @param model - * @param process - * @param sequenceFlows - * @return 返回创建的节点的id标识 - */ - private static String createParallelGatewayBuilder(String formId, JSONObject flowNode, BpmnModel model, Process process, List sequenceFlows) throws InvocationTargetException, IllegalAccessException { - //并行网关节点名 - String name = flowNode.getString("nodeName"); - ParallelGateway parallelGateway = new ParallelGateway(); - String parallelGatewayId = id("parallelGateway"); - parallelGateway.setId(parallelGatewayId); - parallelGateway.setName(name); - process.addFlowElement(parallelGateway); - //与上个节点的连线 - process.addFlowElement(connect(formId, parallelGatewayId, sequenceFlows)); - //1、无条件节点和子节点 - if (Objects.isNull(flowNode.getJSONArray("conditionNodes")) && Objects.isNull(flowNode.getJSONObject("childNode"))) { - return parallelGatewayId; - } - //2、有条件节点或子节点 - //获取条件节点 - List flowNodes = Optional.ofNullable(flowNode.getJSONArray("conditionNodes")).map(e -> e.toJavaList(JSONObject.class)).orElse(Collections.emptyList()); - //每个分支上的最后节点的标识id,用于给整个并行网关的子节点提供fromId - List incoming = Lists.newArrayListWithCapacity(flowNodes.size()); - //为每个并行网关的条件节点的子节点添加后续节点 - for (JSONObject element : flowNodes) { - JSONObject childNode = element.getJSONObject("childNode"); - if (Objects.isNull(childNode)) { - incoming.add(parallelGatewayId); - continue; - } - String identifier = create(parallelGatewayId, childNode, model, process, sequenceFlows); - if (Objects.nonNull(identifier)) { - incoming.add(identifier); - } - } - //当前网关节点的子节点(整个并行网关的子节点) - JSONObject childNode = flowNode.getJSONObject("childNode"); - if (Objects.nonNull(childNode)) { - // 普通结束网关 - //有并行分支但无条件节点对应的子节点 - if (CollectionUtils.isEmpty(incoming)) { - return create(parallelGatewayId, childNode, model, process, sequenceFlows); - } else { - // 所有 service task 连接 end parallel gateway - //并行分支汇合到下面的childNode节点 - childNode.put("incoming", incoming); - FlowElement flowElement = model.getFlowElement(incoming.get(0)); - // 1.0 先进行线连接, 暂存 nextNode - JSONObject nextNode = childNode.getJSONObject("childNode"); - childNode.put("childNode", null); - String identifier = create(incoming.get(0), childNode, model, process, sequenceFlows); - //其他并行分支和第一个并行分支连线的终点节点相同 - for (int i = 1; i < incoming.size(); i++) { - FlowElement flowElement1 = model.getFlowElement(incoming.get(i)); - process.addFlowElement(connect(flowElement1.getId(), identifier, sequenceFlows)); - } - // 1.1 线连接完成后,再进行 nextNode 创建 - if (Objects.nonNull(nextNode)) { - return create(identifier, nextNode, model, process, sequenceFlows); - } else { - return identifier; - } - } - } - return parallelGatewayId; - } - - //流转到服务任务(serviceTask)节点时会自动执行某些操作然后向下流转 - private static String createServiceTask(JSONObject flowNode, Process process, List sequenceFlows) { - List incoming = flowNode.getJSONArray("incoming").toJavaList(String.class); - // 自动生成id - String id = id("serviceTask"); - if (incoming != null && !incoming.isEmpty()) { - ServiceTask serviceTask = new ServiceTask(); - serviceTask.setName(flowNode.getString("nodeName")); - serviceTask.setId(id); - process.addFlowElement(serviceTask); - process.addFlowElement(connect(incoming.get(0), id, sequenceFlows)); - } - return id; - } - - private static String createTask(JSONObject flowNode, Process process, List sequenceFlows) { - List incoming = flowNode.getJSONArray("incoming").toJavaList(String.class); - // 自动生成id - String id = id("userTask"); - if (incoming != null && !incoming.isEmpty()) { - UserTask userTask = new UserTask(); - userTask.setName(flowNode.getString("nodeName")); - userTask.setId(id); - process.addFlowElement(userTask); - //根节点 - if (Type.ROOT.type.equals(flowNode.getInteger("type"))) { - - } - //用户审批任务节点 - else { - //多实例,在业务流程中,为特定步骤定义重复的方式 - MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics(); - String examineMode = flowNode.getString("examineMode"); - // 审批人集合参数 - multiInstanceLoopCharacteristics.setInputDataItem(userTask.getId() + "assigneeList"); - // 迭代集合 - multiInstanceLoopCharacteristics.setElementVariable("assigneeName"); - // 并行 - multiInstanceLoopCharacteristics.setSequential(false); - userTask.setAssignee("${assigneeName}"); - // 设置多实例属性 - userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics); - //多人审批时采用的审批方式 1依次会签 2并行会签 3或签 - //默认并行会签 - if ("1".equals(examineMode)) { - multiInstanceLoopCharacteristics.setSequential(true); - } else if ("3".equals(examineMode)) { - //或签,即设置完成条件nrOfCompletedInstances/nrOfInstances > 0 - //nrOfCompletedInstances:已完成的实例数量,nrOfInstances:实例总数 - multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances/nrOfInstances > 0}"); - } - } - process.addFlowElement(connect(incoming.get(0), id, sequenceFlows)); - } - return id; - } - - private enum Type { - //0 发起人 1审批 2抄送 3条件 4路由 - ROOT(0, UserTask.class), - ROUTER(4, ExclusiveGateway.class), - PARALLEL(5, ParallelGateway.class), - - /** - * 排他事件 - */ -// EXCLUSIVE(4, ExclusiveGateway.class), - - /** - * 任务 - */ - USER_TASK(1, UserTask.class), - CC(2, ServiceTask.class); - - private Integer type; - - private Class typeClass; - - Type(Integer type, Class typeClass) { - this.type = type; - this.typeClass = typeClass; - } - - public final static Map> TYPE_MAP = Maps.newHashMap(); - - static { - for (Type element : Type.values()) { - TYPE_MAP.put(element.type, element.typeClass); - } - } - - public boolean isEqual(String type) { - return this.type.equals(type); - } - - } - - - private static String id(String prefix) { - return prefix + "_" + UUID.randomUUID().toString().replace("-", "").toLowerCase(); - } - - private static ServiceTask serviceTask(String name) { - ServiceTask serviceTask = new ServiceTask(); - serviceTask.setName(name); - return serviceTask; - } - - /** - * 新建连线实体加入连线列表 - */ - protected static SequenceFlow connect(String from, String to, List sequenceFlows) { - SequenceFlow flow = new SequenceFlow(); - flow.setId(id("sequenceFlow")); - flow.setSourceRef(from); - flow.setTargetRef(to); - sequenceFlows.add(flow); - return flow; - } - - protected static StartEvent createStartEvent() { - StartEvent startEvent = new StartEvent(); - startEvent.setId(id("start")); - startEvent.setInitiator("applyUserId"); - return startEvent; - } - - protected static EndEvent createEndEvent() { - EndEvent endEvent = new EndEvent(); - endEvent.setId(id("end")); - return endEvent; - } - - public static ExclusiveGateway createExclusiveGateWayEnd(String id) { - ExclusiveGateway exclusiveGateway = new ExclusiveGateway(); - exclusiveGateway.setId(id); - return exclusiveGateway; - } - - private static ParallelGateway createParallelGateWayEnd(String id) { - ParallelGateway parallelGateway = new ParallelGateway(); - parallelGateway.setId(id); - return parallelGateway; - } -} diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index 45003a0..66f34c9 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -4,7 +4,7 @@ spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true + url: jdbc:mysql://111.198.10.15:11336/casic_metering_xichang?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 redis: diff --git a/casic-metering-api/src/main/resources/config/application-prod.yml b/casic-metering-api/src/main/resources/config/application-prod.yml index 5fe749d..ce49c66 100644 --- a/casic-metering-api/src/main/resources/config/application-prod.yml +++ b/casic-metering-api/src/main/resources/config/application-prod.yml @@ -4,7 +4,7 @@ ################### spring配置 ################### spring: datasource: - url: jdbc:mysql://111.198.10.15:11336/casic_metering?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&nullCatalogMeansCurrent=true + url: jdbc:mysql://111.198.10.15:11336/casic_metering_xichang?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&nullCatalogMeansCurrent=true username: root password: Casic203 initial-size: 2 diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index 4212bf9..ec19795 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -4,7 +4,7 @@ spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true + url: jdbc:mysql://111.198.10.15:11336/casic_metering_xichang?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 #jms: