package cn.fateverse.workflow.process;

import cn.fateverse.common.core.exception.CustomException;
import cn.fateverse.common.core.utils.ObjectUtils;
import cn.fateverse.workflow.constant.ProcessConstant;
import cn.fateverse.workflow.entity.ProcessListener;
import cn.fateverse.workflow.entity.bpmn.*;
import cn.fateverse.workflow.entity.bpmn.Properties;
import cn.fateverse.workflow.enums.FormPermEnum;
import cn.fateverse.workflow.enums.ModeEnums;
import cn.fateverse.workflow.enums.ProcessNodeEnum;
import cn.fateverse.workflow.entity.FormPerm;
import cn.fateverse.workflow.entity.dto.ProcessDto;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.delegate.ExecutionListener;
import org.flowable.engine.delegate.TaskListener;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static org.flowable.bpmn.model.ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION;

/**
 * json 转 bpmn对象工具类
 *
 * @author Clay
 * @date 2022/12/27
 */
public class BpmnParseUtil {

    /**
     * 流程dto
     */
    private final ProcessDto processDto;

    /**
     * 表单权限
     */
    private List<FormPerm> formPerms;

    /**
     * bpmn流程文件
     */
    private final Process process;

    /**
     * bpmn流程模型
     */
    private final BpmnModel bpmnModel;

    /**
     * 自定义流程监听器映射map
     */
    private final Map<String, ProcessListener> processListenerMap;

    /**
     * 父级id的流程节点映射
     */
    private Map<String, ProcessNode> parentMap = null;

    /**
     * 自己id的流程节点映射
     */
    private Map<String, ProcessNode> oneselfMap = null;

    public BpmnParseUtil(ProcessDto processDto, List<ProcessListener> processListeners) {
        process = new Process();
        bpmnModel = new BpmnModel();
        this.processDto = processDto;
        if (null == processListeners || processListeners.isEmpty()) {
            this.processListenerMap = new HashMap<>();
        } else {
            processListenerMap = processListeners.stream().collect(Collectors.toMap(ProcessListener::getId, Function.identity()));
        }
    }

    /**
     * 获取表单权限
     *
     * @return 表单权限信息
     */
    public List<FormPerm> getFormPerms() {
        return formPerms;
    }

    /**
     * 运行函数
     *
     * @return bpmn模型对象
     */
    public BpmnModel run() {
        formPerms = new ArrayList<>();
        //bpmn文件
        //流程对象
        //设置唯一的流程key
        process.setId(processDto.getProcessDefinitionKey());
        //设置流程名称
        process.setName(processDto.getDeploymentName());
        //设置备注名称
        process.setDocumentation(processDto.getRemark());

        ExtensionAttribute processData = new ExtensionAttribute();
        processData.setName(ProcessConstant.BPMN_FORM_PROCESS);
        processData.setNamespace("http://flowable.org/bpmn");
        processData.setValue(JSONObject.toJSONString(processDto.getProcess()));
        process.addAttribute(processData);

        ExtensionAttribute formItems = new ExtensionAttribute();
        formItems.setName(ProcessConstant.BPMN_FORM_ITEMS);
        formItems.setNamespace("http://flowable.org/bpmn");
        formItems.setValue(JSONObject.toJSONString(processDto.getFormItems()));
        process.addAttribute(formItems);
        //将流程对象加入到bpmn模型中
        bpmnModel.addProcess(process);
        //开始解析流程
        List<ProcessNode> processNodeList = processDto.getProcess();
        //将流程中的node根据他们的parentId进行分组,方便递归处理
        parentMap = processNodeList.stream().collect(Collectors.toMap(ProcessNode::getParentId, Function.identity()));
        oneselfMap = processNodeList.stream().collect(Collectors.toMap(ProcessNode::getId, Function.identity()));
        try {
            //开始解析json,创建bpmn模型对象
            crete("admin");
        } catch (Exception e) {
            e.printStackTrace();
            throw new CustomException(e.getMessage());
        }
        //流程结束监听器
        List<FlowableListener> executionListeners = new ArrayList<>();
        FlowableListener flowableListener = new FlowableListener();
        flowableListener.setEvent(ExecutionListener.EVENTNAME_END);
        flowableListener.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
        //使用spring 的 ioc bean管理获取到ProcessListener类,触发监听
        flowableListener.setImplementation("${processListener}");
        executionListeners.add(flowableListener);
        process.setExecutionListeners(executionListeners);
        return bpmnModel;
    }

