Skip to content

Instantly share code, notes, and snippets.

@henryyan
Created March 24, 2012 14:32
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save henryyan/2183557 to your computer and use it in GitHub Desktop.
Save henryyan/2183557 to your computer and use it in GitHub Desktop.
AbstractWorkflowService
/**
* 抽象工作流接口(有部分功能的实现)
*
* @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