【flowable根据条件动态获取用户节点信息】

flowable根据流转条件顺序获取用户节点

前言

参考了flowable获取流程节点顺序,预测审批路径文章,加入了相容网关的内容,网关层级的用户节点列表,以及比较参数那一段的小问题。借鉴前人的轮子。

直接上代码

@Override
    public AjaxResult getUserTask(String procDefId, Map<String, Object> variables) {

        /**
         * 首先拿到BpmnModel,所有流程定义信息都可以通过BpmnModel获取;若流程尚未发起,则用modelId查询最新部署的流程定义数据;
         * 若流程已经发起,可以通过流程实例的processDefinitionId查询流程定义的历史数据。
         * @param variableMap 流程变量,用于计算条件分支
         */
        BpmnModel bpmnModel = repositoryService.getBpmnModel(procDefId);
//        Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();
        List<FlowElement> flowElements = new ArrayList<>(bpmnModel.getMainProcess().getFlowElements());
        List<FlowElement> passElements = new ArrayList<>();
        List<List<FlowElement>> passElementList = new ArrayList<>();
        Optional<FlowElement> startElementOpt = flowElements.stream().filter(flowElement -> flowElement instanceof StartEvent).findFirst();
        startElementOpt.ifPresent(startElement -> {
            flowElements.remove(startElement);
            List<SequenceFlow> outgoingFlows = ((StartEvent) startElement).getOutgoingFlows();
            String targetRef = outgoingFlows.get(0).getTargetRef();
            // 根据ID找到FlowElement
            FlowElement targetElementOfStartElement = getFlowElement(flowElements, targetRef);
            if (targetElementOfStartElement instanceof UserTask) {
                getPassElementList(passElementList,passElements, flowElements, targetElementOfStartElement, variables);
            }
        });
        ArrayList resultList = new ArrayList<String>();

        for (List<FlowElement> elementList:passElementList) {
            ArrayList lists = new ArrayList<String>();
            for (FlowElement passElement:elementList) {
                String taskName = passElement.getName();
                lists.add(taskName);
            }
            resultList.add(lists);
        }
        return AjaxResult.success("", resultList);
    }

    private FlowElement getFlowElement(Collection<FlowElement> flowElements, String targetRef) {
        return flowElements.stream().filter(flowElement -> targetRef.equals(flowElement.getId())).findFirst().orElse(null);
    }

    /**
     * 3. 我只用到了UserTask、ExclusiveGateway、ParallelGateway,所以代码里只列举了这三种,如果用到了其他的,可以再自己补充
     */
    private void getPassElementList(List<List<FlowElement>> passElementList,List<FlowElement> passElements, Collection<FlowElement> flowElements, FlowElement curFlowElement, Map<String, Object> variableMap){
        // 任务节点
        if (curFlowElement instanceof UserTask) {
            this.dueUserTaskElement(passElementList,passElements, flowElements, curFlowElement, variableMap);
            return;
        }
        // 排他网关
        if (curFlowElement instanceof ExclusiveGateway) {
            this.dueExclusiveGateway(passElementList,passElements, flowElements, curFlowElement, variableMap);
            return;
        }
        // 并行网关
        if(curFlowElement instanceof ParallelGateway){
            this.dueParallelGateway(passElementList,passElements, flowElements, curFlowElement, variableMap);
        }
        // 相容网关
        if(curFlowElement instanceof InclusiveGateway){

            this.dueInclusiveGateway(passElementList,passElements, flowElements, curFlowElement, variableMap);
        }

    }

    private void dueUserTaskElement(List<List<FlowElement>> passElementList,List<FlowElement> passElements, Collection<FlowElement> flowElements, FlowElement curFlowElement, Map<String, Object> variableMap){
        passElements.add(curFlowElement);
        List<SequenceFlow> outgoingFlows = ((UserTask) curFlowElement).getOutgoingFlows();
        String targetRef = outgoingFlows.get(0).getTargetRef();
        if (outgoingFlows.size() > 1) {
            // 找到表达式成立的sequenceFlow
            List<SequenceFlow> sequenceFlow = getSequenceFlow(variableMap, outgoingFlows);

            targetRef = sequenceFlow.get(0).getTargetRef();
        }
        // 根据ID找到FlowElement
        FlowElement targetElement = getFlowElement(flowElements, targetRef);
        this.getPassElementList(passElementList,passElements, flowElements, targetElement, variableMap);
    }

    private void dueExclusiveGateway(List<List<FlowElement>> passElementList,List<FlowElement> passElements, Collection<FlowElement> flowElements, FlowElement curFlowElement, Map<String, Object> variableMap){
        // 获取符合条件的sequenceFlow的目标FlowElement
        List<SequenceFlow> exclusiveGatewayOutgoingFlows = ((ExclusiveGateway) curFlowElement).getOutgoingFlows();
        flowElements.remove(curFlowElement);
        // 找到表达式成立的sequenceFlow
        List<SequenceFlow> sequenceFlow = getSequenceFlow(variableMap, exclusiveGatewayOutgoingFlows);
        // 根据ID找到FlowElement
        for (SequenceFlow seqFlow:sequenceFlow
        ) {
            FlowElement targetElement = getFlowElement(flowElements, seqFlow.getTargetRef());
            this.getPassElementList(passElementList,passElements, flowElements, targetElement, variableMap);
        }

    }

    private void dueParallelGateway(List<List<FlowElement>> passElementList,List<FlowElement> passElements, Collection<FlowElement> flowElements, FlowElement curFlowElement, Map<String, Object> variableMap){
        FlowElement targetElement;
        List<SequenceFlow> parallelGatewayOutgoingFlows = ((ParallelGateway) curFlowElement).getOutgoingFlows();
        for(SequenceFlow sequenceFlow : parallelGatewayOutgoingFlows){
            targetElement = getFlowElement(flowElements, sequenceFlow.getTargetRef());
            this.getPassElementList(passElementList,passElements, flowElements, targetElement, variableMap);
        }
    }

    private void dueInclusiveGateway(List<List<FlowElement>> passElementList,List<FlowElement> passElements, Collection<FlowElement> flowElements, FlowElement curFlowElement, Map<String, Object> variableMap){
        // 获取符合条件的sequenceFlow的目标FlowElement
        List<SequenceFlow> inclusiveGatewayOutgoingFlows = ((InclusiveGateway) curFlowElement).getOutgoingFlows();
        flowElements.remove(curFlowElement);
        // 找到表达式成立的sequenceFlow
        List<SequenceFlow> sequenceFlow = getSequenceFlow(variableMap, inclusiveGatewayOutgoingFlows);
        passElementList.add(passElements);
        passElements = new ArrayList<FlowElement>();
        // 根据ID找到FlowElement
        for (SequenceFlow seqFlow:sequenceFlow
             ) {
            FlowElement targetElement = getFlowElement(flowElements, seqFlow.getTargetRef());
            this.getPassElementList(passElementList,passElements, flowElements, targetElement, variableMap);
        }
    }


    /**
     * 4. 根据传入的变量,计算出表达式成立的那一条SequenceFlow
     * @param variableMap
     * @param outgoingFlows
     * @return
     */
    private List<SequenceFlow> getSequenceFlow(Map<String, Object> variableMap, List<SequenceFlow> outgoingFlows) {
        List<SequenceFlow> sequenceFlowOpt = outgoingFlows.stream().filter(item -> {
            try {
                return this.getElValue(item.getConditionExpression(), variableMap);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return false;
            }
        }).collect(Collectors.toList());;

        if(sequenceFlowOpt.size()==0){
            outgoingFlows.get(0);
        }
        return sequenceFlowOpt;
    }

    private boolean getElValue(String exp, Map<String, Object> variableMap){
        return managementService.executeCommand(new ExpressionCmd(runtimeService, processEngineConfiguration, null, exp, variableMap));
    }