    /**
     * 创建分支list
     *
     * @param branch 分支节点
     */
    private String creteBranch(ProcessNode branch) {
        ProcessNode node = parentMap.get(branch.getId());
        if (null == node) {
            throw new CustomException("解析失败,网关下没有节点,请检查流程图!");
        }
        String parentId = branch.getParentId();
        switch (node.getType()) {
            //审批人节点
            case APPROVAL:
                createUserTask(parentId, node);
                break;
            //触发器
            case TRIGGER:
                //抄送节点
            case CC:
                creteServiceTask(parentId, node);
                break;
            //延时等待节点
            case DELAY:
                createDelayService(parentId, node);
                break;
            //并行分支 和 多条件分支
            case CONCURRENTS:
            case CONDITION:
                createGatewayBuilder(parentId, node);
                break;
            default:
                break;
        }
        return crete(node.getId());
    }


    /**
     * 创建节点
     *
     * @param parentId 父id
     */
    private String crete(String parentId) {
        ProcessNode node = parentMap.get(parentId);
        if (null == node) {
            return parentId;
        }
        String processNodeId = node.getId();
        switch (node.getType()) {
            //root节点
            case ROOT:
                createStartEvent(node);
                break;
            //审批人节点
            case APPROVAL:
                createUserTask(parentId, node);
                break;
            //结束节点
            case END:
                createEndProcessNode(parentId, node);
                break;
            //触发器
            case TRIGGER:
                //抄送节点
            case CC:
                creteServiceTask(parentId, node);
                break;
            //延时等待节点
            case DELAY:
                createDelayService(parentId, node);
                break;
            //并行分支 和 多条件分支
            case CONCURRENTS:
            case CONDITIONS:
                createGatewayBuilder(parentId, node);
                ProcessNode nextNode = parentMap.get(node.getId());
                processNodeId = nextNode.getId();
                System.out.println("条件分支解析");
                break;
            default:
                throw new CustomException("节点类型错误!");
        }
        return crete(processNodeId);
    }

    /**
     * 创建网关节点
     *
     * @param parentId 父级id
     * @param node     节点对象信息
     */
    private void createGatewayBuilder(String parentId, ProcessNode node) {
        Gateway gateway = null;
        //获取到合并节点
        ProcessNode merge = parentMap.get(node.getId());
        if (node.getType() == ProcessNodeEnum.CONCURRENTS) {
            ParallelGateway parallelGateway = new ParallelGateway();
            parallelGateway.setId(node.getId());
            parallelGateway.setName(node.getName());
            process.addFlowElement(parallelGateway);
            //创建并行网关的结束网关节点
            gateway = createParallelGateWayEnd(merge.getId());
        } else if (node.getType() == ProcessNodeEnum.CONDITIONS) {
            ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
            exclusiveGateway.setId(node.getId());
            exclusiveGateway.setName(node.getName());
            process.addFlowElement(exclusiveGateway);
            //创建并行网关的结束网关节点
            gateway = createExclusiveGateWayEnd(merge.getId());
        }
        connect(parentId, node.getId());
        List<ProcessNode> branchs = node.getBranchs();
        if (Objects.isNull(branchs)) {
            throw new CustomException("解析失败,网关下没有节点,请检查流程图!");
        }
        //添加到process中
        process.addFlowElement(gateway);
        for (ProcessNode branch : branchs) {
            //创建分支节点
            String endId = creteBranch(branch);
            //连接节点信息
            connect(endId, merge.getId());
        }

    }

