update 更改模块名称
This commit is contained in:
+2097
File diff suppressed because it is too large
Load Diff
+1604
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,224 @@
|
||||
package com.jero.modules.activiti.controller;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.jero.common.api.vo.Result;
|
||||
import com.jero.common.constant.enums.LanguageEnum;
|
||||
import com.jero.common.util.MessageUtils;
|
||||
import com.jero.modules.activiti.service.ProcessService;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.bpmn.converter.BpmnXMLConverter;
|
||||
import org.activiti.bpmn.model.BpmnModel;
|
||||
import org.activiti.engine.*;
|
||||
import org.activiti.engine.repository.Deployment;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
import org.activiti.engine.repository.ProcessDefinitionQuery;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.activiti.engine.task.Task;
|
||||
import org.activiti.engine.task.TaskQuery;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* @author liJiaRao
|
||||
* @date 2023-08-02 15:05
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/modeler")
|
||||
public class AController {
|
||||
@Autowired
|
||||
private ProcessService processService;
|
||||
@Resource
|
||||
private RepositoryService repositoryService;
|
||||
@Resource
|
||||
private TaskService taskService;
|
||||
|
||||
|
||||
@GetMapping("/deploy")
|
||||
public Result<Map<String, String>> deploy(@RequestParam(value = "name", required = false) String name,
|
||||
@RequestParam(value = "classpathResource") String classpathResource) {
|
||||
if (StringUtils.isNotBlank(name)) {
|
||||
//根据流程定义Key查询
|
||||
name = "出差申请流程";
|
||||
}
|
||||
// 3、使用RepositoryService进行部署
|
||||
Deployment deployment = repositoryService.createDeployment()
|
||||
//.addClasspathResource("bpmn/diagram_1.bpmn20.xml") // 添加bpmn资源
|
||||
//.addClasspathResource("bpmn/business-trips.png") // 添加png资源
|
||||
.addClasspathResource(classpathResource)
|
||||
.name(name)
|
||||
.deploy();
|
||||
// 4、输出部署信息
|
||||
Map<String, String> map = new HashMap<>();
|
||||
|
||||
map.put("流程部署id:", deployment.getId());
|
||||
map.put("流程部署名称:", deployment.getName());
|
||||
map.put("流程部署key:", deployment.getKey());
|
||||
return Result.OK(map);
|
||||
}
|
||||
|
||||
@GetMapping("/deleteDeployment")
|
||||
@ApiOperation(value = "删除已部署的流程定义", notes = "删除已部署的流程定义")
|
||||
public Result<Object> deleteDeployment(@RequestParam(value = "id", required = false) String id) {
|
||||
// true 表示级联删除引用,比如 act_ru_execution 数据
|
||||
repositoryService.deleteDeployment(id, true);
|
||||
return Result.OK();
|
||||
}
|
||||
|
||||
@GetMapping("/findProcessDefinition")
|
||||
@ApiOperation(value = "查询流程定义列表", notes = "查询流程定义列表")
|
||||
public Result<List<Map<String, Object>>> findProcessDefinition(@RequestParam(value = "processDefinitionKey", required = false) String processDefinitionKey,
|
||||
@RequestParam(value = "processDefinitionName", required = false) String processDefinitionName) {
|
||||
List<Map<String, Object>> allList = new ArrayList<>();
|
||||
//创建一个流程定义查询
|
||||
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
|
||||
|
||||
if (StringUtils.isNotBlank(processDefinitionKey)) {
|
||||
//根据流程定义Key查询
|
||||
processDefinitionQuery.processDefinitionKey(processDefinitionKey);
|
||||
}
|
||||
if (StringUtils.isNotBlank(processDefinitionName)) {
|
||||
//根据流程定义name查询
|
||||
processDefinitionQuery.processDefinitionNameLike(processDefinitionName);
|
||||
}
|
||||
|
||||
List<ProcessDefinition> processDefinitionList = processDefinitionQuery.list();
|
||||
|
||||
for (ProcessDefinition processDefinition : processDefinitionList) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
String deploymentId = processDefinition.getDeploymentId();
|
||||
Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
|
||||
map.put("processDefinition", BeanUtil.beanToMap(processDefinition));
|
||||
map.put("deployment", deployment.toString());
|
||||
allList.add(map);
|
||||
}
|
||||
return Result.OK(allList);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/start")
|
||||
public Result<Map<String, String>> start(@RequestParam(value = "key", required = false) String key) {
|
||||
// 1、创建ProcessEngine
|
||||
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
|
||||
// 2、获取RunTimeService
|
||||
RuntimeService runtimeService = processEngine.getRuntimeService();
|
||||
// 3、根据流程定义Id启动流程
|
||||
ProcessInstance processInstance = runtimeService
|
||||
.startProcessInstanceByKey(key);
|
||||
|
||||
// 输出内容
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("流程Id:", processInstance.getDeploymentId());
|
||||
map.put("流程定义id:", processInstance.getProcessDefinitionId());
|
||||
map.put("流程实例id:", processInstance.getId());
|
||||
map.put("当前活动Id:", processInstance.getActivityId());
|
||||
|
||||
|
||||
return Result.OK(map);
|
||||
}
|
||||
|
||||
@GetMapping("/getTaskList")
|
||||
public Result<List<Map<String, String>>> testFindPersonalTaskList(@RequestParam(value = "assignee") String assignee,
|
||||
@RequestParam(value = "processKey") String processKey) {
|
||||
// 根据流程key 和 任务负责人 查询任务
|
||||
TaskQuery taskQuery = taskService.createTaskQuery();
|
||||
if (StringUtils.isNotBlank(assignee)) {
|
||||
taskQuery.taskAssignee(assignee);//只查询该任务负责人的任务
|
||||
}
|
||||
if (StringUtils.isNotBlank(processKey)) {
|
||||
taskQuery.processDefinitionKey(processKey); //流程Key
|
||||
}
|
||||
List<Task> list = taskQuery.list();
|
||||
List<Map<String, String>> resut = new ArrayList<>();
|
||||
for (Task task : list) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("流程实例id:", task.getProcessInstanceId());
|
||||
map.put("任务id:", task.getId());
|
||||
map.put("任务负责人:", task.getAssignee());
|
||||
map.put("任务名称:", task.getName());
|
||||
resut.add(map);
|
||||
}
|
||||
return Result.OK(resut);
|
||||
}
|
||||
|
||||
@GetMapping("/complete")
|
||||
public Result<Object> complete(@RequestParam(value = "taskId") String taskId) {
|
||||
taskService.complete(taskId);
|
||||
return Result.OK();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加签
|
||||
* @param taskId
|
||||
* @param loginName
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/delegateTask")
|
||||
public Result<Object> delegateTask(@RequestParam(value = "taskId") String taskId,
|
||||
@RequestParam(value = "loginName") String loginName) {
|
||||
taskService.delegateTask(taskId, loginName);
|
||||
return Result.OK();
|
||||
}
|
||||
|
||||
@GetMapping("/resolveTask")
|
||||
public Result<Object> resolveTask(@RequestParam(value = "taskId") String taskId) {
|
||||
taskService.resolveTask(taskId);
|
||||
return Result.OK();
|
||||
}
|
||||
|
||||
@GetMapping("/addTask")
|
||||
// @ApiOperation("新增节点")
|
||||
public Object addTask(String taskId, String assignee) {
|
||||
return processService.addTask(taskId,assignee);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping(value = "/readResource")
|
||||
@ApiOperation(value = "获取实时流程图", notes = "获取实时流程图,输出跟踪流程信息")
|
||||
public void getFlowImgByInstanceId(@RequestParam(value = "processInstanceId") String processInstanceId, HttpServletResponse response) {
|
||||
processService.getFlowImgByInstanceId(processInstanceId, response);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/export/{modelId}")
|
||||
@ApiOperation(value = "将流程模型导出为 bpmn文件",notes = "将流程模型导出为 bpmn文件")
|
||||
public void export(@PathVariable("modelId") @ApiParam("流程模型Id") String modelId, HttpServletResponse response) {
|
||||
try {
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(modelId);
|
||||
|
||||
// 流程非空判断
|
||||
if (!CollectionUtils.isEmpty(bpmnModel.getProcesses())) {
|
||||
BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
|
||||
byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
|
||||
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
|
||||
String filename = bpmnModel.getMainProcess().getId() + ".bpmn";
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + filename);
|
||||
IOUtils.copy(in, response.getOutputStream());
|
||||
response.flushBuffer();
|
||||
} else {
|
||||
log.error("导出model的bpmn文件失败:modelId={}", modelId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("导出model的bpmn文件失败:modelId={}", modelId, e);
|
||||
}
|
||||
}
|
||||
@GetMapping("test")
|
||||
public Result<String> getRedisTest(){
|
||||
String msg1 = MessageUtils.getMessage("message");
|
||||
String msg2 = MessageUtils.getMessage("message.operate.error","123456");
|
||||
LanguageEnum language = MessageUtils.getLanguage();
|
||||
return Result.OK(msg1+"\n"+msg2) ;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.jero.modules.activiti.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
*
|
||||
*@author liJiaRao
|
||||
*@date 2023-08-04 16:04
|
||||
*/
|
||||
|
||||
/**
|
||||
* 二进制资源表
|
||||
*/
|
||||
@Data
|
||||
@TableName(value = "act_ge_bytearray")
|
||||
public class ActGeBytearray {
|
||||
@TableId(value = "ID_", type = IdType.INPUT)
|
||||
private String id;
|
||||
|
||||
@TableField(value = "REV_")
|
||||
private Integer rev;
|
||||
|
||||
@TableField(value = "NAME_")
|
||||
private String name;
|
||||
|
||||
@TableField(value = "DEPLOYMENT_ID_")
|
||||
private String deploymentId;
|
||||
|
||||
@TableField(value = "BYTES_")
|
||||
private byte[] bytes;
|
||||
|
||||
@TableField(value = "GENERATED_")
|
||||
private Integer generated;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.jero.modules.activiti.listener;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.engine.ProcessEngine;
|
||||
import org.activiti.engine.ProcessEngines;
|
||||
import org.activiti.engine.RuntimeService;
|
||||
import org.activiti.engine.delegate.DelegateTask;
|
||||
import org.activiti.engine.delegate.TaskListener;
|
||||
|
||||
/**
|
||||
* @author liJiaRao
|
||||
* @date 2023-08-04 10:53
|
||||
*/
|
||||
@Slf4j
|
||||
public class SignListener implements TaskListener {
|
||||
@Override
|
||||
public void notify(DelegateTask delegateTask) {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
//获取流程id
|
||||
String taskId = delegateTask.getExecutionId();
|
||||
//获取流程参数pass,会签人员完成自己的审批任务时会添加流程参数pass,false为拒绝,true为同意
|
||||
// 1、创建ProcessEngine
|
||||
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
|
||||
// 2、获取RunTimeService
|
||||
RuntimeService runtimeService = processEngine.getRuntimeService();
|
||||
boolean pass = (Boolean) runtimeService.getVariable(taskId, "pass");
|
||||
|
||||
/* ${nrOfCompletedInstances/nrOfInstances==1}
|
||||
* false:有一个人拒绝,整个流程就结束了,
|
||||
* 因为Complete condition的值为pass == false,即,当流程参数为pass时会签就结束开始下一个任务
|
||||
* 所以,当pass == false时,直接设置下一个流程跳转需要的参数
|
||||
* true:审批人同意,同时要判断是不是所有的人都已经完成了,而不是由一个人同意该会签就结束
|
||||
* 值得注意的是如果一个审批人完成了审批进入到该监听时nrOfCompletedInstances的值还没有更新,因此需要+1
|
||||
*/
|
||||
Integer complete = (Integer) runtimeService.getVariable(taskId, "nrOfCompletedInstances");
|
||||
Integer all = (Integer) runtimeService.getVariable(taskId, "nrOfInstances");
|
||||
// 这里的test对应的是第一个节点中的对应的参数
|
||||
String username= (String) runtimeService.getVariable(delegateTask.getExecutionId(), "test");
|
||||
if(!pass){
|
||||
//会签结束,返回发起人节点
|
||||
runtimeService.setVariable(taskId, "countersignState", 0);
|
||||
runtimeService.setVariable(taskId, "test", username);
|
||||
}else{
|
||||
|
||||
//说明都完成了并且没有人拒绝
|
||||
if((complete + 1) / all == 1){
|
||||
// 流程流向下个节点 test2为下个节点人的参数
|
||||
runtimeService.setVariable(taskId, "countersignState", 1);
|
||||
runtimeService.setVariable(taskId, "test2", "xiaowang");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.jero.modules.activiti.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.jero.modules.activiti.entity.ActGeBytearray;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author liJiaRao
|
||||
* @date 2023-08-04 16:04
|
||||
*/
|
||||
@Mapper
|
||||
public interface ActGeBytearrayMapper extends BaseMapper<ActGeBytearray> {
|
||||
List<ActGeBytearray> getActGeBytearrayList(@Param("processDefinitionId") String processDefinitionId);
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.jero.modules.activiti.mapper.ActGeBytearrayMapper">
|
||||
<resultMap id="BaseResultMap" type="com.jero.modules.activiti.entity.ActGeBytearray">
|
||||
<!--@mbg.generated-->
|
||||
<!--@Table act_ge_bytearray-->
|
||||
<id column="ID_" jdbcType="VARCHAR" property="id" />
|
||||
<result column="REV_" jdbcType="INTEGER" property="rev" />
|
||||
<result column="NAME_" jdbcType="VARCHAR" property="name" />
|
||||
<result column="DEPLOYMENT_ID_" jdbcType="VARCHAR" property="deploymentId" />
|
||||
<result column="BYTES_" jdbcType="BLOB" property="bytes" />
|
||||
<result column="GENERATED_" jdbcType="TINYINT" property="generated" />
|
||||
</resultMap>
|
||||
<sql id="Base_Column_List">
|
||||
<!--@mbg.generated-->
|
||||
ID_, REV_, NAME_, DEPLOYMENT_ID_, BYTES_, GENERATED_
|
||||
</sql>
|
||||
<select id="getActGeBytearrayList" resultType="com.jero.modules.activiti.entity.ActGeBytearray">
|
||||
select a.*
|
||||
from act_ge_bytearray a
|
||||
inner join act_re_procdef b ON a.DEPLOYMENT_ID_ = b.DEPLOYMENT_ID_
|
||||
where b.ID_ = #{processDefinitionId}
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.jero.modules.activiti.service;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @author liJiaRao
|
||||
* @date 2023-08-03 15:37
|
||||
*/
|
||||
public interface ProcessService {
|
||||
void getFlowImgByInstanceId(String pProcessInstanceId, HttpServletResponse response);
|
||||
|
||||
Object addTask(String taskId, String assignee);
|
||||
}
|
||||
+344
@@ -0,0 +1,344 @@
|
||||
package com.jero.modules.activiti.service.impl;
|
||||
|
||||
import com.jero.common.exception.JeroBootException;
|
||||
import com.jero.modules.activiti.config.DefaultProcessDiagramGenerator;
|
||||
import com.jero.modules.activiti.entity.ActGeBytearray;
|
||||
import com.jero.modules.activiti.mapper.ActGeBytearrayMapper;
|
||||
import com.jero.modules.activiti.service.ProcessService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.bpmn.BpmnAutoLayout;
|
||||
import org.activiti.bpmn.converter.BpmnXMLConverter;
|
||||
import org.activiti.bpmn.model.Process;
|
||||
import org.activiti.bpmn.model.*;
|
||||
import org.activiti.engine.*;
|
||||
import org.activiti.engine.history.HistoricActivityInstance;
|
||||
import org.activiti.engine.history.HistoricProcessInstance;
|
||||
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||
import org.activiti.engine.impl.persistence.deploy.DeploymentManager;
|
||||
import org.activiti.engine.runtime.Execution;
|
||||
import org.activiti.engine.task.Task;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author liJiaRao
|
||||
* @date 2023-08-03 15:38
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ProcessServiceImpl implements ProcessService {
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
@Autowired
|
||||
private HistoryService historyService;
|
||||
@Autowired
|
||||
private ProcessEngine processEngine;
|
||||
@Autowired
|
||||
private RuntimeService runtimeService;
|
||||
@Autowired
|
||||
private TaskService taskService;
|
||||
@Autowired
|
||||
private ManagementService managementService;
|
||||
@Resource
|
||||
private ActGeBytearrayMapper actGeBytearrayMapper;
|
||||
|
||||
@Override
|
||||
public void getFlowImgByInstanceId(String processInstanceId, HttpServletResponse response) {
|
||||
InputStream imageStream = null;
|
||||
try {
|
||||
// 获取历史流程实例
|
||||
HistoricProcessInstance historicProcessInstance = historyService
|
||||
.createHistoricProcessInstanceQuery()
|
||||
.processInstanceId(processInstanceId).singleResult();
|
||||
if (historicProcessInstance == null){
|
||||
throw new JeroBootException("历史流程不存在");
|
||||
}
|
||||
// 获取流程中已经执行的节点,按照执行先后顺序排序
|
||||
List<HistoricActivityInstance> historicActivityInstances = historyService
|
||||
.createHistoricActivityInstanceQuery()
|
||||
.processInstanceId(processInstanceId)
|
||||
.orderByHistoricActivityInstanceId()
|
||||
.asc().list();
|
||||
// 高亮已经执行流程节点ID集合
|
||||
List<String> highLightedActivitiIds = new ArrayList<>();
|
||||
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
|
||||
// 用默认颜色
|
||||
highLightedActivitiIds.add(historicActivityInstance.getActivityId());
|
||||
}
|
||||
// 正在执行的节点
|
||||
List<Execution> runTaskList = runtimeService.createExecutionQuery()
|
||||
.processInstanceId(processInstanceId)
|
||||
.list();
|
||||
List<String> runningActivityIdList = new ArrayList<>();
|
||||
for (Execution execution : runTaskList) {
|
||||
if (!StringUtils.isEmpty(execution.getActivityId())) {
|
||||
runningActivityIdList.add(execution.getActivityId());
|
||||
}
|
||||
}
|
||||
List<String> currIds = historicActivityInstances.stream()
|
||||
.filter(item -> item.getEndTime() != null)
|
||||
.map(HistoricActivityInstance::getActivityId).collect(Collectors.toList());
|
||||
|
||||
// 获得流程引擎配置
|
||||
ProcessEngineConfiguration processEngineConfiguration = processEngine.getProcessEngineConfiguration();
|
||||
|
||||
BpmnModel bpmnModel = repositoryService
|
||||
.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
|
||||
// 高亮流程已发生流转的线id集合
|
||||
List<String> highLightedFlowIds = getHighLightedFlows(bpmnModel, historicActivityInstances);
|
||||
//
|
||||
imageStream = new DefaultProcessDiagramGenerator().generateDiagram(
|
||||
bpmnModel,
|
||||
"png",
|
||||
highLightedActivitiIds,//所有活动过的节点,包括当前在激活状态下的节点
|
||||
currIds,//当前为激活状态下的节点
|
||||
highLightedFlowIds,//活动过的线
|
||||
"宋体",
|
||||
"宋体",
|
||||
"宋体",
|
||||
processEngineConfiguration.getClassLoader(),
|
||||
1.0,
|
||||
runningActivityIdList);
|
||||
|
||||
OutputStream out = null;
|
||||
out = response.getOutputStream();
|
||||
int len = 0;
|
||||
byte[] b = new byte[1024];
|
||||
while ((len = imageStream.read(b)) != -1) {
|
||||
out.write(b, 0, len);
|
||||
}
|
||||
out.flush();
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (imageStream != null) {
|
||||
try {
|
||||
imageStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object addTask(String taskId, String assignee) {
|
||||
// 1、创建ProcessEngine
|
||||
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
|
||||
final TaskService taskService = processEngine.getTaskService();
|
||||
final RepositoryService repositoryService = processEngine.getRepositoryService();
|
||||
Task userTask = taskService.createTaskQuery()
|
||||
.taskId(taskId)
|
||||
// .taskAssignee(assignee)
|
||||
.singleResult();
|
||||
|
||||
final BpmnModel bpmnModel = repositoryService.getBpmnModel(userTask.getProcessDefinitionId());
|
||||
Process process = bpmnModel.getMainProcess();
|
||||
process.removeFlowElement("add");//移除最终节点连线
|
||||
process.removeFlowElement("sequenceFlow-5d7e3faa-6c00-4010-8485-fe79c286448b");//移除最终节点连线
|
||||
process.removeFlowElement("sequenceFlow-aba52ded-835d-4863-b303-1b9771ae93cf");//移除最终节点连线
|
||||
process.addFlowElement(createSequenceFlow("Activity_0m576ex", "Event_17e1txx"));//新增节点 于原节点连线
|
||||
/*process.removeFlowElement("Flow_0stcykp");//移除最终节点连线
|
||||
process.addFlowElement(createUserTask("add", "First task", "fred"));//新增节点
|
||||
process.addFlowElement(createSequenceFlow("Activity_0m576ex", "add"));//新增节点 于原节点连线
|
||||
process.addFlowElement(createSequenceFlow("add", "Event_17e1txx"));//新增节点 于原节点连线*/
|
||||
//重新绘画图形
|
||||
BpmnAutoLayout bpmnAutoLayout = new BpmnAutoLayout(bpmnModel);
|
||||
bpmnAutoLayout.execute();
|
||||
BpmnXMLConverter converter = new BpmnXMLConverter();
|
||||
//把bpmnModel对象转换成字符
|
||||
byte[] bytes = converter.convertToXML(bpmnModel);
|
||||
//清除缓存
|
||||
ProcessEngineConfigurationImpl configuration = (ProcessEngineConfigurationImpl) processEngine.getProcessEngineConfiguration();
|
||||
DeploymentManager deploymentManager = configuration.getDeploymentManager();
|
||||
deploymentManager.getProcessDefinitionCache().remove(userTask.getProcessDefinitionId());
|
||||
|
||||
// String xmlContenxt = new String(bytes);
|
||||
List<ActGeBytearray> actGeBytearrayList = actGeBytearrayMapper.getActGeBytearrayList(userTask.getProcessDefinitionId());
|
||||
actGeBytearrayList = actGeBytearrayList.stream().filter(item -> item.getName().endsWith(".bpmn")).peek(item -> {
|
||||
item.setBytes(bytes);
|
||||
}).collect(Collectors.toList());
|
||||
if (ObjectUtils.isNotEmpty(actGeBytearrayList)) {
|
||||
actGeBytearrayMapper.updateById(actGeBytearrayList.get(0));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
protected static UserTask createUserTask(String id, String name, String assignee) {
|
||||
UserTask userTask = new UserTask();
|
||||
userTask.setName(name);
|
||||
userTask.setId(id);
|
||||
userTask.setAssignee(assignee);
|
||||
return userTask;
|
||||
}
|
||||
|
||||
protected static SequenceFlow createSequenceFlow(String from, String to) {
|
||||
SequenceFlow flow = new SequenceFlow();
|
||||
flow.setSourceRef(from);
|
||||
flow.setTargetRef(to);
|
||||
return flow;
|
||||
}
|
||||
/**
|
||||
* @param bpmnModel bpmnModel
|
||||
* @param historicActivityInstanceList historicActivityInstanceList
|
||||
* @return HighLightedFlows
|
||||
*/
|
||||
public List<String> getHighLightedFlows(BpmnModel bpmnModel,
|
||||
List<HistoricActivityInstance> historicActivityInstanceList) {
|
||||
//historicActivityInstanceList 是 流程中已经执行的历史活动实例
|
||||
// 已经流经的顺序流,需要高亮显示
|
||||
List<String> highFlows = new ArrayList<>();
|
||||
|
||||
// 全部活动节点
|
||||
List<FlowNode> allHistoricActivityNodeList = new ArrayList<>();
|
||||
|
||||
// 拥有endTime的历史活动实例,即已经完成了的节点
|
||||
List<HistoricActivityInstance> finishedActivityInstancesList = new ArrayList<>();
|
||||
|
||||
/*
|
||||
* 循环的目的:
|
||||
* 获取所有的历史节点FlowNode并放入allHistoricActivityNodeList
|
||||
* 获取所有确定结束了的历史节点finishedActivityInstancesList
|
||||
*/
|
||||
for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
|
||||
// 获取流程节点
|
||||
// bpmnModel.getMainProcess()获取一个Process对象
|
||||
FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true);
|
||||
allHistoricActivityNodeList.add(flowNode);
|
||||
|
||||
// 如果结束时间不为空,表示当前节点已经完成
|
||||
if (historicActivityInstance.getEndTime() != null) {
|
||||
finishedActivityInstancesList.add(historicActivityInstance);
|
||||
}
|
||||
}
|
||||
|
||||
FlowNode currentFlowNode;
|
||||
FlowNode targetFlowNode;
|
||||
HistoricActivityInstance currentActivityInstance;
|
||||
|
||||
// 遍历已经完成的活动实例,从每个实例的outgoingFlows中找到已经执行的
|
||||
for (int k = 0; k < finishedActivityInstancesList.size(); k++) {
|
||||
currentActivityInstance = finishedActivityInstancesList.get(k);
|
||||
|
||||
// 获得当前活动对应的节点信息以及outgoingFlows信息
|
||||
currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true);
|
||||
|
||||
// 当前节点的所有流出线
|
||||
List<SequenceFlow> outgoingFlowList = currentFlowNode.getOutgoingFlows();
|
||||
|
||||
/*
|
||||
* 遍历outgoingFlows并找到已经流转的 满足如下条件认为已经流转:
|
||||
* 1、当前节点是并行网关或者兼容网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已经流转
|
||||
* 2、当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最早的流转节点视为有效流转
|
||||
* (第二点有问题,有过驳回的,会只绘制驳回的流程线,通过走向下一级的流程线没有高亮显示)
|
||||
*/
|
||||
if ("parallelGateway".equals(currentActivityInstance.getActivityType()) ||
|
||||
"inclusiveGateway".equals(currentActivityInstance.getActivityType())) {
|
||||
// 遍历历史活动节点,找到匹配流程目标节点的
|
||||
for (SequenceFlow outgoingFlow : outgoingFlowList) {
|
||||
// 获取当前节点流程线对应的下一级节点
|
||||
targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(outgoingFlow.getTargetRef(), true);
|
||||
|
||||
// 如果下级节点包含在所有历史节点中,则将当前节点的流出线高亮显示
|
||||
if (allHistoricActivityNodeList.contains(targetFlowNode)) {
|
||||
highFlows.add(outgoingFlow.getId());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* 2、当前节点不是并行网关或者兼容网关
|
||||
* 【已解决-问题】如果当前节点有驳回功能,驳回到申请节点,
|
||||
* 则因为申请节点在历史节点中,导致当前节点驳回到申请节点的流程线被高亮显示,但实际并没有进行驳回操作
|
||||
*/
|
||||
List<Map<String, Object>> tempMapList = new ArrayList<>();
|
||||
|
||||
// 当前节点ID
|
||||
String currentActivityId = currentActivityInstance.getActivityId();
|
||||
|
||||
int size = historicActivityInstanceList.size();
|
||||
boolean ifStartFind = false;
|
||||
boolean ifFinded = false;
|
||||
HistoricActivityInstance historicActivityInstance;
|
||||
|
||||
// 循环当前节点的所有流出线
|
||||
// 循环所有的历史节点
|
||||
// log.info("【开始】-匹配当前节点-ActivityId=【{}】需要高亮显示的流出线", currentActivityId);
|
||||
// log.info("循环历史节点");
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
// // 如果当前节点流程线对应的下级节点在历史节点中,则该条流程线进行高亮显示(【问题】有驳回流程线时,即使没有进行驳回操作,因为申请节点在历史节点中,也会将驳回流程线高亮显示-_-||)
|
||||
// if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
|
||||
// Map<String, Object> map = new HashMap<>();
|
||||
// map.put("highLightedFlowId", sequenceFlow.getId());
|
||||
// map.put("highLightedFlowStartTime", historicActivityInstance.getStartTime().getTime());
|
||||
// tempMapList.add(map);
|
||||
// // highFlows.add(sequenceFlow.getId());
|
||||
// }
|
||||
|
||||
// 历史节点
|
||||
historicActivityInstance = historicActivityInstanceList.get(i);
|
||||
// log.info("第【{}/{}】个历史节点-ActivityId=【{}】", i + 1, size, historicActivityInstance.getActivityId());
|
||||
|
||||
// 如果循环历史节点中的id等于当前节点id,从当前历史节点继续先后查找是否有当前流程线等于的节点
|
||||
// 历史节点的序号需要大于等于已经完成历史节点的序号,放置驳回重审一个节点经过两次时只取第一次的流出线高亮显示,第二次的不显示
|
||||
if (i >= k && historicActivityInstance.getActivityId().equals(currentActivityId)) {
|
||||
// log.info("第【{}】个历史节点和当前节点一致-ActivityId=【{}】", i + 1, historicActivityInstance.getActivityId());
|
||||
ifStartFind = true;
|
||||
// 跳过当前节点继续查找下一个节点
|
||||
continue;
|
||||
}
|
||||
if (ifStartFind) {
|
||||
// log.info("[开始]-循环当前节点-ActivityId=【{}】的所有流出线", currentActivityId);
|
||||
|
||||
ifFinded = false;
|
||||
for (SequenceFlow sequenceFlow : outgoingFlowList) {
|
||||
// 如果当前节点流程线对应的下级节点在其后面的历史节点中,则该条流程线进行高亮显示
|
||||
// 【问题】
|
||||
// log.info("当前流出线的下级节点=[{}]", sequenceFlow.getTargetRef());
|
||||
if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
|
||||
// log.info("当前节点[{}]需高亮显示的流出线=[{}]", currentActivityId, sequenceFlow.getId());
|
||||
highFlows.add(sequenceFlow.getId());
|
||||
// 暂时默认找到离当前节点最近的下一级节点即退出循环,否则有多条流出线时将全部被高亮显示
|
||||
ifFinded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// log.info("[完成]-循环当前节点-ActivityId=【{}】的所有流出线", currentActivityId);
|
||||
}
|
||||
if (ifFinded) {
|
||||
// 暂时默认找到离当前节点最近的下一级节点即退出历史节点循环,否则有多条流出线时将全部被高亮显示
|
||||
break;
|
||||
}
|
||||
}
|
||||
// log.info("【完成】-匹配当前节点-ActivityId=【{}】需要高亮显示的流出线", currentActivityId);
|
||||
// if (!CollectionUtils.isEmpty(tempMapList)) {
|
||||
// // 遍历匹配的集合,取得开始时间最早的一个
|
||||
// long earliestStamp = 0L;
|
||||
// String highLightedFlowId = null;
|
||||
// for (Map<String, Object> map : tempMapList) {
|
||||
// long highLightedFlowStartTime = Long.valueOf(map.get("highLightedFlowStartTime").toString());
|
||||
// if (earliestStamp == 0 || earliestStamp <= highLightedFlowStartTime) {
|
||||
// highLightedFlowId = map.get("highLightedFlowId").toString();
|
||||
// earliestStamp = highLightedFlowStartTime;
|
||||
// }
|
||||
// }
|
||||
// highFlows.add(highLightedFlowId);
|
||||
// }
|
||||
}
|
||||
}
|
||||
return highFlows;
|
||||
}
|
||||
}
|
||||
+1194
File diff suppressed because it is too large
Load Diff
+925
@@ -0,0 +1,925 @@
|
||||
package com.jero.modules.activiti.service.impl.image;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.activiti.bpmn.model.Process;
|
||||
import org.activiti.bpmn.model.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* Class to generate an image based the diagram interchange information in a BPMN 2.0 process.
|
||||
* 在 BPMN 2.0 流程中基于图表交换信息生成图像的类。
|
||||
*
|
||||
* @author Joram Barrez
|
||||
* @author Tijs Rademakers
|
||||
*/
|
||||
@Slf4j
|
||||
public class CustomProcessDiagramGenerator implements ICustomProcessDiagramGenerator {
|
||||
|
||||
protected String ACTIVITY_FONT_NAME = "微软雅黑";
|
||||
protected String LABEL_FONT_NAME = "微软雅黑";
|
||||
protected String ANNOTATION_FONT_NAME = "微软雅黑";
|
||||
|
||||
protected Map<Class<? extends BaseElement>, ActivityDrawInstruction> activityDrawInstructions = new HashMap<>();
|
||||
protected Map<Class<? extends BaseElement>, ArtifactDrawInstruction> artifactDrawInstructions = new HashMap<>();
|
||||
|
||||
/**
|
||||
* The instructions on how to draw a certain construct is
|
||||
* created statically and stored in a map for performance.
|
||||
*/
|
||||
public CustomProcessDiagramGenerator() {
|
||||
// start event
|
||||
activityDrawInstructions.put(StartEvent.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
StartEvent startEvent = (StartEvent) flowNode;
|
||||
if (startEvent.getEventDefinitions() != null && !startEvent.getEventDefinitions().isEmpty()) {
|
||||
EventDefinition eventDefinition = startEvent.getEventDefinitions().get(0);
|
||||
if (eventDefinition instanceof TimerEventDefinition) {
|
||||
processDiagramCanvas.drawTimerStartEvent(flowNode.getId(), graphicInfo);
|
||||
} else if (eventDefinition instanceof ErrorEventDefinition) {
|
||||
processDiagramCanvas.drawErrorStartEvent(flowNode.getId(), graphicInfo);
|
||||
} else if (eventDefinition instanceof SignalEventDefinition) {
|
||||
processDiagramCanvas.drawSignalStartEvent(flowNode.getId(), graphicInfo);
|
||||
} else if (eventDefinition instanceof MessageEventDefinition) {
|
||||
processDiagramCanvas.drawMessageStartEvent(flowNode.getId(), graphicInfo);
|
||||
} else {
|
||||
processDiagramCanvas.drawNoneStartEvent(flowNode.getId(), graphicInfo);
|
||||
}
|
||||
} else {
|
||||
processDiagramCanvas.drawNoneStartEvent(flowNode.getId(), graphicInfo);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// signal catch
|
||||
activityDrawInstructions.put(IntermediateCatchEvent.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
IntermediateCatchEvent intermediateCatchEvent = (IntermediateCatchEvent) flowNode;
|
||||
if (intermediateCatchEvent.getEventDefinitions() != null && !intermediateCatchEvent
|
||||
.getEventDefinitions().isEmpty()) {
|
||||
if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof SignalEventDefinition) {
|
||||
processDiagramCanvas.drawCatchingSignalEvent(flowNode.getId(), flowNode.getName(), graphicInfo, true);
|
||||
} else if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof TimerEventDefinition) {
|
||||
processDiagramCanvas.drawCatchingTimerEvent(flowNode.getId(), flowNode.getName(), graphicInfo, true);
|
||||
} else if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof MessageEventDefinition) {
|
||||
processDiagramCanvas.drawCatchingMessageEvent(flowNode.getId(), flowNode.getName(), graphicInfo, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// signal throw
|
||||
activityDrawInstructions.put(ThrowEvent.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
ThrowEvent throwEvent = (ThrowEvent) flowNode;
|
||||
if (throwEvent.getEventDefinitions() != null && !throwEvent.getEventDefinitions().isEmpty()) {
|
||||
if (throwEvent.getEventDefinitions().get(0) instanceof SignalEventDefinition) {
|
||||
processDiagramCanvas.drawThrowingSignalEvent(flowNode.getId(), graphicInfo);
|
||||
} else if (throwEvent.getEventDefinitions().get(0) instanceof CompensateEventDefinition) {
|
||||
processDiagramCanvas.drawThrowingCompensateEvent(flowNode.getId(), graphicInfo);
|
||||
} else {
|
||||
processDiagramCanvas.drawThrowingNoneEvent(flowNode.getId(), graphicInfo);
|
||||
}
|
||||
} else {
|
||||
processDiagramCanvas.drawThrowingNoneEvent(flowNode.getId(), graphicInfo);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// end event
|
||||
activityDrawInstructions.put(EndEvent.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
EndEvent endEvent = (EndEvent) flowNode;
|
||||
if (endEvent.getEventDefinitions() != null && !endEvent.getEventDefinitions().isEmpty()) {
|
||||
if (endEvent.getEventDefinitions().get(0) instanceof ErrorEventDefinition) {
|
||||
processDiagramCanvas.drawErrorEndEvent(flowNode.getId(), flowNode.getName(), graphicInfo);
|
||||
} else {
|
||||
processDiagramCanvas.drawNoneEndEvent(flowNode.getId(), flowNode.getName(), graphicInfo);
|
||||
}
|
||||
} else {
|
||||
processDiagramCanvas.drawNoneEndEvent(flowNode.getId(), flowNode.getName(), graphicInfo);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// task
|
||||
activityDrawInstructions.put(Task.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
processDiagramCanvas.drawTask(flowNode.getId(), flowNode.getName(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// user task
|
||||
activityDrawInstructions.put(UserTask.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
processDiagramCanvas.drawUserTask(flowNode.getId(), flowNode.getName(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// script task
|
||||
activityDrawInstructions.put(ScriptTask.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
processDiagramCanvas.drawScriptTask(flowNode.getId(), flowNode.getName(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// service task
|
||||
activityDrawInstructions.put(ServiceTask.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
ServiceTask serviceTask = (ServiceTask) flowNode;
|
||||
processDiagramCanvas.drawServiceTask(flowNode.getId(), flowNode.getName(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// receive task
|
||||
activityDrawInstructions.put(ReceiveTask.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
processDiagramCanvas.drawReceiveTask(flowNode.getId(), flowNode.getName(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// send task
|
||||
activityDrawInstructions.put(SendTask.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
processDiagramCanvas.drawSendTask(flowNode.getId(), flowNode.getName(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// manual task
|
||||
activityDrawInstructions.put(ManualTask.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
processDiagramCanvas.drawManualTask(flowNode.getId(), flowNode.getName(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// businessRuleTask task
|
||||
activityDrawInstructions.put(BusinessRuleTask.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
processDiagramCanvas.drawBusinessRuleTask(flowNode.getId(), flowNode.getName(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// exclusive gateway
|
||||
activityDrawInstructions.put(ExclusiveGateway.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
processDiagramCanvas.drawExclusiveGateway(flowNode.getId(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// inclusive gateway
|
||||
activityDrawInstructions.put(InclusiveGateway.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
processDiagramCanvas.drawInclusiveGateway(flowNode.getId(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// parallel gateway
|
||||
activityDrawInstructions.put(ParallelGateway.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
processDiagramCanvas.drawParallelGateway(flowNode.getId(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// event based gateway
|
||||
activityDrawInstructions.put(EventGateway.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
processDiagramCanvas.drawEventBasedGateway(flowNode.getId(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// Boundary timer
|
||||
activityDrawInstructions.put(BoundaryEvent.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
BoundaryEvent boundaryEvent = (BoundaryEvent) flowNode;
|
||||
if (boundaryEvent.getEventDefinitions() != null && !boundaryEvent.getEventDefinitions().isEmpty()) {
|
||||
if (boundaryEvent.getEventDefinitions().get(0) instanceof TimerEventDefinition) {
|
||||
processDiagramCanvas.drawCatchingTimerEvent(flowNode.getId(), flowNode.getName(), graphicInfo, boundaryEvent.isCancelActivity());
|
||||
} else if (boundaryEvent.getEventDefinitions().get(0) instanceof ErrorEventDefinition) {
|
||||
processDiagramCanvas.drawCatchingErrorEvent(flowNode.getId(), graphicInfo, boundaryEvent.isCancelActivity());
|
||||
} else if (boundaryEvent.getEventDefinitions().get(0) instanceof SignalEventDefinition) {
|
||||
processDiagramCanvas.drawCatchingSignalEvent(flowNode.getId(), flowNode.getName(), graphicInfo, boundaryEvent.isCancelActivity());
|
||||
} else if (boundaryEvent.getEventDefinitions().get(0) instanceof MessageEventDefinition) {
|
||||
processDiagramCanvas.drawCatchingMessageEvent(flowNode.getId(), flowNode.getName(), graphicInfo, boundaryEvent.isCancelActivity());
|
||||
} else if (boundaryEvent.getEventDefinitions().get(0) instanceof CompensateEventDefinition) {
|
||||
processDiagramCanvas.drawCatchingCompensateEvent(flowNode.getId(), graphicInfo, boundaryEvent.isCancelActivity());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// subprocess
|
||||
activityDrawInstructions.put(SubProcess.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) {
|
||||
processDiagramCanvas.drawCollapsedSubProcess(flowNode.getId(), flowNode.getName(), graphicInfo, false);
|
||||
} else {
|
||||
processDiagramCanvas.drawExpandedSubProcess(flowNode.getId(), flowNode.getName(), graphicInfo, SubProcess.class);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Event subprocess
|
||||
activityDrawInstructions.put(EventSubProcess.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) {
|
||||
processDiagramCanvas.drawCollapsedSubProcess(flowNode.getId(), flowNode.getName(), graphicInfo, false);
|
||||
} else {
|
||||
processDiagramCanvas.drawExpandedSubProcess(flowNode.getId(), flowNode.getName(), graphicInfo, Transaction.class);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// call activity
|
||||
activityDrawInstructions.put(CallActivity.class, new ActivityDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
processDiagramCanvas.drawCollapsedCallActivity(flowNode.getId(), flowNode.getName(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// text annotation
|
||||
artifactDrawInstructions.put(TextAnnotation.class, new ArtifactDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(artifact.getId());
|
||||
TextAnnotation textAnnotation = (TextAnnotation) artifact;
|
||||
processDiagramCanvas.drawTextAnnotation(textAnnotation.getId(), textAnnotation.getText(), graphicInfo);
|
||||
}
|
||||
});
|
||||
|
||||
// association
|
||||
artifactDrawInstructions.put(Association.class, new ArtifactDrawInstruction() {
|
||||
@Override
|
||||
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact) {
|
||||
Association association = (Association) artifact;
|
||||
String sourceRef = association.getSourceRef();
|
||||
String targetRef = association.getTargetRef();
|
||||
|
||||
// source and target can be instance of FlowElement or Artifact
|
||||
BaseElement sourceElement = bpmnModel.getFlowElement(sourceRef);
|
||||
BaseElement targetElement = bpmnModel.getFlowElement(targetRef);
|
||||
if (sourceElement == null) {
|
||||
sourceElement = bpmnModel.getArtifact(sourceRef);
|
||||
}
|
||||
if (targetElement == null) {
|
||||
targetElement = bpmnModel.getArtifact(targetRef);
|
||||
}
|
||||
List<GraphicInfo> graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(artifact.getId());
|
||||
graphicInfoList = connectionPerfectionizer(processDiagramCanvas, bpmnModel, sourceElement, targetElement, graphicInfoList);
|
||||
int[] xPoints = new int[graphicInfoList.size()];
|
||||
int[] yPoints = new int[graphicInfoList.size()];
|
||||
for (int i = 1; i < graphicInfoList.size(); i++) {
|
||||
GraphicInfo graphicInfo = graphicInfoList.get(i);
|
||||
GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1);
|
||||
|
||||
if (i == 1) {
|
||||
xPoints[0] = (int) previousGraphicInfo.getX();
|
||||
yPoints[0] = (int) previousGraphicInfo.getY();
|
||||
}
|
||||
xPoints[i] = (int) graphicInfo.getX();
|
||||
yPoints[i] = (int) graphicInfo.getY();
|
||||
}
|
||||
|
||||
AssociationDirection associationDirection = association.getAssociationDirection();
|
||||
processDiagramCanvas.drawAssociation(xPoints, yPoints, associationDirection, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
protected CustomProcessDiagramCanvas generateProcessDiagram(BpmnModel bpmnModel,
|
||||
List<String> highLightedActivities, List<String> runningActivityIdList, List<String> highLightedFlows, List<String> runningActivityFlowsIds,
|
||||
String activityFontName, String labelFontName, String annotationFontName) {
|
||||
|
||||
CustomProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(bpmnModel, activityFontName, labelFontName, annotationFontName);
|
||||
|
||||
// Draw pool shape, if process is participant in collaboration
|
||||
for (Pool pool : bpmnModel.getPools()) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId());
|
||||
processDiagramCanvas.drawPoolOrLane(pool.getId(), pool.getName(), graphicInfo);
|
||||
}
|
||||
|
||||
// Draw lanes
|
||||
for (Process process : bpmnModel.getProcesses()) {
|
||||
for (Lane lane : process.getLanes()) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(lane.getId());
|
||||
processDiagramCanvas.drawPoolOrLane(lane.getId(), lane.getName(), graphicInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw activities and their sequence-flows
|
||||
/**
|
||||
* 绘制流程图上的所有节点和流程线,对高亮显示的节点和流程线进行特殊处理
|
||||
*/
|
||||
for (FlowNode flowNode : bpmnModel.getProcesses().get(0).findFlowElementsOfType(FlowNode.class)) {
|
||||
drawActivity(processDiagramCanvas, bpmnModel, flowNode, highLightedActivities, runningActivityIdList,
|
||||
highLightedFlows, runningActivityFlowsIds);
|
||||
}
|
||||
|
||||
// Draw artifacts
|
||||
for (Process process : bpmnModel.getProcesses()) {
|
||||
for (Artifact artifact : process.getArtifacts()) {
|
||||
drawArtifact(processDiagramCanvas, bpmnModel, artifact);
|
||||
}
|
||||
}
|
||||
|
||||
return processDiagramCanvas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Desc: 绘制流程图上的所有节点和流程线,对高亮显示的节点和流程线进行特殊处理
|
||||
*
|
||||
* @param processDiagramCanvas
|
||||
* @param bpmnModel
|
||||
* @param flowNode
|
||||
* @param highLightedActivities
|
||||
* @param highLightedFlows
|
||||
* @author Fuxs
|
||||
*/
|
||||
protected void drawActivity(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode,
|
||||
List<String> highLightedActivities, List<String> runningActivityIdList, List<String> highLightedFlows, List<String> runningActivityFlowsIds) {
|
||||
|
||||
ActivityDrawInstruction drawInstruction = activityDrawInstructions.get(flowNode.getClass());
|
||||
if (drawInstruction != null) {
|
||||
|
||||
drawInstruction.draw(processDiagramCanvas, bpmnModel, flowNode);
|
||||
|
||||
// Gather info on the multi instance marker
|
||||
boolean multiInstanceSequential = false;
|
||||
boolean multiInstanceParallel = false;
|
||||
boolean highLighted = false;
|
||||
if (flowNode instanceof Activity) {
|
||||
Activity activity = (Activity) flowNode;
|
||||
MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = activity.getLoopCharacteristics();
|
||||
if (multiInstanceLoopCharacteristics != null) {
|
||||
multiInstanceSequential = multiInstanceLoopCharacteristics.isSequential();
|
||||
multiInstanceParallel = !multiInstanceSequential;
|
||||
}
|
||||
}
|
||||
|
||||
// Gather info on the highLighted marker
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
if (!(flowNode instanceof SubProcess)) {
|
||||
if (flowNode instanceof CallActivity) {
|
||||
highLighted = true;
|
||||
}
|
||||
} else {
|
||||
highLighted = graphicInfo.getExpanded() != null && !graphicInfo.getExpanded();
|
||||
}
|
||||
|
||||
processDiagramCanvas.drawActivityMarkers((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight(), multiInstanceSequential, multiInstanceParallel, highLighted);
|
||||
|
||||
|
||||
// Draw highlighted activities
|
||||
if (highLightedActivities.contains(flowNode.getId())) {
|
||||
/*
|
||||
* 如果节点为当前正在处理中的节点,则红色高亮显示
|
||||
*/
|
||||
if (runningActivityIdList.contains(flowNode.getId())) {
|
||||
log.debug("[绘制]-当前正在处理中的节点-红色高亮显示节点[{}-{}]", flowNode.getId(), flowNode.getName());
|
||||
drawRunningActivityHighLight(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId()));
|
||||
} else {
|
||||
log.debug("[绘制]-高亮显示节点[{}-{}]", flowNode.getId(), flowNode.getName());
|
||||
drawHighLight(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 绘制当前节点的流程线
|
||||
*/
|
||||
for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
|
||||
boolean highLighted = (highLightedFlows.contains(sequenceFlow.getId()));
|
||||
String defaultFlow = null;
|
||||
if (flowNode instanceof Activity) {
|
||||
defaultFlow = ((Activity) flowNode).getDefaultFlow();
|
||||
} else if (flowNode instanceof Gateway) {
|
||||
defaultFlow = ((Gateway) flowNode).getDefaultFlow();
|
||||
}
|
||||
|
||||
boolean isDefault = false;
|
||||
if (defaultFlow != null && defaultFlow.equalsIgnoreCase(sequenceFlow.getId())) {
|
||||
isDefault = true;
|
||||
}
|
||||
boolean drawConditionalIndicator = sequenceFlow.getConditionExpression() != null
|
||||
&& !(flowNode instanceof Gateway);
|
||||
|
||||
String sourceRef = sequenceFlow.getSourceRef();
|
||||
String targetRef = sequenceFlow.getTargetRef();
|
||||
FlowElement sourceElement = bpmnModel.getFlowElement(sourceRef);
|
||||
FlowElement targetElement = bpmnModel.getFlowElement(targetRef);
|
||||
List<GraphicInfo> graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId());
|
||||
if (graphicInfoList != null && graphicInfoList.size() > 0) {
|
||||
graphicInfoList = connectionPerfectionizer(processDiagramCanvas, bpmnModel, sourceElement,
|
||||
targetElement, graphicInfoList);
|
||||
int[] xPoints = new int[graphicInfoList.size()];
|
||||
int[] yPoints = new int[graphicInfoList.size()];
|
||||
|
||||
for (int i = 1; i < graphicInfoList.size(); i++) {
|
||||
GraphicInfo graphicInfo = graphicInfoList.get(i);
|
||||
GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1);
|
||||
|
||||
if (i == 1) {
|
||||
xPoints[0] = (int) previousGraphicInfo.getX();
|
||||
yPoints[0] = (int) previousGraphicInfo.getY();
|
||||
}
|
||||
xPoints[i] = (int) graphicInfo.getX();
|
||||
yPoints[i] = (int) graphicInfo.getY();
|
||||
|
||||
}
|
||||
|
||||
if (highLightedFlows.contains(sequenceFlow.getId()) && runningActivityFlowsIds.contains(sequenceFlow.getId())) {
|
||||
processDiagramCanvas.drawLastSequenceflow(xPoints, yPoints, drawConditionalIndicator, isDefault, highLighted);
|
||||
} else {
|
||||
processDiagramCanvas.drawSequenceflow(xPoints, yPoints, drawConditionalIndicator, isDefault, highLighted);
|
||||
}
|
||||
|
||||
/*
|
||||
* 绘制流程线名称
|
||||
*/
|
||||
// GraphicInfo lineCenter = getLineCenter(graphicInfoList);
|
||||
// processDiagramCanvas.drawLabel(sequenceFlow.getName(), lineCenter, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Nested elements
|
||||
if (flowNode instanceof FlowElementsContainer) {
|
||||
for (FlowElement nestedFlowElement : ((FlowElementsContainer) flowNode).getFlowElements()) {
|
||||
if (nestedFlowElement instanceof FlowNode) {
|
||||
drawActivity(processDiagramCanvas, bpmnModel, (FlowNode) nestedFlowElement, highLightedActivities,
|
||||
runningActivityIdList, highLightedFlows, runningActivityFlowsIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method makes coordinates of connection flow better.
|
||||
*
|
||||
* @param processDiagramCanvas
|
||||
* @param bpmnModel
|
||||
* @param sourceElement
|
||||
* @param targetElement
|
||||
* @param graphicInfoList
|
||||
* @return
|
||||
*/
|
||||
protected static List<GraphicInfo> connectionPerfectionizer(CustomProcessDiagramCanvas processDiagramCanvas,
|
||||
BpmnModel bpmnModel, BaseElement sourceElement, BaseElement targetElement,
|
||||
List<GraphicInfo> graphicInfoList) {
|
||||
GraphicInfo sourceGraphicInfo = bpmnModel.getGraphicInfo(sourceElement.getId());
|
||||
GraphicInfo targetGraphicInfo = bpmnModel.getGraphicInfo(targetElement.getId());
|
||||
|
||||
CustomProcessDiagramCanvas.SHAPE_TYPE sourceShapeType = getShapeType(sourceElement);
|
||||
CustomProcessDiagramCanvas.SHAPE_TYPE targetShapeType = getShapeType(targetElement);
|
||||
|
||||
return processDiagramCanvas.connectionPerfectionizer(sourceShapeType, targetShapeType, sourceGraphicInfo,
|
||||
targetGraphicInfo, graphicInfoList);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns shape type of base element.<br>
|
||||
* Each element can be presented as rectangle, rhombus, or ellipse.
|
||||
*
|
||||
* @param baseElement
|
||||
* @return CustomProcessDiagramCanvas.SHAPE_TYPE
|
||||
*/
|
||||
protected static CustomProcessDiagramCanvas.SHAPE_TYPE getShapeType(BaseElement baseElement) {
|
||||
if (baseElement instanceof Task || baseElement instanceof Activity || baseElement instanceof TextAnnotation) {
|
||||
return CustomProcessDiagramCanvas.SHAPE_TYPE.Rectangle;
|
||||
} else if (baseElement instanceof Gateway) {
|
||||
return CustomProcessDiagramCanvas.SHAPE_TYPE.Rhombus;
|
||||
} else if (baseElement instanceof Event) {
|
||||
return CustomProcessDiagramCanvas.SHAPE_TYPE.Ellipse;
|
||||
} else {
|
||||
// unknown source element, just do not correct coordinates
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static GraphicInfo getLineCenter(List<GraphicInfo> graphicInfoList) {
|
||||
GraphicInfo gi = new GraphicInfo();
|
||||
|
||||
int[] xPoints = new int[graphicInfoList.size()];
|
||||
int[] yPoints = new int[graphicInfoList.size()];
|
||||
|
||||
double length = 0;
|
||||
double[] lengths = new double[graphicInfoList.size()];
|
||||
lengths[0] = 0;
|
||||
double m;
|
||||
for (int i = 1; i < graphicInfoList.size(); i++) {
|
||||
GraphicInfo graphicInfo = graphicInfoList.get(i);
|
||||
GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1);
|
||||
|
||||
if (i == 1) {
|
||||
xPoints[0] = (int) previousGraphicInfo.getX();
|
||||
yPoints[0] = (int) previousGraphicInfo.getY();
|
||||
}
|
||||
xPoints[i] = (int) graphicInfo.getX();
|
||||
yPoints[i] = (int) graphicInfo.getY();
|
||||
|
||||
length += Math.sqrt(Math.pow((int) graphicInfo.getX() - (int) previousGraphicInfo.getX(), 2) + Math.pow(
|
||||
(int) graphicInfo.getY() - (int) previousGraphicInfo.getY(), 2));
|
||||
lengths[i] = length;
|
||||
}
|
||||
m = length / 2;
|
||||
int p1 = 0, p2 = 1;
|
||||
for (int i = 1; i < lengths.length; i++) {
|
||||
double len = lengths[i];
|
||||
p1 = i - 1;
|
||||
p2 = i;
|
||||
if (len > m) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GraphicInfo graphicInfo1 = graphicInfoList.get(p1);
|
||||
GraphicInfo graphicInfo2 = graphicInfoList.get(p2);
|
||||
|
||||
double AB = (int) graphicInfo2.getX() - (int) graphicInfo1.getX();
|
||||
double OA = (int) graphicInfo2.getY() - (int) graphicInfo1.getY();
|
||||
double OB = lengths[p2] - lengths[p1];
|
||||
double ob = m - lengths[p1];
|
||||
double ab = AB * ob / OB;
|
||||
double oa = OA * ob / OB;
|
||||
|
||||
double mx = graphicInfo1.getX() + ab;
|
||||
double my = graphicInfo1.getY() + oa;
|
||||
|
||||
gi.setX(mx);
|
||||
gi.setY(my);
|
||||
return gi;
|
||||
}
|
||||
|
||||
protected void drawArtifact(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel,
|
||||
Artifact artifact) {
|
||||
|
||||
ArtifactDrawInstruction drawInstruction = artifactDrawInstructions.get(artifact.getClass());
|
||||
if (drawInstruction != null) {
|
||||
drawInstruction.draw(processDiagramCanvas, bpmnModel, artifact);
|
||||
}
|
||||
}
|
||||
|
||||
private static void drawHighLight(CustomProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo) {
|
||||
processDiagramCanvas.drawHighLight((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo
|
||||
.getWidth(), (int) graphicInfo.getHeight());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Desc:绘制正在执行中的节点红色高亮显示
|
||||
*
|
||||
* @param processDiagramCanvas CustomProcessDiagramCanvas
|
||||
* @param graphicInfo GraphicInfo
|
||||
* @author Fuxs
|
||||
*/
|
||||
private static void drawRunningActivityHighLight(CustomProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo) {
|
||||
processDiagramCanvas.drawRunningActivityHighLight((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo
|
||||
.getWidth(), (int) graphicInfo.getHeight());
|
||||
|
||||
}
|
||||
|
||||
protected static CustomProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel, String activityFontName,
|
||||
String labelFontName, String annotationFontName) {
|
||||
|
||||
// We need to calculate maximum values to know how big the image will be in its entirety
|
||||
double minX = 1.7976931348623157E308D;
|
||||
double maxX = 0.0D;
|
||||
double minY = 1.7976931348623157E308D;
|
||||
double maxY = 0.0D;
|
||||
|
||||
|
||||
for (Pool pool : bpmnModel.getPools()) {
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId());
|
||||
minX = graphicInfo.getX();
|
||||
maxX = graphicInfo.getX() + graphicInfo.getWidth();
|
||||
minY = graphicInfo.getY();
|
||||
maxY = graphicInfo.getY() + graphicInfo.getHeight();
|
||||
}
|
||||
|
||||
List<FlowNode> flowNodes = gatherAllFlowNodes(bpmnModel);
|
||||
for (FlowNode flowNode : flowNodes) {
|
||||
|
||||
GraphicInfo flowNodeGraphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||
|
||||
// width
|
||||
if (flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth() > maxX) {
|
||||
maxX = flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth();
|
||||
}
|
||||
if (flowNodeGraphicInfo.getX() < minX) {
|
||||
minX = flowNodeGraphicInfo.getX();
|
||||
}
|
||||
// height
|
||||
if (flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight() > maxY) {
|
||||
maxY = flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight();
|
||||
}
|
||||
if (flowNodeGraphicInfo.getY() < minY) {
|
||||
minY = flowNodeGraphicInfo.getY();
|
||||
}
|
||||
|
||||
for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
|
||||
List<GraphicInfo> graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId());
|
||||
if (graphicInfoList != null) {
|
||||
for (GraphicInfo graphicInfo : graphicInfoList) {
|
||||
// width
|
||||
if (graphicInfo.getX() > maxX) {
|
||||
maxX = graphicInfo.getX();
|
||||
}
|
||||
if (graphicInfo.getX() < minX) {
|
||||
minX = graphicInfo.getX();
|
||||
}
|
||||
// height
|
||||
if (graphicInfo.getY() > maxY) {
|
||||
maxY = graphicInfo.getY();
|
||||
}
|
||||
if (graphicInfo.getY() < minY) {
|
||||
minY = graphicInfo.getY();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Artifact> artifacts = gatherAllArtifacts(bpmnModel);
|
||||
for (Artifact artifact : artifacts) {
|
||||
|
||||
GraphicInfo artifactGraphicInfo = bpmnModel.getGraphicInfo(artifact.getId());
|
||||
|
||||
if (artifactGraphicInfo != null) {
|
||||
// width
|
||||
if (artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth() > maxX) {
|
||||
maxX = artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth();
|
||||
}
|
||||
if (artifactGraphicInfo.getX() < minX) {
|
||||
minX = artifactGraphicInfo.getX();
|
||||
}
|
||||
// height
|
||||
if (artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight() > maxY) {
|
||||
maxY = artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight();
|
||||
}
|
||||
if (artifactGraphicInfo.getY() < minY) {
|
||||
minY = artifactGraphicInfo.getY();
|
||||
}
|
||||
}
|
||||
|
||||
List<GraphicInfo> graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(artifact.getId());
|
||||
if (graphicInfoList != null) {
|
||||
for (GraphicInfo graphicInfo : graphicInfoList) {
|
||||
// width
|
||||
if (graphicInfo.getX() > maxX) {
|
||||
maxX = graphicInfo.getX();
|
||||
}
|
||||
if (graphicInfo.getX() < minX) {
|
||||
minX = graphicInfo.getX();
|
||||
}
|
||||
// height
|
||||
if (graphicInfo.getY() > maxY) {
|
||||
maxY = graphicInfo.getY();
|
||||
}
|
||||
if (graphicInfo.getY() < minY) {
|
||||
minY = graphicInfo.getY();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nrOfLanes = 0;
|
||||
for (Process process : bpmnModel.getProcesses()) {
|
||||
for (Lane l : process.getLanes()) {
|
||||
|
||||
nrOfLanes++;
|
||||
|
||||
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(l.getId());
|
||||
// // width
|
||||
if (graphicInfo.getX() + graphicInfo.getWidth() > maxX) {
|
||||
maxX = graphicInfo.getX() + graphicInfo.getWidth();
|
||||
}
|
||||
if (graphicInfo.getX() < minX) {
|
||||
minX = graphicInfo.getX();
|
||||
}
|
||||
// height
|
||||
if (graphicInfo.getY() + graphicInfo.getHeight() > maxY) {
|
||||
maxY = graphicInfo.getY() + graphicInfo.getHeight();
|
||||
}
|
||||
if (graphicInfo.getY() < minY) {
|
||||
minY = graphicInfo.getY();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Special case, see http://jira.codehaus.org/browse/ACT-1431
|
||||
if (flowNodes.isEmpty() && bpmnModel.getPools().isEmpty() && nrOfLanes == 0) {
|
||||
// Nothing to show
|
||||
minX = 0.0D;
|
||||
minY = 0.0D;
|
||||
}
|
||||
//width和height代表最大的长宽
|
||||
return new CustomProcessDiagramCanvas((int) maxX + 30, (int) maxY + 50, (int) minX, (int) minY, activityFontName, labelFontName, annotationFontName);
|
||||
}
|
||||
|
||||
protected static List<Artifact> gatherAllArtifacts(BpmnModel bpmnModel) {
|
||||
List<Artifact> artifacts = new ArrayList<Artifact>();
|
||||
for (Process process : bpmnModel.getProcesses()) {
|
||||
artifacts.addAll(process.getArtifacts());
|
||||
}
|
||||
return artifacts;
|
||||
}
|
||||
|
||||
protected static List<FlowNode> gatherAllFlowNodes(BpmnModel bpmnModel) {
|
||||
List<FlowNode> flowNodes = new ArrayList<FlowNode>();
|
||||
for (Process process : bpmnModel.getProcesses()) {
|
||||
flowNodes.addAll(gatherAllFlowNodes(process));
|
||||
}
|
||||
return flowNodes;
|
||||
}
|
||||
|
||||
protected static List<FlowNode> gatherAllFlowNodes(FlowElementsContainer flowElementsContainer) {
|
||||
List<FlowNode> flowNodes = new ArrayList<FlowNode>();
|
||||
for (FlowElement flowElement : flowElementsContainer.getFlowElements()) {
|
||||
if (flowElement instanceof FlowNode) {
|
||||
flowNodes.add((FlowNode) flowElement);
|
||||
}
|
||||
if (flowElement instanceof FlowElementsContainer) {
|
||||
flowNodes.addAll(gatherAllFlowNodes((FlowElementsContainer) flowElement));
|
||||
}
|
||||
}
|
||||
return flowNodes;
|
||||
}
|
||||
|
||||
public Map<Class<? extends BaseElement>, ActivityDrawInstruction> getActivityDrawInstructions() {
|
||||
return activityDrawInstructions;
|
||||
}
|
||||
|
||||
public void setActivityDrawInstructions(Map<Class<? extends BaseElement>, ActivityDrawInstruction> activityDrawInstructions) {
|
||||
this.activityDrawInstructions = activityDrawInstructions;
|
||||
}
|
||||
|
||||
public Map<Class<? extends BaseElement>, ArtifactDrawInstruction> getArtifactDrawInstructions() {
|
||||
return artifactDrawInstructions;
|
||||
}
|
||||
|
||||
public void setArtifactDrawInstructions(Map<Class<? extends BaseElement>, ArtifactDrawInstruction> artifactDrawInstructions) {
|
||||
this.artifactDrawInstructions = artifactDrawInstructions;
|
||||
}
|
||||
|
||||
protected interface ActivityDrawInstruction {
|
||||
void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode);
|
||||
}
|
||||
|
||||
protected interface ArtifactDrawInstruction {
|
||||
void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact);
|
||||
}
|
||||
|
||||
/**
|
||||
* Desc: 输入所有的参数,以获取图像
|
||||
*
|
||||
* @param bpmnModel
|
||||
* @param highLightedActivities
|
||||
* @param runningActivityIdList
|
||||
* @param highLightedFlows
|
||||
* @param activityFontName
|
||||
* @param labelFontName
|
||||
* @param annotationFontName
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public InputStream generateDiagramCustom(BpmnModel bpmnModel,
|
||||
List<String> highLightedActivities,
|
||||
List<String> runningActivityIdList,
|
||||
List<String> highLightedFlows,
|
||||
List<String> runningActivityFlowsIds,
|
||||
String activityFontName,
|
||||
String labelFontName,
|
||||
String annotationFontName) {
|
||||
// TODO
|
||||
return generateProcessDiagram(bpmnModel,
|
||||
highLightedActivities,
|
||||
runningActivityIdList,
|
||||
highLightedFlows,
|
||||
runningActivityFlowsIds,
|
||||
activityFontName,
|
||||
labelFontName,
|
||||
annotationFontName).generateImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream generateDiagramCustom(BpmnModel bpmnModel,
|
||||
List<String> highLightedActivities,
|
||||
List<String> runningActivityIdList,
|
||||
List<String> highLightedFlows,
|
||||
String activityFontName,
|
||||
String labelFontName,
|
||||
String annotationFontName) {
|
||||
return generateProcessDiagram(bpmnModel,
|
||||
highLightedActivities,
|
||||
runningActivityIdList,
|
||||
highLightedFlows,
|
||||
Collections.emptyList(),
|
||||
activityFontName,
|
||||
labelFontName,
|
||||
annotationFontName).generateImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream generateDiagramCustom(BpmnModel bpmnModel,
|
||||
List<String> highLightedActivities,
|
||||
List<String> highLightedFlows,
|
||||
String activityFontName,
|
||||
String labelFontName,
|
||||
String annotationFontName) {
|
||||
return generateProcessDiagram(bpmnModel,
|
||||
highLightedActivities,
|
||||
Collections.emptyList(),
|
||||
highLightedFlows,
|
||||
Collections.emptyList(),
|
||||
activityFontName,
|
||||
labelFontName,
|
||||
annotationFontName).generateImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream generateDiagramCustom(BpmnModel bpmnModel,
|
||||
List<String> highLightedActivities,
|
||||
List<String> runningActivityIdList,
|
||||
List<String> highLightedFlows,
|
||||
List<String> runningActivityFlowsIds) {
|
||||
return generateProcessDiagram(bpmnModel,
|
||||
highLightedActivities,
|
||||
runningActivityIdList,
|
||||
highLightedFlows,
|
||||
runningActivityFlowsIds,
|
||||
ACTIVITY_FONT_NAME,
|
||||
LABEL_FONT_NAME,
|
||||
ANNOTATION_FONT_NAME).generateImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream generateDiagramCustom(BpmnModel bpmnModel,
|
||||
List<String> highLightedActivities,
|
||||
List<String> runningActivityIdList,
|
||||
List<String> highLightedFlows) {
|
||||
return generateProcessDiagram(bpmnModel,
|
||||
highLightedActivities,
|
||||
runningActivityIdList,
|
||||
highLightedFlows,
|
||||
Collections.emptyList(),
|
||||
ACTIVITY_FONT_NAME,
|
||||
LABEL_FONT_NAME,
|
||||
ANNOTATION_FONT_NAME).generateImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream generateDiagramCustom(BpmnModel bpmnModel,
|
||||
List<String> highLightedActivities,
|
||||
List<String> highLightedFlows) {
|
||||
return generateProcessDiagram(bpmnModel,
|
||||
highLightedActivities,
|
||||
Collections.emptyList(),
|
||||
highLightedFlows,
|
||||
Collections.emptyList(),
|
||||
ACTIVITY_FONT_NAME,
|
||||
LABEL_FONT_NAME,
|
||||
ANNOTATION_FONT_NAME).generateImage();
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package com.jero.modules.activiti.service.impl.image;
|
||||
|
||||
import org.activiti.bpmn.model.BpmnModel;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* bpmnModel bpmn模型
|
||||
* activityFontName 活动字体
|
||||
* labelFontName 标签字体
|
||||
* annotationFontName 标注字体
|
||||
* highLightedActivities 高亮活动节点(绿色)
|
||||
* runningActivityIdList 正在运行的活动节点(红色)
|
||||
* highLightedFlows 高亮顺序流(绿色)
|
||||
* lastFlowIdList 最后一条执行的顺序流(红色) ——————未实现
|
||||
*/
|
||||
public interface ICustomProcessDiagramGenerator{
|
||||
|
||||
//指定字体
|
||||
InputStream generateDiagramCustom(BpmnModel bpmnModel,
|
||||
List<String> highLightedActivities,
|
||||
List<String> runningActivityIdList,
|
||||
List<String> highLightedFlows,
|
||||
List<String> runningActivityFlowsIds,
|
||||
String activityFontName,
|
||||
String labelFontName,
|
||||
String annotationFontName);
|
||||
|
||||
InputStream generateDiagramCustom(BpmnModel bpmnModel,
|
||||
List<String> highLightedActivities,
|
||||
List<String> runningActivityIdList,
|
||||
List<String> highLightedFlows,
|
||||
String activityFontName,
|
||||
String labelFontName,
|
||||
String annotationFontName);
|
||||
|
||||
InputStream generateDiagramCustom(BpmnModel bpmnModel,
|
||||
List<String> highLightedActivities,
|
||||
List<String> highLightedFlows,
|
||||
String activityFontName,
|
||||
String labelFontName,
|
||||
String annotationFontName);
|
||||
|
||||
//无指定字体,使用默认字体
|
||||
InputStream generateDiagramCustom(BpmnModel bpmnModel,
|
||||
List<String> highLightedActivities,
|
||||
List<String> runningActivityIdList,
|
||||
List<String> highLightedFlows,
|
||||
List<String> runningActivityFlowsIds);
|
||||
|
||||
InputStream generateDiagramCustom(BpmnModel bpmnModel,
|
||||
List<String> highLightedActivities,
|
||||
List<String> runningActivityIdList,
|
||||
List<String> highLightedFlows);
|
||||
|
||||
InputStream generateDiagramCustom(BpmnModel bpmnModel,
|
||||
List<String> highLightedActivities,
|
||||
List<String> highLightedFlows);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user