json转bpmn协议开发

This commit is contained in:
lvshaohua 2023-06-06 18:38:36 +08:00
parent 21e48ea486
commit f7be7b64da
4 changed files with 440 additions and 3 deletions

View File

@ -0,0 +1,14 @@
package cn.axzo.server.repository.mapper;
import cn.axzo.server.service.dto.process.BpmProcessInstanceExtDO;
import cn.axzo.server.service.dto.response.PageResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.util.StringUtils;
@Mapper
public interface BpmProcessInstanceExtMapper extends BaseMapper<BpmProcessInstanceExtDO> {
}

View File

@ -0,0 +1,98 @@
package cn.axzo.server.service.dto.process;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
import java.util.Map;
@TableName(value = "bpm_process_instance_ext", autoResultMap = true)
@Data
@ToString(callSuper = true)
public class BpmProcessInstanceExtDO {
/**
* 编号自增
*/
@TableId
private Long id;
/**
* 流程实例的名字
* <p>
* 冗余 ProcessInstance name 属性用于筛选
*/
private String name;
/**
* 自定义的流程实例的编号
*/
private String customProInstId;
/**
* 流程实例的编号
* <p>
* 关联 ProcessInstance id 属性
*/
private String processInstanceId;
/**
* 流程定义的编号
* <p>
* 关联 ProcessDefinition id 属性
*/
private String processDefinitionId;
/**
* 流程分类
* <p>
* 冗余 ProcessDefinition category 属性 数据字典 bpm_model_category
*/
private String category;
/**
* 流程实例的状态
* <p>
* 枚举 {@link BpmProcessInstanceStatusEnum}
*/
private Integer status;
/**
* 流程实例的结果
* <p>
* 枚举 {@link BpmProcessInstanceResultEnum}
*/
private Integer result;
/**
* 结束时间
* <p>
* 冗余 HistoricProcessInstance endTime 属性
*/
private Date endTime;
/**
* 提交的表单值
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private Map<String, Object> formVariables;
/**
* 发起人所在的工作台ID(企业/项目)
* <p>
* 使用租户字段隔离
*/
private String tenantId;
/**
* 发起人所在的项目工作台中的具体单位ID
*/
private Long startCompanyId;
/**
* 发起人的身份ID
*/
private Long startIdentityId;
/**
* 发起人的姓名
*/
private String startUserName;
}

View File

@ -0,0 +1,4 @@
package cn.axzo.server.service.impl;
public class BpmProcessServiceImpl {
}

View File