import org.apache.commons.lang3.StringUtils;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.common.engine.impl.el.VariableContainerWrapper;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;

import java.io.Serializable;
import java.util.Map;

public class ExpressionCmd implements Command<Boolean>, Serializable {
    protected RuntimeService runtimeService;

    protected ProcessEngineConfigurationImpl processEngineConfiguration;

    protected String processInstanceId;

    protected String exp;

    protected Map<String, Object> variableMap;

    public ExpressionCmd(RuntimeService runtimeService, ProcessEngineConfigurationImpl processEngineConfiguration, String processInstanceId, String exp, Map<String, Object> variableMap) {
        this.runtimeService = runtimeService;
        this.processEngineConfiguration = processEngineConfiguration;
        this.processInstanceId = processInstanceId;
        this.exp = exp;
        this.variableMap = variableMap;
    }

    @Override
    public Boolean execute(CommandContext commandContext) {
        if(this.exp==null){
            return false;
        }
        Expression expression = processEngineConfiguration.getExpressionManager().createExpression(this.exp);
        Object value;
        if(StringUtils.isNotBlank(this.processInstanceId)){
            ExecutionEntity executionEntity = (ExecutionEntity) runtimeService.createProcessInstanceQuery().processInstanceId(this.processInstanceId).includeProcessVariables().singleResult();
            value = expression.getValue(executionEntity);
        }else {
            VariableContainerWrapper variableContainerWrapper = new VariableContainerWrapper(variableMap);
            value = expression.getValue(variableContainerWrapper);
        }
        return value != null && "true".equals(value.toString());
    }
}

备注

适配的参数结构variables
{“type”:“4”
}

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值