|
|
|
@ -41,6 +41,7 @@ import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.flowable.bpmn.converter.BpmnXMLConverter; |
|
|
|
import org.flowable.bpmn.converter.BpmnXMLConverter; |
|
|
|
import org.flowable.bpmn.model.*; |
|
|
|
import org.flowable.bpmn.model.*; |
|
|
|
import org.flowable.bpmn.model.Process; |
|
|
|
import org.flowable.bpmn.model.Process; |
|
|
|
|
|
|
|
import org.flowable.common.engine.api.delegate.Expression; |
|
|
|
import org.flowable.common.engine.impl.de.odysseus.el.ExpressionFactoryImpl; |
|
|
|
import org.flowable.common.engine.impl.de.odysseus.el.ExpressionFactoryImpl; |
|
|
|
import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext; |
|
|
|
import org.flowable.common.engine.impl.de.odysseus.el.util.SimpleContext; |
|
|
|
import org.flowable.common.engine.impl.identity.Authentication; |
|
|
|
import org.flowable.common.engine.impl.identity.Authentication; |
|
|
|
@ -52,7 +53,10 @@ import org.flowable.engine.delegate.TaskListener; |
|
|
|
import org.flowable.engine.history.HistoricActivityInstance; |
|
|
|
import org.flowable.engine.history.HistoricActivityInstance; |
|
|
|
import org.flowable.engine.history.HistoricProcessInstance; |
|
|
|
import org.flowable.engine.history.HistoricProcessInstance; |
|
|
|
import org.flowable.engine.history.HistoricProcessInstanceQuery; |
|
|
|
import org.flowable.engine.history.HistoricProcessInstanceQuery; |
|
|
|
|
|
|
|
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; |
|
|
|
|
|
|
|
import org.flowable.engine.impl.persistence.entity.ExecutionEntity; |
|
|
|
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl; |
|
|
|
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl; |
|
|
|
|
|
|
|
import org.flowable.engine.impl.util.CommandContextUtil; |
|
|
|
import org.flowable.engine.repository.ProcessDefinition; |
|
|
|
import org.flowable.engine.repository.ProcessDefinition; |
|
|
|
import org.flowable.engine.runtime.ChangeActivityStateBuilder; |
|
|
|
import org.flowable.engine.runtime.ChangeActivityStateBuilder; |
|
|
|
import org.flowable.engine.runtime.Execution; |
|
|
|
import org.flowable.engine.runtime.Execution; |
|
|
|
@ -1526,14 +1530,78 @@ public class FlowApiServiceImpl implements FlowApiService { |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public List<String> getCandidateUsernames(FlowTaskExt flowTaskExt, String taskId) { |
|
|
|
public List<String> getCandidateUsernames(FlowTaskExt flowTaskExt, String taskId) { |
|
|
|
if (StrUtil.isBlank(flowTaskExt.getCandidateUsernames())) { |
|
|
|
String configured = flowTaskExt.getCandidateUsernames(); |
|
|
|
|
|
|
|
if (StrUtil.isBlank(configured)) { |
|
|
|
return Collections.emptyList(); |
|
|
|
return Collections.emptyList(); |
|
|
|
} |
|
|
|
} |
|
|
|
if (!StrUtil.equals(flowTaskExt.getCandidateUsernames(), "${" + FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR + "}")) { |
|
|
|
if (StrUtil.equals(configured, "${" + FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR + "}")) { |
|
|
|
return StrUtil.split(flowTaskExt.getCandidateUsernames(), ","); |
|
|
|
String value = getTaskVariableStringWithSafe(taskId, FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR); |
|
|
|
|
|
|
|
return value == null ? null : StrUtil.splitTrim(value, ","); |
|
|
|
} |
|
|
|
} |
|
|
|
Object candidateUsernames = getTaskVariableStringWithSafe(taskId, FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR); |
|
|
|
if (!configured.startsWith("${")) { |
|
|
|
return candidateUsernames == null ? null : StrUtil.split(candidateUsernames.toString(), ","); |
|
|
|
return StrUtil.splitTrim(configured, ","); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Task task = this.getTaskById(taskId); |
|
|
|
|
|
|
|
return task == null ? Collections.emptyList() : this.getCandidateUsernamesByExecution(flowTaskExt, task.getExecutionId()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public List<String> getCandidateUsernamesByExecution(FlowTaskExt flowTaskExt, String executionId) { |
|
|
|
|
|
|
|
String configured = flowTaskExt.getCandidateUsernames(); |
|
|
|
|
|
|
|
if (StrUtil.isBlank(configured)) { |
|
|
|
|
|
|
|
return Collections.emptyList(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (StrUtil.equals(configured, "${" + FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR + "}")) { |
|
|
|
|
|
|
|
String value = getExecutionVariableStringWithSafe(executionId, FlowConstant.TASK_APPOINTED_ASSIGNEE_VAR); |
|
|
|
|
|
|
|
return value == null ? null : StrUtil.splitTrim(value, ","); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!configured.startsWith("${")) { |
|
|
|
|
|
|
|
return StrUtil.splitTrim(configured, ","); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// 形如${projectBean.getCommonReportManager(execution)}的EL表达式,交给引擎的表达式管理器求值。
|
|
|
|
|
|
|
|
return this.parseCandidateUsernames(this.getExpressionValue(configured, executionId)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private List<String> parseCandidateUsernames(Object value) { |
|
|
|
|
|
|
|
if (value == null) { |
|
|
|
|
|
|
|
return Collections.emptyList(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (value instanceof Collection) { |
|
|
|
|
|
|
|
List<String> candidateUsernames = new LinkedList<>(); |
|
|
|
|
|
|
|
for (Object element : (Collection<?>) value) { |
|
|
|
|
|
|
|
if (element != null && StrUtil.isNotBlank(element.toString())) { |
|
|
|
|
|
|
|
candidateUsernames.add(element.toString()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return candidateUsernames; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (StrUtil.isBlank(value.toString())) { |
|
|
|
|
|
|
|
return Collections.emptyList(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return StrUtil.splitTrim(value.toString(), ","); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Object getExpressionValue(String expressionStr, String executionId) { |
|
|
|
|
|
|
|
ProcessEngineConfigurationImpl engineConfiguration = CommandContextUtil.getProcessEngineConfiguration(); |
|
|
|
|
|
|
|
if (engineConfiguration != null) { |
|
|
|
|
|
|
|
return this.evaluateExpression(engineConfiguration, expressionStr, executionId); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// 待办详情等HTTP接口场景没有活动的命令上下文,交由引擎开启一次后再求值,保证execution关键字可正常绑定。
|
|
|
|
|
|
|
|
return managementService.executeCommand(commandContext -> this.evaluateExpression( |
|
|
|
|
|
|
|
CommandContextUtil.getProcessEngineConfiguration(commandContext), expressionStr, executionId)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Object evaluateExpression( |
|
|
|
|
|
|
|
ProcessEngineConfigurationImpl engineConfiguration, String expressionStr, String executionId) { |
|
|
|
|
|
|
|
ExecutionEntity execution = CommandContextUtil.getExecutionEntityManager().findById(executionId); |
|
|
|
|
|
|
|
if (execution == null) { |
|
|
|
|
|
|
|
log.error("Failed to getExpressionValue expression [{}], executionId [{}], execution not found.", |
|
|
|
|
|
|
|
expressionStr, executionId); |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// 与引擎UserTaskActivityBehavior.handleAssignments的求值方式保持一致,execution关键字可正常绑定到当前执行流对象。
|
|
|
|
|
|
|
|
Expression expression = engineConfiguration.getExpressionManager().createExpression(expressionStr); |
|
|
|
|
|
|
|
return expression.getValue(execution); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
|