001/**
002 * Copyright (c) 2025-2026, Michael Yang 杨福海 (fuhai999@gmail.com).
003 * <p>
004 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * http://www.gnu.org/licenses/lgpl-3.0.txt
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package dev.tinyflow.core.node;
017
018
019import dev.tinyflow.core.chain.Chain;
020import dev.tinyflow.core.chain.ChainSuspendException;
021import dev.tinyflow.core.chain.Parameter;
022import dev.tinyflow.core.chain.RefType;
023import dev.tinyflow.core.chain.repository.ChainStateField;
024
025import java.util.*;
026
027public class ConfirmNode extends BaseNode {
028
029    private String message;
030    private List<Parameter> confirms;
031
032    public String getMessage() {
033        return message;
034    }
035
036    public void setMessage(String message) {
037        this.message = message;
038    }
039
040    public List<Parameter> getConfirms() {
041        return confirms;
042    }
043
044    public void setConfirms(List<Parameter> confirms) {
045        if (confirms != null) {
046            for (Parameter confirm : confirms) {
047                confirm.setRefType(RefType.INPUT);
048                confirm.setRequired(true); // 必填,才能正确通过 getParameterValuesOnly 获取参数值
049                confirm.setName(confirm.getName());
050            }
051        }
052        this.confirms = confirms;
053    }
054
055
056    @Override
057    public Map<String, Object> execute(Chain chain) {
058
059        List<Parameter> confirmParameters = new ArrayList<>();
060        addConfirmParameter(confirmParameters);
061
062        if (confirms != null) {
063            for (Parameter confirm : confirms) {
064                Parameter clone = confirm.clone();
065                clone.setName(confirm.getName() + "__" + getId());
066                clone.setRefType(RefType.INPUT);
067                confirmParameters.add(clone);
068            }
069        }
070
071        Map<String, Object> values;
072        try {
073            values = chain.getState().resolveParameters(this, confirmParameters);
074            // 移除 confirm 参数,方便在其他节点二次确认,或者在 for 循环中第二次获取
075            chain.updateStateSafely(state -> {
076                for (Parameter confirmParameter : confirmParameters) {
077                    state.getMemory().remove(confirmParameter.getName());
078                }
079                return EnumSet.of(ChainStateField.MEMORY);
080            });
081        } catch (ChainSuspendException e) {
082            chain.updateStateSafely(state -> {
083                state.setMessage(message);
084                return EnumSet.of(ChainStateField.MESSAGE);
085            });
086
087            if (confirms != null) {
088                List<Parameter> newParameters = new ArrayList<>();
089                for (Parameter confirm : confirms) {
090                    Parameter clone = confirm.clone();
091                    clone.setName(confirm.getName() + "__" + getId());
092                    clone.setRefType(RefType.REF); // 固定为 REF
093                    newParameters.add(clone);
094                }
095
096                // 获取参数值,不会触发 ChainSuspendException 错误
097                Map<String, Object> parameterValues = chain.getState().resolveParameters(this, newParameters, null, true);
098
099                // 设置 enums,方便前端给用户进行选择
100                for (Parameter confirmParameter : confirmParameters) {
101                    if (confirmParameter.getEnums() == null) {
102                        Object enumsObject = parameterValues.get(confirmParameter.getName());
103                        confirmParameter.setEnumsObject(enumsObject);
104                    }
105                }
106            }
107
108            throw e;
109        }
110
111
112        Map<String, Object> results = new HashMap<>(values.size());
113        values.forEach((key, value) -> {
114            int index = key.lastIndexOf("__");
115            if (index >= 0) {
116                results.put(key.substring(0, index), value);
117            } else {
118                results.put(key, value);
119            }
120        });
121
122        return results;
123    }
124
125
126    private void addConfirmParameter(List<Parameter> parameters) {
127        // “确认 和 取消” 的参数
128        Parameter parameter = new Parameter();
129        parameter.setRefType(RefType.INPUT);
130        parameter.setId("confirm");
131        parameter.setName("confirm__" + getId());
132        parameter.setRequired(true);
133
134        List<Object> selectionData = new ArrayList<>();
135        selectionData.add("yes");
136        selectionData.add("no");
137
138        parameter.setEnums(selectionData);
139        parameter.setContentType("text");
140        parameter.setFormType("confirm");
141        parameters.add(parameter);
142    }
143
144
145}