package com.mossle.bpm.cmd; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.activiti.engine.ActivitiException; 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.delegate.ActivityExecution; import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CounterSignCmd implements Command<Object> { private static Logger log = LoggerFactory.getLogger(CounterSignCmd.class); private String operateType; private String activityId; private String assignee; private String processInstanceId; private String collectionVariableName; private String collectionElementVariableName; private CommandContext commandContext; private String taskId; public CounterSignCmd(String operateType, String assignee, String taskId) { this.operateType = operateType; this.assignee = assignee; this.taskId = taskId; } /** * @param operateType * 操作类型 add or remove * @param activityId * 节点ID * @param assignee * 人员代码 * @param processInstanceId * 流程实例ID * @param collectionVariableName * collection 设置的变量名 * @param collectionElementVariableName * collection 的每个元素变量名 */ public CounterSignCmd(final String operateType, final String activityId, final String assignee, final String processInstanceId, final String collectionVariableName, final String collectionElementVariableName) { this.operateType = operateType; this.activityId = activityId; this.assignee = assignee; this.processInstanceId = processInstanceId; this.collectionVariableName = collectionVariableName; this.collectionElementVariableName = collectionElementVariableName; } public Object execute(CommandContext commandContext) { this.commandContext = commandContext; if (this.taskId != null) { TaskEntity taskEntity = commandContext.getTaskEntityManager() .findTaskById(taskId); activityId = taskEntity.getExecution().getActivityId(); processInstanceId = taskEntity.getProcessInstanceId(); this.collectionVariableName = "countersignUsers"; this.collectionElementVariableName = "countersignUser"; } if (operateType.equalsIgnoreCase("add")) { addInstance(); } else if (operateType.equalsIgnoreCase("remove")) { removeInstance(); } return null; } /** * <li>加签 */ public void addInstance() { if (isParallel()) { addParallelInstance(); } else { addSequentialInstance(); } } /** * <li>减签 */ public void removeInstance() { if (isParallel()) { removeParallelInstance(); } else { removeSequentialInstance(); } } /** * <li>添加一条并行实例 */ private void addParallelInstance() { ExecutionEntity parentExecutionEntity = commandContext .getExecutionEntityManager() .findExecutionById(processInstanceId).findExecution(activityId); ActivityImpl activity = getActivity(); ExecutionEntity execution = parentExecutionEntity.createExecution(); execution.setActive(true); execution.setConcurrent(true); execution.setScope(false); if (getActivity().getProperty("type").equals("subProcess")) { ExecutionEntity extraScopedExecution = execution.createExecution(); extraScopedExecution.setActive(true); extraScopedExecution.setConcurrent(false); extraScopedExecution.setScope(true); execution = extraScopedExecution; } setLoopVariable(parentExecutionEntity, "nrOfInstances", (Integer) parentExecutionEntity .getVariableLocal("nrOfInstances") + 1); setLoopVariable(parentExecutionEntity, "nrOfActiveInstances", (Integer) parentExecutionEntity .getVariableLocal("nrOfActiveInstances") + 1); setLoopVariable(execution, "loopCounter", parentExecutionEntity .getExecutions().size() + 1); setLoopVariable(execution, collectionElementVariableName, assignee); execution.executeActivity(activity); } /** * <li>给串行实例集合中添加一个审批人 */ private void addSequentialInstance() { ExecutionEntity execution = getActivieExecutions().get(0); if (getActivity().getProperty("type").equals("subProcess")) { if (!execution.isActive() && execution.isEnded() && ((execution.getExecutions() == null) || (execution .getExecutions().size() == 0))) { execution.setActive(true); } } Collection<String> col = (Collection<String>) execution .getVariable(collectionVariableName); col.add(assignee); execution.setVariable(collectionVariableName, col); setLoopVariable(execution, "nrOfInstances", (Integer) execution.getVariableLocal("nrOfInstances") + 1); } /** * <li>移除一条并行实例 */ private void removeParallelInstance() { List<ExecutionEntity> executions = getActivieExecutions(); for (ExecutionEntity executionEntity : executions) { String executionVariableAssignee = (String) executionEntity .getVariableLocal(collectionElementVariableName); if ((executionVariableAssignee != null) && executionVariableAssignee.equals(assignee)) { executionEntity.remove(); ExecutionEntity parentConcurrentExecution = executionEntity .getParent(); if (getActivity().getProperty("type").equals("subProcess")) { parentConcurrentExecution = parentConcurrentExecution .getParent(); } setLoopVariable(parentConcurrentExecution, "nrOfInstances", (Integer) parentConcurrentExecution .getVariableLocal("nrOfInstances") - 1); setLoopVariable(parentConcurrentExecution, "nrOfActiveInstances", (Integer) parentConcurrentExecution .getVariableLocal("nrOfActiveInstances") - 1); break; } } } /** * <li>冲串行列表中移除未完成的用户(当前执行的用户无法移除) */ private void removeSequentialInstance() { ExecutionEntity executionEntity = getActivieExecutions().get(0); Collection<String> col = (Collection<String>) executionEntity .getVariable(collectionVariableName); log.info("移除前审批列表 : {}", col.toString()); col.remove(assignee); executionEntity.setVariable(collectionVariableName, col); setLoopVariable(executionEntity, "nrOfInstances", (Integer) executionEntity.getVariableLocal("nrOfInstances") - 1); // 如果串行要删除的人是当前active执行, if (executionEntity.getVariableLocal(collectionElementVariableName) .equals(assignee)) { throw new ActivitiException("当前正在执行的实例,无法移除!"); } log.info("移除后审批列表 : {}", col.toString()); } /** * <li>获取活动的执行 , 子流程的活动执行是其孩子执行(并行多实例情况下) <li>串行情况下获取的结果数量为1 */ protected List<ExecutionEntity> getActivieExecutions() { List<ExecutionEntity> activeExecutions = new ArrayList<ExecutionEntity>(); ActivityImpl activity = getActivity(); List<ExecutionEntity> executions = getChildExecutionByProcessInstanceId(); for (ExecutionEntity execution : executions) { if (execution.isActive() && (execution.getActivityId().equals(activityId) || activity .contains(execution.getActivity()))) { activeExecutions.add(execution); } } return activeExecutions; } /** * <li>获取流程实例根的所有子执行 */ protected List<ExecutionEntity> getChildExecutionByProcessInstanceId() { return commandContext.getExecutionEntityManager() .findChildExecutionsByProcessInstanceId(processInstanceId); } /** * <li>返回当前节点对象 */ protected ActivityImpl getActivity() { return this.getProcessDefinition().findActivity(activityId); } /** * <li>判断节点多实例类型是否是并发 */ protected boolean isParallel() { return getActivity().getProperty("multiInstance").equals("parallel"); } /** * <li>返回流程定义对象 */ protected ProcessDefinitionImpl getProcessDefinition() { return this.getProcessInstanceEntity().getProcessDefinition(); } /** * <li>返回流程实例的根执行对象 */ protected ExecutionEntity getProcessInstanceEntity() { return commandContext.getExecutionEntityManager().findExecutionById( processInstanceId); } /** * <li>添加本地变量 */ protected void setLoopVariable(ActivityExecution execution, String variableName, Object value) { execution.setVariableLocal(variableName, value); } }