package com.norteksoft.wf.engine.core;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.activity.ActivityExecution;
import org.jbpm.api.activity.ExternalActivityBehaviour;
import org.jbpm.internal.log.Log;
import org.springframework.transaction.annotation.Transactional;
import com.norteksoft.product.util.ContextUtils;
import com.norteksoft.task.base.enumeration.TaskState;
import com.norteksoft.task.entity.WorkflowTask;
import com.norteksoft.wf.base.enumeration.CommonStrings;
import com.norteksoft.wf.base.enumeration.TaskTransactorCondition;
import com.norteksoft.wf.engine.client.AfterSubProcessEnd;
import com.norteksoft.wf.engine.client.BeforeStartSubProcess;
import com.norteksoft.wf.engine.entity.InstanceHistory;
import com.norteksoft.wf.engine.entity.WorkflowInstance;
import com.norteksoft.wf.engine.service.InstanceHistoryManager;
import com.norteksoft.wf.engine.service.TaskService;
import com.norteksoft.wf.engine.service.WorkflowInstanceManager;
/**
* 该类处理子流程节点的相关业务
* 初始化变量
* 获得子流程环节开始前的事件处理类,如果该类不空并且方法isIntoSubProcess(Long id)返回了false,将不发起子流程,直接跳过子流程。否则,发起子流程。
* 如果需要发起子流程,先判断是否共用表单
* 如果共用表单,判断表单类型,根据不同表单流程进行启动流程
* 如果不公用表单,判断父子表单类型,然后赋值,启动子流程
* 在启动子流程时,还需要分析子流程环节的办理人设置
* 如果子流程环节设置的是多人办理,那么将给根据条件选出的每一个人发起一个子流程实例。
* 如果子流程环节设置的是单人办理,将只发起一个流程实例
* 如果子流程环节没有选择办理人,子流程实例的文档创建人将用父流程的文档创建人。
* @author wurong
*/
@Transactional
public class SubProcessService implements ExternalActivityBehaviour{
private static final long serialVersionUID = 1L;
private static final Log log = Log.getLog(SubProcessService.class.getName());
private SubProcessParse subprocessParse;
private WorkflowInstance parentWorkflow;
//-------
private static final String PROCESS_ENTER = "流程进入";
private static final String PROCESS_LEAVE = "流程离开";
//流转历史常量
private static final String COMMA = ", ";
private static final String DELTA_START = "[ ";
private static final String DELTA_END = " ]";
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private void init(ActivityExecution execution){
WorkflowInstanceManager workflowInstanceManager = (WorkflowInstanceManager)ContextUtils.getBean("workflowInstanceManager");
ProcessEngine processEngine = (ProcessEngine)ContextUtils.getBean("processEngine");
log.info("开始变量初始化...");
subprocessParse=new SubProcessParse();
subprocessParse.setParentInstanceId(execution.getProcessInstance().getId());
log.info("parentInstanceId:" + subprocessParse.getParentInstanceId());
parentWorkflow=workflowInstanceManager.getWorkflowInstance(subprocessParse.getParentInstanceId());
ActivityExecution activityExecution = (ActivityExecution)execution;
subprocessParse.setActivityName(activityExecution.getActivityName());
log.info("当前环节名字:" + subprocessParse.getActivityName());
subprocessParse.setCreator(execution.getVariable("creator").toString());
log.info("creator:"+subprocessParse.getCreator());
subprocessParse.setParentExecutionId(execution.getId());
log.info("parentExecutionId:" + subprocessParse.getParentExecutionId());
subprocessParse.setParentDefinitionId(parentWorkflow.getProcessDefinitionId());
subprocessParse.setSubDefinitionId(DefinitionXmlParse.getSubDefinitionId(parentWorkflow.getProcessDefinitionId(), subprocessParse.getActivityName()));
log.info("subDefinitionId");
Object priorityObject = processEngine.getExecutionService().getVariable(execution.getId(), CommonStrings.PRIORITY);
if(priorityObject != null){
subprocessParse.setPriority(Integer.valueOf(priorityObject.toString()));
}
subprocessParse.setExecutionId(execution.getId());
}
public void execute(ActivityExecution execution) throws Exception {
TaskService taskService = (TaskService) ContextUtils.getBean("taskService");
ProcessEngine processEngine = (ProcessEngine)ContextUtils.getBean("processEngine");
log.info("子流程开始执行...");
init(execution);
String beforeStartSubProcessName = DefinitionXmlParse.getBeforeStartSubProcess(subprocessParse.getParentDefinitionId(),subprocessParse.getActivityName());
log.info("实现类的beforeStartSubProcessName:"+beforeStartSubProcessName);
BeforeStartSubProcess beforeStartSubProcess = null;
if(StringUtils.isNotEmpty(beforeStartSubProcessName)){
beforeStartSubProcess = (BeforeStartSubProcess)ContextUtils.getBean(beforeStartSubProcessName);
log.debug("beforeStartSubProcess:"+beforeStartSubProcess);
}
if(beforeStartSubProcess==null || beforeStartSubProcess.isIntoSubProcess(parentWorkflow.getDataId())){
Object originalUser=processEngine.getExecutionService().getVariable(execution.getId(),CommonStrings.IS_ORIGINAL_USER);
Map<TaskTransactorCondition, String> transactor = DefinitionXmlParse.getTaskTransactor(subprocessParse.getParentDefinitionId(),this.subprocessParse.getActivityName());
String userCondition = transactor.get(TaskTransactorCondition.USER_CONDITION);
if("${previousTransactorAssignment}".equals(userCondition)){
if("true".equals(originalUser)){//是否使用原办理人
taskService.startSubProcessWorkflow(transactor,subprocessParse,null);
}else{
taskService.executionVariableCommand(new ExecutionVariableCommand(execution.getId(), CommonStrings.TRANSACTOR_ASSIGNMENT, "${previousTransactorAssignment}"));
taskService.executionVariableCommand(new ExecutionVariableCommand(execution.getId(), CommonStrings.SUBPROCESS_PARSE, subprocessParse));
}
}else{
taskService.startSubProcessWorkflow(transactor,subprocessParse,null);
}
execution.waitForSignal();
}
}
public void signal(ActivityExecution execution, String signalName, Map<String, ?> parameters) throws Exception {
TaskService taskService = (TaskService) ContextUtils.getBean("taskService");
init(execution);
log.info("父流程得到继续执行的信号。");
String subProcessEndName = DefinitionXmlParse.getSubProcessEnd(subprocessParse.getParentDefinitionId(),subprocessParse.getActivityName());
log.info("实现类的subProcessEndName:"+subProcessEndName);
if(StringUtils.isNotEmpty(subProcessEndName)){
AfterSubProcessEnd afterSubProcessEnd = (AfterSubProcessEnd)ContextUtils.getBean(subProcessEndName);
log.info("subProcessEnd:"+afterSubProcessEnd);
if(afterSubProcessEnd!=null) afterSubProcessEnd.execute(parentWorkflow.getDataId());
}
Long taskId = (Long)execution.getVariable(CommonStrings.SUBPROCESS_TASK_ID);
WorkflowTask task = taskService.getTask(taskId);
task.setActive(TaskState.COMPLETED.getIndex());
taskService.saveTask(task);
generateFlowHistory( execution, PROCESS_LEAVE);
execution.take(signalName);
execution.setVariable(CommonStrings.NEED_GENERATE_TASK, true);
execution.setVariable(CommonStrings.PARENT_INSTANCE_ID, subprocessParse.getParentInstanceId());
}
private void generateFlowHistory(ActivityExecution execution, String state){
InstanceHistoryManager instanceHistoryManager = (InstanceHistoryManager)ContextUtils.getBean("instanceHistoryManager");
InstanceHistory ih = new InstanceHistory();
ih.setCompanyId(parentWorkflow.getCompanyId());
if(PROCESS_ENTER.equals(state)){
ih.setType(InstanceHistory.TYPE_FLOW_INTO);
}else if(PROCESS_LEAVE.equals(state)){
ih.setType(InstanceHistory.TYPE_TASK);
}
ih.setInstanceId(subprocessParse.getParentInstanceId());
ih.setExecutionId(execution.getId());
ih.setCreatedTime(new Date());
ih.setTransactionResult(new StringBuilder(dateFormat.format(new Date()))
.append(COMMA).append(state).append(DELTA_START)
.append(subprocessParse.getActivityName()).append(DELTA_END).toString());
ih.setTaskName(subprocessParse.getActivityName());
instanceHistoryManager.saveHistory(ih);
}
}