package com.example.demo.controller ;
import com.fasterxml.jackson.databind.JsonNode ;
import com.fasterxml.jackson.databind.ObjectMapper ;
import io.swagger.annotations.Api ;
import io.swagger.annotations.ApiOperation ;
import org.activiti.bpmn.converter.BpmnXMLConverter ;
import org.activiti.bpmn.converter.CallActivityXMLConverter ;
import org.activiti.bpmn.converter.UserTaskXMLConverter ;
import org.activiti.bpmn.model.* ;
import org.activiti.bpmn.model.Process ;
import org.activiti.editor.language.json.converter.BpmnJsonConverter ;
import org.activiti.engine.* ;
import org.activiti.engine.history.HistoricActivityInstance ;
import org.activiti.engine.history.HistoricTaskInstance ;
import org.activiti.engine.repository.Deployment ;
import org.activiti.engine.repository.DeploymentBuilder ;
import org.activiti.engine.repository.Model ;
import org.activiti.engine.runtime.Execution ;
import org.activiti.engine.runtime.ProcessInstance ;
import org.activiti.engine.task.Task ;
import org.apache.commons.lang3.StringUtils ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.core.io.ClassPathResource ;
import org.springframework.web.bind.annotation.GetMapping ;
import org.springframework.web.bind.annotation.RequestMapping ;
import org.springframework.web.bind.annotation.RestController ;
import javax.xml.stream.XMLInputFactory ;
import javax.xml.stream.XMLStreamReader ;
import java.io.UnsupportedEncodingException ;
import java.nio.charset.Charset ;
import java.util.* ;
import java.util.stream.Collectors ;
/ * *
* @author yanpeng
* @version 1 . 0
* @desc TODO
* @company 北京中经网软件有限公司
* @date 2020 / 10 / 27 14 : 34
* /
@RestController
@RequestMapping ( "workflow" )
@Api ( tags = "工作流接口" )
public class WorkFlowController {
@Autowired
private ProcessEngine processEngine ;
@ApiOperation ( value = "保存工作流" )
@GetMapping ( "model" )
public void model ( ) {
RepositoryService repositoryService = processEngine . getRepositoryService ( ) ;
Model model = repositoryService . newModel ( ) ;
model . setName ( "请假工作流市场部" ) ;
model . setKey ( "holidayex" ) ;
repositoryService . saveModel ( model ) ;
System . out . println ( model . getId ( ) ) ;
}
@ApiOperation ( value = "保存xml" )
@GetMapping ( "modelxml" )
public void modelXml ( String modeid ) throws UnsupportedEncodingException {
RepositoryService repositoryService = processEngine . getRepositoryService ( ) ;
Model model = repositoryService . getModel ( modeid ) ;
// Deployment deploy = repositoryService.createDeployment().addClasspathResource("bpmn/testex1.bpmn").name("请假申请流程").deploy();
// 创建转换对象
BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter ( ) ;
// XMLStreamReader读取XML资源
XMLInputFactory xmlInputFactory = XMLInputFactory . newInstance ( ) ;
XMLStreamReader xmlStreamReader = null ;
try {
ClassPathResource resource = new ClassPathResource ( "bpmn/testex1.xml" ) ;
xmlStreamReader = xmlInputFactory . createXMLStreamReader ( resource . getInputStream ( ) ) ;
} catch ( Exception e ) {
e . printStackTrace ( ) ;
}
BpmnXMLConverter . addConverter ( new UserTaskXMLConverter ( ) ) ;
BpmnXMLConverter . addConverter ( new CallActivityXMLConverter ( ) ) ;
// 把xml转换成BpmnModel对象
BpmnModel bpmnModel = bpmnXMLConverter . convertToBpmnModel ( xmlStreamReader ) ;
// 创建转换对象
BpmnJsonConverter bpmnJsonConverter = new BpmnJsonConverter ( ) ;
// 把BpmnModel对象转换成json
String bpmnXml = bpmnJsonConverter . convertToJson ( bpmnModel ) . toString ( ) ;
repositoryService . addModelEditorSource ( model . getId ( ) , bpmnXml . getBytes ( "utf-8" ) ) ;
}
@Autowired
private RepositoryService repositoryService ;
@ApiOperation ( value = "发布工作流" )
@GetMapping ( "deploy" )
public void deploy ( String modeid ) throws Exception {
Model modelData = repositoryService . getModel ( modeid ) ;
byte [ ] bytes = repositoryService . getModelEditorSource ( modelData . getId ( ) ) ;
JsonNode modelNode = new ObjectMapper ( ) . readTree ( bytes ) ;
BpmnModel model = new BpmnJsonConverter ( ) . convertToBpmnModel ( modelNode ) ;
model . getProcesses ( ) . get ( 0 ) . setName ( modelData . getName ( ) ) ;
model . getProcesses ( ) . get ( 0 ) . setId ( modelData . getKey ( ) ) ;
//校验有没有开始结束节点-
List < EndEvent > endEventList = model . getProcesses ( ) . get ( 0 ) . findFlowElementsOfType ( EndEvent . class ) ;
List < StartEvent > startEventList = model . getProcesses ( ) . get ( 0 ) . findFlowElementsOfType ( StartEvent . class ) ;
List < ExclusiveGateway > gateways = model . getProcesses ( ) . get ( 0 ) . findFlowElementsOfType ( ExclusiveGateway . class ) ;
if ( gateways ! = null ) {
for ( ExclusiveGateway gateway : gateways ) {
System . out . println ( gateway . getId ( ) ) ;
Collection < FlowElement > flowElements = model . getProcesses ( ) . get ( 0 ) . getFlowElements ( ) ;
List < SequenceFlow > collect = model . getProcesses ( ) . get ( 0 ) . findFlowElementsOfType ( SequenceFlow . class ) . stream ( ) . filter ( x - > x . getSourceRef ( ) . equals ( gateway . getId ( ) ) ) . collect ( Collectors . toList ( ) ) ;
flowElements . removeAll ( collect ) ;
Collections . sort ( collect , ( x1 , x2 ) - > x1 . getConditionExpression ( ) = = null & & x2 . getConditionExpression ( ) ! = null ? 1 : x1 . getConditionExpression ( ) ! = null & & x2 . getConditionExpression ( ) = = null ? - 1 : 0 ) ;
flowElements . addAll ( collect ) ;
System . out . println ( collect ) ;
}
}
if ( startEventList . size ( ) = = 0 ) {
System . out . println ( "没开始节点" ) ;
}
if ( endEventList . size ( ) = = 0 ) {
System . out . println ( "没有结束节点" ) ;
}
byte [ ] bpmnByates = new BpmnXMLConverter ( ) . convertToXML ( model ) ;
//发布流程
String processName = modelData . getName ( ) + ".bpmn20.xml" ;
String convertToXML = new String ( bpmnByates , "UTF-8" ) ;
System . out . println ( convertToXML ) ;
DeploymentBuilder deployment = repositoryService . createDeployment ( ) ;
deployment . name ( modelData . getName ( ) ) ;
deployment . addString ( processName , convertToXML ) ;
deployment . key ( modelData . getKey ( ) ) ;
Deployment deploy = deployment . deploy ( ) ;
modelData . setDeploymentId ( deploy . getId ( ) ) ;
System . out . println ( deploy . getId ( ) ) ;
System . out . println ( deploy . getKey ( ) ) ;
repositoryService . saveModel ( modelData ) ;
}
@ApiOperation ( value = "启动工作流" )
@GetMapping ( "start" )
public void start ( Integer num ) {
RuntimeService runtimeService = processEngine . getRuntimeService ( ) ;
Map < String , Object > map = new HashMap < > ( ) ;
map . put ( "num" , num ) ;
ProcessInstance processInstance = runtimeService . startProcessInstanceByKey ( "holidayex" , map ) ;
System . out . println ( processInstance . getProcessDefinitionId ( ) ) ;
System . out . println ( processInstance . getId ( ) ) ;
}
@Autowired
private TaskService taskService ;
@ApiOperation ( value = "查询任务" )
@GetMapping ( "query" )
public Boolean query ( ) {
List < Task > holidayex = taskService . createTaskQuery ( ) . processDefinitionKey ( "holidayex" ) . list ( ) ;
holidayex . stream ( ) . forEach ( x - > {
System . out . println ( x . getProcessDefinitionId ( ) ) ;
System . out . println ( x . getId ( ) ) ;
System . out . println ( x . getName ( ) ) ;
System . out . println ( x . getAssignee ( ) ) ;
} ) ;
return true ;
}
@ApiOperation ( value = "完成任务" )
@GetMapping ( "ok" )
public Boolean ok ( String taskid ) {
TaskService taskService = processEngine . getTaskService ( ) ;
taskService . complete ( taskid ) ;
return true ;
}
@Autowired
private HistoryService historyService ;
@Autowired
private RuntimeService runtimeService ;
public void backProcess ( Task task ) throws Exception {
String processInstanceId = task . getProcessInstanceId ( ) ;
// 取得所有历史任务按时间降序排序
List < HistoricTaskInstance > htiList = historyService . createHistoricTaskInstanceQuery ( )
. processInstanceId ( processInstanceId )
. orderByTaskCreateTime ( )
. desc ( )
. list ( ) ;
if ( htiList ! = null | | htiList . size ( ) < 2 ) {
return ;
}
// list里的第二条代表上一个任务
HistoricTaskInstance lastTask = htiList . get ( 1 ) ;
// list里第一条代表当前任务
HistoricTaskInstance curTask = htiList . get ( 0 ) ;
// 当前节点的executionId
String curExecutionId = curTask . getExecutionId ( ) ;
// 上个节点的taskId
String lastTaskId = lastTask . getId ( ) ;
// 上个节点的executionId
String lastExecutionId = lastTask . getExecutionId ( ) ;
if ( null = = lastTaskId ) {
throw new Exception ( "LAST TASK IS NULL" ) ;
}
String processDefinitionId = lastTask . getProcessDefinitionId ( ) ;
BpmnModel bpmnModel = repositoryService . getBpmnModel ( processDefinitionId ) ;
String lastActivityId = null ;
List < HistoricActivityInstance > haiFinishedList = historyService . createHistoricActivityInstanceQuery ( )
. executionId ( lastExecutionId ) . finished ( ) . list ( ) ;
for ( HistoricActivityInstance hai : haiFinishedList ) {
if ( lastTaskId . equals ( hai . getTaskId ( ) ) ) {
// 得到ActivityId,只有HistoricActivityInstance对象里才有此方法
lastActivityId = hai . getActivityId ( ) ;
break ;
}
}
// 得到上个节点的信息
FlowNode lastFlowNode = ( FlowNode ) bpmnModel . getMainProcess ( ) . getFlowElement ( lastActivityId ) ;
// 取得当前节点的信息
Execution execution = runtimeService . createExecutionQuery ( ) . executionId ( curExecutionId ) . singleResult ( ) ;
String curActivityId = execution . getActivityId ( ) ;
FlowNode curFlowNode = ( FlowNode ) bpmnModel . getMainProcess ( ) . getFlowElement ( curActivityId ) ;
//记录当前节点的原活动方向
List < SequenceFlow > oriSequenceFlows = new ArrayList < > ( ) ;
oriSequenceFlows . addAll ( curFlowNode . getOutgoingFlows ( ) ) ;
//清理活动方向
curFlowNode . getOutgoingFlows ( ) . clear ( ) ;
//建立新方向
List < SequenceFlow > newSequenceFlowList = new ArrayList < > ( ) ;
SequenceFlow newSequenceFlow = new SequenceFlow ( ) ;
newSequenceFlow . setId ( "newSequenceFlowId" ) ;
newSequenceFlow . setSourceFlowElement ( curFlowNode ) ;
newSequenceFlow . setTargetFlowElement ( lastFlowNode ) ;
newSequenceFlowList . add ( newSequenceFlow ) ;
curFlowNode . setOutgoingFlows ( newSequenceFlowList ) ;
// 完成任务
taskService . complete ( task . getId ( ) ) ;
//恢复原方向
curFlowNode . setOutgoingFlows ( oriSequenceFlows ) ;
org . activiti . engine . task . Task nextTask = taskService
. createTaskQuery ( ) . processInstanceId ( processInstanceId ) . singleResult ( ) ;
// 设置执行人
if ( nextTask ! = null ) {
taskService . setAssignee ( nextTask . getId ( ) , lastTask . getAssignee ( ) ) ;
}
}
}