新增流程运行实例流程图查看和节点、连线高亮功能
This commit is contained in:
parent
558b82a033
commit
ec72a2c181
@ -9,16 +9,17 @@ import ink.wgink.interfaces.consts.ISystemConstant;
|
|||||||
import ink.wgink.module.activiti.service.activiti.IActivitiModelService;
|
import ink.wgink.module.activiti.service.activiti.IActivitiModelService;
|
||||||
import ink.wgink.util.ResourceUtil;
|
import ink.wgink.util.ResourceUtil;
|
||||||
import org.activiti.bpmn.model.BpmnModel;
|
import org.activiti.bpmn.model.BpmnModel;
|
||||||
|
import org.activiti.bpmn.model.FlowNode;
|
||||||
|
import org.activiti.bpmn.model.SequenceFlow;
|
||||||
import org.activiti.editor.constants.ModelDataJsonConstants;
|
import org.activiti.editor.constants.ModelDataJsonConstants;
|
||||||
import org.activiti.engine.HistoryService;
|
import org.activiti.engine.HistoryService;
|
||||||
import org.activiti.engine.ProcessEngine;
|
|
||||||
import org.activiti.engine.RepositoryService;
|
import org.activiti.engine.RepositoryService;
|
||||||
import org.activiti.engine.RuntimeService;
|
import org.activiti.engine.RuntimeService;
|
||||||
|
import org.activiti.engine.history.HistoricActivityInstance;
|
||||||
import org.activiti.engine.history.HistoricProcessInstance;
|
import org.activiti.engine.history.HistoricProcessInstance;
|
||||||
import org.activiti.engine.repository.Model;
|
import org.activiti.engine.repository.Model;
|
||||||
import org.activiti.engine.repository.ProcessDefinition;
|
import org.activiti.engine.repository.ProcessDefinition;
|
||||||
import org.activiti.engine.runtime.ProcessInstance;
|
import org.activiti.engine.runtime.ProcessInstance;
|
||||||
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
|
|
||||||
import org.apache.batik.transcoder.TranscoderInput;
|
import org.apache.batik.transcoder.TranscoderInput;
|
||||||
import org.apache.batik.transcoder.TranscoderOutput;
|
import org.apache.batik.transcoder.TranscoderOutput;
|
||||||
import org.apache.batik.transcoder.image.PNGTranscoder;
|
import org.apache.batik.transcoder.image.PNGTranscoder;
|
||||||
@ -28,9 +29,7 @@ import org.springframework.stereotype.Service;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,8 +51,6 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct
|
|||||||
private RuntimeService runtimeService;
|
private RuntimeService runtimeService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private HistoryService historyService;
|
private HistoryService historyService;
|
||||||
@Autowired
|
|
||||||
private ProcessEngine processEngine;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveModel(String modelId, String name, String description, String json_xml, String svg_xml) throws Exception {
|
public void saveModel(String modelId, String name, String description, String json_xml, String svg_xml) throws Exception {
|
||||||
@ -127,10 +124,11 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct
|
|||||||
if (processDefinition == null) {
|
if (processDefinition == null) {
|
||||||
throw new SearchException("流程定义不存在,请检查流程部署情况");
|
throw new SearchException("流程定义不存在,请检查流程部署情况");
|
||||||
}
|
}
|
||||||
|
String fontName = "宋体";
|
||||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
|
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
|
||||||
DefaultProcessDiagramGenerator defaultProcessDiagramGenerator = new DefaultProcessDiagramGenerator();
|
CustomProcessDiagramGenerator customProcessDiagramGenerator = new CustomProcessDiagramGenerator();
|
||||||
response.setContentType("image/png");
|
response.setContentType("image/png");
|
||||||
try (InputStream inputStream = defaultProcessDiagramGenerator.generateDiagram(bpmnModel, "png", new ArrayList<>(), new ArrayList<>(), 1.0D);
|
try (InputStream inputStream = customProcessDiagramGenerator.generateDiagram(bpmnModel, "png", new ArrayList<>(), new ArrayList<>(), fontName, fontName, fontName, null, 1.0D);
|
||||||
OutputStream outputStream = response.getOutputStream();
|
OutputStream outputStream = response.getOutputStream();
|
||||||
) {
|
) {
|
||||||
byte[] buf = new byte[1024];
|
byte[] buf = new byte[1024];
|
||||||
@ -159,10 +157,16 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取运行流程图输入流
|
||||||
|
*
|
||||||
|
* @param processInstanceId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public InputStream getRuntimeProcessImageInputStream(String processInstanceId) {
|
public InputStream getRuntimeProcessImageInputStream(String processInstanceId) {
|
||||||
//获得流程实例
|
//获得流程实例
|
||||||
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
||||||
String processDefinitionId = StringUtils.EMPTY;
|
String processDefinitionId;
|
||||||
if (processInstance == null) {
|
if (processInstance == null) {
|
||||||
//查询已经结束的流程实例
|
//查询已经结束的流程实例
|
||||||
HistoricProcessInstance processInstanceHistory = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
HistoricProcessInstance processInstanceHistory = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
|
||||||
@ -178,13 +182,79 @@ public class ActivitiModelServiceImpl extends DefaultBaseService implements IAct
|
|||||||
//使用宋体
|
//使用宋体
|
||||||
String fontName = "宋体";
|
String fontName = "宋体";
|
||||||
//获取BPMN模型对象
|
//获取BPMN模型对象
|
||||||
BpmnModel model = repositoryService.getBpmnModel(processDefinitionId);
|
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
|
||||||
|
|
||||||
//获取流程实例当前的节点,需要高亮显示
|
//获取流程实例当前的节点,需要高亮显示
|
||||||
List<String> currentActs = Collections.EMPTY_LIST;
|
List<String> highLightedActivitiIds = Collections.EMPTY_LIST;
|
||||||
if (processInstance != null) {
|
if (processInstance != null) {
|
||||||
currentActs = runtimeService.getActiveActivityIds(processInstance.getId());
|
highLightedActivitiIds = runtimeService.getActiveActivityIds(processInstance.getId());
|
||||||
|
// 获取历史节点
|
||||||
|
List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
|
||||||
|
if (!historicActivityInstances.isEmpty()) {
|
||||||
|
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
|
||||||
|
highLightedActivitiIds.add("#" + historicActivityInstance.getActivityId());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator().generateDiagram(model, "png", currentActs, new ArrayList<>(),
|
List<String> listSequenceFlows = listSequenceFlows(bpmnModel, highLightedActivitiIds);
|
||||||
|
CustomProcessDiagramGenerator customProcessDiagramGenerator = new CustomProcessDiagramGenerator();
|
||||||
|
return customProcessDiagramGenerator.generateDiagram(bpmnModel, "png", highLightedActivitiIds, listSequenceFlows,
|
||||||
fontName, fontName, fontName, null, 1D);
|
fontName, fontName, fontName, null, 1D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 序列流列表
|
||||||
|
*
|
||||||
|
* @param bpmnModel 模型
|
||||||
|
* @param highLightedActivitiIds 高亮的活动ID
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<String> listSequenceFlows(BpmnModel bpmnModel, List<String> highLightedActivitiIds) {
|
||||||
|
Set<String> flowSet = new HashSet<>();
|
||||||
|
// 获取有关的点
|
||||||
|
List<FlowNode> flowElementsOfType = bpmnModel.getProcesses().get(0).findFlowElementsOfType(FlowNode.class);
|
||||||
|
List<FlowNode> activitiFlowNode = new ArrayList<>();
|
||||||
|
// 加载高亮的节点
|
||||||
|
for (FlowNode flowNode : flowElementsOfType) {
|
||||||
|
for (String highLightedActivitiId : highLightedActivitiIds) {
|
||||||
|
String activitiId = highLightedActivitiId;
|
||||||
|
if (activitiId.startsWith("#")) {
|
||||||
|
activitiId = highLightedActivitiId.substring(1);
|
||||||
|
}
|
||||||
|
if (StringUtils.equals(flowNode.getId(), activitiId)) {
|
||||||
|
activitiFlowNode.add(flowNode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 找出高亮节点之间的连线
|
||||||
|
for (int i = 0; i < activitiFlowNode.size() - 1; i++) {
|
||||||
|
FlowNode flowNode = activitiFlowNode.get(i);
|
||||||
|
List<SequenceFlow> incomingFlows = flowNode.getIncomingFlows();
|
||||||
|
List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows();
|
||||||
|
for (int j = 0; j < activitiFlowNode.size(); j++) {
|
||||||
|
FlowNode nextFlowNode = activitiFlowNode.get(j);
|
||||||
|
List<SequenceFlow> nextIncomingFlows = nextFlowNode.getIncomingFlows();
|
||||||
|
List<SequenceFlow> nextOutgoingFlows = nextFlowNode.getOutgoingFlows();
|
||||||
|
// 前节点的出与后节点的入相同,则有关系
|
||||||
|
for (SequenceFlow outgoingFlow : outgoingFlows) {
|
||||||
|
for (SequenceFlow nextIncomingFlow : nextIncomingFlows) {
|
||||||
|
if (StringUtils.equals(outgoingFlow.getId(), nextIncomingFlow.getId())) {
|
||||||
|
flowSet.add(outgoingFlow.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 前节点的入与后节点的出相同,则有关系
|
||||||
|
for (SequenceFlow incomingFlow : incomingFlows) {
|
||||||
|
for (SequenceFlow nextOutgoingFlow : nextOutgoingFlows) {
|
||||||
|
if (StringUtils.equals(incomingFlow.getId(), nextOutgoingFlow.getId())) {
|
||||||
|
flowSet.add(incomingFlow.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ArrayList<>(flowSet);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,935 @@
|
|||||||
|
package ink.wgink.module.activiti.service.activiti.impl;
|
||||||
|
|
||||||
|
import org.activiti.bpmn.model.Process;
|
||||||
|
import org.activiti.bpmn.model.*;
|
||||||
|
import org.activiti.image.ProcessDiagramGenerator;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义流程图生成器
|
||||||
|
*/
|
||||||
|
public class CustomProcessDiagramGenerator implements ProcessDiagramGenerator {
|
||||||
|
|
||||||
|
protected Map<Class<? extends BaseElement>, ActivityDrawInstruction> activityDrawInstructions = new HashMap<Class<? extends BaseElement>, ActivityDrawInstruction>();
|
||||||
|
protected Map<Class<? extends BaseElement>, ArtifactDrawInstruction> artifactDrawInstructions = new HashMap<Class<? extends BaseElement>, ArtifactDrawInstruction>();
|
||||||
|
|
||||||
|
public CustomProcessDiagramGenerator() {
|
||||||
|
this(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The instructions on how to draw a certain construct is
|
||||||
|
// created statically and stored in a map for performance.
|
||||||
|
public CustomProcessDiagramGenerator(final double scaleFactor) {
|
||||||
|
// start event
|
||||||
|
activityDrawInstructions.put(StartEvent.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
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(graphicInfo, scaleFactor);
|
||||||
|
} else if (eventDefinition instanceof ErrorEventDefinition) {
|
||||||
|
processDiagramCanvas.drawErrorStartEvent(graphicInfo, scaleFactor);
|
||||||
|
} else if (eventDefinition instanceof SignalEventDefinition) {
|
||||||
|
processDiagramCanvas.drawSignalStartEvent(graphicInfo, scaleFactor);
|
||||||
|
} else if (eventDefinition instanceof MessageEventDefinition) {
|
||||||
|
processDiagramCanvas.drawMessageStartEvent(graphicInfo, scaleFactor);
|
||||||
|
} else {
|
||||||
|
processDiagramCanvas.drawNoneStartEvent(graphicInfo);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
processDiagramCanvas.drawNoneStartEvent(graphicInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// signal catch
|
||||||
|
activityDrawInstructions.put(IntermediateCatchEvent.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
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.getName(), graphicInfo, true, scaleFactor);
|
||||||
|
} else if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof TimerEventDefinition) {
|
||||||
|
processDiagramCanvas.drawCatchingTimerEvent(flowNode.getName(), graphicInfo, true, scaleFactor);
|
||||||
|
} else if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof MessageEventDefinition) {
|
||||||
|
processDiagramCanvas.drawCatchingMessageEvent(flowNode.getName(), graphicInfo, true, scaleFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// signal throw
|
||||||
|
activityDrawInstructions.put(ThrowEvent.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
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(graphicInfo, scaleFactor);
|
||||||
|
} else if (throwEvent.getEventDefinitions().get(0) instanceof CompensateEventDefinition) {
|
||||||
|
processDiagramCanvas.drawThrowingCompensateEvent(graphicInfo, scaleFactor);
|
||||||
|
} else {
|
||||||
|
processDiagramCanvas.drawThrowingNoneEvent(graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
processDiagramCanvas.drawThrowingNoneEvent(graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// end event
|
||||||
|
activityDrawInstructions.put(EndEvent.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
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.getName(), graphicInfo, scaleFactor);
|
||||||
|
} else {
|
||||||
|
processDiagramCanvas.drawNoneEndEvent(graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
processDiagramCanvas.drawNoneEndEvent(graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// task
|
||||||
|
activityDrawInstructions.put(Task.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
processDiagramCanvas.drawTask(flowNode.getName(), graphicInfo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// user task
|
||||||
|
activityDrawInstructions.put(UserTask.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
processDiagramCanvas.drawUserTask(flowNode.getName(), graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// script task
|
||||||
|
activityDrawInstructions.put(ScriptTask.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
processDiagramCanvas.drawScriptTask(flowNode.getName(), graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// service task
|
||||||
|
activityDrawInstructions.put(ServiceTask.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
ServiceTask serviceTask = (ServiceTask) flowNode;
|
||||||
|
if ("camel".equalsIgnoreCase(serviceTask.getType())) {
|
||||||
|
processDiagramCanvas.drawCamelTask(serviceTask.getName(), graphicInfo, scaleFactor);
|
||||||
|
} else if ("mule".equalsIgnoreCase(serviceTask.getType())) {
|
||||||
|
processDiagramCanvas.drawMuleTask(serviceTask.getName(), graphicInfo, scaleFactor);
|
||||||
|
} else {
|
||||||
|
processDiagramCanvas.drawServiceTask(serviceTask.getName(), graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// receive task
|
||||||
|
activityDrawInstructions.put(ReceiveTask.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
processDiagramCanvas.drawReceiveTask(flowNode.getName(), graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// send task
|
||||||
|
activityDrawInstructions.put(SendTask.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
processDiagramCanvas.drawSendTask(flowNode.getName(), graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// manual task
|
||||||
|
activityDrawInstructions.put(ManualTask.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
processDiagramCanvas.drawManualTask(flowNode.getName(), graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// businessRuleTask task
|
||||||
|
activityDrawInstructions.put(BusinessRuleTask.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
processDiagramCanvas.drawBusinessRuleTask(flowNode.getName(), graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// exclusive gateway
|
||||||
|
activityDrawInstructions.put(ExclusiveGateway.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
processDiagramCanvas.drawExclusiveGateway(graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// inclusive gateway
|
||||||
|
activityDrawInstructions.put(InclusiveGateway.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
processDiagramCanvas.drawInclusiveGateway(graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// parallel gateway
|
||||||
|
activityDrawInstructions.put(ParallelGateway.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
processDiagramCanvas.drawParallelGateway(graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// event based gateway
|
||||||
|
activityDrawInstructions.put(EventGateway.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
processDiagramCanvas.drawEventBasedGateway(graphicInfo, scaleFactor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Boundary timer
|
||||||
|
activityDrawInstructions.put(BoundaryEvent.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
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.getName(), graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor);
|
||||||
|
|
||||||
|
} else if (boundaryEvent.getEventDefinitions().get(0) instanceof ErrorEventDefinition) {
|
||||||
|
|
||||||
|
processDiagramCanvas.drawCatchingErrorEvent(graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor);
|
||||||
|
|
||||||
|
} else if (boundaryEvent.getEventDefinitions().get(0) instanceof SignalEventDefinition) {
|
||||||
|
processDiagramCanvas.drawCatchingSignalEvent(flowNode.getName(), graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor);
|
||||||
|
|
||||||
|
} else if (boundaryEvent.getEventDefinitions().get(0) instanceof MessageEventDefinition) {
|
||||||
|
processDiagramCanvas.drawCatchingMessageEvent(flowNode.getName(), graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor);
|
||||||
|
|
||||||
|
} else if (boundaryEvent.getEventDefinitions().get(0) instanceof CompensateEventDefinition) {
|
||||||
|
processDiagramCanvas.drawCatchingCompensateEvent(graphicInfo, boundaryEvent.isCancelActivity(), scaleFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// subprocess
|
||||||
|
activityDrawInstructions.put(SubProcess.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) {
|
||||||
|
processDiagramCanvas.drawCollapsedSubProcess(flowNode.getName(), graphicInfo, false);
|
||||||
|
} else {
|
||||||
|
processDiagramCanvas.drawExpandedSubProcess(flowNode.getName(), graphicInfo, false, scaleFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Event subprocess
|
||||||
|
activityDrawInstructions.put(EventSubProcess.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) {
|
||||||
|
processDiagramCanvas.drawCollapsedSubProcess(flowNode.getName(), graphicInfo, true);
|
||||||
|
} else {
|
||||||
|
processDiagramCanvas.drawExpandedSubProcess(flowNode.getName(), graphicInfo, true, scaleFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// call activity
|
||||||
|
activityDrawInstructions.put(CallActivity.class, new ActivityDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
processDiagramCanvas.drawCollapsedCallActivity(flowNode.getName(), graphicInfo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// text annotation
|
||||||
|
artifactDrawInstructions.put(TextAnnotation.class, new ArtifactDrawInstruction() {
|
||||||
|
|
||||||
|
public void draw(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(artifact.getId());
|
||||||
|
TextAnnotation textAnnotation = (TextAnnotation) artifact;
|
||||||
|
processDiagramCanvas.drawTextAnnotation(textAnnotation.getText(), graphicInfo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// association
|
||||||
|
artifactDrawInstructions.put(Association.class, new ArtifactDrawInstruction() {
|
||||||
|
|
||||||
|
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, scaleFactor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List<String> highLightedActivities, List<String> highLightedFlows,
|
||||||
|
String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor) {
|
||||||
|
|
||||||
|
return generateProcessDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows,
|
||||||
|
activityFontName, labelFontName, annotationFontName, customClassLoader, scaleFactor).generateImage(imageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List<String> highLightedActivities, List<String> highLightedFlows) {
|
||||||
|
return generateDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows, null, null, null, null, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream generateDiagram(BpmnModel bpmnModel, String imageType,
|
||||||
|
List<String> highLightedActivities, List<String> highLightedFlows, double scaleFactor) {
|
||||||
|
return generateDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows, null, null, null, null, scaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List<String> highLightedActivities) {
|
||||||
|
return generateDiagram(bpmnModel, imageType, highLightedActivities, Collections.<String>emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, List<String> highLightedActivities, double scaleFactor) {
|
||||||
|
return generateDiagram(bpmnModel, imageType, highLightedActivities, Collections.<String>emptyList(), scaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, String activityFontName,
|
||||||
|
String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
|
||||||
|
|
||||||
|
return generateDiagram(bpmnModel, imageType, Collections.<String>emptyList(), Collections.<String>emptyList(),
|
||||||
|
activityFontName, labelFontName, annotationFontName, customClassLoader, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream generateDiagram(BpmnModel bpmnModel, String imageType, String activityFontName,
|
||||||
|
String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor) {
|
||||||
|
|
||||||
|
return generateDiagram(bpmnModel, imageType, Collections.<String>emptyList(), Collections.<String>emptyList(),
|
||||||
|
activityFontName, labelFontName, annotationFontName, customClassLoader, scaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream generatePngDiagram(BpmnModel bpmnModel) {
|
||||||
|
return generatePngDiagram(bpmnModel, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream generatePngDiagram(BpmnModel bpmnModel, double scaleFactor) {
|
||||||
|
return generateDiagram(bpmnModel, "png", Collections.<String>emptyList(), Collections.<String>emptyList(), scaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream generateJpgDiagram(BpmnModel bpmnModel) {
|
||||||
|
return generateJpgDiagram(bpmnModel, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream generateJpgDiagram(BpmnModel bpmnModel, double scaleFactor) {
|
||||||
|
return generateDiagram(bpmnModel, "jpg", Collections.<String>emptyList(), Collections.<String>emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferedImage generateImage(BpmnModel bpmnModel, String imageType, List<String> highLightedActivities, List<String> highLightedFlows,
|
||||||
|
String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor) {
|
||||||
|
|
||||||
|
return generateProcessDiagram(bpmnModel, imageType, highLightedActivities, highLightedFlows,
|
||||||
|
activityFontName, labelFontName, annotationFontName, customClassLoader, scaleFactor).generateBufferedImage(imageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferedImage generateImage(BpmnModel bpmnModel, String imageType,
|
||||||
|
List<String> highLightedActivities, List<String> highLightedFlows, double scaleFactor) {
|
||||||
|
|
||||||
|
return generateImage(bpmnModel, imageType, highLightedActivities, highLightedFlows, null, null, null, null, scaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferedImage generatePngImage(BpmnModel bpmnModel, double scaleFactor) {
|
||||||
|
return generateImage(bpmnModel, "png", Collections.<String>emptyList(), Collections.<String>emptyList(), scaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CustomProcessDiagramCanvas generateProcessDiagram(BpmnModel bpmnModel, String imageType,
|
||||||
|
List<String> highLightedActivities, List<String> highLightedFlows,
|
||||||
|
String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader, double scaleFactor) {
|
||||||
|
|
||||||
|
prepareBpmnModel(bpmnModel);
|
||||||
|
|
||||||
|
CustomProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(bpmnModel, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
|
||||||
|
|
||||||
|
// Draw pool shape, if process is participant in collaboration
|
||||||
|
for (Pool pool : bpmnModel.getPools()) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId());
|
||||||
|
processDiagramCanvas.drawPoolOrLane(pool.getName(), graphicInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw lanes
|
||||||
|
for (Process process : bpmnModel.getProcesses()) {
|
||||||
|
for (Lane lane : process.getLanes()) {
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(lane.getId());
|
||||||
|
processDiagramCanvas.drawPoolOrLane(lane.getName(), graphicInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw activities and their sequence-flows
|
||||||
|
for (FlowNode flowNode : bpmnModel.getProcesses().get(0).findFlowElementsOfType(FlowNode.class)) {
|
||||||
|
drawActivity(processDiagramCanvas, bpmnModel, flowNode, highLightedActivities, highLightedFlows, scaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Process process : bpmnModel.getProcesses()) {
|
||||||
|
for (FlowNode flowNode : process.findFlowElementsOfType(FlowNode.class)) {
|
||||||
|
drawActivity(processDiagramCanvas, bpmnModel, flowNode, highLightedActivities, highLightedFlows, scaleFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw artifacts
|
||||||
|
for (Process process : bpmnModel.getProcesses()) {
|
||||||
|
|
||||||
|
for (Artifact artifact : process.getArtifacts()) {
|
||||||
|
drawArtifact(processDiagramCanvas, bpmnModel, artifact);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SubProcess> subProcesses = process.findFlowElementsOfType(SubProcess.class, true);
|
||||||
|
if (subProcesses != null) {
|
||||||
|
for (SubProcess subProcess : subProcesses) {
|
||||||
|
for (Artifact subProcessArtifact : subProcess.getArtifacts()) {
|
||||||
|
drawArtifact(processDiagramCanvas, bpmnModel, subProcessArtifact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return processDiagramCanvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void prepareBpmnModel(BpmnModel bpmnModel) {
|
||||||
|
|
||||||
|
// Need to make sure all elements have positive x and y.
|
||||||
|
// Check all graphicInfo and update the elements accordingly
|
||||||
|
|
||||||
|
List<GraphicInfo> allGraphicInfos = new ArrayList<GraphicInfo>();
|
||||||
|
if (bpmnModel.getLocationMap() != null) {
|
||||||
|
allGraphicInfos.addAll(bpmnModel.getLocationMap().values());
|
||||||
|
}
|
||||||
|
if (bpmnModel.getLabelLocationMap() != null) {
|
||||||
|
allGraphicInfos.addAll(bpmnModel.getLabelLocationMap().values());
|
||||||
|
}
|
||||||
|
if (bpmnModel.getFlowLocationMap() != null) {
|
||||||
|
for (List<GraphicInfo> flowGraphicInfos : bpmnModel.getFlowLocationMap().values()) {
|
||||||
|
allGraphicInfos.addAll(flowGraphicInfos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allGraphicInfos.size() > 0) {
|
||||||
|
|
||||||
|
boolean needsTranslationX = false;
|
||||||
|
boolean needsTranslationY = false;
|
||||||
|
|
||||||
|
double lowestX = 0.0;
|
||||||
|
double lowestY = 0.0;
|
||||||
|
|
||||||
|
// Collect lowest x and y
|
||||||
|
for (GraphicInfo graphicInfo : allGraphicInfos) {
|
||||||
|
|
||||||
|
double x = graphicInfo.getX();
|
||||||
|
double y = graphicInfo.getY();
|
||||||
|
|
||||||
|
if (x < lowestX) {
|
||||||
|
needsTranslationX = true;
|
||||||
|
lowestX = x;
|
||||||
|
}
|
||||||
|
if (y < lowestY) {
|
||||||
|
needsTranslationY = true;
|
||||||
|
lowestY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update all graphicInfo objects
|
||||||
|
if (needsTranslationX || needsTranslationY) {
|
||||||
|
|
||||||
|
double translationX = Math.abs(lowestX);
|
||||||
|
double translationY = Math.abs(lowestY);
|
||||||
|
|
||||||
|
for (GraphicInfo graphicInfo : allGraphicInfos) {
|
||||||
|
if (needsTranslationX) {
|
||||||
|
graphicInfo.setX(graphicInfo.getX() + translationX);
|
||||||
|
}
|
||||||
|
if (needsTranslationY) {
|
||||||
|
graphicInfo.setY(graphicInfo.getY() + translationY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void drawActivity(CustomProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel,
|
||||||
|
FlowNode flowNode, List<String> highLightedActivities, List<String> highLightedFlows, double scaleFactor) {
|
||||||
|
|
||||||
|
ActivityDrawInstruction drawInstruction = activityDrawInstructions.get(flowNode.getClass());
|
||||||
|
if (drawInstruction != null) {
|
||||||
|
|
||||||
|
drawInstruction.draw(processDiagramCanvas, bpmnModel, flowNode);
|
||||||
|
|
||||||
|
// Gather info on the multi instance marker
|
||||||
|
boolean multiInstanceSequential = false, multiInstanceParallel = false, collapsed = 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 collapsed marker
|
||||||
|
GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
|
||||||
|
if (flowNode instanceof SubProcess) {
|
||||||
|
collapsed = graphicInfo.getExpanded() != null && !graphicInfo.getExpanded();
|
||||||
|
} else if (flowNode instanceof CallActivity) {
|
||||||
|
collapsed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scaleFactor == 1.0) {
|
||||||
|
// Actually draw the markers
|
||||||
|
processDiagramCanvas.drawActivityMarkers((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight(),
|
||||||
|
multiInstanceSequential, multiInstanceParallel, collapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw highlighted activities
|
||||||
|
if (highLightedActivities.contains(flowNode.getId())) {
|
||||||
|
drawHighLight(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId()));
|
||||||
|
}
|
||||||
|
// Drow highlighted history activities
|
||||||
|
if (highLightedActivities.contains("#" + flowNode.getId())) {
|
||||||
|
drawHighLightHistory(processDiagramCanvas, bpmnModel.getGraphicInfo(flowNode.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outgoing transitions of activity
|
||||||
|
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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
processDiagramCanvas.drawSequenceflow(xPoints, yPoints, drawConditionalIndicator, isDefault, highLighted, scaleFactor);
|
||||||
|
|
||||||
|
// Draw sequenceflow label
|
||||||
|
GraphicInfo labelGraphicInfo = bpmnModel.getLabelGraphicInfo(sequenceFlow.getId());
|
||||||
|
if (labelGraphicInfo != null) {
|
||||||
|
processDiagramCanvas.drawLabel(sequenceFlow.getName(), labelGraphicInfo, false);
|
||||||
|
} else {
|
||||||
|
GraphicInfo lineCenter = getLineCenter(graphicInfoList);
|
||||||
|
processDiagramCanvas.drawLabel(sequenceFlow.getName(), lineCenter, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nested elements
|
||||||
|
if (flowNode instanceof FlowElementsContainer) {
|
||||||
|
for (FlowElement nestedFlowElement : ((FlowElementsContainer) flowNode).getFlowElements()) {
|
||||||
|
if (nestedFlowElement instanceof FlowNode) {
|
||||||
|
drawActivity(processDiagramCanvas, bpmnModel, (FlowNode) nestedFlowElement,
|
||||||
|
highLightedActivities, highLightedFlows, scaleFactor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void drawHighLightHistory(CustomProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo) {
|
||||||
|
processDiagramCanvas.drawHighLightHistory((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static CustomProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel, String imageType,
|
||||||
|
String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
|
||||||
|
|
||||||
|
// We need to calculate maximum values to know how big the image will be in its entirety
|
||||||
|
double minX = Double.MAX_VALUE;
|
||||||
|
double maxX = 0;
|
||||||
|
double minY = Double.MAX_VALUE;
|
||||||
|
double maxY = 0;
|
||||||
|
|
||||||
|
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 https://activiti.atlassian.net/browse/ACT-1431
|
||||||
|
if (flowNodes.isEmpty() && bpmnModel.getPools().isEmpty() && nrOfLanes == 0) {
|
||||||
|
// Nothing to show
|
||||||
|
minX = 0;
|
||||||
|
minY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CustomProcessDiagramCanvas((int) maxX + 10, (int) maxY + 10, (int) minX, (int) minY,
|
||||||
|
imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user