盘古BPM体验地址    盘古BPM交流群盘古BPM交流群号:963222735

activiti自定义图片生成实现

Activiti 分享牛 6093℃

摘要:

前面的activiti系列课程中,我们详细讲解了自由流程的实现,其中自由流程中需要的节点肯定是我们手动构建的,这些节点在流程模板中是没有定义的,因此虽然满足了动态流程的需求,但是如果我们使用原生的流程图生成逻辑,就会发现新增加的节点并不会在流程图中体现出来,因为默认的流程图生成逻辑是按照流程模板中已经定义好的的节点进行查找绘制的,那我们该怎么办呢?下面提供两种设计思路以及实现供大家参考。

    因为自由流程中的新增的节点为流程虚拟机中的ActivityImpl类,那么很显然这个已经是对象解析层的类了,流程图的生成默认是查询的元素解析层BaseElement类,那将ActivityImpl类转化为BaseElement类意义也不大,更致命的问题是模板是一个,流程实例是多个,因此该方式不可行。谨记:该方式不可行。

    流程图的生成是根据BpmnModel类实现的,因此呢?我们可以根据流程实例将流程历史实例中所有运行的节点查询出来(包括模板中的节点以及自由流中动态添加的节点),可以按照创建的时间进行排序,然后将这些历史阶段组装为BpmnModel实例对象。

    注意一点:查询出来的已经运转的历史节点+后续节点(以最后一个历史数据的节点为起点,模板中还没走的节点),两者数据合并才为一个完整的数据。

    根据流程实例将流程历史实例中所有运行的节点查询出来并排序相对来说比较简单,因为我们只需要用到节点的id以及名称即可,因为坐标是我们手动构造的。如下图所示:

  对于上面的场景解释一下:

    比如,我们现在定义了两个任务节点分别为usertask1以及usertask2。如果不涉及到自由流程(也就是常规性的流转)。那肯定生成的流程图是没有问题的。自由流程如下:

比如当usertask1完成之后,这个节点的处理人可以增加一系列的节点,可以是多实例,可以是普通的任务节点,比如增加了a,b,c三个节点顺序执行的节点,当c节点完毕之后开始执行usertask2节点。因此这个流程实例的完整轨迹为:

   开始节点-usertask1-a-b-c-usertask2-结束节点。

那问题就出现了a,b,c三个节点在上图中并没有绘制,所以我们最终需要绘制这些节点以及坐标信息,(坐标的绘制过程最复杂,因为坐标绘制的不对劲可以出现节点的叠加以及重影)。

代码书写

ok,接下来我们就看一下我实际项目开发中是如何解决该问题的,代码如下:

package com.shareniu.chapter18.image;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.EndEvent;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.GraphicInfo;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.bpmn.model.UserTask;

