class FallbackNode extends Node {

    // 原节点 id
    private String expectedNodeId;

    // 降级节点
    private Node fallbackNode;

    public FallbackNode() {
        this.setType(NodeTypeEnum.FALLBACK);
    }

    public FallbackNode(String expectedNodeId) {
        this();
        this.expectedNodeId = expectedNodeId;
    }

    @Override
    public void execute(Integer slotIndex) throws Exception {
        Node node = FlowBus.getNode(this.expectedNodeId);
        if (node != null){
            this.fallbackNode = node;
        }else{
            loadFallBackNode(slotIndex);
        }
        this.fallbackNode.setCurrChainId(this.getCurrChainId());
        this.fallbackNode.execute(slotIndex);
    }

    private void loadFallBackNode(Integer slotIndex) throws Exception {<FILL_FUNCTION_BODY>}

    private Node findFallbackNode(Condition condition) {
        ConditionTypeEnum conditionType = condition.getConditionType();
        switch (conditionType) {
            case TYPE_THEN:
            case TYPE_WHEN:
            case TYPE_PRE:
            case TYPE_FINALLY:
            case TYPE_CATCH:
                return FlowBus.getFallBackNode(NodeTypeEnum.COMMON);
            case TYPE_IF:
                return findNodeInIf((IfCondition) condition);
            case TYPE_SWITCH:
                return findNodeInSwitch((SwitchCondition) condition);
            case TYPE_FOR:
                return findNodeInFor((ForCondition) condition);
            case TYPE_WHILE:
                return findNodeInWhile((WhileCondition) condition);
            case TYPE_ITERATOR:
                return findNodeInIterator((IteratorCondition) condition);
            case TYPE_NOT_OPT:
            case TYPE_AND_OR_OPT:
                //组件降级用在与并或中，只能用在IF表达式中
                return FlowBus.getFallBackNode(NodeTypeEnum.BOOLEAN);
            default:
                return null;
        }
    }

    private Node findNodeInIf(IfCondition ifCondition) {
        Executable ifItem = ifCondition.getIfItem();
        if (ifItem == this) {
            // 需要条件组件
            return FlowBus.getFallBackNode(NodeTypeEnum.BOOLEAN);
        }

        // 需要普通组件
        return FlowBus.getFallBackNode(NodeTypeEnum.COMMON);
    }

    private Node findNodeInSwitch(SwitchCondition switchCondition) {
        Node switchNode = switchCondition.getSwitchNode();
        if (switchNode == this) {
            return FlowBus.getFallBackNode(NodeTypeEnum.SWITCH);
        }

        return FlowBus.getFallBackNode(NodeTypeEnum.COMMON);
    }

    private Node findNodeInFor(ForCondition forCondition) {
        Node forNode = forCondition.getForNode();
        if (forNode == this) {
            return FlowBus.getFallBackNode(NodeTypeEnum.FOR);
        }

        return findNodeInLoop(forCondition);
    }

    private Node findNodeInWhile(WhileCondition whileCondition) {
        Executable whileItem = whileCondition.getWhileItem();
        if (whileItem == this) {
            return FlowBus.getFallBackNode(NodeTypeEnum.BOOLEAN);
        }

        return findNodeInLoop(whileCondition);
    }

    private Node findNodeInIterator(IteratorCondition iteratorCondition) {
        Node iteratorNode = iteratorCondition.getIteratorNode();
        if (iteratorNode == this) {
            return FlowBus.getFallBackNode(NodeTypeEnum.ITERATOR);
        }

        return findNodeInLoop(iteratorCondition);
    }

    private Node findNodeInLoop(LoopCondition loopCondition) {
        Executable breakItem = loopCondition.getExecutableOne(ConditionKey.BREAK_KEY);
        if (breakItem == this) {
            return FlowBus.getFallBackNode(NodeTypeEnum.BOOLEAN);
        }

        return FlowBus.getFallBackNode(NodeTypeEnum.COMMON);
    }

    @Override
    public <T> T getItemResultMetaValue(Integer slotIndex) {
        return this.fallbackNode.getItemResultMetaValue(slotIndex);
    }

    @Override
    public boolean isAccess(Integer slotIndex) throws Exception {
        // 可能会先访问这个方法，所以在这里就要加载降级节点
        loadFallBackNode(slotIndex);
        return this.fallbackNode.isAccess(slotIndex);
    }