@ -20,11 +20,84 @@ import static org.flowable.bpmn.model.ImplementationType.IMPLEMENTATION_TYPE_DEL
public class BpmTransformUtil { public class BpmTransformUtil {
public String transformBpmnJsonToXml(DDBpmModelSaveReqVO updateReqVO) {
JSONObject bpmnJson = (JSONObject) updateReqVO.getBpmnJson();
BpmnModel bpmnModel =new BpmnModel();
Process process=new Process();
bpmnModel.addProcess(process);
List<SequenceFlow> sequenceFlows = Lists.newArrayList();
process.setId(updateReqVO.getKey());
StartEvent startEvent = DDBpmnModelUtils.createStartEvent();
process.addFlowElement(startEvent);
process.setName(updateReqVO.getName());
ExtensionAttribute extensionAttribute=new ExtensionAttribute();
extensionAttribute.setName("TestName");
extensionAttribute.setNamespace("http://flowable.org/bpmn");
extensionAttribute.setValue(bpmnJson.toJSONString());
// process.addAttribute(extensionAttribute);
JSONObject processNodes = bpmnJson.getJSONObject("nodeConfig");
String lastNode = null;
try {
lastNode = create(startEvent.getId(), processNodes,bpmnModel,process,sequenceFlows);
} catch (Exception e) {
e.printStackTrace();
throw new ServiceException(1245, "协议解析出错");
}
EndEvent endEvent = createEndEvent();
process.addFlowElement(endEvent);
process.addFlowElement(connect(lastNode, endEvent.getId(),sequenceFlows));
new BpmnAutoLayout(bpmnModel).execute();
String xmlResult = new String(new BpmnXMLConverter().convertToXML(bpmnModel));
System.err.println(xmlResult);
return xmlResult;
}
// @PostMapping("/jsonToBpmn")
// public Object saveForm(@RequestBody com.alibaba.fastjson.JSONObject jsonObject) throws InvocationTargetException, IllegalAccessException {
// System.err.println(jsonObject.toJSONString());
// BpmnModel bpmnModel =new BpmnModel();
// Process process=new Process();
// bpmnModel.addProcess(process);
// List<SequenceFlow> sequenceFlows = Lists.newArrayList();
// process.setId("flowableV2_"+idWorker.nextId());
// StartEvent startEvent = BpmnModelUtils.createStartEvent();
// process.addFlowElement(startEvent);
// com.alibaba.fastjson.JSONObject workFlowObj = jsonObject.getJSONObject("_value");
// String name = workFlowObj.getJSONObject("workFlowDef").getString("name");
// process.setName(name);
//
// ExtensionAttribute extensionAttribute=new ExtensionAttribute();
// extensionAttribute.setName("DingDing");
// extensionAttribute.setNamespace("http://flowable.org/bpmn");
// extensionAttribute.setValue(jsonObject.toJSONString());
// process.addAttribute(extensionAttribute);
// com.alibaba.fastjson.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 R.ok("保存成功");
// }
private static String create(String fromId, com.alibaba.fastjson.JSONObject flowNode, BpmnModel model, Process process, List<SequenceFlow> sequenceFlows) throws InvocationTargetException, IllegalAccessException { private static String create(String fromId, com.alibaba.fastjson.JSONObject flowNode, BpmnModel model, Process process, List<SequenceFlow> sequenceFlows) throws InvocationTargetException, IllegalAccessException {
String nodeType = flowNode.getString("type"); String nodeType = flowNode.getString("type");
if (DDFlowNodeType.NODE_PARALLEL.name().equals(nodeType)) {
if ("userTask".equals(nodeType)) { return createParallelGatewayBuilder(fromId, flowNode,model,process,sequenceFlows);
}
else if (DDFlowNodeType.NODE_ROUTER.name().equals(nodeType)) {
return createExclusiveGatewayBuilder(fromId, flowNode,model,process,sequenceFlows);
}
else if (DDFlowNodeType.NODE_STARTER.name().equals(nodeType)) {
// flowNode.put("incoming", Collections.singletonList(fromId));
String id = fromId; String id = fromId;
// 如果当前任务还有后续任务则遍历创建后续任务 // 如果当前任务还有后续任务则遍历创建后续任务
com.alibaba.fastjson.JSONObject nextNode = flowNode.getJSONObject("childNode"); com.alibaba.fastjson.JSONObject nextNode = flowNode.getJSONObject("childNode");
if (Objects.nonNull(nextNode)) { if (Objects.nonNull(nextNode)) {
@ -34,7 +107,20 @@ public class BpmTransformUtil {
return id; return id;
} }
} }
else if ("condition".equals(nodeType)) { else if (DDFlowNodeType.NODE_COPY.name().equals(nodeType)) {
flowNode.put("incoming", Collections.singletonList(fromId));
String id = createServiceTask(flowNode,process,sequenceFlows);
// 如果当前任务还有后续任务则遍历创建后续任务
com.alibaba.fastjson.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 (DDFlowNodeType.NODE_TASK.name().equals(nodeType)) {
flowNode.put("incoming", Collections.singletonList(fromId)); flowNode.put("incoming", Collections.singletonList(fromId));
String id = createTask(flowNode,process,sequenceFlows); String id = createTask(flowNode,process,sequenceFlows);
@ -52,6 +138,229 @@ public class BpmTransformUtil {
} }
} }
private static String createExclusiveGatewayBuilder(String formId, com.alibaba.fastjson.JSONObject flowNode, BpmnModel model, Process process, List<SequenceFlow> 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<com.alibaba.fastjson.JSONObject> flowNodes = Optional.ofNullable(flowNode.getJSONArray("conditionNodes")).map(e -> e.toJavaList(com.alibaba.fastjson.JSONObject.class)).orElse(Collections.emptyList());
List<String> incoming = Lists.newArrayListWithCapacity(flowNodes.size());
List<com.alibaba.fastjson.JSONObject> conditions = Lists.newCopyOnWriteArrayList();
for (com.alibaba.fastjson.JSONObject element : flowNodes) {
com.alibaba.fastjson.JSONObject childNode = element.getJSONObject("childNode");
String nodeName = element.getString("nodeName");
String expression = element.getString("conditionExpression");
if (Objects.isNull(childNode)) {
incoming.add(exclusiveGatewayId);
com.alibaba.fastjson.JSONObject condition = new com.alibaba.fastjson.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);
List<SequenceFlow> 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);
}
}
com.alibaba.fastjson.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.put("incoming", incoming);
FlowElement flowElement = model.getFlowElement(incoming.get(0));
// 1.0 先进行边连接, 暂存 nextNode
com.alibaba.fastjson.JSONObject nextNode = childNode.getJSONObject("childNode");
String endExId=id("exclusiveGateway")+"end";
process.addFlowElement(DDBpmnModelUtils.createExclusiveGateWayEnd(endExId));
childNode.put("childNode", null);
String identifier =endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/
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<SequenceFlow> 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()) {
com.alibaba.fastjson.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(DDBpmnModelUtils.createExclusiveGateWayEnd(endExId));
String identifier =endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/
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<SequenceFlow> 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()) {
com.alibaba.fastjson.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;
}
private static String createParallelGatewayBuilder(String formId, com.alibaba.fastjson.JSONObject flowNode, BpmnModel model, Process process, List<SequenceFlow> 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));
if (Objects.isNull(flowNode.getJSONArray("conditionNodes"))
&& Objects.isNull(flowNode.getJSONObject("childNode"))) {
return parallelGatewayId;
}
List<com.alibaba.fastjson.JSONObject> flowNodes = Optional.ofNullable(flowNode.getJSONArray("conditionNodes")).map(e -> e.toJavaList(com.alibaba.fastjson.JSONObject.class)).orElse(Collections.emptyList());
List<String> incoming = Lists.newArrayListWithCapacity(flowNodes.size());
for (com.alibaba.fastjson.JSONObject element : flowNodes) {
com.alibaba.fastjson.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);
}
}
com.alibaba.fastjson.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.put("incoming", incoming);
FlowElement flowElement = model.getFlowElement(incoming.get(0));
// 1.0 先进行边连接, 暂存 nextNode
com.alibaba.fastjson.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;
}
private static String createServiceTask(com.alibaba.fastjson.JSONObject flowNode, Process process, List<SequenceFlow> sequenceFlows) {
List<String> 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);
// todo lvshaohua
serviceTask.setImplementationType("class");
serviceTask.setImplementation("com.dingding.mid.listener.Vue3Listener");
process.addFlowElement(serviceTask);
process.addFlowElement(connect(incoming.get(0), id,sequenceFlows));
}
return id;
}
private static String createTask(com.alibaba.fastjson.JSONObject flowNode, Process process, List<SequenceFlow> sequenceFlows) { private static String createTask(com.alibaba.fastjson.JSONObject flowNode, Process process, List<SequenceFlow> sequenceFlows) {
List<String> incoming = flowNode.getJSONArray("incoming").toJavaList(String.class); List<String> incoming = flowNode.getJSONArray("incoming").toJavaList(String.class);
@ -144,4 +453,16 @@ public class BpmTransformUtil {
sequenceFlows.add(flow); sequenceFlows.add(flow);
return flow; return flow;
} }
protected static StartEvent createStartEvent() {
StartEvent startEvent = new StartEvent();
startEvent.setId(id("start"));
return startEvent;
}
protected static EndEvent createEndEvent() {
EndEvent endEvent = new EndEvent();
endEvent.setId(id("end"));
return endEvent;
}
} }