    /**
     * 创建条件网关的结束节点
     *
     * @param id 结束节点id
     * @return 条件网关对象
     */
    private ExclusiveGateway createExclusiveGateWayEnd(String id) {
        ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
        exclusiveGateway.setName(ProcessConstant.GATEWAY_END);
        exclusiveGateway.setId(id);
        return exclusiveGateway;
    }

    /**
     * 创建并行网关的结束节点
     *
     * @param id 结束节点id
     * @return 并行网关对象
     */
    private ParallelGateway createParallelGateWayEnd(String id) {
        ParallelGateway parallelGateway = new ParallelGateway();
        parallelGateway.setId(id);
        return parallelGateway;
    }

    /**
     * 创建结束节点
     *
     * @param parentId 父节点id
     * @param node     节点对象
     */
    private void createEndProcessNode(String parentId, ProcessNode node) {
        EndEvent endEvent = new EndEvent();
        endEvent.setId(node.getId());
        process.addFlowElement(endEvent);
        connect(parentId, node.getId());
    }

    /**
     * 连接节点
     *
     * @param sourceRef 源
     * @param targetRef 目标
     */
    private void connect(String sourceRef, String targetRef) {
        FlowElement flowElement = process.getFlowElement(sourceRef);
        SequenceFlow connect = connect(sourceRef, targetRef, flowElement);
        process.addFlowElement(connect);
    }

    /**
     * 连接节点
     *
     * @param sourceRef   源
     * @param targetRef   目标
     * @param flowElement 流对象
     * @return 线对象
     */
    private SequenceFlow connect(String sourceRef, String targetRef, FlowElement flowElement) {
        String flowId = getEdgeId();
        SequenceFlow flow = new SequenceFlow();
        if (flowElement instanceof ExclusiveGateway && !ProcessConstant.GATEWAY_END.equals(flowElement.getName())) {
            parseCondition(sourceRef, targetRef, flow);
        }
        flow.setId(flowId);
        flow.setSourceRef(sourceRef);
        flow.setTargetRef(targetRef);
        return flow;
    }

    /**
     * 解析条件表达式
     *
     * @param sourceRef 源
     * @param targetRef 目标
     * @param flow      连线
     */
    private void parseCondition(String sourceRef, String targetRef, SequenceFlow flow) {
        ProcessNode processNode = oneselfMap.get(targetRef);
        ProcessNode branch = oneselfMap.get(sourceRef).getBranchs().stream().filter(item -> item.getId().equals(processNode.getParentId())).findAny().get();
        if (branch.getType() != ProcessNodeEnum.CONDITION) {
            throw new CustomException("流程图有误,请检查流程图!");
        }
        //解析表达式
        Properties props = branch.getProps();
        //将表达式组取出
        List<GroupsInfo> groups = props.getGroups();
        if (ObjectUtils.isEmpty(groups)) {
            throw new CustomException(branch.getName() + "条件分支的条件组数据为空,请检查");
        }
        //构建条件表达式
        StringBuilder conditionsStrBu = new StringBuilder();
        conditionsStrBu.append("${ ");
        //遍历条件组
        List<String> conditionGroupsList = new ArrayList<>();
        for (GroupsInfo info : groups) {
            List<ConditionInfo> conditions = info.getConditions();
            if (ObjectUtils.isEmpty(conditions)) {
                throw new CustomException(branch.getName() + "条件分支,条件组中条件为空,请检查");
            }
            //遍历条件表达式
            List<String> conditionList = new ArrayList<>();
            for (ConditionInfo condition : conditions) {
                String conditionStr;
                switch (condition.getValueType()) {
                    //用户
                    case "User":
                        conditionStr = parseConditionUser(condition);
                        break;
                    //字符串
                    case "String":
                        conditionStr = parseConditionString(condition);
                        break;
                    //数值
                    case "Number":
                        conditionStr = parseConditionNumber(condition);
                        break;
                    //时间
                    case "Date":
                        //部门
                    case "Dept":
                    default:
                        throw new CustomException("其他占时还未实现!");
                }
                conditionList.add(conditionStr);
            }
            //组合条件
            String relation = "OR".equals(info.getGroupType()) ? " || " : " && ";
            conditionGroupsList.add("(" + StringUtils.join(conditionList, relation) + ")");
        }
        //组合条件组表达式
        String relationGroups = "OR".equals(props.getGroupsType()) ? " || " : " && ";
        conditionsStrBu.append(StringUtils.join(conditionGroupsList, relationGroups)).append(" } ");
        flow.setConditionExpression(conditionsStrBu.toString());
    }