    @Override
    public NodeComponent getInstance() {
        if (fallbackNode == null){
            return null;
        }
        return fallbackNode.getInstance();
    }

    @Override
    public String getId() {
        return this.fallbackNode == null ? null : this.fallbackNode.getId();
    }

    @Override
    public Node clone() {
        // 代理节点不复制
        return this;
    }

    @Override
    public NodeTypeEnum getType() {
        return NodeTypeEnum.FALLBACK;
    }

    public String getExpectedNodeId() {
        return expectedNodeId;
    }

    public void setExpectedNodeId(String expectedNodeId) {
        this.expectedNodeId = expectedNodeId;
    }
}

        if (ObjectUtil.isNotNull(this.fallbackNode)) {
            // 已经加载过了
            return;
        }
        Slot slot = DataBus.getSlot(slotIndex);
        Condition curCondition = slot.getCurrentCondition();
        if (ObjectUtil.isNull(curCondition)) {
            throw new FlowSystemException("The current executing condition could not be found.");
        }
        Node node = findFallbackNode(curCondition);
        if (ObjectUtil.isNull(node)) {
            throw new FallbackCmpNotFoundException(
                    StrFormatter.format("No fallback component found for [{}] in chain[{}].", this.expectedNodeId,
                            this.getCurrChainId()));
        }
        // 使用 node 的副本
        this.fallbackNode = node.clone();
    
<methods>public void <init>() ,public void <init>(com.yomahub.liteflow.core.NodeComponent) ,public com.yomahub.liteflow.flow.element.Node clone() throws java.lang.CloneNotSupportedException,public void execute(java.lang.Integer) throws java.lang.Exception,public boolean getAccessResult() ,public java.lang.String getClazz() ,public java.lang.String getCmpData() ,public java.lang.String getCurrChainId() ,public T getCurrLoopObject() ,public com.yomahub.liteflow.enums.ExecuteableTypeEnum getExecuteType() ,public java.lang.String getId() ,public com.yomahub.liteflow.core.NodeComponent getInstance() ,public boolean getIsContinueOnErrorResult() ,public java.lang.Boolean getIsEnd() ,public T getItemResultMetaValue(java.lang.Integer) ,public java.lang.String getLanguage() ,public java.lang.Integer getLoopIndex() ,public java.lang.String getName() ,public java.lang.String getScript() ,public java.lang.Integer getSlotIndex() ,public java.lang.String getTag() ,public com.yomahub.liteflow.enums.NodeTypeEnum getType() ,public boolean isAccess(java.lang.Integer) throws java.lang.Exception,public void removeAccessResult() ,public void removeCurrLoopObject() ,public void removeIsContinueOnErrorResult() ,public void removeIsEnd() ,public void removeLoopIndex() ,public void removeSlotIndex() ,public void rollback(java.lang.Integer) throws java.lang.Exception,public void setAccessResult(boolean) ,public void setClazz(java.lang.String) ,public void setCmpData(java.lang.String) ,public void setCurrChainId(java.lang.String) ,public void setCurrLoopObject(java.lang.Object) ,public void setId(java.lang.String) ,public void setInstance(com.yomahub.liteflow.core.NodeComponent) ,public void setIsContinueOnErrorResult(boolean) ,public void setIsEnd(java.lang.Boolean) ,public void setLanguage(java.lang.String) ,public void setLoopIndex(int) ,public void setName(java.lang.String) ,public void setScript(java.lang.String) ,public void setSlotIndex(java.lang.Integer) ,public void setTag(java.lang.String) ,public void setType(com.yomahub.liteflow.enums.NodeTypeEnum) <variables>private static final com.yomahub.liteflow.log.LFLog LOG,private TransmittableThreadLocal<java.lang.Boolean> accessResult,private java.lang.String clazz,private java.lang.String cmpData,private java.lang.String currChainId,private TransmittableThreadLocal<java.lang.Object> currLoopObject,private java.lang.String id,private com.yomahub.liteflow.core.NodeComponent instance,private TransmittableThreadLocal<java.lang.Boolean> isContinueOnErrorResult,private TransmittableThreadLocal<java.lang.Boolean> isEndTL,private java.lang.String language,private TransmittableThreadLocal<java.lang.Integer> loopIndexTL,private java.lang.String name,private java.lang.String script,private TransmittableThreadLocal<java.lang.Integer> slotIndexTL,private java.lang.String tag,private com.yomahub.liteflow.enums.NodeTypeEnum type