package com.thinkgem.jeesite.modules.act.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.bpmn.helper.ClassDelegate;
import org.activiti.engine.impl.javax.el.ExpressionFactory;
import org.activiti.engine.impl.javax.el.ValueExpression;
import org.activiti.engine.impl.juel.ExpressionFactoryImpl;
import org.activiti.engine.impl.juel.SimpleContext;
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.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.modules.act.entity.Condition;
import com.thinkgem.jeesite.modules.act.utils.ActUtils;
/**
* ActComponent2
* @author yuguo
*
*/
@Component
public class ActComponent2 {
/**
* 日志对象
*/
protected Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private RepositoryService repositoryService;
@Autowired
private TaskService taskService;
public Task getCurrentTask(String taskId) {
return taskService.createTaskQuery().taskId(taskId).singleResult();
}
/**
* 获取ProcessDefinitionEntity
* @param procDefId
* @return
*/
public ProcessDefinitionEntity getProcDefEntByprocDefId (String procDefId) {
return (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
.getDeployedProcessDefinition(procDefId);
}
/**
*
*
获取ProcessDefinitionEntity
* @param definitionId
* @return
*/
public ProcessDefinitionEntity getProcDefEntBy (String definitionId) {
return (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
.getDeployedProcessDefinition(definitionId);
}
/**
*
获取流程上的所有节点 包括 task gateway start end
* @param processDefinitionEntity
* @return
*/
public List getAllActivityImpl(ProcessDefinitionEntity processDefinitionEntity){
return processDefinitionEntity.getActivities();
}
/**
* 根据Id获取指定Activity
* @param activityList
* @param activityId
* @return
*/
public ActivityImpl findActivityImpl (List activityList, String activityId) {
for (ActivityImpl ac : activityList) {
if (activityId.equals(ac.getId())) {
return ac;
}
}
return null;
}
/**
* 获取目标最近的flow_line
* @param activityImpl
* @return
*/
public List getNearFlow (ActivityImpl activityImpl) {
//因为下面使用了递归,这里使用引用当作参数传递
List pvmTransitionList = new ArrayList();
//递归查找临近节点
recursionPvmTransition(pvmTransitionList, activityImpl);
//返回查找到的所有节点
return pvmTransitionList;
}
/**
* 递归获取到目标task最近的flow_line
* @param pvmTransitionList
* @param activityImpl
*/
public void recursionPvmTransition (List pvmTransitionList, ActivityImpl activityImpl) {
List tmpPvmTransition = activityImpl.getOutgoingTransitions();
for (PvmTransition tr : tmpPvmTransition) {
PvmActivity ac = tr.getDestination();
//flow_line 连接的目标类型
String desType = (String)ac.getProperty("type");
//判断类型是不是用户审批节点
if ("userTask".equals(desType)) {
//如果是用户审批节点 添加节点
pvmTransitionList.add(tr);
}else {
//如果不是的话 继续递归
recursionPvmTransition(pvmTransitionList, (ActivityImpl) ac);
}
}
return ;
}
/**
* 根据表达式获取目标ActivityImpl
* @param pvmTransitionList
* @param flagValue
* @return
*/
public ActivityImpl getActivityImplByCondition (List pvmTransitionList, String flagValue) {
//String condition = (String)tr1.getProperty("conditionText");
if (pvmTransitionList.size()>1) {
for (PvmTransition tmpPvm : pvmTransitionList) {
//获取表达式
String condition = (String)tmpPvm.getProperty("conditionText");
//判断表达式是不是成立
boolean judge = isCondition("flag", condition, flagValue);
if (judge) {
return (ActivityImpl)tmpPvm.getDestination();
}
}
}else {
return (ActivityImpl)pvmTransitionList.get(0).getDestination();
}
return null;
}
/**
* 根据key和value判断el表达式是否通过信息
* @param String key el表达式key信息 如 $(flag==0) 这里的flag就是key
* @param String el el表达式
* @param String value el表达式传入值信息
* @return
*/
public boolean isCondition(String key, String el, String value) {
ExpressionFactory factory = new ExpressionFactoryImpl();
SimpleContext context = new SimpleContext();
context.setVariable(key, factory.createValueExpression(value, String.class));
ValueExpression e = factory.createValueExpression(context, el, boolean.class);
return (Boolean) e.getValue(context);
}
/**
* 判断是不是多实例
* @param procDefId
* @param taskId task定义Id 开始节点Id请设置为start
* @param flagValue 前台传递过来的值用于判断分支走向 如果没有多分支设置为null即可
* @return
*/
public Boolean isMultiInstance (String procDefId, String activityId, String flagValue) {
ProcessDefinitionEntity procEntity = this.getProcDefEntByprocDefId(procDefId);
ActivityImpl ac = this.findActivityImpl(this.getAllActivityImpl(procEntity), activityId);
List nearFlowLine = this.getNearFlow(ac);
ActivityImpl targetAc = this.getActivityImplByCondition(nearFlowLine, flagValue);
Object mutil = targetAc.getProperty("multiInstance");
if (mutil != null) {
return true;
}
return false;
}
/**
* 获取单实例task定义信息
* @param ac
* @return
*/
public TaskDefinition getTaskDefinition (PvmActivity ac) {
return ((UserTaskActivityBehavior) ((ActivityImpl) ac).getActivityBehavior()).getTaskDefinition();
}
/**
* 封装ConditionList 用于前台选择分支
* @param procDefId
* @param activityId
* @return
*/
public List getConditions (String procDefId, String activityId){
List conditions = new ArrayList();
ProcessDefinitionEntity procEntity = this.getProcDefEntByprocDefId(procDefId);
ActivityImpl ac = this.findActivityImpl(this.getAllActivityImpl(procEntity), activityId);
List nearFlowLine = this.getNearFlow(ac);
for (PvmTransition tmpPvm : nearFlowLine) {
String condition = (String)tmpPvm.getProperty("conditionText");
ActivityImpl targetAc = (ActivityImpl)tmpPvm.getDestination();
Object multi = targetAc.getProperty("multiInstance");
String name = (String)tmpPvm.getProperty("name");
Boolean isAssignee = false;
if (multi != null) {
Map> executionListeners = ((ActivityImpl) targetAc).getExecutionListeners();
isAssignee = isSetAssignee(executionListeners);
}else {
TaskDefinition taskDefinition = this.getTaskDefinition((ActivityImpl)targetAc);
isAssignee = this.isSetAssignee(taskDefinition);
}
conditions.add(this.setCondition(condition, name, isAssignee));
}
return conditions;
}
/**
*
* @param condition 条件表达式
* @param name flow_line的名称
* @param isSetAssignee 有没有设置办理人
* @return
*/
public Condition setCondition (String condition, String name, Boolean isSetAssignee){
Pattern p = null;
Integer valueNumber = null;
if (condition.indexOf("\"")>=0 || condition.indexOf("'")>=0) {
p = Pattern.compile(ActUtils.conditionRegex);
valueNumber = 5;
}else {
p = Pattern.compile(ActUtils.conditionRegexNumber);
valueNumber = 4;
}
Matcher m = p.matcher(condition);
if (m.find() && m.groupCount()==ActUtils.groupCount) {
Condition conditionEntity = new Condition();
conditionEntity.setKey(m.group(2));
conditionEntity.setOperation(m.group(3));
conditionEntity.setValue(m.group(valueNumber));
conditionEntity.setName(name);
conditionEntity.setIsSetAssignee(isSetAssignee);
return conditionEntity;
}else {
throw new RuntimeException(this.getClass().getName()+".matcherCondition :条件表达式错误");
}
}
/**
* 多实例情况下判断有没有设置办理人 注意这里使用的是执行监听 不要设置成task监听
* @param executionListeners 多实例的监听
* @return
*/
public Boolean isSetAssignee (Map> executionListeners) {
Set>> entrySet = executionListeners.entrySet();
for (Entry> tmpEntry : entrySet) {
List executionListenerList = tmpEntry.getValue();
for (ExecutionListener tmpExecution : executionListenerList) {
if (tmpExecution instanceof ClassDelegate) {
try {
Class tmpClass = Class.forName(((ClassDelegate)tmpExecution).getClassName());
Class supClass = tmpClass.getSuperclass();
if ("com.thinkgem.jeesite.activity.taskListener.abs.SetMultiplayerAbs".equals(supClass.getName())) {
return true;
}
} catch (ClassNotFoundException e) {
logger.error(getClass().getName()+":isuMutilInstanceSetAssignee ClassNotFoundException");
}
}
}
}
return false;
}
/**
* 单实例的情况下判断是不是需要前台选择人员
* @param taskDefinition
* @return
*/
public Boolean isSetAssignee (TaskDefinition taskDefinition) {
Expression expression = taskDefinition.getAssigneeExpression();
String assigee = null;
if (expression != null) {
assigee = expression.getExpressionText();
}
//候选人
Integer cduId = taskDefinition.getCandidateUserIdExpressions().size();
//候选组
Integer cdgId = taskDefinition.getCandidateGroupIdExpressions().size();
//如果匹配不上要不要写日志提示一下呢 考虑一下觉得这个流程图配置不正确属实没办法
if (StringUtils.isNotEmpty(assigee)) {
if (!Pattern.matches(ActUtils.matchesAssigneeConditiob, assigee) || cduId>0 || cdgId>0) {
return true;
}
}
return false;
}
}
这个工具类提供了获取之后的临近节点
根据activiti条件表达式获取节点
判断是不是多人会签