public class ImaGegenerateUtils {
public static final String startEvent = "startEvent";
public static final String endEvent = "endEvent";
public static final String parallelGateway = "parallelGateway";
public static final String userTask = "userTask";
public static final String sequenceFlow = "sequenceFlow";
public static final String serviceTask = "serviceTask";
public static final String exclusiveGateway = "exclusiveGateway";
public static final double startEvent_X = 50D;
public static final double startEvent_Y = 75D;
public static final double userTask_Y = 50D;
public static final double startEvent_HEIGHT = 30D;
public static final double startEvent_WIDTH = 30D;
public static final double userTask_HEIGHT = 100D;
public static final double userTask_WIDTH = 80D;
//偏移量
public static final double userTask_OFFSET = 200D;
public static InputStream gegenerate(List<String> userTasks,
List<String> activeActivityIds, List<String> highLightedFlows) {
BpmnModel bpmnModel = new BpmnModel();
Process process = new Process();
bpmnModel.addProcess(process);
InputStream in = null;
gegenerateCore(userTasks, bpmnModel);
in = new HMProcessDiagramGenerator().generateDiagram(bpmnModel, "png",
activeActivityIds, highLightedFlows, "微软雅黑", "微软雅黑", "微软雅黑",
null, 1.0);
return in;
}



private static void gegenerateCore(List<String> userTasks,
BpmnModel bpmnModel) {
// 生成开始节点
StartEvent gegenerateStartEvent = gegenerateStartEvent(startEvent, startEvent, bpmnModel);
// 生成任务节点
List<UserTask> gegenerateUserTasks = gegenerateUserTask(userTasks,bpmnModel);
SequenceFlow startSequenceFlow = gegenerateSequenceFlow(gegenerateStartEvent.getId()+userTasks.get(0), "", gegenerateStartEvent.getId(), userTasks.get(0), bpmnModel);
startToUserTask(userTasks, bpmnModel, gegenerateStartEvent,
gegenerateUserTasks, startSequenceFlow);
EndEvent gegenerateEndEvent = gegenerateEndEvent(endEvent, endEvent, bpmnModel, userTasks.size());
SequenceFlow endSequenceFlow = gegenerateSequenceFlow(userTasks.get(userTasks.size()-1)+gegenerateEndEvent.getId(), "", userTasks.get(userTasks.size()-1),gegenerateEndEvent.getId(), bpmnModel);
lastUserTaskToEnd(userTasks, bpmnModel, gegenerateEndEvent,
gegenerateUserTasks, endSequenceFlow);
}



private static void lastUserTaskToEnd(List<String> userTasks,
BpmnModel bpmnModel, EndEvent endEvent,
List<UserTask> gegenerateUserTasks, SequenceFlow endSequenceFlow) {
List<SequenceFlow> endEventOutgoingFlows=new ArrayList<>();
endEventOutgoingFlows.add(endSequenceFlow);
endEvent.setIncomingFlows(endEventOutgoingFlows);
UserTask lastUserTask = gegenerateUserTasks.get(userTasks.size()-1);
lastUserTask.setOutgoingFlows(endEventOutgoingFlows);
GraphicInfo graphicInfo1 = gegenerateGraphicInfo(getLastUserTaskX(gegenerateUserTasks.size()), 50L, 30L, 30L);
GraphicInfo graphicInfo2 = gegenerateGraphicInfo(getEndEventX(gegenerateUserTasks.size()), 50L, 30L, 30L);
List<GraphicInfo> graphicInfoList=new ArrayList<>();
graphicInfoList.add(graphicInfo1);
graphicInfoList.add(graphicInfo2);
bpmnModel.addFlowGraphicInfoList(userTasks.get(userTasks.size()-1)+endEvent.getId(), graphicInfoList);
}
private static void startToUserTask(List<String> userTasks,
BpmnModel bpmnModel, StartEvent gegenerateStartEvent,
List<UserTask> gegenerateUserTasks, SequenceFlow startSequenceFlow) {
List<SequenceFlow> startEventOutgoingFlows=new ArrayList<>();
startEventOutgoingFlows.add(startSequenceFlow);
gegenerateStartEvent.setOutgoingFlows(startEventOutgoingFlows);
gegenerateUserTasks.get(0).setIncomingFlows(startEventOutgoingFlows);
GraphicInfo graphicInfo1 = gegenerateGraphicInfo(50L, 50L, 30L, 30L);
GraphicInfo graphicInfo2 = gegenerateGraphicInfo(userTask_OFFSET*1, 50L, 30L, 30L);
List<GraphicInfo> graphicInfoList=new ArrayList<>();
graphicInfoList.add(graphicInfo1);
graphicInfoList.add(graphicInfo2);
bpmnModel.addFlowGraphicInfoList(gegenerateStartEvent.getId()+userTasks.get(0), graphicInfoList);
}



private static List<UserTask> gegenerateUserTask(List<String> userTasks,BpmnModel bpmnModel) {
List<UserTask> result=new ArrayList<>();
for (int i = 0; i < userTasks.size(); i++) {
UserTask userTask = gegenerateUserTask(userTasks.get(i), userTasks.get(i), bpmnModel, userTask_OFFSET*(i+1), userTask_Y);
result.add(userTask);
}
//关联创建任务节点的连线信息
gegenerateUserTaskAndSequence(result,userTasks,bpmnModel);
return result;

}

private static void gegenerateUserTaskAndSequence(List<UserTask> UserTaskModels,
List<String> userTasks, BpmnModel bpmnModel) {
for (int i = 0; i < userTasks.size(); i++) {
//设置出线
if (i<userTasks.size()-1) {
UserTask userTask = UserTaskModels.get(i);
String userTaskId=userTasks.get(i);
SequenceFlow sequenceFlow = gegenerateSequenceFlow(userTaskId+userTasks.get(i+1), "", userTaskId, userTasks.get(i+1), bpmnModel,userTask_OFFSET);
List<SequenceFlow> outgoingFlows=new ArrayList<SequenceFlow>();
//添加入线以及出线
outgoingFlows.add(sequenceFlow);
userTask.setOutgoingFlows(outgoingFlows);
}
}
}

private static SequenceFlow gegenerateSequenceFlow(String id, String name,
String sourceRef, String targetRef, BpmnModel bpmnModel) {
SequenceFlow sequenceFlow = new SequenceFlow();
sequenceFlow.setId(id);
sequenceFlow.setName(name);
sequenceFlow.setSourceRef(sourceRef);
sequenceFlow.setTargetRef(targetRef);
addFlowElement(bpmnModel, sequenceFlow);
return sequenceFlow;

}
private static SequenceFlow gegenerateSequenceFlow(String id, String name,
String sourceRef, String targetRef, BpmnModel bpmnModel,double x) {
SequenceFlow sequenceFlow = new SequenceFlow();
sequenceFlow.setId(id);
sequenceFlow.setName(name);
sequenceFlow.setSourceRef(sourceRef);
sequenceFlow.setTargetRef(targetRef);
GraphicInfo graphicInfo3= gegenerateGraphicInfo(x*1+2, 50L, 30L, 30L);
GraphicInfo graphicInfo4 = gegenerateGraphicInfo(x*2, 50L, 30L, 30L);
List<GraphicInfo> graphicInfoList=new ArrayList<>();
graphicInfoList.add(graphicInfo3);
graphicInfoList.add(graphicInfo4);
bpmnModel.addFlowGraphicInfoList(id, graphicInfoList);
addFlowElement(bpmnModel, sequenceFlow);
return sequenceFlow;

}

private static StartEvent gegenerateStartEvent(String id, String name,
BpmnModel bpmnModel) {
StartEvent startEvent = new StartEvent();
startEvent.setId(id);
startEvent.setName(name);
GraphicInfo graphicInfo = gegenerateGraphicInfo(startEvent_X,
startEvent_Y, startEvent_WIDTH, startEvent_HEIGHT);
bpmnModel.addGraphicInfo(id, graphicInfo);
addFlowElement(bpmnModel, startEvent);
return startEvent;
}
private static EndEvent gegenerateEndEvent(String id, String name,
BpmnModel bpmnModel,int nodeNum) {
EndEvent startEvent = new EndEvent();
startEvent.setId(id);
startEvent.setName(name);
GraphicInfo graphicInfo = gegenerateGraphicInfo(getEndEventX(nodeNum),
startEvent_Y, startEvent_WIDTH, startEvent_HEIGHT);
bpmnModel.addGraphicInfo(id, graphicInfo);
addFlowElement(bpmnModel, startEvent);
return startEvent;
}



private static double getEndEventX(int nodeNum) {
return startEvent_X+userTask_OFFSET*(nodeNum+1);
}
private static double getLastUserTaskX(int nodeNum) {
return startEvent_X+userTask_OFFSET*(nodeNum);
}

private static void addFlowElement(BpmnModel bpmnModel,
FlowElement flowElement) {
bpmnModel.getProcesses().get(0).addFlowElement(flowElement);
}

private static UserTask gegenerateUserTask(String id, String name,
BpmnModel bpmnModel, double x, double y) {
UserTask userTask = new UserTask();
userTask.setId(id);
userTask.setName(name);
GraphicInfo graphicInfo = gegenerateGraphicInfo(x, y, userTask_HEIGHT, userTask_WIDTH);
bpmnModel.addGraphicInfo(id, graphicInfo);
addFlowElement(bpmnModel, userTask);
return userTask;
}

private static GraphicInfo gegenerateGraphicInfo(double x, double y,
double width, double height) {
GraphicInfo graphicInfo1 = new GraphicInfo();
graphicInfo1.setWidth(width);
graphicInfo1.setHeight(height);
graphicInfo1.setX(x);
graphicInfo1.setY(y);
return graphicInfo1;
}
}

上面代码写完之后,我们就写一个测试类,代码如下:

	@Test
public void getBpmnModel3() {
List<String> activeActivityIds = new ArrayList<>(0);
activeActivityIds.add("usertask2");
List<String> highLightedFlows = new ArrayList<>(0);
List<String> userTasks=new ArrayList<>();
userTasks.add("usertask1");
userTasks.add("usertask2");
userTasks.add("usertask3");
/*userTasks.add("usertask4");
userTasks.add("usertask5");*/
InputStream in = ImaGegenerateUtils.gegenerate(userTasks, activeActivityIds, highLightedFlows);
FileOutputStream fw = null;
try {
fw = new FileOutputStream("D:/zxn.jpg");
byte[] buf = new byte[1024];
int len = 0;
while ((len = in.read(buf)) != -1) { // 将byte数据读到最多buf长度的buf数组中
fw.write(buf, 0, len); // 将buf中 从0-len长度的数据写到文件中
}
} catch (IOException e) {
System.out.println("输入错误");
}
}

测试

执行上述代码之后,生成的图片如下所示:

图片以及成功生成。


转载请注明:分享牛 » activiti自定义图片生成实现