    /**
     * 解析条件表达式中数据number类型
     *
     * @param condition 条件对象
     * @return 条件表达式
     */
    private String parseConditionNumber(ConditionInfo condition) {
        String id = condition.getId();
        String str;
        switch (condition.getCompare().trim()) {
            case "=":
            case ">":
            case "<":
            case ">=":
            case "<=":
                str = condition.getValue().get(0).toString();
                return " " + id + condition.getCompare() + str + " ";
            case "IN":
                return conditionValueToConditionStr(condition);
            case "B":
            case "AB":
            case "BA":
            case "ABA":
                List<String> valueList = valueObjectToString(condition.getValue());
                str = StringUtils.join(valueList, ",");
                return " " + ProcessConstant.PROCESS_UTIL_CLASS + condition.getCompare().trim().toUpperCase() + "( " + id + "," + str + ") ";
            default:
                throw new CustomException("条件类型错误!");
        }
    }

    /**
     * object 的 list 转String list
     *
     * @param list object list
     * @return String list
     */
    private List<String> valueObjectToString(List<Object> list) {
        return list.stream().map(Object::toString).collect(Collectors.toList());
    }

    /**
     * 将条件数据转为为String类型的
     *
     * @param condition 条件对象
     * @return 条件表达式
     */
    private String conditionValueToConditionStr(ConditionInfo condition) {
        List<String> valueList = valueObjectToString(condition.getValue());
        String str = StringUtils.join(valueList, ",");
        return " " + ProcessConstant.PROCESS_UTIL_CLASS + " strArrContainsMethod(" + condition.getId() + "," + str + ") ";
    }

    /**
     * 将条件对象转换为String
     *
     * @param condition 条件对象
     * @return 条件表达式
     */
    private String parseConditionString(ConditionInfo condition) {
        if ("=".equals(condition.getValueType().trim())) {
            String str = "'" + condition.getValue().get(0).toString() + "'";
            return " " + ProcessConstant.PROCESS_UTIL_CLASS + " strEqualsMethod(" + condition.getId() + "," + str + ") ";
        } else {
            return conditionValueToConditionStr(condition);
        }
    }

    /**
     * 将条件对象的用户信息转化为条件表达式
     *
     * @param condition 条件对象
     * @return 条件表达式
     */
    private String parseConditionUser(ConditionInfo condition) {
        List<Object> valueList = condition.getValue();
        List<String> userIds = new ArrayList<>(valueList.size());
        for (Object value : valueList) {
            JSONObject user = JSON.parseObject(JSON.toJSONString(value));
            userIds.add(user.getString("id"));
        }
        String str = StringUtils.join(userIds, ",");
        return " " + ProcessConstant.PROCESS_UTIL_CLASS + " strArrContainsMethod(" + condition.getId() + "," + str + ") ";
    }

