Commit 20e6484f authored by HuangBingGui's avatar HuangBingGui
Browse files

no commit message

parent 22579f13
package com.jeespring.modules.act;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
@Configuration
@ImportResource(locations= {"classpath:spring-context-activiti.xml"})
public class ActConfig{
}
/**
* Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
*/
package com.jeespring.modules.act.dao;
import com.jeespring.common.persistence.InterfaceBaseDao;
import com.jeespring.common.persistence.annotation.MyBatisDao;
import com.jeespring.modules.act.entity.Act;
import org.apache.ibatis.annotations.Mapper;
/**
* 审批DAO接口
* @author thinkgem
* @version 2014-05-16
*/
@Mapper
public interface ActDao extends InterfaceBaseDao<Act> {
public int updateProcInsIdByBusinessId(Act act);
}
/**
* Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
*/
package com.jeespring.modules.act.entity;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.jeespring.common.persistence.AbstractBaseEntity;
import com.jeespring.common.utils.StringUtils;
import com.jeespring.common.utils.TimeUtils;
import com.jeespring.modules.act.utils.Variable;
/**
* 工作流Entity
* @author ThinkGem
* @version 2013-11-03
*/
public class Act extends AbstractBaseEntity<Act> {
private static final long serialVersionUID = 1L;
private String taskId; // 任务编号
private String taskName; // 任务名称
private String taskDefKey; // 任务定义Key(任务环节标识)
private String procInsId; // 流程实例ID
private String procDefId; // 流程定义ID
private String procDefKey; // 流程定义Key(流程定义标识)
private String businessTable; // 业务绑定Table
private String businessId; // 业务绑定ID
private String title; // 任务标题
private String status; // 任务状态(todo/claim/finish)
// private String procExecUrl; // 流程执行(办理)RUL
private String comment; // 任务意见
private String flag; // 意见状态
private Task task; // 任务对象
private ProcessDefinition procDef; // 流程定义对象
private ProcessInstance procIns; // 流程实例对象
private HistoricTaskInstance histTask; // 历史任务
private HistoricActivityInstance histIns; //历史活动任务
private String assignee; // 任务执行人编号
private String assigneeName; // 任务执行人名称
private Variable vars; // 流程变量
// private Variable taskVars; // 流程任务变量
private Date beginDate; // 开始查询日期
private Date endDate; // 结束查询日期
private List<Act> list; // 任务列表
public Act() {
super();
}
public String getTaskId() {
if (taskId == null && task != null){
taskId = task.getId();
}
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public String getTaskName() {
if (taskName == null && task != null){
taskName = task.getName();
}
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
public String getTaskDefKey() {
if (taskDefKey == null && task != null){
taskDefKey = task.getTaskDefinitionKey();
}
return taskDefKey;
}
public void setTaskDefKey(String taskDefKey) {
this.taskDefKey = taskDefKey;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public Date getTaskCreateDate() {
if (task != null){
return task.getCreateTime();
}
return null;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public Date getTaskEndDate() {
if (histTask != null){
return histTask.getEndTime();
}
return null;
}
@JsonIgnore
public Task getTask() {
return task;
}
public void setTask(Task task) {
this.task = task;
}
@JsonIgnore
public ProcessDefinition getProcDef() {
return procDef;
}
public void setProcDef(ProcessDefinition procDef) {
this.procDef = procDef;
}
public String getProcDefName() {
return procDef.getName();
}
@JsonIgnore
public ProcessInstance getProcIns() {
return procIns;
}
public void setProcIns(ProcessInstance procIns) {
this.procIns = procIns;
if (procIns != null && procIns.getBusinessKey() != null){
String[] ss = procIns.getBusinessKey().split(":");
setBusinessTable(ss[0]);
setBusinessId(ss[1]);
}
}
// public String getProcExecUrl() {
// return procExecUrl;
// }
//
// public void setProcExecUrl(String procExecUrl) {
// this.procExecUrl = procExecUrl;
// }
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
@JsonIgnore
public HistoricTaskInstance getHistTask() {
return histTask;
}
public void setHistTask(HistoricTaskInstance histTask) {
this.histTask = histTask;
}
@JsonIgnore
public HistoricActivityInstance getHistIns() {
return histIns;
}
public void setHistIns(HistoricActivityInstance histIns) {
this.histIns = histIns;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public Date getBeginDate() {
return beginDate;
}
public void setBeginDate(Date beginDate) {
this.beginDate = beginDate;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
public String getProcDefId() {
if (procDefId == null && task != null){
procDefId = task.getProcessDefinitionId();
}
return procDefId;
}
public void setProcDefId(String procDefId) {
this.procDefId = procDefId;
}
public String getProcInsId() {
if (procInsId == null && task != null){
procInsId = task.getProcessInstanceId();
}
return procInsId;
}
public void setProcInsId(String procInsId) {
this.procInsId = procInsId;
}
public String getBusinessId() {
return businessId;
}
public void setBusinessId(String businessId) {
this.businessId = businessId;
}
public String getBusinessTable() {
return businessTable;
}
public void setBusinessTable(String businessTable) {
this.businessTable = businessTable;
}
public String getAssigneeName() {
return assigneeName;
}
public void setAssigneeName(String assigneeName) {
this.assigneeName = assigneeName;
}
public String getAssignee() {
if (assignee == null && task != null){
assignee = task.getAssignee();
}
return assignee;
}
public void setAssignee(String assignee) {
this.assignee = assignee;
}
public List<Act> getList() {
return list;
}
public void setList(List<Act> list) {
this.list = list;
}
public Variable getVars() {
return vars;
}
public void setVars(Variable vars) {
this.vars = vars;
}
/**
* 通过Map设置流程变量值
* @param map
*/
public void setVars(Map<String, Object> map) {
this.vars = new Variable(map);
}
// public Variable getTaskVars() {
// return taskVars;
// }
//
// public void setTaskVars(Variable taskVars) {
// this.taskVars = taskVars;
// }
//
// /**
// * 通过Map设置流程任务变量值
// * @param map
// */
// public void setTaskVars(Map<String, Object> map) {
// this.taskVars = new Variable(map);
// }
/**
* 获取流程定义KEY
* @return
*/
public String getProcDefKey() {
if (StringUtils.isBlank(procDefKey) && StringUtils.isNotBlank(procDefId)){
procDefKey = StringUtils.split(procDefId, ":")[0];
}
return procDefKey;
}
public void setProcDefKey(String procDefKey) {
this.procDefKey = procDefKey;
}
/**
* 获取过去的任务历时
* @return
*/
public String getDurationTime(){
if (histIns!=null && histIns.getDurationInMillis() != null){
return TimeUtils.toTimeString(histIns.getDurationInMillis());
}
return "";
}
/**
* 是否是一个待办任务
* @return
*/
public boolean isTodoTask(){
return "todo".equals(status) || "claim".equals(status);
}
/**
* 是否是已完成任务
* @return
*/
public boolean isFinishTask(){
return "finish".equals(status) || StringUtils.isBlank(taskId);
}
@Override
public void preInsert() {
}
@Override
public void preUpdate() {
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeespring.modules.act.rest.diagram.services;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.impl.bpmn.behavior.BoundaryEventActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.CallActivityBehavior;
import org.activiti.engine.impl.bpmn.parser.BpmnParse;
import org.activiti.engine.impl.bpmn.parser.ErrorEventDefinition;
import org.activiti.engine.impl.bpmn.parser.EventSubscriptionDeclaration;
import org.activiti.engine.impl.jobexecutor.TimerDeclarationImpl;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.delegate.ActivityBehavior;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.Lane;
import org.activiti.engine.impl.pvm.process.LaneSet;
import org.activiti.engine.impl.pvm.process.ParticipantProcess;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class BaseProcessDefinitionDiagramLayoutResource {
@Autowired
private RuntimeService runtimeService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private HistoryService historyService;
public ObjectNode getDiagramNode(String processInstanceId, String processDefinitionId) {
List<String> highLightedFlows = Collections.<String> emptyList();
List<String> highLightedActivities = Collections.<String> emptyList();
Map<String, ObjectNode> subProcessInstanceMap = new HashMap<String, ObjectNode>();
ProcessInstance processInstance = null;
if (processInstanceId != null) {
processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
if (processInstance == null) {
throw new ActivitiObjectNotFoundException("Process instance could not be found");
}
processDefinitionId = processInstance.getProcessDefinitionId();
List<ProcessInstance> subProcessInstances = runtimeService.createProcessInstanceQuery().superProcessInstanceId(processInstanceId).list();
for (ProcessInstance subProcessInstance : subProcessInstances) {
String subDefId = subProcessInstance.getProcessDefinitionId();
String superExecutionId = ((ExecutionEntity) subProcessInstance).getSuperExecutionId();
ProcessDefinitionEntity subDef = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(subDefId);
ObjectNode processInstanceJSON = new ObjectMapper().createObjectNode();
processInstanceJSON.put("processInstanceId", subProcessInstance.getId());
processInstanceJSON.put("superExecutionId", superExecutionId);
processInstanceJSON.put("processDefinitionId", subDef.getId());
processInstanceJSON.put("processDefinitionKey", subDef.getKey());
processInstanceJSON.put("processDefinitionName", subDef.getName());
subProcessInstanceMap.put(superExecutionId, processInstanceJSON);
}
}
if (processDefinitionId == null) {
throw new ActivitiObjectNotFoundException("No process definition id provided");
}
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId);
if (processDefinition == null) {
throw new ActivitiException("Process definition " + processDefinitionId + " could not be found");
}
ObjectNode responseJSON = new ObjectMapper().createObjectNode();
// Process definition
JsonNode pdrJSON = getProcessDefinitionResponse(processDefinition);
if (pdrJSON != null) {
responseJSON.put("processDefinition", pdrJSON);
}
// Highlighted activities
if (processInstance != null) {
ArrayNode activityArray = new ObjectMapper().createArrayNode();
ArrayNode flowsArray = new ObjectMapper().createArrayNode();
highLightedActivities = runtimeService.getActiveActivityIds(processInstanceId);
highLightedFlows = getHighLightedFlows(processInstanceId, processDefinition);
for (String activityName : highLightedActivities) {
activityArray.add(activityName);
}
for (String flow : highLightedFlows)
flowsArray.add(flow);
responseJSON.put("highLightedActivities", activityArray);
responseJSON.put("highLightedFlows", flowsArray);
}
// Pool shape, if process is participant in collaboration
if (processDefinition.getParticipantProcess() != null) {
ParticipantProcess pProc = processDefinition.getParticipantProcess();
ObjectNode participantProcessJSON = new ObjectMapper().createObjectNode();
participantProcessJSON.put("id", pProc.getId());
if (StringUtils.isNotEmpty(pProc.getName())) {
participantProcessJSON.put("name", pProc.getName());
} else {
participantProcessJSON.put("name", "");
}
participantProcessJSON.put("x", pProc.getX());
participantProcessJSON.put("y", pProc.getY());
participantProcessJSON.put("width", pProc.getWidth());
participantProcessJSON.put("height", pProc.getHeight());
responseJSON.put("participantProcess", participantProcessJSON);
}
// Draw lanes
if (processDefinition.getLaneSets() != null && !processDefinition.getLaneSets().isEmpty()) {
ArrayNode laneSetArray = new ObjectMapper().createArrayNode();
for (LaneSet laneSet : processDefinition.getLaneSets()) {
ArrayNode laneArray = new ObjectMapper().createArrayNode();
if (laneSet.getLanes() != null && !laneSet.getLanes().isEmpty()) {
for (Lane lane : laneSet.getLanes()) {
ObjectNode laneJSON = new ObjectMapper().createObjectNode();
laneJSON.put("id", lane.getId());
if (StringUtils.isNotEmpty(lane.getName())) {
laneJSON.put("name", lane.getName());
} else {
laneJSON.put("name", "");
}
laneJSON.put("x", lane.getX());
laneJSON.put("y", lane.getY());
laneJSON.put("width", lane.getWidth());
laneJSON.put("height", lane.getHeight());
List<String> flowNodeIds = lane.getFlowNodeIds();
ArrayNode flowNodeIdsArray = new ObjectMapper().createArrayNode();
for (String flowNodeId : flowNodeIds) {
flowNodeIdsArray.add(flowNodeId);
}
laneJSON.put("flowNodeIds", flowNodeIdsArray);
laneArray.add(laneJSON);
}
}
ObjectNode laneSetJSON = new ObjectMapper().createObjectNode();
laneSetJSON.put("id", laneSet.getId());
if (StringUtils.isNotEmpty(laneSet.getName())) {
laneSetJSON.put("name", laneSet.getName());
} else {
laneSetJSON.put("name", "");
}
laneSetJSON.put("lanes", laneArray);
laneSetArray.add(laneSetJSON);
}
if (laneSetArray.size() > 0)
responseJSON.put("laneSets", laneSetArray);
}
ArrayNode sequenceFlowArray = new ObjectMapper().createArrayNode();
ArrayNode activityArray = new ObjectMapper().createArrayNode();
// Activities and their sequence-flows
for (ActivityImpl activity : processDefinition.getActivities()) {
getActivity(processInstanceId, activity, activityArray, sequenceFlowArray, processInstance, highLightedFlows, subProcessInstanceMap);
}
responseJSON.put("activities", activityArray);
responseJSON.put("sequenceFlows", sequenceFlowArray);
return responseJSON;
}
private List<String> getHighLightedFlows(String processInstanceId, ProcessDefinitionEntity processDefinition) {
List<String> highLightedFlows = new ArrayList<String>();
List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
List<String> historicActivityInstanceList = new ArrayList<String>();
for (HistoricActivityInstance hai : historicActivityInstances) {
historicActivityInstanceList.add(hai.getActivityId());
}
// add current activities to list
List<String> highLightedActivities = runtimeService.getActiveActivityIds(processInstanceId);
historicActivityInstanceList.addAll(highLightedActivities);
// activities and their sequence-flows
for (ActivityImpl activity : processDefinition.getActivities()) {
int index = historicActivityInstanceList.indexOf(activity.getId());
if (index >= 0 && index + 1 < historicActivityInstanceList.size()) {
List<PvmTransition> pvmTransitionList = activity.getOutgoingTransitions();
for (PvmTransition pvmTransition : pvmTransitionList) {
String destinationFlowId = pvmTransition.getDestination().getId();
if (destinationFlowId.equals(historicActivityInstanceList.get(index + 1))) {
highLightedFlows.add(pvmTransition.getId());
}
}
}
}
return highLightedFlows;
}
private void getActivity(String processInstanceId, ActivityImpl activity, ArrayNode activityArray, ArrayNode sequenceFlowArray,
ProcessInstance processInstance, List<String> highLightedFlows, Map<String, ObjectNode> subProcessInstanceMap) {
ObjectNode activityJSON = new ObjectMapper().createObjectNode();
// Gather info on the multi instance marker
String multiInstance = (String) activity.getProperty("multiInstance");
if (multiInstance != null) {
if (!"sequential".equals(multiInstance)) {
multiInstance = "parallel";
}
}
ActivityBehavior activityBehavior = activity.getActivityBehavior();
// Gather info on the collapsed marker
Boolean collapsed = (activityBehavior instanceof CallActivityBehavior);
Boolean expanded = (Boolean) activity.getProperty(BpmnParse.PROPERTYNAME_ISEXPANDED);
if (expanded != null) {
collapsed = !expanded;
}
Boolean isInterrupting = null;
if (activityBehavior instanceof BoundaryEventActivityBehavior) {
isInterrupting = ((BoundaryEventActivityBehavior) activityBehavior).isInterrupting();
}
// Outgoing transitions of activity
for (PvmTransition sequenceFlow : activity.getOutgoingTransitions()) {
String flowName = (String) sequenceFlow.getProperty("name");
boolean isHighLighted = (highLightedFlows.contains(sequenceFlow.getId()));
boolean isConditional = sequenceFlow.getProperty(BpmnParse.PROPERTYNAME_CONDITION) != null
&& !((String) activity.getProperty("type")).toLowerCase().contains("gateway");
boolean isDefault = sequenceFlow.getId().equals(activity.getProperty("default"))
&& ((String) activity.getProperty("type")).toLowerCase().contains("gateway");
List<Integer> waypoints = ((TransitionImpl) sequenceFlow).getWaypoints();
ArrayNode xPointArray = new ObjectMapper().createArrayNode();
ArrayNode yPointArray = new ObjectMapper().createArrayNode();
for (int i = 0; i < waypoints.size(); i += 2) { // waypoints.size()
// minimally 4: x1, y1,
// x2, y2
xPointArray.add(waypoints.get(i));
yPointArray.add(waypoints.get(i + 1));
}
ObjectNode flowJSON = new ObjectMapper().createObjectNode();
flowJSON.put("id", sequenceFlow.getId());
flowJSON.put("name", flowName);
flowJSON.put("flow", "(" + sequenceFlow.getSource().getId() + ")--" + sequenceFlow.getId() + "-->("
+ sequenceFlow.getDestination().getId() + ")");
if (isConditional)
flowJSON.put("isConditional", isConditional);
if (isDefault)
flowJSON.put("isDefault", isDefault);
if (isHighLighted)
flowJSON.put("isHighLighted", isHighLighted);
flowJSON.put("xPointArray", xPointArray);
flowJSON.put("yPointArray", yPointArray);
sequenceFlowArray.add(flowJSON);
}
// Nested activities (boundary events)
ArrayNode nestedActivityArray = new ObjectMapper().createArrayNode();
for (ActivityImpl nestedActivity : activity.getActivities()) {
nestedActivityArray.add(nestedActivity.getId());
}
Map<String, Object> properties = activity.getProperties();
ObjectNode propertiesJSON = new ObjectMapper().createObjectNode();
for (String key : properties.keySet()) {
Object prop = properties.get(key);
if (prop instanceof String)
propertiesJSON.put(key, (String) properties.get(key));
else if (prop instanceof Integer)
propertiesJSON.put(key, (Integer) properties.get(key));
else if (prop instanceof Boolean)
propertiesJSON.put(key, (Boolean) properties.get(key));
else if ("initial".equals(key)) {
ActivityImpl act = (ActivityImpl) properties.get(key);
propertiesJSON.put(key, act.getId());
} else if ("timerDeclarations".equals(key)) {
ArrayList<TimerDeclarationImpl> timerDeclarations = (ArrayList<TimerDeclarationImpl>) properties.get(key);
ArrayNode timerDeclarationArray = new ObjectMapper().createArrayNode();
if (timerDeclarations != null)
for (TimerDeclarationImpl timerDeclaration : timerDeclarations) {
ObjectNode timerDeclarationJSON = new ObjectMapper().createObjectNode();
timerDeclarationJSON.put("isExclusive", timerDeclaration.isExclusive());
if (timerDeclaration.getRepeat() != null)
timerDeclarationJSON.put("repeat", timerDeclaration.getRepeat());
timerDeclarationJSON.put("retries", String.valueOf(timerDeclaration.getRetries()));
timerDeclarationJSON.put("type", timerDeclaration.getJobHandlerType());
timerDeclarationJSON.put("configuration", timerDeclaration.getJobHandlerConfiguration());
//timerDeclarationJSON.put("expression", timerDeclaration.getDescription());
timerDeclarationArray.add(timerDeclarationJSON);
}
if (timerDeclarationArray.size() > 0)
propertiesJSON.put(key, timerDeclarationArray);
// TODO: implement getting description
} else if ("eventDefinitions".equals(key)) {
ArrayList<EventSubscriptionDeclaration> eventDefinitions = (ArrayList<EventSubscriptionDeclaration>) properties.get(key);
ArrayNode eventDefinitionsArray = new ObjectMapper().createArrayNode();
if (eventDefinitions != null) {
for (EventSubscriptionDeclaration eventDefinition : eventDefinitions) {
ObjectNode eventDefinitionJSON = new ObjectMapper().createObjectNode();
if (eventDefinition.getActivityId() != null)
eventDefinitionJSON.put("activityId", eventDefinition.getActivityId());
eventDefinitionJSON.put("eventName", eventDefinition.getEventName());
eventDefinitionJSON.put("eventType", eventDefinition.getEventType());
eventDefinitionJSON.put("isAsync", eventDefinition.isAsync());
eventDefinitionJSON.put("isStartEvent", eventDefinition.isStartEvent());
eventDefinitionsArray.add(eventDefinitionJSON);
}
}
if (eventDefinitionsArray.size() > 0)
propertiesJSON.put(key, eventDefinitionsArray);
// TODO: implement it
} else if ("errorEventDefinitions".equals(key)) {
ArrayList<ErrorEventDefinition> errorEventDefinitions = (ArrayList<ErrorEventDefinition>) properties.get(key);
ArrayNode errorEventDefinitionsArray = new ObjectMapper().createArrayNode();
if (errorEventDefinitions != null) {
for (ErrorEventDefinition errorEventDefinition : errorEventDefinitions) {
ObjectNode errorEventDefinitionJSON = new ObjectMapper().createObjectNode();
if (errorEventDefinition.getErrorCode() != null)
errorEventDefinitionJSON.put("errorCode", errorEventDefinition.getErrorCode());
else
errorEventDefinitionJSON.putNull("errorCode");
errorEventDefinitionJSON.put("handlerActivityId", errorEventDefinition.getHandlerActivityId());
errorEventDefinitionsArray.add(errorEventDefinitionJSON);
}
}
if (errorEventDefinitionsArray.size() > 0)
propertiesJSON.put(key, errorEventDefinitionsArray);
}
}
if ("callActivity".equals(properties.get("type"))) {
CallActivityBehavior callActivityBehavior = null;
if (activityBehavior instanceof CallActivityBehavior) {
callActivityBehavior = (CallActivityBehavior) activityBehavior;
}
if (callActivityBehavior != null) {
propertiesJSON.put("processDefinitonKey", callActivityBehavior.getProcessDefinitonKey());
// get processDefinitonId from execution or get last processDefinitonId
// by key
ArrayNode processInstanceArray = new ObjectMapper().createArrayNode();
if (processInstance != null) {
List<Execution> executionList = runtimeService.createExecutionQuery().processInstanceId(processInstanceId)
.activityId(activity.getId()).list();
if (!executionList.isEmpty()) {
for (Execution execution : executionList) {
ObjectNode processInstanceJSON = subProcessInstanceMap.get(execution.getId());
processInstanceArray.add(processInstanceJSON);
}
}
}
// If active activities nas no instance of this callActivity then add
// last definition
if (processInstanceArray.size() == 0 && StringUtils.isNotEmpty(callActivityBehavior.getProcessDefinitonKey())) {
// Get last definition by key
ProcessDefinition lastProcessDefinition = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(callActivityBehavior.getProcessDefinitonKey()).latestVersion().singleResult();
// TODO: unuseful fields there are processDefinitionName, processDefinitionKey
if (lastProcessDefinition != null) {
ObjectNode processInstanceJSON = new ObjectMapper().createObjectNode();
processInstanceJSON.put("processDefinitionId", lastProcessDefinition.getId());
processInstanceJSON.put("processDefinitionKey", lastProcessDefinition.getKey());
processInstanceJSON.put("processDefinitionName", lastProcessDefinition.getName());
processInstanceArray.add(processInstanceJSON);
}
}
if (processInstanceArray.size() > 0) {
propertiesJSON.put("processDefinitons", processInstanceArray);
}
}
}
activityJSON.put("activityId", activity.getId());
activityJSON.put("properties", propertiesJSON);
if (multiInstance != null)
activityJSON.put("multiInstance", multiInstance);
if (collapsed)
activityJSON.put("collapsed", collapsed);
if (nestedActivityArray.size() > 0)
activityJSON.put("nestedActivities", nestedActivityArray);
if (isInterrupting != null)
activityJSON.put("isInterrupting", isInterrupting);
activityJSON.put("x", activity.getX());
activityJSON.put("y", activity.getY());
activityJSON.put("width", activity.getWidth());
activityJSON.put("height", activity.getHeight());
activityArray.add(activityJSON);
// Nested activities (boundary events)
for (ActivityImpl nestedActivity : activity.getActivities()) {
getActivity(processInstanceId, nestedActivity, activityArray, sequenceFlowArray, processInstance, highLightedFlows, subProcessInstanceMap);
}
}
private JsonNode getProcessDefinitionResponse(ProcessDefinitionEntity processDefinition) {
ObjectMapper mapper = new ObjectMapper();
ObjectNode pdrJSON = mapper.createObjectNode();
pdrJSON.put("id", processDefinition.getId());
pdrJSON.put("name", processDefinition.getName());
pdrJSON.put("key", processDefinition.getKey());
pdrJSON.put("version", processDefinition.getVersion());
pdrJSON.put("deploymentId", processDefinition.getDeploymentId());
pdrJSON.put("isGraphicNotationDefined", isGraphicNotationDefined(processDefinition));
return pdrJSON;
}
private boolean isGraphicNotationDefined(ProcessDefinitionEntity processDefinition) {
return ((ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinition.getId())).isGraphicalNotationDefined();
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeespring.modules.act.rest.diagram.services;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.node.ObjectNode;
@RestController
public class ProcessDefinitionDiagramLayoutResource extends BaseProcessDefinitionDiagramLayoutResource {
@RequiresUser
@RequestMapping(value = "/act/service/process-definition/{processDefinitionId}/diagram-layout", method = RequestMethod.GET, produces = "application/json")
public ObjectNode getDiagram(@PathVariable String processDefinitionId) {
return getDiagramNode(null, processDefinitionId);
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeespring.modules.act.rest.diagram.services;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.node.ObjectNode;
@RestController
public class ProcessInstanceDiagramLayoutResource extends BaseProcessDefinitionDiagramLayoutResource {
@RequiresUser
@RequestMapping(value = "/act/service/process-instance/{processInstanceId}/diagram-layout", method = RequestMethod.GET, produces = "application/json")
public ObjectNode getDiagram(@PathVariable String processInstanceId) {
return getDiagramNode(processInstanceId, null);
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeespring.modules.act.rest.diagram.services;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
@RestController
public class ProcessInstanceHighlightsResource {
@Autowired
private RuntimeService runtimeService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private HistoryService historyService;
protected ObjectMapper objectMapper = new ObjectMapper();
@RequiresUser
@RequestMapping(value = "/act/service/process-instance/{processInstanceId}/highlights", method = RequestMethod.GET, produces = "application/json")
public ObjectNode getHighlighted(@PathVariable String processInstanceId) {
ObjectNode responseJSON = objectMapper.createObjectNode();
responseJSON.put("processInstanceId", processInstanceId);
ArrayNode activitiesArray = objectMapper.createArrayNode();
ArrayNode flowsArray = objectMapper.createArrayNode();
try {
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processInstance
.getProcessDefinitionId());
responseJSON.put("processDefinitionId", processInstance.getProcessDefinitionId());
List<String> highLightedActivities = runtimeService.getActiveActivityIds(processInstanceId);
List<String> highLightedFlows = getHighLightedFlows(processDefinition, processInstanceId);
for (String activityId : highLightedActivities) {
activitiesArray.add(activityId);
}
for (String flow : highLightedFlows) {
flowsArray.add(flow);
}
} catch (Exception e) {
e.printStackTrace();
}
responseJSON.put("activities", activitiesArray);
responseJSON.put("flows", flowsArray);
return responseJSON;
}
/**
* getHighLightedFlows
*
* @param processDefinition
* @param processInstanceId
* @return
*/
private List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinition, String processInstanceId) {
List<String> highLightedFlows = new ArrayList<String>();
List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
.processInstanceId(processInstanceId)
//order by startime asc is not correct. use default order is correct.
//.orderByHistoricActivityInstanceStartTime().asc()/*.orderByActivityId().asc()*/
.list();
LinkedList<HistoricActivityInstance> hisActInstList = new LinkedList<HistoricActivityInstance>();
hisActInstList.addAll(historicActivityInstances);
getHighlightedFlows(processDefinition.getActivities(), hisActInstList, highLightedFlows);
return highLightedFlows;
}
/**
* getHighlightedFlows
*
* code logic: 1. Loop all activities by id asc order; 2. Check each activity's outgoing transitions and eventBoundery outgoing transitions, if
* outgoing transitions's destination.id is in other executed activityIds, add this transition to highLightedFlows List; 3. But if activity is not
* a parallelGateway or inclusiveGateway, only choose the earliest flow.
*
* @param activityList
* @param hisActInstList
* @param highLightedFlows
*/
private void getHighlightedFlows(List<ActivityImpl> activityList, LinkedList<HistoricActivityInstance> hisActInstList,
List<String> highLightedFlows) {
//check out startEvents in activityList
List<ActivityImpl> startEventActList = new ArrayList<ActivityImpl>();
Map<String, ActivityImpl> activityMap = new HashMap<String, ActivityImpl>(activityList.size());
for (ActivityImpl activity : activityList) {
activityMap.put(activity.getId(), activity);
String actType = (String) activity.getProperty("type");
if (actType != null && actType.toLowerCase().indexOf("startevent") >= 0) {
startEventActList.add(activity);
}
}
//These codes is used to avoid a bug:
//ACT-1728 If the process instance was started by a callActivity, it will be not have the startEvent activity in ACT_HI_ACTINST table
//Code logic:
//Check the first activity if it is a startEvent, if not check out the startEvent's highlight outgoing flow.
HistoricActivityInstance firstHistActInst = hisActInstList.getFirst();
String firstActType = (String) firstHistActInst.getActivityType();
if (firstActType != null && firstActType.toLowerCase().indexOf("startevent") < 0) {
PvmTransition startTrans = getStartTransaction(startEventActList, firstHistActInst);
if (startTrans != null) {
highLightedFlows.add(startTrans.getId());
}
}
while (!hisActInstList.isEmpty()) {
HistoricActivityInstance histActInst = hisActInstList.removeFirst();
ActivityImpl activity = activityMap.get(histActInst.getActivityId());
if (activity != null) {
boolean isParallel = false;
String type = histActInst.getActivityType();
if ("parallelGateway".equals(type) || "inclusiveGateway".equals(type)) {
isParallel = true;
} else if ("subProcess".equals(histActInst.getActivityType())) {
getHighlightedFlows(activity.getActivities(), hisActInstList, highLightedFlows);
}
List<PvmTransition> allOutgoingTrans = new ArrayList<PvmTransition>();
allOutgoingTrans.addAll(activity.getOutgoingTransitions());
allOutgoingTrans.addAll(getBoundaryEventOutgoingTransitions(activity));
List<String> activityHighLightedFlowIds = getHighlightedFlows(allOutgoingTrans, hisActInstList, isParallel);
highLightedFlows.addAll(activityHighLightedFlowIds);
}
}
}
/**
* Check out the outgoing transition connected to firstActInst from startEventActList
*
* @param startEventActList
* @param firstActInst
* @return
*/
private PvmTransition getStartTransaction(List<ActivityImpl> startEventActList, HistoricActivityInstance firstActInst) {
for (ActivityImpl startEventAct : startEventActList) {
for (PvmTransition trans : startEventAct.getOutgoingTransitions()) {
if (trans.getDestination().getId().equals(firstActInst.getActivityId())) {
return trans;
}
}
}
return null;
}
/**
* getBoundaryEventOutgoingTransitions
*
* @param activity
* @return
*/
private List<PvmTransition> getBoundaryEventOutgoingTransitions(ActivityImpl activity) {
List<PvmTransition> boundaryTrans = new ArrayList<PvmTransition>();
for (ActivityImpl subActivity : activity.getActivities()) {
String type = (String) subActivity.getProperty("type");
if (type != null && type.toLowerCase().indexOf("boundary") >= 0) {
boundaryTrans.addAll(subActivity.getOutgoingTransitions());
}
}
return boundaryTrans;
}
/**
* find out single activity's highlighted flowIds
*
* @param activity
* @param hisActInstList
* @param isExclusive if true only return one flowId(Such as exclusiveGateway, BoundaryEvent On Task)
* @return
*/
private List<String> getHighlightedFlows(List<PvmTransition> pvmTransitionList, LinkedList<HistoricActivityInstance> hisActInstList,
boolean isParallel) {
List<String> highLightedFlowIds = new ArrayList<String>();
PvmTransition earliestTrans = null;
HistoricActivityInstance earliestHisActInst = null;
for (PvmTransition pvmTransition : pvmTransitionList) {
String destActId = pvmTransition.getDestination().getId();
HistoricActivityInstance destHisActInst = findHisActInst(hisActInstList, destActId);
if (destHisActInst != null) {
if (isParallel) {
highLightedFlowIds.add(pvmTransition.getId());
} else if (earliestHisActInst == null || (earliestHisActInst.getId().compareTo(destHisActInst.getId()) > 0)) {
earliestTrans = pvmTransition;
earliestHisActInst = destHisActInst;
}
}
}
if ((!isParallel) && earliestTrans != null) {
highLightedFlowIds.add(earliestTrans.getId());
}
return highLightedFlowIds;
}
private HistoricActivityInstance findHisActInst(LinkedList<HistoricActivityInstance> hisActInstList, String actId) {
for (HistoricActivityInstance hisActInst : hisActInstList) {
if (hisActInst.getActivityId().equals(actId)) {
return hisActInst;
}
}
return null;
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeespring.modules.act.rest.editor.main;
import java.io.InputStream;
import org.activiti.engine.ActivitiException;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Tijs Rademakers
*/
@RestController
public class StencilsetRestResource {
@RequestMapping(value = "/act/service/editor/stencilset", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
public @ResponseBody String getStencilset() {
InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("stencilset.json");
try {
return IOUtils.toString(stencilsetStream, "utf-8");
} catch (Exception e) {
throw new ActivitiException("Error while loading stencil set", e);
}
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeespring.modules.act.rest.editor.model;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* @author Tijs Rademakers
*/
@RestController
public class ModelEditorJsonRestResource implements ModelDataJsonConstants {
protected static final Logger LOGGER = LoggerFactory.getLogger(ModelEditorJsonRestResource.class);
@Autowired
private RepositoryService repositoryService;
// @Autowired
// private ObjectMapper objectMapper;
protected ObjectMapper objectMapper = new ObjectMapper();
@RequiresPermissions("act:model:edit")
@RequestMapping(value = "/act/service/model/{modelId}/json", method = RequestMethod.GET, produces = "application/json")
public ObjectNode getEditorJson(@PathVariable String modelId) {
ObjectNode modelNode = null;
Model model = repositoryService.getModel(modelId);
if (model != null) {
try {
if (StringUtils.isNotEmpty(model.getMetaInfo())) {
modelNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
} else {
modelNode = objectMapper.createObjectNode();
modelNode.put(MODEL_NAME, model.getName());
}
modelNode.put(MODEL_ID, model.getId());
ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(new String(repositoryService.getModelEditorSource(model.getId()),
"utf-8"));
modelNode.put("model", editorJsonNode);
} catch (Exception e) {
LOGGER.error("Error creating model JSON", e);
throw new ActivitiException("Error creating model JSON", e);
}
}
return modelNode;
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeespring.modules.act.rest.editor.model;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Model;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.apache.log4j.Logger;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author Tijs Rademakers
*/
@RestController
public class ModelSaveRestResource implements ModelDataJsonConstants {
protected static final Logger LOGGER = Logger.getLogger(ModelSaveRestResource.class);
@Autowired
private RepositoryService repositoryService;
// @Autowired
// private ObjectMapper objectMapper;
protected ObjectMapper objectMapper = new ObjectMapper();
@RequiresPermissions("act:model:edit")
@RequestMapping(value = "/act/service/model/{modelId}/save",method ={RequestMethod.POST,RequestMethod.GET,RequestMethod.PUT})
@ResponseStatus(value = HttpStatus.OK)
// @RequestBody MultiValueMap<String, String> values,MultiValueMap<String, String> valuesa
public void saveModel(@PathVariable String modelId, HttpServletRequest request, HttpServletResponse response) {
try {
MultiValueMap<String, String> values=new LinkedMultiValueMap<>();;
Model model = repositoryService.getModel(modelId);
String name="",description="",json_xml="",svg_xml="";
values.add("name",request.getParameter("name"));
values.add("description",request.getParameter("description"));
values.add("json_xml",request.getParameter("json_xml"));
values.add("svg_xml",request.getParameter("svg_xml"));
ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
modelJson.put(MODEL_NAME, values.getFirst("name"));
modelJson.put(MODEL_DESCRIPTION, values.getFirst("description"));
model.setMetaInfo(modelJson.toString());
model.setName(values.getFirst("name"));
repositoryService.saveModel(model);
repositoryService.addModelEditorSource(model.getId(), values.getFirst("json_xml").getBytes("utf-8"));
InputStream svgStream = new ByteArrayInputStream(values.getFirst("svg_xml").getBytes("utf-8"));
TranscoderInput input = new TranscoderInput(svgStream);
PNGTranscoder transcoder = new PNGTranscoder();
// Setup output
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
TranscoderOutput output = new TranscoderOutput(outStream);
// Do the transformation
transcoder.transcode(input, output);
final byte[] result = outStream.toByteArray();
repositoryService.addModelEditorSourceExtra(model.getId(), result);
outStream.close();
} catch (Exception e) {
LOGGER.error("Error saving model", e);
throw new ActivitiException("Error saving model", e);
}
}
}
package com.jeespring.modules.act.rest.servlet;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
public class FilterServletOutputStream extends ServletOutputStream {
private DataOutputStream stream;
public FilterServletOutputStream(OutputStream output) {
stream = new DataOutputStream(output);
}
public void write(int b) throws IOException {
stream.write(b);
}
public void write(byte[] b) throws IOException {
stream.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
stream.write(b, off, len);
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setWriteListener(WriteListener writeListener) {
}
}
\ No newline at end of file
package com.jeespring.modules.act.rest.servlet;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class GenericResponseWrapper extends HttpServletResponseWrapper {
private ByteArrayOutputStream output;
private int contentLength;
private String contentType;
public GenericResponseWrapper(HttpServletResponse response) {
super(response);
output = new ByteArrayOutputStream();
}
public byte[] getData() {
return output.toByteArray();
}
public ServletOutputStream getOutputStream() {
return new FilterServletOutputStream(output);
}
public PrintWriter getWriter() {
return new PrintWriter(getOutputStream(), true);
}
public void setContentLength(int length) {
this.contentLength = length;
super.setContentLength(length);
}
public int getContentLength() {
return contentLength;
}
public void setContentType(String type) {
this.contentType = type;
super.setContentType(type);
}
public String getContentType() {
return contentType;
}
}
package com.jeespring.modules.act.rest.servlet;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@WebFilter(urlPatterns={"/act/service/*"})
public class JsonpCallbackFilter implements Filter
{
private static Logger log = LoggerFactory.getLogger(JsonpCallbackFilter.class);
public void init(FilterConfig fConfig) throws ServletException {}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
@SuppressWarnings("unchecked")
Map<String, String[]> parms = httpRequest.getParameterMap();
if (parms.containsKey("callback")) {
if (log.isDebugEnabled())
log.debug("Wrapping response with JSONP callback '" + parms.get("callback")[0] + "'");
OutputStream out = httpResponse.getOutputStream();
GenericResponseWrapper wrapper = new GenericResponseWrapper(httpResponse);
chain.doFilter(request, wrapper);
//handles the content-size truncation
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(new String(parms.get("callback")[0] + "(").getBytes());
outputStream.write(wrapper.getData());
outputStream.write(new String(");").getBytes());
byte jsonpResponse[] = outputStream.toByteArray();
wrapper.setContentType("text/javascript;charset=UTF-8");
wrapper.setContentLength(jsonpResponse.length);
out.write(jsonpResponse);
out.close();
} else {
chain.doFilter(request, response);
}
}
public void destroy() {}
}
/**
* Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
*/
package com.jeespring.modules.act.service;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ModelQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.jeespring.common.persistence.Page;
import com.jeespring.common.service.AbstractService;
/**
* 流程模型相关Controller
* @author ThinkGem
* @version 2013-11-03
*/
@Service
@Transactional(readOnly = true)
public class ActModelService extends AbstractService {
@Autowired
private RepositoryService repositoryService;
// @Autowired
// private ObjectMapper objectMapper;
protected ObjectMapper objectMapper = new ObjectMapper();
/**
* 流程模型列表
*/
public Page<Model> modelList(Page<Model> page, String category) {
ModelQuery modelQuery = repositoryService.createModelQuery().latestVersion().orderByLastUpdateTime().desc();
if (StringUtils.isNotEmpty(category)){
modelQuery.modelCategory(category);
}
page.setCount(modelQuery.count());
page.setList(modelQuery.listPage(page.getFirstResult(), page.getMaxResults()));
return page;
}
/**
* 创建模型
* @throws UnsupportedEncodingException
*/
@Transactional(readOnly = false)
public Model create(String name, String key, String description, String category) throws UnsupportedEncodingException {
ObjectNode editorNode = objectMapper.createObjectNode();
editorNode.put("id", "canvas");
editorNode.put("resourceId", "canvas");
ObjectNode properties = objectMapper.createObjectNode();
properties.put("process_author", "jeesite");
editorNode.put("properties", properties);
ObjectNode stencilset = objectMapper.createObjectNode();
stencilset.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
editorNode.put("stencilset", stencilset);
Model modelData = repositoryService.newModel();
description = StringUtils.defaultString(description);
modelData.setKey(StringUtils.defaultString(key));
modelData.setName(name);
modelData.setCategory(category);
modelData.setVersion(Integer.parseInt(String.valueOf(repositoryService.createModelQuery().modelKey(modelData.getKey()).count()+1)));
ObjectNode modelObjectNode = objectMapper.createObjectNode();
modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, name);
modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, modelData.getVersion());
modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
modelData.setMetaInfo(modelObjectNode.toString());
repositoryService.saveModel(modelData);
repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));
return modelData;
}
/**
* 根据Model部署流程
*/
@Transactional(readOnly = false)
public String deploy(String id) {
String message = "";
try {
Model modelData = repositoryService.getModel(id);
BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
String processName = modelData.getName();
if (!StringUtils.endsWith(processName, ".bpmn20.xml")){
processName += ".bpmn20.xml";
}
// System.out.println("========="+processName+"============"+modelData.getName());
ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
Deployment deployment = repositoryService.createDeployment().name(modelData.getName())
.addInputStream(processName, in).deploy();
// .addString(processName, new String(bpmnBytes)).deploy();
// 设置流程分类
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
for (ProcessDefinition processDefinition : list) {
repositoryService.setProcessDefinitionCategory(processDefinition.getId(), modelData.getCategory());
message = "部署成功,流程ID=" + processDefinition.getId();
}
if (list.size() == 0){
message = "部署失败,没有流程。";
}
} catch (Exception e) {
throw new ActivitiException("设计模型图不正确,检查模型正确性,模型ID="+id, e);
}
return message;
}
/**
* 导出model的xml文件
* @throws IOException
* @throws JsonProcessingException
*/
public void export(String id, HttpServletResponse response) {
try {
Model modelData = repositoryService.getModel(id);
BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
IOUtils.copy(in, response.getOutputStream());
String filename = bpmnModel.getMainProcess().getId() + ".bpmn20.xml";
response.setHeader("Content-Disposition", "attachment; filename=" + filename);
response.flushBuffer();
} catch (Exception e) {
throw new ActivitiException("导出model的xml文件失败,模型ID="+id, e);
}
}
/**
* 更新Model分类
*/
@Transactional(readOnly = false)
public void updateCategory(String id, String category) {
Model modelData = repositoryService.getModel(id);
modelData.setCategory(category);
repositoryService.saveModel(modelData);
}
/**
* 删除模型
* @param id
* @return
*/
@Transactional(readOnly = false)
public void delete(String id) {
repositoryService.deleteModel(id);
}
}
/**
* Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
*/
package com.jeespring.modules.act.service;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipInputStream;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
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.runtime.ProcessInstanceQuery;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.jeespring.common.persistence.Page;
import com.jeespring.common.service.AbstractService;
import com.jeespring.common.utils.StringUtils;
/**
* 流程定义相关Controller
* @author ThinkGem
* @version 2013-11-03
*/
@Service
@Transactional(readOnly = true)
public class ActProcessService extends AbstractService {
@Autowired
private RepositoryService repositoryService;
@Autowired
private RuntimeService runtimeService;
/**
* 流程定义列表
*/
public Page<Object[]> processList(Page<Object[]> page, String category) {
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
.latestVersion().orderByProcessDefinitionKey().asc();
if (StringUtils.isNotEmpty(category)){
processDefinitionQuery.processDefinitionCategory(category);
}
page.setCount(processDefinitionQuery.count());
List<ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage(page.getFirstResult(), page.getMaxResults());
for (ProcessDefinition processDefinition : processDefinitionList) {
String deploymentId = processDefinition.getDeploymentId();
Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
page.getList().add(new Object[]{processDefinition, deployment});
}
return page;
}
/**
* 流程定义列表
*/
public Page<ProcessInstance> runningList(Page<ProcessInstance> page, String procInsId, String procDefKey) {
ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
if (StringUtils.isNotBlank(procInsId)){
processInstanceQuery.processInstanceId(procInsId);
}
if (StringUtils.isNotBlank(procDefKey)){
processInstanceQuery.processDefinitionKey(procDefKey);
}
page.setCount(processInstanceQuery.count());
page.setList(processInstanceQuery.listPage(page.getFirstResult(), page.getMaxResults()));
return page;
}
/**
* 读取资源,通过部署ID
* @param processDefinitionId 流程定义ID
* @param processInstanceId 流程实例ID
* @param resourceType 资源类型(xml|image)
*/
public InputStream resourceRead(String procDefId, String proInsId, String resType) throws Exception {
if (StringUtils.isBlank(procDefId)){
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(proInsId).singleResult();
procDefId = processInstance.getProcessDefinitionId();
}
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(procDefId).singleResult();
String resourceName = "";
if (resType.equals("image")) {
resourceName = processDefinition.getDiagramResourceName();
} else if (resType.equals("xml")) {
resourceName = processDefinition.getResourceName();
}
InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
return resourceAsStream;
}
/**
* 部署流程 - 保存
* @param file
* @return
*/
@Transactional(readOnly = false)
public String deploy(String exportDir, String category, MultipartFile file) {
String message = "";
String fileName = file.getOriginalFilename();
try {
InputStream fileInputStream = file.getInputStream();
Deployment deployment;
String extension = FilenameUtils.getExtension(fileName);
if (extension.equals("zip") || extension.equals("bar")) {
ZipInputStream zip = new ZipInputStream(fileInputStream);
deployment = repositoryService.createDeployment().addZipInputStream(zip).deploy();
} else if (extension.equals("png")) {
deployment = repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy();
} else if (fileName.indexOf("bpmn20.xml") != -1) {
deployment = repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy();
} else if (extension.equals("bpmn")) { // bpmn扩展名特殊处理,转换为bpmn20.xml
String baseName = FilenameUtils.getBaseName(fileName);
deployment = repositoryService.createDeployment().addInputStream(baseName + ".bpmn20.xml", fileInputStream).deploy();
} else {
message = "不支持的文件类型:" + extension;
return message;
}
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
// 设置流程分类
for (ProcessDefinition processDefinition : list) {
// ActUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir);
repositoryService.setProcessDefinitionCategory(processDefinition.getId(), category);
message += "部署成功,流程ID=" + processDefinition.getId() + "<br/>";
}
if (list.size() == 0){
message = "部署失败,没有流程。";
}
} catch (Exception e) {
throw new ActivitiException("部署失败!", e);
}
return message;
}
/**
* 设置流程分类
*/
@Transactional(readOnly = false)
public void updateCategory(String procDefId, String category) {
repositoryService.setProcessDefinitionCategory(procDefId, category);
}
/**
* 挂起、激活流程实例
*/
@Transactional(readOnly = false)
public String updateState(String state, String procDefId) {
if (state.equals("active")) {
repositoryService.activateProcessDefinitionById(procDefId, true, null);
return "已激活ID为[" + procDefId + "]的流程定义。";
} else if (state.equals("suspend")) {
repositoryService.suspendProcessDefinitionById(procDefId, true, null);
return "已挂起ID为[" + procDefId + "]的流程定义。";
}
return "无操作";
}
/**
* 将部署的流程转换为模型
* @param procDefId
* @throws UnsupportedEncodingException
* @throws XMLStreamException
*/
@Transactional(readOnly = false)
public org.activiti.engine.repository.Model convertToModel(String procDefId) throws UnsupportedEncodingException, XMLStreamException {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(procDefId).singleResult();
InputStream bpmnStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
processDefinition.getResourceName());
XMLInputFactory xif = XMLInputFactory.newInstance();
InputStreamReader in = new InputStreamReader(bpmnStream, "UTF-8");
XMLStreamReader xtr = xif.createXMLStreamReader(in);
BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr);
BpmnJsonConverter converter = new BpmnJsonConverter();
ObjectNode modelNode = converter.convertToJson(bpmnModel);
org.activiti.engine.repository.Model modelData = repositoryService.newModel();
modelData.setKey(processDefinition.getKey());
modelData.setName(processDefinition.getResourceName());
modelData.setCategory(processDefinition.getCategory());//.getDeploymentId());
modelData.setDeploymentId(processDefinition.getDeploymentId());
modelData.setVersion(Integer.parseInt(String.valueOf(repositoryService.createModelQuery().modelKey(modelData.getKey()).count()+1)));
ObjectNode modelObjectNode = new ObjectMapper().createObjectNode();
modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processDefinition.getName());
modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, modelData.getVersion());
modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription());
modelData.setMetaInfo(modelObjectNode.toString());
repositoryService.saveModel(modelData);
repositoryService.addModelEditorSource(modelData.getId(), modelNode.toString().getBytes("utf-8"));
return modelData;
}
/**
* 导出图片文件到硬盘
*/
public List<String> exportDiagrams(String exportDir) throws IOException {
List<String> files = new ArrayList<String>();
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
for (ProcessDefinition processDefinition : list) {
String diagramResourceName = processDefinition.getDiagramResourceName();
String key = processDefinition.getKey();
int version = processDefinition.getVersion();
String diagramPath = "";
InputStream resourceAsStream = repositoryService.getResourceAsStream(
processDefinition.getDeploymentId(), diagramResourceName);
byte[] b = new byte[resourceAsStream.available()];
@SuppressWarnings("unused")
int len = -1;
resourceAsStream.read(b, 0, b.length);
// create file if not exist
String diagramDir = exportDir + "/" + key + "/" + version;
File diagramDirFile = new File(diagramDir);
if (!diagramDirFile.exists()) {
diagramDirFile.mkdirs();
}
diagramPath = diagramDir + "/" + diagramResourceName;
File file = new File(diagramPath);
// 文件存在退出
if (file.exists()) {
// 文件大小相同时直接返回否则重新创建文件(可能损坏)
logger.debug("diagram exist, ignore... : {}", diagramPath);
files.add(diagramPath);
} else {
file.createNewFile();
logger.debug("export diagram to : {}", diagramPath);
// wirte bytes to file
FileUtils.writeByteArrayToFile(file, b, true);
files.add(diagramPath);
}
}
return files;
}
/**
* 删除部署的流程,级联删除流程实例
* @param deploymentId 流程部署ID
*/
@Transactional(readOnly = false)
public void deleteDeployment(String deploymentId) {
repositoryService.deleteDeployment(deploymentId, true);
}
/**
* 删除部署的流程实例
* @param procInsId 流程实例ID
* @param deleteReason 删除原因,可为空
*/
@Transactional(readOnly = false)
public void deleteProcIns(String procInsId, String deleteReason) {
runtimeService.deleteProcessInstance(procInsId, deleteReason);
}
}
/**
* Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
*/
package com.jeespring.modules.act.service;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.RuntimeServiceImpl;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.interceptor.CommandExecutor;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.delegate.ActivityBehavior;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jeespring.common.persistence.Page;
import com.jeespring.common.service.AbstractService;
import com.jeespring.common.utils.StringUtils;
import com.jeespring.modules.act.dao.ActDao;
import com.jeespring.modules.act.entity.Act;
import com.jeespring.modules.act.service.cmd.CreateAndTakeTransitionCmd;
import com.jeespring.modules.act.service.cmd.JumpTaskCmd;
import com.jeespring.modules.act.service.creator.ChainedActivitiesCreator;
import com.jeespring.modules.act.service.creator.MultiInstanceActivityCreator;
import com.jeespring.modules.act.service.creator.RuntimeActivityDefinitionEntityIntepreter;
import com.jeespring.modules.act.service.creator.SimpleRuntimeActivityDefinitionEntity;
import com.jeespring.modules.act.utils.ActUtils;
import com.jeespring.modules.act.utils.ProcessDefCache;
import com.jeespring.modules.act.utils.ProcessDefUtils;
import com.jeespring.modules.sys.entity.User;
import com.jeespring.modules.sys.utils.UserUtils;
/**
* 流程定义相关Service
* @author ThinkGem
* @version 2013-11-03
*/
@Service
@Transactional(readOnly = true)
public class ActTaskService extends AbstractService {
@Autowired
private ActDao actDao;
@Autowired
private ProcessEngineFactoryBean processEngineFactory;
@Autowired
private ProcessEngine processEngine;
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private FormService formService;
@Autowired
private HistoryService historyService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private IdentityService identityService;
/**
* 获取待办列表
* @param procDefKey 流程定义标识
* @return
*/
public List<Act> todoList(Act act){
String userId = UserUtils.getUser().getLoginName();//ObjectUtils.toString(UserUtils.getUser().getId());
List<Act> result = new ArrayList<Act>();
// =============== 已经签收的任务 ===============
TaskQuery todoTaskQuery = taskService.createTaskQuery().taskAssignee(userId).active()
.includeProcessVariables().orderByTaskCreateTime().desc();
// 设置查询条件
if (StringUtils.isNotBlank(act.getProcDefKey())){
todoTaskQuery.processDefinitionKey(act.getProcDefKey());
}
if (act.getBeginDate() != null){
todoTaskQuery.taskCreatedAfter(act.getBeginDate());
}
if (act.getEndDate() != null){
todoTaskQuery.taskCreatedBefore(act.getEndDate());
}
// 查询列表
List<Task> todoList = todoTaskQuery.list();
for (Task task : todoList) {
Act e = new Act();
e.setTask(task);
e.setVars(task.getProcessVariables());
// e.setTaskVars(task.getTaskLocalVariables());
// System.out.println(task.getId()+" = "+task.getProcessVariables() + " ========== " + task.getTaskLocalVariables());
e.setProcDef(ProcessDefCache.get(task.getProcessDefinitionId()));
// e.setProcIns(runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult());
// e.setProcExecUrl(ActUtils.getProcExeUrl(task.getProcessDefinitionId()));
e.setStatus("todo");
result.add(e);
}
// =============== 等待签收的任务 ===============
TaskQuery toClaimQuery = taskService.createTaskQuery().taskCandidateUser(userId)
.includeProcessVariables().active().orderByTaskCreateTime().desc();
// 设置查询条件
if (StringUtils.isNotBlank(act.getProcDefKey())){
toClaimQuery.processDefinitionKey(act.getProcDefKey());
}
if (act.getBeginDate() != null){
toClaimQuery.taskCreatedAfter(act.getBeginDate());
}
if (act.getEndDate() != null){
toClaimQuery.taskCreatedBefore(act.getEndDate());
}
// 查询列表
List<Task> toClaimList = toClaimQuery.list();
for (Task task : toClaimList) {
Act e = new Act();
e.setTask(task);
e.setVars(task.getProcessVariables());
// e.setTaskVars(task.getTaskLocalVariables());
// System.out.println(task.getId()+" = "+task.getProcessVariables() + " ========== " + task.getTaskLocalVariables());
e.setProcDef(ProcessDefCache.get(task.getProcessDefinitionId()));
// e.setProcIns(runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult());
// e.setProcExecUrl(ActUtils.getProcExeUrl(task.getProcessDefinitionId()));
e.setStatus("claim");
result.add(e);
}
return result;
}
/**
* 获取已办任务
* @param page
* @param procDefKey 流程定义标识
* @return
*/
public Page<Act> historicList(Page<Act> page, Act act){
String userId = UserUtils.getUser().getLoginName();//ObjectUtils.toString(UserUtils.getUser().getId());
HistoricTaskInstanceQuery histTaskQuery = historyService.createHistoricTaskInstanceQuery().taskAssignee(userId).finished()
.includeProcessVariables().orderByHistoricTaskInstanceEndTime().desc();
// 设置查询条件
if (StringUtils.isNotBlank(act.getProcDefKey())){
histTaskQuery.processDefinitionKey(act.getProcDefKey());
}
if (act.getBeginDate() != null){
histTaskQuery.taskCompletedAfter(act.getBeginDate());
}
if (act.getEndDate() != null){
histTaskQuery.taskCompletedBefore(act.getEndDate());
}
// 查询总数
page.setCount(histTaskQuery.count());
// 查询列表
List<HistoricTaskInstance> histList = histTaskQuery.listPage(page.getFirstResult(), page.getMaxResults());
//处理分页问题
List<Act> actList=Lists.newArrayList();
for (HistoricTaskInstance histTask : histList) {
Act e = new Act();
e.setHistTask(histTask);
e.setVars(histTask.getProcessVariables());
// e.setTaskVars(histTask.getTaskLocalVariables());
// System.out.println(histTask.getId()+" = "+histTask.getProcessVariables() + " ========== " + histTask.getTaskLocalVariables());
e.setProcDef(ProcessDefCache.get(histTask.getProcessDefinitionId()));
// e.setProcIns(runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult());
// e.setProcExecUrl(ActUtils.getProcExeUrl(task.getProcessDefinitionId()));
e.setStatus("finish");
actList.add(e);
//page.getList().add(e);
}
page.setList(actList);
return page;
}
/**
* 获取流转历史列表
* @param procInsId 流程实例
* @param startAct 开始活动节点名称
* @param endAct 结束活动节点名称
*/
public List<Act> histoicFlowList(String procInsId, String startAct, String endAct){
List<Act> actList = Lists.newArrayList();
List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(procInsId)
.orderByHistoricActivityInstanceStartTime().asc().orderByHistoricActivityInstanceEndTime().asc().list();
boolean start = false;
Map<String, Integer> actMap = Maps.newHashMap();
for (int i=0; i<list.size(); i++){
HistoricActivityInstance histIns = list.get(i);
// 过滤开始节点前的节点
if (StringUtils.isNotBlank(startAct) && startAct.equals(histIns.getActivityId())){
start = true;
}
if (StringUtils.isNotBlank(startAct) && !start){
continue;
}
// 只显示开始节点和结束节点,并且执行人不为空的任务
if (StringUtils.isNotBlank(histIns.getAssignee())
|| "startEvent".equals(histIns.getActivityType())
|| "endEvent".equals(histIns.getActivityType())){
// 给节点增加一个序号
Integer actNum = actMap.get(histIns.getActivityId());
if (actNum == null){
actMap.put(histIns.getActivityId(), actMap.size());
}
Act e = new Act();
e.setHistIns(histIns);
// 获取流程发起人名称
if ("startEvent".equals(histIns.getActivityType())){
List<HistoricProcessInstance> il = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInsId).orderByProcessInstanceStartTime().asc().list();
// List<HistoricIdentityLink> il = historyService.getHistoricIdentityLinksForProcessInstance(procInsId);
if (il.size() > 0){
if (StringUtils.isNotBlank(il.get(0).getStartUserId())){
User user = UserUtils.getByLoginName(il.get(0).getStartUserId());
if (user != null){
e.setAssignee(histIns.getAssignee());
e.setAssigneeName(user.getName());
}
}
}
}
// 获取任务执行人名称
if (StringUtils.isNotEmpty(histIns.getAssignee())){
User user = UserUtils.getByLoginName(histIns.getAssignee());
if (user != null){
e.setAssignee(histIns.getAssignee());
e.setAssigneeName(user.getName());
}
}
// 获取意见评论内容
if (StringUtils.isNotBlank(histIns.getTaskId())){
List<Comment> commentList = taskService.getTaskComments(histIns.getTaskId());
if (commentList.size()>0){
e.setComment(commentList.get(0).getFullMessage());
}
}
actList.add(e);
}
// 过滤结束节点后的节点
if (StringUtils.isNotBlank(endAct) && endAct.equals(histIns.getActivityId())){
boolean bl = false;
Integer actNum = actMap.get(histIns.getActivityId());
// 该活动节点,后续节点是否在结束节点之前,在后续节点中是否存在
for (int j=i+1; j<list.size(); j++){
HistoricActivityInstance hi = list.get(j);
Integer actNumA = actMap.get(hi.getActivityId());
if ((actNumA != null && actNumA < actNum) || StringUtils.equals(hi.getActivityId(), histIns.getActivityId())){
bl = true;
}
}
if (!bl){
break;
}
}
}
return actList;
}
/**
* 获取流程列表
* @param category 流程分类
*/
public Page<Object[]> processList(Page<Object[]> page, String category) {
/*
* 保存两个对象,一个是ProcessDefinition(流程定义),一个是Deployment(流程部署)
*/
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
.latestVersion().active().orderByProcessDefinitionKey().asc();
if (StringUtils.isNotEmpty(category)){
processDefinitionQuery.processDefinitionCategory(category);
}
page.setCount(processDefinitionQuery.count());
List<ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage(page.getFirstResult(), page.getMaxResults());
for (ProcessDefinition processDefinition : processDefinitionList) {
String deploymentId = processDefinition.getDeploymentId();
Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
page.getList().add(new Object[]{processDefinition, deployment});
}
return page;
}
/**
* 获取流程表单(首先获取任务节点表单KEY,如果没有则取流程开始节点表单KEY)
* @return
*/
public String getFormKey(String procDefId, String taskDefKey){
String formKey = "";
if (StringUtils.isNotBlank(procDefId)){
if (StringUtils.isNotBlank(taskDefKey)){
try{
formKey = formService.getTaskFormKey(procDefId, taskDefKey);
}catch (Exception e) {
formKey = "";
}
}
if (StringUtils.isBlank(formKey)){
formKey = formService.getStartFormKey(procDefId);
}
if (StringUtils.isBlank(formKey)){
formKey = "/404";
}
}
logger.debug("getFormKey: {}", formKey);
return formKey;
}
/**
* 获取流程实例对象
* @param procInsId
* @return
*/
@Transactional(readOnly = false)
public ProcessInstance getProcIns(String procInsId) {
return runtimeService.createProcessInstanceQuery().processInstanceId(procInsId).singleResult();
}
/**
* 启动流程
* @param procDefKey 流程定义KEY
* @param businessTable 业务表表名
* @param businessId 业务表编号
* @return 流程实例ID
*/
@Transactional(readOnly = false)
public String startProcess(String procDefKey, String businessTable, String businessId) {
return startProcess(procDefKey, businessTable, businessId, "");
}
/**
* 启动流程
* @param procDefKey 流程定义KEY
* @param businessTable 业务表表名
* @param businessId 业务表编号
* @param title 流程标题,显示在待办任务标题
* @return 流程实例ID
*/
@Transactional(readOnly = false)
public String startProcess(String procDefKey, String businessTable, String businessId, String title) {
Map<String, Object> vars = Maps.newHashMap();
return startProcess(procDefKey, businessTable, businessId, title, vars);
}
/**
* 启动流程
* @param procDefKey 流程定义KEY
* @param businessTable 业务表表名
* @param businessId 业务表编号
* @param title 流程标题,显示在待办任务标题
* @param vars 流程变量
* @return 流程实例ID
*/
@Transactional(readOnly = false)
public String startProcess(String procDefKey, String businessTable, String businessId, String title, Map<String, Object> vars) {
String userId = UserUtils.getUser().getLoginName();//ObjectUtils.toString(UserUtils.getUser().getId())
// 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中
identityService.setAuthenticatedUserId(userId);
// 设置流程变量
if (vars == null){
vars = Maps.newHashMap();
}
// 设置流程标题
if (StringUtils.isNotBlank(title)){
vars.put("title", title);
}
// 启动流程
ProcessInstance procIns = runtimeService.startProcessInstanceByKey(procDefKey, businessTable+":"+businessId, vars);
// 更新业务表流程实例ID
Act act = new Act();
act.setBusinessTable(businessTable);// 业务表名
act.setBusinessId(businessId); // 业务表ID
act.setProcInsId(procIns.getId());
actDao.updateProcInsIdByBusinessId(act);
return act.getProcInsId();
}
/**
* 获取任务
* @param taskId 任务ID
*/
public Task getTask(String taskId){
return taskService.createTaskQuery().taskId(taskId).singleResult();
}
/**
* 删除任务
* @param taskId 任务ID
* @param deleteReason 删除原因
*/
@Transactional(readOnly = false)
public void deleteTask(String taskId, String deleteReason){
taskService.deleteTask(taskId, deleteReason);
}
/**
* 签收任务
* @param taskId 任务ID
* @param userId 签收用户ID(用户登录名)
*/
@Transactional(readOnly = false)
public void claim(String taskId, String userId){
taskService.claim(taskId, userId);
}
/**
* 提交任务, 并保存意见
* @param taskId 任务ID
* @param procInsId 流程实例ID,如果为空,则不保存任务提交意见
* @param comment 任务提交意见的内容
* @param vars 任务变量
*/
@Transactional(readOnly = false)
public void complete(String taskId, String procInsId, String comment, Map<String, Object> vars){
complete(taskId, procInsId, comment, "", vars);
}
/**
* 提交任务, 并保存意见
* @param taskId 任务ID
* @param procInsId 流程实例ID,如果为空,则不保存任务提交意见
* @param comment 任务提交意见的内容
* @param title 流程标题,显示在待办任务标题
* @param vars 任务变量
*/
@Transactional(readOnly = false)
public void complete(String taskId, String procInsId, String comment, String title, Map<String, Object> vars){
// 添加意见
if (StringUtils.isNotBlank(procInsId) && StringUtils.isNotBlank(comment)){
taskService.addComment(taskId, procInsId, comment);
}
// 设置流程变量
if (vars == null){
vars = Maps.newHashMap();
}
// 设置流程标题
if (StringUtils.isNotBlank(title)){
vars.put("title", title);
}
// 提交任务
taskService.complete(taskId, vars);
}
/**
* 完成第一个任务
* @param procInsId
*/
@Transactional(readOnly = false)
public void completeFirstTask(String procInsId){
completeFirstTask(procInsId, null, null, null);
}
/**
* 完成第一个任务
* @param procInsId
* @param comment
* @param title
* @param vars
*/
@Transactional(readOnly = false)
public void completeFirstTask(String procInsId, String comment, String title, Map<String, Object> vars){
String userId = UserUtils.getUser().getLoginName();
Task task = taskService.createTaskQuery().taskAssignee(userId).processInstanceId(procInsId).active().singleResult();
if (task != null){
complete(task.getId(), procInsId, comment, title, vars);
}
}
// /**
// * 委派任务
// * @param taskId 任务ID
// * @param userId 被委派人
// */
// public void delegateTask(String taskId, String userId){
// taskService.delegateTask(taskId, userId);
// }
//
// /**
// * 被委派人完成任务
// * @param taskId 任务ID
// */
// public void resolveTask(String taskId){
// taskService.resolveTask(taskId);
// }
//
// /**
// * 回退任务
// * @param taskId
// */
// public void backTask(String taskId){
// taskService.
// }
/**
* 添加任务意见
*/
public void addTaskComment(String taskId, String procInsId, String comment){
taskService.addComment(taskId, procInsId, comment);
}
////////////////// 回退、前进、跳转、前加签、后加签、分裂 移植 https://github.com/bluejoe2008/openwebflow //////////////////////////////////////////////////
/**
* 任务后退一步
*/
public void taskBack(String procInsId, Map<String, Object> variables) {
taskBack(getCurrentTask(procInsId), variables);
}
/**
* 任务后退至指定活动
*/
public void taskBack(TaskEntity currentTaskEntity, Map<String, Object> variables) {
ActivityImpl activity = (ActivityImpl) ProcessDefUtils
.getActivity(processEngine, currentTaskEntity.getProcessDefinitionId(), currentTaskEntity.getTaskDefinitionKey())
.getIncomingTransitions().get(0).getSource();
jumpTask(currentTaskEntity, activity, variables);
}
/**
* 任务前进一步
*/
public void taskForward(String procInsId, Map<String, Object> variables) {
taskForward(getCurrentTask(procInsId), variables);
}
/**
* 任务前进至指定活动
*/
public void taskForward(TaskEntity currentTaskEntity, Map<String, Object> variables) {
ActivityImpl activity = (ActivityImpl) ProcessDefUtils
.getActivity(processEngine, currentTaskEntity.getProcessDefinitionId(), currentTaskEntity.getTaskDefinitionKey())
.getOutgoingTransitions().get(0).getDestination();
jumpTask(currentTaskEntity, activity, variables);
}
/**
* 跳转(包括回退和向前)至指定活动节点
*/
public void jumpTask(String procInsId, String targetTaskDefinitionKey, Map<String, Object> variables) {
jumpTask(getCurrentTask(procInsId), targetTaskDefinitionKey, variables);
}
/**
* 跳转(包括回退和向前)至指定活动节点
*/
public void jumpTask(String procInsId, String currentTaskId, String targetTaskDefinitionKey, Map<String, Object> variables) {
jumpTask(getTaskEntity(currentTaskId), targetTaskDefinitionKey, variables);
}
/**
* 跳转(包括回退和向前)至指定活动节点
* @param currentTaskEntity 当前任务节点
* @param targetTaskDefinitionKey 目标任务节点(在模型定义里面的节点名称)
* @throws Exception
*/
public void jumpTask(TaskEntity currentTaskEntity, String targetTaskDefinitionKey, Map<String, Object> variables) {
ActivityImpl activity = ProcessDefUtils.getActivity(processEngine, currentTaskEntity.getProcessDefinitionId(),
targetTaskDefinitionKey);
jumpTask(currentTaskEntity, activity, variables);
}
/**
* 跳转(包括回退和向前)至指定活动节点
* @param currentTaskEntity 当前任务节点
* @param targetActivity 目标任务节点(在模型定义里面的节点名称)
* @throws Exception
*/
private void jumpTask(TaskEntity currentTaskEntity, ActivityImpl targetActivity, Map<String, Object> variables) {
CommandExecutor commandExecutor = ((RuntimeServiceImpl) runtimeService).getCommandExecutor();
commandExecutor.execute(new JumpTaskCmd(currentTaskEntity, targetActivity, variables));
}
/**
* 后加签
*/
@SuppressWarnings("unchecked")
public ActivityImpl[] insertTasksAfter(String procDefId, String procInsId, String targetTaskDefinitionKey, Map<String, Object> variables, String... assignees) {
List<String> assigneeList = new ArrayList<String>();
assigneeList.add(Authentication.getAuthenticatedUserId());
assigneeList.addAll(CollectionUtils.arrayToList(assignees));
String[] newAssignees = assigneeList.toArray(new String[0]);
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(procDefId);
ActivityImpl prototypeActivity = ProcessDefUtils.getActivity(processEngine, processDefinition.getId(), targetTaskDefinitionKey);
return cloneAndMakeChain(processDefinition, procInsId, targetTaskDefinitionKey, prototypeActivity.getOutgoingTransitions().get(0).getDestination().getId(), variables, newAssignees);
}
/**
* 前加签
*/
public ActivityImpl[] insertTasksBefore(String procDefId, String procInsId, String targetTaskDefinitionKey, Map<String, Object> variables, String... assignees) {
ProcessDefinitionEntity procDef = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(procDefId);
return cloneAndMakeChain(procDef, procInsId, targetTaskDefinitionKey, targetTaskDefinitionKey, variables, assignees);
}
/**
* 分裂某节点为多实例节点
*/
public ActivityImpl splitTask(String procDefId, String procInsId, String targetTaskDefinitionKey, Map<String, Object> variables, String... assignee) {
return splitTask(procDefId, procInsId, targetTaskDefinitionKey, variables, true, assignee);
}
/**
* 分裂某节点为多实例节点
*/
@SuppressWarnings("unchecked")
public ActivityImpl splitTask(String procDefId, String procInsId, String targetTaskDefinitionKey, Map<String, Object> variables, boolean isSequential, String... assignees) {
SimpleRuntimeActivityDefinitionEntity info = new SimpleRuntimeActivityDefinitionEntity();
info.setProcessDefinitionId(procDefId);
info.setProcessInstanceId(procInsId);
RuntimeActivityDefinitionEntityIntepreter radei = new RuntimeActivityDefinitionEntityIntepreter(info);
radei.setPrototypeActivityId(targetTaskDefinitionKey);
radei.setAssignees(CollectionUtils.arrayToList(assignees));
radei.setSequential(isSequential);
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity)repositoryService.getProcessDefinition(procDefId);
ActivityImpl clone = new MultiInstanceActivityCreator().createActivities(processEngine, processDefinition, info)[0];
TaskEntity currentTaskEntity = this.getCurrentTask(procInsId);
CommandExecutor commandExecutor = ((RuntimeServiceImpl) runtimeService).getCommandExecutor();
commandExecutor.execute(new CreateAndTakeTransitionCmd(currentTaskEntity, clone, variables));
// recordActivitiesCreation(info);
return clone;
}
private TaskEntity getCurrentTask(String procInsId) {
return (TaskEntity) taskService.createTaskQuery().processInstanceId(procInsId).active().singleResult();
}
private TaskEntity getTaskEntity(String taskId) {
return (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
}
@SuppressWarnings("unchecked")
private ActivityImpl[] cloneAndMakeChain(ProcessDefinitionEntity procDef, String procInsId, String prototypeActivityId, String nextActivityId, Map<String, Object> variables, String... assignees) {
SimpleRuntimeActivityDefinitionEntity info = new SimpleRuntimeActivityDefinitionEntity();
info.setProcessDefinitionId(procDef.getId());
info.setProcessInstanceId(procInsId);
RuntimeActivityDefinitionEntityIntepreter radei = new RuntimeActivityDefinitionEntityIntepreter(info);
radei.setPrototypeActivityId(prototypeActivityId);
radei.setAssignees(CollectionUtils.arrayToList(assignees));
radei.setNextActivityId(nextActivityId);
ActivityImpl[] activities = new ChainedActivitiesCreator().createActivities(processEngine, procDef, info);
jumpTask(procInsId, activities[0].getId(), variables);
// recordActivitiesCreation(info);
return activities;
}
// private void recordActivitiesCreation(SimpleRuntimeActivityDefinitionEntity info) {
// info.serializeProperties();
// _activitiesCreationStore.save(info);
// }
////////////////////////////////////////////////////////////////////
// private void recordActivitiesCreation(SimpleRuntimeActivityDefinitionEntity info) throws Exception {
// info.serializeProperties();
// _activitiesCreationStore.save(info);
// }
//
// /**
// * 分裂某节点为多实例节点
// *
// * @param targetTaskDefinitionKey
// * @param assignee
// * @throws IOException
// * @throws IllegalAccessException
// * @throws IllegalArgumentException
// */
// public ActivityImpl split(String targetTaskDefinitionKey, boolean isSequential, String... assignees) throws Exception {
// SimpleRuntimeActivityDefinitionEntity info = new SimpleRuntimeActivityDefinitionEntity();
// info.setProcessDefinitionId(processDefinition.getId());
// info.setProcessInstanceId(_processInstanceId);
//
// RuntimeActivityDefinitionEntityIntepreter radei = new RuntimeActivityDefinitionEntityIntepreter(info);
//
// radei.setPrototypeActivityId(targetTaskDefinitionKey);
// radei.setAssignees(CollectionUtils.arrayToList(assignees));
// radei.setSequential(isSequential);
//
// ActivityImpl clone = new MultiInstanceActivityCreator().createActivities(_processEngine, processDefinition, info)[0];
//
// TaskEntity currentTaskEntity = getCurrentTask();
// executeCommand(new CreateAndTakeTransitionCmd(currentTaskEntity.getExecutionId(), clone));
// executeCommand(new DeleteRunningTaskCmd(currentTaskEntity));
//
// recordActivitiesCreation(info);
// return clone;
// }
//
// public ActivityImpl split(String targetTaskDefinitionKey, String... assignee) throws Exception {
// return split(targetTaskDefinitionKey, true, assignee);
// }
////////////////////////////////////////////////////////////////////
/**
* 读取带跟踪的图片
* @param executionId 环节ID
* @return 封装了各种节点信息
*/
public InputStream tracePhoto(String processDefinitionId, String executionId) {
// ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(executionId).singleResult();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
List<String> activeActivityIds = Lists.newArrayList();
if (runtimeService.createExecutionQuery().executionId(executionId).count() > 0){
activeActivityIds = runtimeService.getActiveActivityIds(executionId);
}
// 不使用spring请使用下面的两行代码
// ProcessEngineImpl defaultProcessEngine = (ProcessEngineImpl)ProcessEngines.getDefaultProcessEngine();
// Context.setProcessEngineConfiguration(defaultProcessEngine.getProcessEngineConfiguration());
// 使用spring注入引擎请使用下面的这行代码
Context.setProcessEngineConfiguration(processEngineFactory.getProcessEngineConfiguration());
// return ProcessDiagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds);
return processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator()
.generateDiagram(bpmnModel, "png", activeActivityIds);
}
/**
* 流程跟踪图信息
* @param processInstanceId 流程实例ID
* @return 封装了各种节点信息
*/
public List<Map<String, Object>> traceProcess(String processInstanceId) throws Exception {
Execution execution = runtimeService.createExecutionQuery().executionId(processInstanceId).singleResult();//执行实例
Object property = PropertyUtils.getProperty(execution, "activityId");
String activityId = "";
if (property != null) {
activityId = property.toString();
}
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId)
.singleResult();
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
.getDeployedProcessDefinition(processInstance.getProcessDefinitionId());
List<ActivityImpl> activitiList = processDefinition.getActivities();//获得当前任务的所有节点
List<Map<String, Object>> activityInfos = new ArrayList<Map<String, Object>>();
for (ActivityImpl activity : activitiList) {
boolean currentActiviti = false;
String id = activity.getId();
// 当前节点
if (id.equals(activityId)) {
currentActiviti = true;
}
Map<String, Object> activityImageInfo = packageSingleActivitiInfo(activity, processInstance, currentActiviti);
activityInfos.add(activityImageInfo);
}
return activityInfos;
}
/**
* 封装输出信息,包括:当前节点的X、Y坐标、变量信息、任务类型、任务描述
* @param activity
* @param processInstance
* @param currentActiviti
* @return
*/
private Map<String, Object> packageSingleActivitiInfo(ActivityImpl activity, ProcessInstance processInstance,
boolean currentActiviti) throws Exception {
Map<String, Object> vars = new HashMap<String, Object>();
Map<String, Object> activityInfo = new HashMap<String, Object>();
activityInfo.put("currentActiviti", currentActiviti);
setPosition(activity, activityInfo);
setWidthAndHeight(activity, activityInfo);
Map<String, Object> properties = activity.getProperties();
vars.put("节点名称", properties.get("name"));
vars.put("任务类型", ActUtils.parseToZhType(properties.get("type").toString()));
ActivityBehavior activityBehavior = activity.getActivityBehavior();
logger.debug("activityBehavior={}", activityBehavior);
if (activityBehavior instanceof UserTaskActivityBehavior) {
Task currentTask = null;
// 当前节点的task
if (currentActiviti) {
currentTask = getCurrentTaskInfo(processInstance);
}
// 当前任务的分配角色
UserTaskActivityBehavior userTaskActivityBehavior = (UserTaskActivityBehavior) activityBehavior;
TaskDefinition taskDefinition = userTaskActivityBehavior.getTaskDefinition();
Set<Expression> candidateGroupIdExpressions = taskDefinition.getCandidateGroupIdExpressions();
if (!candidateGroupIdExpressions.isEmpty()) {
// 任务的处理角色
setTaskGroup(vars, candidateGroupIdExpressions);
// 当前处理人
if (currentTask != null) {
setCurrentTaskAssignee(vars, currentTask);
}
}
}
vars.put("节点说明", properties.get("documentation"));
String description = activity.getProcessDefinition().getDescription();
vars.put("描述", description);
logger.debug("trace variables: {}", vars);
activityInfo.put("vars", vars);
return activityInfo;
}
/**
* 设置任务组
* @param vars
* @param candidateGroupIdExpressions
*/
private void setTaskGroup(Map<String, Object> vars, Set<Expression> candidateGroupIdExpressions) {
String roles = "";
for (Expression expression : candidateGroupIdExpressions) {
String expressionText = expression.getExpressionText();
String roleName = identityService.createGroupQuery().groupId(expressionText).singleResult().getName();
roles += roleName;
}
vars.put("任务所属角色", roles);
}
/**
* 设置当前处理人信息
* @param vars
* @param currentTask
*/
private void setCurrentTaskAssignee(Map<String, Object> vars, Task currentTask) {
String assignee = currentTask.getAssignee();
if (assignee != null) {
org.activiti.engine.identity.User assigneeUser = identityService.createUserQuery().userId(assignee).singleResult();
String userInfo = assigneeUser.getFirstName() + " " + assigneeUser.getLastName();
vars.put("当前处理人", userInfo);
}
}
/**
* 获取当前节点信息
* @param processInstance
* @return
*/
private Task getCurrentTaskInfo(ProcessInstance processInstance) {
Task currentTask = null;
try {
String activitiId = (String) PropertyUtils.getProperty(processInstance, "activityId");
logger.debug("current activity id: {}", activitiId);
currentTask = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskDefinitionKey(activitiId)
.singleResult();
logger.debug("current task for processInstance: {}", ToStringBuilder.reflectionToString(currentTask));
} catch (Exception e) {
logger.error("can not get property activityId from processInstance: {}", processInstance);
}
return currentTask;
}
/**
* 设置宽度、高度属性
* @param activity
* @param activityInfo
*/
private void setWidthAndHeight(ActivityImpl activity, Map<String, Object> activityInfo) {
activityInfo.put("width", activity.getWidth());
activityInfo.put("height", activity.getHeight());
}
/**
* 设置坐标位置
* @param activity
* @param activityInfo
*/
private void setPosition(ActivityImpl activity, Map<String, Object> activityInfo) {
activityInfo.put("x", activity.getX());
activityInfo.put("y", activity.getY());
}
public ProcessEngine getProcessEngine() {
return processEngine;
}
}
package com.jeespring.modules.act.service.cmd;
import java.util.Map;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.runtime.AtomicOperation;
public class CreateAndTakeTransitionCmd implements Command<Void> {
private TaskEntity currentTaskEntity;
private ActivityImpl activity;
protected Map<String, Object> variables;
public CreateAndTakeTransitionCmd(TaskEntity currentTaskEntity, ActivityImpl activity, Map<String, Object> variables) {
this.currentTaskEntity = currentTaskEntity;
this.activity = activity;
this.variables = variables;
}
@Override
public Void execute(CommandContext commandContext) {
if (currentTaskEntity != null) {
ExecutionEntity execution = commandContext.getExecutionEntityManager().findExecutionById(currentTaskEntity.getExecutionId());
execution.setActivity(activity);
execution.performOperation(AtomicOperation.TRANSITION_CREATE_SCOPE);
if (variables != null) {
if (currentTaskEntity.getExecutionId() != null) {
currentTaskEntity.setExecutionVariables(variables);
} else {
currentTaskEntity.setVariables(variables);
}
}
//删除当前的任务,不能删除当前正在执行的任务,所以要先清除掉关联
Context.getCommandContext().getTaskEntityManager().deleteTask(currentTaskEntity, TaskEntity.DELETE_REASON_DELETED, false);
}
return null;
}
}
\ No newline at end of file
package com.jeespring.modules.act.service.cmd;
import java.util.Map;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.runtime.AtomicOperation;
public class JumpTaskCmd implements Command<Void> {
private TaskEntity taskEntity;
private ActivityImpl targetActivity;
protected Map<String, Object> variables;
public JumpTaskCmd(TaskEntity taskEntity, ActivityImpl targetActivity, Map<String, Object> variables) {
this.taskEntity = taskEntity;
this.targetActivity = targetActivity;
this.variables = variables;
}
@Override
public Void execute(CommandContext commandContext) {
if (taskEntity != null) {
//删除当前的任务,不能删除当前正在执行的任务,所以要先清除掉关联
if (variables != null) {
if (taskEntity.getExecutionId() != null) {
taskEntity.setExecutionVariables(variables);
} else {
taskEntity.setVariables(variables);
}
}
// // 完成活动历史
// Context.getCommandContext().getHistoryManager()
// .recordActivityEnd((ExecutionEntity) taskEntity.getExecution());
// 完成待办任务
Context.getCommandContext().getTaskEntityManager().deleteTask(taskEntity,
TaskEntity.DELETE_REASON_COMPLETED, false); // DELETE_REASON_DELETED DELETE_REASON_COMPLETED
// 跳转任务
ExecutionEntity execution = taskEntity.getExecution();
execution.setActivity(targetActivity);
execution.performOperation(AtomicOperation.ACTIVITY_START);
}
return null;
}
}
\ No newline at end of file
package com.jeespring.modules.act.service.cmd;
import java.io.ByteArrayInputStream;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.db.DbSqlSession;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.DeploymentEntity;
import org.activiti.engine.impl.persistence.entity.ResourceEntity;
import org.activiti.engine.impl.persistence.entity.ResourceEntityManager;
import org.activiti.engine.impl.util.IoUtil;
import org.activiti.engine.repository.ProcessDefinition;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* 模型部署或更新到流程定义
* @author ThinkGem
* @version 2016年8月2日
*/
public class ModelDeployProcessDefinitionCmd implements Command<Void> {
private String modelId;
private String procDefKey;
private String procDefName;
public ModelDeployProcessDefinitionCmd(String modelId, String procDefKey, String procDefName) {
this.modelId = modelId;
this.procDefKey = procDefKey;
this.procDefName = procDefName;
}
@Override
public Void execute(CommandContext commandContext) {
RepositoryService repositoryService = Context.getProcessEngineConfiguration()
.getRepositoryService();
try{
// 生成部署名称和数据 ThinkGem
JsonNode editorNode = new ObjectMapper().readTree(repositoryService
.getModelEditorSource(modelId));
BpmnModel bpmnModel = new BpmnJsonConverter().convertToBpmnModel(editorNode);
byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(bpmnModel);
// 查询流程定义是否已经存在了 ThinkGem
ProcessDefinition processDefinition = Context.getProcessEngineConfiguration()
.getRepositoryService().createProcessDefinitionQuery()
.processDefinitionKey(procDefKey).latestVersion().singleResult();
if (processDefinition != null){
ResourceEntityManager resourceEntityManager = commandContext.getResourceEntityManager();
DeploymentEntity deployment = (DeploymentEntity)repositoryService.createDeploymentQuery()
.deploymentId(processDefinition.getDeploymentId()).singleResult();
// 删除原资源
resourceEntityManager.deleteResourcesByDeploymentId(deployment.getId());
Context.getCommandContext().getSession(DbSqlSession.class).flush();
// 插入新资源
ResourceEntity resource = new ResourceEntity();
resource.setDeploymentId(deployment.getId());
resource.setName(procDefName + ".bpmn20.xml");
resource.setBytes(bpmnBytes);
deployment.addResource(resource);
resourceEntityManager.insertResource(resource);
// 插入资源图片
ProcessEngineConfigurationImpl processEngineConfiguration = Context.getProcessEngineConfiguration();
byte[] diagramBytes = IoUtil.readInputStream(processEngineConfiguration.
getProcessDiagramGenerator().generateDiagram(bpmnModel, "png", processEngineConfiguration.getActivityFontName(),
processEngineConfiguration.getLabelFontName(),processEngineConfiguration.getAnnotationFontName(), processEngineConfiguration.getClassLoader()), null);
ResourceEntity diagramResource = new ResourceEntity();
diagramResource.setDeploymentId(deployment.getId());
diagramResource.setName(procDefName + "." + processDefinition.getKey() + ".png");
diagramResource.setBytes(diagramBytes);
deployment.addResource(diagramResource);
resourceEntityManager.insertResource(diagramResource);
}
// 不存在部署一个新的流程 ThinkGem
else{
repositoryService.createDeployment().name(procDefName).addInputStream(
procDefName + ".bpmn20.xml", new ByteArrayInputStream(bpmnBytes)).deploy();
}
}catch(Exception e){
throw new ActivitiException("模型部署到流程定义错误", e);
}
return null;
}
}
\ No newline at end of file
package com.jeespring.modules.act.service.creator;
import java.util.ArrayList;
import java.util.List;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.springframework.util.CollectionUtils;
import com.jeespring.modules.act.utils.ProcessDefUtils;
public class ChainedActivitiesCreator extends RuntimeActivityCreatorSupport implements RuntimeActivityCreator {
@SuppressWarnings("unchecked")
public ActivityImpl[] createActivities(ProcessEngine processEngine, ProcessDefinitionEntity processDefinition,
RuntimeActivityDefinitionEntity info) {
info.setFactoryName(ChainedActivitiesCreator.class.getName());
RuntimeActivityDefinitionEntityIntepreter radei = new RuntimeActivityDefinitionEntityIntepreter(info);
if (radei.getCloneActivityIds() == null) {
radei.setCloneActivityIds(CollectionUtils.arrayToList(new String[radei.getAssignees().size()]));
}
return createActivities(processEngine, processDefinition, info.getProcessInstanceId(), radei.getPrototypeActivityId(),
radei.getNextActivityId(), radei.getAssignees(), radei.getCloneActivityIds());
}
private ActivityImpl[] createActivities(ProcessEngine processEngine, ProcessDefinitionEntity processDefinition, String processInstanceId,
String prototypeActivityId, String nextActivityId, List<String> assignees, List<String> activityIds) {
ActivityImpl prototypeActivity = ProcessDefUtils.getActivity(processEngine, processDefinition.getId(), prototypeActivityId);
List<ActivityImpl> activities = new ArrayList<ActivityImpl>();
for (int i = 0; i < assignees.size(); i++) {
if (activityIds.get(i) == null) {
String activityId = createUniqueActivityId(processInstanceId, prototypeActivityId);
activityIds.set(i, activityId);
}
ActivityImpl clone = createActivity(processEngine, processDefinition, prototypeActivity, activityIds.get(i), assignees.get(i));
activities.add(clone);
}
ActivityImpl nextActivity = ProcessDefUtils.getActivity(processEngine, processDefinition.getId(), nextActivityId);
createActivityChain(activities, nextActivity);
return activities.toArray(new ActivityImpl[0]);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment