Created
March 24, 2012 14:32
-
-
Save henryyan/2183557 to your computer and use it in GitHub Desktop.
AbstractWorkflowService
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 抽象工作流接口(有部分功能的实现) | |
* | |
* @author HenryYan | |
* | |
*/ | |
public abstract class AbstractWorkflowService<T extends BaseWorkflowEntity, PK extends Serializable> { | |
protected Logger logger = LoggerFactory.getLogger(getClass()); | |
@Autowired | |
protected RuntimeService runtimeService; | |
@Autowired | |
protected TaskService taskService; | |
@Autowired | |
protected RepositoryService repositoryService; | |
@Autowired | |
protected HistoryService historyService; | |
private Class<?> entityKeyClazz; | |
public AbstractWorkflowService() { | |
super(); | |
entityKeyClazz = ReflectionUtils.getSuperClassGenricType(getClass(), 1); | |
} | |
/** | |
* 启动流程 | |
* @param entity 实体 | |
* @return 启动后的流程实例 | |
* @throws IllegalAccessException 设置processInstanceId时 | |
* @throws InvocationTargetException 设置processInstanceId时 | |
* @throws NoSuchMethodException 设置processInstanceId时 | |
*/ | |
protected ProcessInstance start(T entity, User user) throws IllegalAccessException, InvocationTargetException, | |
NoSuchMethodException, Exception { | |
return start(entity, user, null); | |
} | |
/** | |
* 启动流程 | |
* @param entity 实体 | |
* @param user 用户 | |
* @param variables 启动流程的变量 | |
* @return 启动后的流程实例 | |
* @throws IllegalAccessException 设置processInstanceId时 | |
* @throws InvocationTargetException 设置processInstanceId时 | |
* @throws NoSuchMethodException 设置processInstanceId时 | |
*/ | |
protected ProcessInstance start(T entity, User user, Map<String, Object> variables) throws IllegalAccessException, | |
InvocationTargetException, NoSuchMethodException, Exception { | |
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(getProcessDefKey(), entity.getId().toString(), | |
variables); | |
PropertyUtils.setProperty(entity, "processInstanceId", processInstance.getId()); | |
getEntityManager().saveEntity(entity); | |
return processInstance; | |
} | |
/** | |
* 启动工作流 | |
* @param entity 实体 | |
* @param user 用户 | |
* @param variables 启动流程的变量 | |
* @return 响应结果,用map形式返回以便前台读取JSON格式数据 | |
* @throws Exception | |
*/ | |
public Map<String, Object> startWorkflow(T entity, User user, Map<String, Object> variables) throws Exception { | |
if (EntityUtils.isNew(entity.getId())) { | |
getEntityManager().saveEntity(entity); | |
} | |
ProcessInstance processInstance = start(entity, user, variables); | |
Map<String, Object> responses = new HashMap<String, Object>(); | |
responses.put("bkey", entity.getId()); | |
responses.put("pid", processInstance.getId()); | |
responses.put("success", true); | |
responses.put("started", true); | |
logger.debug("started workflow, entity={}, user={}, responses={}", | |
new Object[] { entity, user.getLoginName(), responses }); | |
return responses; | |
} | |
/** | |
* 启动工作流 | |
* @param entity 实体 | |
* @return 响应结果,用map形式返回以便前台读取JSON格式数据 | |
* @throws Exception | |
*/ | |
public Map<String, Object> startWorkflow(T entity, User user) throws Exception { | |
return startWorkflow(entity, user, null); | |
} | |
/** | |
* 完成任务 | |
* @param taskId | |
* @param user | |
* @param variables | |
*/ | |
public void complete(String taskId, User user, Map<String, Object> variables) throws Exception { | |
taskService.complete(taskId, variables); | |
logger.debug("complete task, id={}, user={}, variables={}", new Object[] { taskId, user.getLoginName(), variables }); | |
} | |
/** | |
* 根据任务名称查询任务集合 | |
* @param processDefKey 流程定义key | |
* @param taskDefKey 流程定义文件中的task英文名称 | |
* @return 实体集合,包含task属性 | |
* @throws Exception | |
*/ | |
@Transactional(readOnly = true) | |
public List<T> searchTasksWithEntities(String processDefKey, String taskDefKey) throws Exception { | |
if (StringUtils.isBlank(taskDefKey)) { | |
throw new IllegalArgumentException("taskDefKey can not be null"); | |
} | |
TaskQuery taskAssigneeQuery = taskService.createTaskQuery().processDefinitionKey(getProcessDefKey()) | |
.taskDefinitionKey(taskDefKey); | |
List<Task> tasks = taskAssigneeQuery.list(); | |
List<T> results = parseTaskToEntities(tasks); | |
return results; | |
} | |
/** | |
* 通过task对象转换为包含task属性的业务实体集合 | |
* @param tasks 工作流的task集合 | |
* @return 包含task属性的业务实体集合 | |
* @throws IllegalAccessException | |
* @throws InvocationTargetException | |
* @throws NoSuchMethodException | |
*/ | |
@SuppressWarnings("unchecked") | |
protected List<T> parseTaskToEntities(List<Task> tasks) throws IllegalAccessException, InvocationTargetException, | |
NoSuchMethodException { | |
// 缓存流程实例 | |
Set<String> processInstanceIdSet = new HashSet<String>(); | |
processInstanceIdSet.addAll(ConvertUtils.convertElementPropertyToList(tasks, "processInstanceId")); | |
List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery() | |
.processInstanceIds(processInstanceIdSet).list(); | |
Map<String, ProcessInstance> processInstanceMap = new HashMap<String, ProcessInstance>(); | |
for (ProcessInstance processInstance : processInstanceList) { | |
processInstanceMap.put(processInstance.getId(), processInstance); | |
} | |
// 缓存实体 | |
Map<String, T> entityMap = extractEntitiesFromDatabase(processInstanceList); | |
List<T> results = packageTasksUseEntity(tasks, entityMap, processInstanceMap); | |
return results; | |
} | |
/** | |
* 同一任务数量,包括:未签收、处理中、正在运行、已结束 | |
* @param userId 用户ID | |
* @return unsigned:未签收,todo:处理中,unfinished:运行中,finished:已完成 | |
*/ | |
@Transactional(readOnly = true) | |
public Map<String, Long> countTasks(String userId) { | |
Map<String, Long> workflowCounter = new HashMap<String, Long>(); | |
// 根据角色查询任务--未签收的 | |
TaskQuery taskCandidateUserQuery = createUnsignedTaskQuery(userId); | |
long taskForGroupCounter = taskCandidateUserQuery.count(); | |
workflowCounter.put("unsigned", taskForGroupCounter); | |
// 根据代理人查询任务--待处理 | |
TaskQuery taskAssigneeQuery = createTodoTaskQuery(userId); | |
long todoTaskCounter = taskAssigneeQuery.count(); | |
workflowCounter.put("todo", todoTaskCounter); | |
// 运行中流程 | |
// TODO 查询到底使用history还是runtime查询正在运行的流程 | |
ProcessInstanceQuery unfinishedQuery = createUnFinishedProcessInstanceQuery(userId); | |
long unFinishedCounter = unfinishedQuery.count(); | |
workflowCounter.put("unfinished", unFinishedCounter); | |
// TODO 已完结流程 | |
// 1、查询当前登录人的历史task | |
// 2、根据task的processInstanceId查询流程实例 | |
HistoricProcessInstanceQuery finishedQuery = createFinishedProcessInstanceQuery(userId); | |
long finishedCounter = finishedQuery.count(); | |
workflowCounter.put("finished", finishedCounter); | |
return workflowCounter; | |
} | |
/** | |
* 分页查询工作流数据并封装成业务实体 | |
* @param flowDataType 任务/实例状态,{@link WorkflowConstants} | |
* @param userId 用户ID | |
* @param page 分页对象 | |
* @return 包含工作流信息的业务实体 | |
* @throws Exception | |
*/ | |
@Transactional(readOnly = true) | |
public List<T> searchForPage(String flowDataType, String userId, Page<T> page) throws Exception { | |
List<T> results = null; | |
List<Task> tasks = null; | |
TaskQuery taskCandidateUserQuery = createUnsignedTaskQuery(userId); | |
TaskQuery taskAssigneeQuery = createTodoTaskQuery(userId); | |
// HistoricProcessInstanceQuery unfinishedQuery = getUnFinishedProcessInstanceQuery(userId); | |
ProcessInstanceQuery unfinishedQuery = createUnFinishedProcessInstanceQuery(userId); | |
HistoricProcessInstanceQuery finishedQuery = createFinishedProcessInstanceQuery(userId); | |
List<ProcessInstance> runtimeProcessInstances = null; | |
List<HistoricProcessInstance> historicProcessInstances = null; | |
if (flowDataType.equals(WorkflowConstants.TASK_STATUS_UNSIGNED)) { | |
if (!page.isOrderBySetted()) { | |
page.setOrderBy("task.priority,task.createTime"); | |
page.setOrder("desc,desc"); | |
} | |
setOrders(taskCandidateUserQuery, page); | |
tasks = taskCandidateUserQuery.listPage(page.getFirst() - 1, page.getPageSize()); | |
} else if (flowDataType.equals(WorkflowConstants.TASK_STATUS_TODO)) { | |
if (!page.isOrderBySetted()) { | |
page.setOrderBy("task.priority,task.createTime"); | |
page.setOrder("desc,desc"); | |
} | |
setOrders(taskAssigneeQuery, page); | |
tasks = taskAssigneeQuery.listPage(page.getFirst() - 1, page.getPageSize()); | |
} else if (flowDataType.equals(WorkflowConstants.PROCESS_INSTANCE_STATUS_UNFINISHED)) { | |
setOrders(unfinishedQuery, page); | |
runtimeProcessInstances = unfinishedQuery.listPage(page.getFirst() - 1, page.getPageSize()); | |
} else if (flowDataType.equals(WorkflowConstants.PROCESS_INSTANCE_STATUS_FINISHED)) { | |
if (!page.isOrderBySetted()) { | |
page.setOrderBy("historicProcessInstance.endTime"); | |
page.setOrder("desc"); | |
} | |
setOrders(finishedQuery, page); | |
historicProcessInstances = finishedQuery.listPage(page.getFirst() - 1, page.getPageSize()); | |
} | |
if (tasks != null && !tasks.isEmpty()) { | |
results = this.parseTaskToEntities(tasks); | |
} else if (historicProcessInstances != null && !historicProcessInstances.isEmpty()) { | |
results = packageHistoricProcessInstances(flowDataType, historicProcessInstances); | |
} else if (runtimeProcessInstances != null && !runtimeProcessInstances.isEmpty()) { | |
// TODO 对于嵌入式子流程,父流程显示当前节点为null | |
/*for (ProcessInstance processInstance : runtimeProcessInstances) { | |
ExecutionEntity executionEntity = (ExecutionEntity) processInstance; | |
if (processInstance.getBusinessKey() == null) { | |
} | |
}*/ | |
results = packageRuntimeProcessInstances(flowDataType, runtimeProcessInstances); | |
} | |
return results; | |
} | |
/** | |
* 设置查询对象的排序条件 | |
* @param query | |
* @param page | |
* @throws NoSuchMethodException | |
* @throws SecurityException | |
*/ | |
private void setOrders(Query<?, ?> query, Page<T> page) throws SecurityException, NoSuchMethodException { | |
if (!page.isOrderBySetted()) { | |
return; | |
} | |
String[] orderArray = StringUtils.split(page.getOrder(), ','); | |
String[] orderByArray = StringUtils.split(page.getOrderBy(), ','); | |
for (int i = 0; i < orderByArray.length; i++) { | |
String orderBy = orderByArray[i]; | |
String order = orderArray[i]; | |
System.out.println(orderBy + "=" + order); | |
if (orderBy.startsWith("task.")) { | |
String innerOrderBy = orderBy.split("\\.")[1]; | |
String withFirstUpperCharOrderBy = StringUtils.upperCase(innerOrderBy.substring(0, 1)) | |
+ innerOrderBy.substring(1); | |
String methodName = "orderByTask" + withFirstUpperCharOrderBy; | |
ReflectionUtils.invokeMethod(query, methodName, null, null); | |
ReflectionUtils.invokeMethod(query, order, null, null); | |
} else if (orderBy.startsWith("historicProcessInstance.")) { | |
String innerOrderBy = orderBy.split("\\.")[1]; | |
String withFirstUpperCharOrderBy = StringUtils.upperCase(innerOrderBy.substring(0, 1)) | |
+ innerOrderBy.substring(1); | |
String methodName = "orderByProcessInstance" + withFirstUpperCharOrderBy; | |
ReflectionUtils.invokeMethod(query, methodName, null, null); | |
ReflectionUtils.invokeMethod(query, order, null, null); | |
} | |
} | |
} | |
/** | |
* 获取已经完成的流程实例查询对象 | |
* @param userId 用户ID | |
*/ | |
@Transactional(readOnly = true) | |
public HistoricProcessInstanceQuery createFinishedProcessInstanceQuery(String userId) { | |
HistoricProcessInstanceQuery finishedQuery = historyService.createHistoricProcessInstanceQuery() | |
.processDefinitionKey(getProcessDefKey()).finished(); | |
return finishedQuery; | |
} | |
// /** | |
// * 获取未经完成的流程实例查询对象 | |
// * @param userId 用户ID | |
// */ | |
// @Transactional(readOnly = true) | |
// public HistoricProcessInstanceQuery getUnFinishedProcessInstanceQuery(String userId) { | |
// HistoricProcessInstanceQuery unfinishedQuery = historyService.createHistoricProcessInstanceQuery().processDefinitionKey(getProcessName()) | |
// .unfinished(); | |
// return unfinishedQuery; | |
// } | |
/** | |
* 获取未经完成的流程实例查询对象 | |
* @param userId 用户ID | |
*/ | |
@Transactional(readOnly = true) | |
public ProcessInstanceQuery createUnFinishedProcessInstanceQuery(String userId) { | |
ProcessInstanceQuery unfinishedQuery = runtimeService.createProcessInstanceQuery().processDefinitionKey(getProcessDefKey()) | |
.active(); | |
return unfinishedQuery; | |
} | |
/** | |
* 获取正在处理的任务查询对象 | |
* @param userId 用户ID | |
*/ | |
@Transactional(readOnly = true) | |
public TaskQuery createTodoTaskQuery(String userId) { | |
TaskQuery taskAssigneeQuery = taskService.createTaskQuery().processDefinitionKey(getProcessDefKey()).taskAssignee(userId); | |
return taskAssigneeQuery; | |
} | |
/** | |
* 获取未签收的任务查询对象 | |
* @param userId 用户ID | |
*/ | |
@Transactional(readOnly = true) | |
public TaskQuery createUnsignedTaskQuery(String userId) { | |
TaskQuery taskCandidateUserQuery = taskService.createTaskQuery().processDefinitionKey(getProcessDefKey()) | |
.taskCandidateUser(userId); | |
return taskCandidateUserQuery; | |
} | |
/** | |
* 从流程实例中抽取businessKey属性,然后根据这些属性从数据库查询业务对象 | |
* @param processInstanceList 流程实例集合 | |
* @return Map<实体ID, 实体对象> | |
*/ | |
@SuppressWarnings("unchecked") | |
@Transactional(readOnly = true) | |
protected Map<String, T> extractEntitiesFromDatabase(List<?> processInstanceList) { | |
List<String> businessKeys = ConvertUtils.convertElementPropertyToList(processInstanceList, "businessKey"); | |
List<PK> entityIds = new ArrayList<PK>(); | |
for (String string : businessKeys) { | |
entityIds.add((PK) ConvertUtils.convertStringToObject(string, entityKeyClazz)); | |
} | |
Map<String, T> entityMap = new HashMap<String, T>(); | |
List<T> entities = getEntityManager().getEntities(entityIds.toArray()); | |
for (T entity : entities) { | |
entityMap.put(entity.getId().toString(), entity); | |
} | |
return entityMap; | |
} | |
/** | |
* 绑定业务实体和任务的关系 | |
* @param tasks 任务集合 | |
* @param entityMap 实体集合,作用:内存缓存 | |
* @param processInstanceMap 流程实例集合 | |
* @return 设置了task、processDefinition、processInstance属性 | |
* @throws IllegalAccessException 克隆流程对象时 | |
* @throws InvocationTargetException 克隆流程对象时 | |
* @throws NoSuchMethodException 克隆流程对象时 | |
* @see {@link WorkflowUtils} | |
*/ | |
@Transactional(readOnly = true) | |
protected List<T> packageTasksUseEntity(List<Task> tasks, Map<String, T> entityMap, | |
Map<String, ProcessInstance> processInstanceMap) throws IllegalAccessException, InvocationTargetException, | |
NoSuchMethodException { | |
List<T> results = new ArrayList<T>(); | |
Map<String, ProcessDefinition> processDefinitionMap = new HashMap<String, ProcessDefinition>(); | |
for (Task task : tasks) { | |
ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId()); | |
String processDefinitionId = processInstance.getProcessDefinitionId(); | |
ProcessDefinition processDefinition = processDefinitionMap.get(processDefinitionId); | |
if (processDefinition == null) { | |
processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId) | |
.singleResult(); | |
} | |
if (processInstance != null) { | |
String businessKey = processInstance.getBusinessKey(); | |
T workflowEntity = entityMap.get(businessKey); | |
if (workflowEntity == null) { | |
continue; | |
} | |
workflowEntity.setProcessInstance(WorkflowUtils.cloneExProcessInstance(processInstance)); | |
ExTask cloneExTask = WorkflowUtils.cloneExTask(task); | |
cloneExTask.setVariables(runtimeService.getVariables(task.getExecutionId())); | |
workflowEntity.setTask(cloneExTask); | |
workflowEntity.setProcessDefinition(WorkflowUtils.cloneExProcessDefinition(processDefinition)); | |
results.add(workflowEntity); | |
} | |
} | |
return results; | |
} | |
/** | |
* 绑定业务实体和<b>已结束</b>流程实例的关系 | |
* @param flowDataType 流程状态,{@link WorkflowConstants} | |
* @param processInstances 历史流程实例集合 | |
* @return 实体集合,设置了historicProcessInstance属性 | |
* @throws IllegalAccessException 克隆流程对象时 | |
* @throws InvocationTargetException 克隆流程对象时 | |
* @throws NoSuchMethodException 克隆流程对象时 | |
* @see {@link WorkflowUtils} | |
*/ | |
@Transactional(readOnly = true) | |
protected List<T> packageHistoricProcessInstances(String flowDataType, List<HistoricProcessInstance> processInstances) | |
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { | |
List<T> results = new ArrayList<T>(); | |
Map<String, T> entityMap = extractEntitiesFromDatabase(processInstances); | |
for (HistoricProcessInstance historicProcessInstance : processInstances) { | |
String businessKey = historicProcessInstance.getBusinessKey(); | |
ExHistoricProcessInstance exHistoricProcessInstance = WorkflowUtils | |
.cloneExHistoricProcessInstance(historicProcessInstance); | |
T workflowEntity = entityMap.get(businessKey); | |
if (workflowEntity == null) { | |
continue; | |
} | |
workflowEntity.setHistoricProcessInstance(exHistoricProcessInstance); | |
results.add(workflowEntity); | |
} | |
return results; | |
} | |
/** | |
* 绑定业务实体和<b>正在运行</b>的流程实例的关系 | |
* @param flowDataType 流程状态,{@link WorkflowConstants} | |
* @param runtimeProcessInstances 运行中的流程实例集合 | |
* @return 实体集合,设置了processInstance属性 | |
* @throws IllegalAccessException 克隆流程对象时 | |
* @throws InvocationTargetException 克隆流程对象时 | |
* @throws NoSuchMethodException 克隆流程对象时 | |
* @see {@link WorkflowUtils} | |
*/ | |
@Transactional(readOnly = true) | |
protected List<T> packageRuntimeProcessInstances(String flowDataType, List<ProcessInstance> runtimeProcessInstances) | |
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { | |
List<T> results = new ArrayList<T>(); | |
Map<String, T> entityMap = extractEntitiesFromDatabase(runtimeProcessInstances); | |
for (ProcessInstance runtimeProcessInstance : runtimeProcessInstances) { | |
String businessKey = runtimeProcessInstance.getBusinessKey(); | |
ExProcessInstance exProcessInstance = WorkflowUtils.cloneExProcessInstance(runtimeProcessInstance); | |
T workflowEntity = entityMap.get(businessKey); | |
if (workflowEntity == null) { | |
continue; | |
} | |
workflowEntity.setProcessInstance(exProcessInstance); | |
if (flowDataType.equals(WorkflowConstants.PROCESS_INSTANCE_STATUS_UNFINISHED)) { | |
Task singleResult = taskService.createTaskQuery().processInstanceId(runtimeProcessInstance.getId()) | |
.orderByTaskCreateTime().desc().singleResult(); | |
workflowEntity.setTask(WorkflowUtils.cloneExTask(singleResult)); | |
} | |
results.add(workflowEntity); | |
} | |
return results; | |
} | |
/** | |
* 获取流程定义key | |
* @return 流程定义key | |
*/ | |
@Transactional(readOnly = true) | |
public abstract String getProcessDefKey(); | |
/** | |
* 获取实体管理类 | |
* | |
* @return ${@link BaseEntityManager} | |
*/ | |
public abstract BaseEntityManager<T, PK> getEntityManager(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment