package com.mossle.bpm.cmd; import com.mossle.api.form.FormDTO; import org.activiti.engine.delegate.Expression; import org.activiti.engine.impl.bpmn.parser.BpmnParse; import org.activiti.engine.impl.context.Context; import org.activiti.engine.impl.form.DefaultFormHandler; import org.activiti.engine.impl.interceptor.Command; import org.activiti.engine.impl.interceptor.CommandContext; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; import org.activiti.engine.impl.pvm.PvmActivity; import org.activiti.engine.impl.pvm.PvmTransition; import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.impl.task.TaskDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 查找发起流程表单的逻辑. * * 如果startEvent有formKey,直接返回。 如果startEvent后续的第一个节点是userTask,并且userTask的负责人是流程发起人,也返回它的formKey。 */ public class FindStartFormCmd implements Command<FormDTO> { private static Logger logger = LoggerFactory .getLogger(FindStartFormCmd.class); private String processDefinitionId; public FindStartFormCmd(String processDefinitionId) { this.processDefinitionId = processDefinitionId; } public FormDTO execute(CommandContext commandContext) { ProcessDefinitionEntity processDefinitionEntity = Context .getProcessEngineConfiguration().getDeploymentManager() .findDeployedProcessDefinitionById(processDefinitionId); if (processDefinitionEntity == null) { throw new IllegalArgumentException( "cannot find processDefinition : " + processDefinitionId); } FormDTO formDto = new FormDTO(); formDto.setProcessDefinitionId(processDefinitionId); // startEvent存在formKey的情况 if (processDefinitionEntity.hasStartFormKey()) { formDto.setAutoCompleteFirstTask(false); DefaultFormHandler formHandler = (DefaultFormHandler) processDefinitionEntity .getStartFormHandler(); if (formHandler.getFormKey() == null) { // 这个逻辑很古怪,上面判断了hasStartFormKey应该就避免这里为null的情况 logger.info("weired start form key is null"); return formDto; } String formKey = formHandler.getFormKey().getExpressionText(); formDto.setCode(formKey); formDto.setActivityId(processDefinitionEntity.getInitial().getId()); return formDto; } formDto.setAutoCompleteFirstTask(true); ActivityImpl startActivity = processDefinitionEntity.getInitial(); if (startActivity.getOutgoingTransitions().size() != 1) { throw new IllegalStateException( "start activity outgoing transitions cannot more than 1, now is : " + startActivity.getOutgoingTransitions().size()); } PvmTransition pvmTransition = startActivity.getOutgoingTransitions() .get(0); PvmActivity targetActivity = pvmTransition.getDestination(); if (!"userTask".equals(targetActivity.getProperty("type"))) { logger.info("first activity is not userTask, just skip"); return formDto; } String taskDefinitionKey = targetActivity.getId(); logger.debug("activityId : {}", targetActivity.getId()); TaskDefinition taskDefinition = processDefinitionEntity .getTaskDefinitions().get(taskDefinitionKey); Expression expression = taskDefinition.getAssigneeExpression(); if (expression == null) { logger.info("assignee is null, just skip"); return formDto; } String expressionText = expression.getExpressionText(); logger.debug("{}", expressionText); logger.debug("{}", startActivity.getProperties()); logger.debug("{}", processDefinitionEntity.getProperties()); String initiatorVariableName = (String) processDefinitionEntity .getProperty(BpmnParse.PROPERTYNAME_INITIATOR_VARIABLE_NAME); if (!("${" + initiatorVariableName + "}").equals(expressionText)) { logger.info("the assignee of {} is not {}, just skip", taskDefinitionKey, "${" + initiatorVariableName + "}"); return formDto; } DefaultFormHandler formHandler = (DefaultFormHandler) taskDefinition .getTaskFormHandler(); if (formHandler.getFormKey() == null) { // 满足一切要求,但是xml里没配置formKey,再给一次机会,去上层搜索一遍数据库配置里是不是配置了这个userTask的formKey logger.info("cannot find formKey : {}, {}", processDefinitionId, taskDefinitionKey); formDto.setActivityId(taskDefinitionKey); return formDto; } String formKey = formHandler.getFormKey().getExpressionText(); formDto.setCode(formKey); formDto.setActivityId(taskDefinitionKey); return formDto; } }