    /**
     * 创建任务节点
     *
     * @param parentId 父节点id
     * @param node     节点对象
     */
    private void createUserTask(String parentId, ProcessNode node) {
        UserTask userTask = new UserTask();
        userTask.setName(node.getName());
        userTask.setId(node.getId());


        //定义任务监听器
        List<FlowableListener> taskListeners = new ArrayList<>();
        FlowableListener taskListener = new FlowableListener();
        // 事件类型,
        taskListener.setEvent(TaskListener.EVENTNAME_CREATE);
        // 监听器类型
        taskListener.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
        // 设置实现了，这里设置监听器的类型是delegateExpression，这样可以在实现类注入Spring bean.
        taskListener.setImplementation("${taskCreatedListener}");
        taskListeners.add(taskListener);
        userTask.setTaskListeners(taskListeners);
        //定义执行监听器
        FlowableListener flowableListener = new FlowableListener();
        // 事件类型,
        flowableListener.setEvent(ExecutionListener.EVENTNAME_START);
        // 监听器类型
        flowableListener.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
        // 设置实现了，这里设置监听器的类型是delegateExpression，这样可以在实现类注入Spring bean.,会签监听器
        flowableListener.setImplementation("${counterSignListener}");
        userTask.setExecutionListeners(Collections.singletonList(flowableListener));
        createUserTaskBoundaryEvent(node, userTask);
        MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics();
        // 审批人集合参数 assigneeList 为 集合，例如["kermit", "gonzo", "fozzie"]；
        multiInstanceLoopCharacteristics.setInputDataItem(userTask.getId() + ProcessConstant.ASSIGNEE_LIST);
        // 迭代集合 activiti:elementVariable="assignee" 为 接收 loop 中的值的变量名；
        multiInstanceLoopCharacteristics.setElementVariable("assigneeName");
        // 串行
        multiInstanceLoopCharacteristics.setSequential(false);
        //方便系统开发,直接设置为当前登录用户 activiti:assignee="${assignee}" 相当于将认领人指定为loop中取得的变量对象，就和java 中 foreach 差不多的意思；
        userTask.setAssignee("${assigneeName}");
        // 设置多实例属性
        Properties props = node.getProps();
        String mode = props.getMode();
        userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
        if (ModeEnums.AND.getTypeName().equals(mode)) {
            // nrOfInstances ：实例总数
            // nrOfActiveInstances：当前活动（即尚未完成）实例的数量。对于顺序多实例，这将始终为1。
            // nrOfCompletedInstances：已完成实例的数量。
            multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances==nrOfInstances}");
        } else if (ModeEnums.OR.getTypeName().equals(mode)) {
            multiInstanceLoopCharacteristics.setSequential(false);
            multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances > 0}");
        } else if (ModeEnums.NEXT.getTypeName().equals(mode)) {
            multiInstanceLoopCharacteristics.setSequential(true);
            multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances==nrOfInstances}");
        }
        setUserTaskProcessListener(props.getListener(), userTask);
        String fromKey = getId();
        userTask.setFormKey(fromKey);
        createFromPerms(node, fromKey);
        process.addFlowElement(userTask);
        connect(parentId, node.getId());
    }

    /**
     * 设置监听器
     *
     * @param info     监听器信息
     * @param userTask 用户任务节点
     */
    private void setUserTaskProcessListener(ListenerInfo info, UserTask userTask) {
        if (!info.getState()) {
            return;
        }
        List<FlowableListener> taskListeners = userTask.getTaskListeners();
        List<FlowableListener> executionListeners = userTask.getExecutionListeners();
        for (ListenerItem listenerItem : info.getList()) {
            if (listenerItem.getIsSys()) {
                ProcessListener processListener = processListenerMap.get(listenerItem.getListenerValue());
                if (null == processListener) {
                    continue;
                }
                List<String> eventList = JSON.parseArray(processListener.getEventType(), String.class);
                markFlowableListener(taskListeners, executionListeners, eventList, processListener.getListenerValueType(), processListener.getListenerType());
            } else {
                List<String> eventList = listenerItem.getEventType();
                markFlowableListener(taskListeners, executionListeners, eventList, listenerItem.getListenerValueType(), listenerItem.getListenerType());
            }
        }
        userTask.setTaskListeners(taskListeners);
        userTask.setExecutionListeners(executionListeners);
    }

    /**
     * 制作监听器
     *
     * @param taskListeners      用户监听器列表
     * @param executionListeners 执行器监听列表
     * @param eventList          事件列表
     * @param listenerValueType  监听器值类型
     * @param listenerType       监听器类型
     */
    private void markFlowableListener(List<FlowableListener> taskListeners, List<FlowableListener> executionListeners, List<String> eventList, String listenerValueType, String listenerType) {
        for (String event : eventList) {
            FlowableListener listener = new FlowableListener();
            listener.setEvent(event);
            listener.setImplementationType(getImplementationType(listenerValueType));
            if ("0".equals(listenerType)) {
                executionListeners.add(listener);
            } else {
                taskListeners.add(listener);
            }
        }
    }

    /**
     * 根据监听器值类型获取到对应的加载类型
     *
     * @param listenerValueType 值类型
     * @return 加载类型
     */
    private String getImplementationType(String listenerValueType) {
        switch (listenerValueType) {
            case "0":
                return "class";
            case "1":
                return "expression";
            case "2":
                return "delegateExpression";
            default:
                throw new CustomException("类型异常");
        }


    }

    /**
     * 创建延时处理的service服务
     *
     * @param parentId 父级id
     * @param node     节点信息
     */
    private void createDelayService(String parentId, ProcessNode node) {
        //创建定时任务
        IntermediateCatchEvent intermediateCatchEvent = new IntermediateCatchEvent();
        intermediateCatchEvent.setId(node.getId());
        intermediateCatchEvent.setName(node.getName());
        List<FlowableListener> flowableListenerList = new ArrayList<>();
        //添加定时任务触发的开始监听器
        FlowableListener catchEventListenerStart = new FlowableListener();
        catchEventListenerStart.setEvent(ExecutionListener.EVENTNAME_START);
        catchEventListenerStart.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
        catchEventListenerStart.setImplementation("${intermediateCatchEventListener}");
        flowableListenerList.add(catchEventListenerStart);
        //添加定时任务触发的结束监听器
        FlowableListener catchEventListenerEnd = new FlowableListener();
        catchEventListenerEnd.setEvent(ExecutionListener.EVENTNAME_END);
        catchEventListenerEnd.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
        catchEventListenerEnd.setImplementation("${intermediateCatchEventListener}");
        flowableListenerList.add(catchEventListenerEnd);
        intermediateCatchEvent.setExecutionListeners(flowableListenerList);

        TimerEventDefinition timerEventDefinition = new TimerEventDefinition();

        Properties props = node.getProps();
        switch (props.getType()) {
            case "FIXED":
                //指定时间触发
                timerEventDefinition.setTimeDuration("PT" + props.getTime() + props.getUnit());
                break;
            case "AUTO":
                //自动到当天的时间,如果已经过来当天的时间,则需要指定到下一天
                timerEventDefinition.setTimeDate("${" + node.getId() + "}");
                break;
            default:
                throw new CustomException("模式还未实现!");
        }
        ////设置好时间事件
        intermediateCatchEvent.setEventDefinitions(Collections.singletonList(timerEventDefinition));
        //将流程添加到process文件中
        process.addFlowElement(intermediateCatchEvent);
        //将节点连接起来
        connect(parentId, node.getId());
    }

    /**
     * 创建userTask的边界事件
     *
     * @param node     节点信息
     * @param userTask 用户任务
     */
    public void createUserTaskBoundaryEvent(ProcessNode node, UserTask userTask) {
        Properties props = node.getProps();
        JSONObject timeLimit = props.getTimeLimit();
        JSONObject timeout = timeLimit.getJSONObject("timeout");
        long value = timeout.getLongValue("value");
        if (value <= 0) {
            return;
        }
        //定义边界事件
        BoundaryEvent boundaryEvent = new BoundaryEvent();
        boundaryEvent.setId(userTask.getId().replace("node_", "boundary_"));
        boundaryEvent.setAttachedToRef(userTask);
        boundaryEvent.setAttachedToRefId(userTask.getId());

        //边界事件监听器
        List<FlowableListener> boundaryEventList = new ArrayList<>();
        //监听器
        FlowableListener boundaryEventListener = new FlowableListener();
        boundaryEventListener.setEvent(ExecutionListener.EVENTNAME_END);
        boundaryEventListener.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
        boundaryEventListener.setImplementation("${boundaryEvenListener}");
        boundaryEventList.add(boundaryEventListener);
        //边界事件结束,设置不关闭主流程
        boundaryEvent.setCancelActivity(false);
        //todo 方便测试,占时不做真的数据解析
        TimerEventDefinition eventDefinition = new TimerEventDefinition();
        //添加时间表达式
        eventDefinition.setTimeDuration("PT" + props.getTime() + props.getUnit());
        //eventDefinition.setTimeDuration("PT10S");
        JSONObject notify = timeLimit.getJSONObject("handler").getJSONObject("notify");
        if (!notify.getBoolean("once")) {
            String hour = notify.getString("hour");
            eventDefinition.setTimeCycle("R/PT" + hour + props.getUnit() + "/2100-01-01");
            //eventDefinition.setTimeCycle("R/PT10S/2100-01-01");
        }
        //时间表达式
        boundaryEvent.setEventDefinitions(Collections.singletonList(eventDefinition));
        boundaryEvent.setExecutionListeners(boundaryEventList);
        process.addFlowElement(boundaryEvent);
    }

    /**
     * 创建service Task (CC, TRIGGER)
     *
     * @param parentId 父级id
     * @param node     节点信息
     */
    private void creteServiceTask(String parentId, ProcessNode node) {
        ServiceTask serviceTask = new ServiceTask();
        serviceTask.setId(node.getId());
        serviceTask.setName(node.getName());
        serviceTask.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
        serviceTask.setImplementation("${serviceListener}");
        process.addFlowElement(serviceTask);
        connect(parentId, node.getId());
    }

    /**
     * 创建开始节点
     *
     * @param node 节点对象
     */
    public void createStartEvent(ProcessNode node) {
        StartEvent startEvent = new StartEvent();
        startEvent.setId(node.getId());
        startEvent.setInitiator("applyUserId");
        //定义任务监听器
        FlowableListener listener = new FlowableListener();
        // 事件类型,
        listener.setEvent(ExecutionListener.EVENTNAME_START);
        // 监听器类型
        listener.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
        // 设置实现了，这里设置监听器的类型是delegateExpression，这样可以在实现类注入Spring bean.
        listener.setImplementation("${createStartEventListener}");
        startEvent.setExecutionListeners(Collections.singletonList(listener));

        createFromPerms(node, ProcessConstant.ROOT_NODE);
        process.addFlowElement(startEvent);
    }

    /**
     * 创建表单权限
     *
     * @param node    节点对象
     * @param fromKey 表单对应的key
     */
    private void createFromPerms(ProcessNode node, String fromKey) {
        Properties props = node.getProps();
        List<FormOperates> formPerms = props.getFormPerms();
        if (null != formPerms && !formPerms.isEmpty()) {
            System.out.println(formPerms);
            for (FormOperates formPerm : formPerms) {
                createFromPerm(formPerm, fromKey);
            }
        }
    }

    /**
     * 创建表单权限对象并存储
     *
     * @param formOperates 表单对象
     * @param fromKey      表单对应的key
     */
    private void createFromPerm(FormOperates formOperates, String fromKey) {
        FormPerm formPerm = FormPerm.builder()
                .id(formOperates.getId())
                .fromKey(fromKey)
                .required(formOperates.getRequired())
                .build();
        switch (formOperates.getPerm()) {
            //可读
            case "R":
                formPerm.setPerm(FormPermEnum.READ);
                break;
            //可写
            case "E":
                formPerm.setPerm(FormPermEnum.EDIT);
                break;
            //影藏
            case "H":
                formPerm.setPerm(FormPermEnum.HIDE);
                break;
            default:
                break;
        }
        formPerms.add(formPerm);
    }

    /**
     * 获取连线的随机id
     *
     * @return 返回连线id
     */
    public String getEdgeId() {
        return "flow_" + getId();
    }

    /**
     * 获取uuid
     *
     * @return 返回uuid
     */
    public String getId() {
        return UUID.randomUUID().toString();
    }

}
