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.chain;
017
018import dev.tinyflow.core.util.StringUtil;
019
020import java.io.Serializable;
021import java.util.ArrayList;
022import java.util.Collections;
023import java.util.List;
024import java.util.UUID;
025
026
027public class ChainDefinition implements Serializable {
028    protected String id;
029    protected String name;
030    protected String description;
031    protected List<Node> nodes;
032    protected List<Edge> edges;
033
034    public ChainDefinition() {
035    }
036
037    public String getId() {
038        return id;
039    }
040
041    public void setId(String id) {
042        this.id = id;
043    }
044
045    public String getName() {
046        return name;
047    }
048
049    public void setName(String name) {
050        this.name = name;
051    }
052
053    public String getDescription() {
054        return description;
055    }
056
057    public void setDescription(String description) {
058        this.description = description;
059    }
060
061    public List<Node> getNodes() {
062        return nodes;
063    }
064
065    public void setNodes(List<Node> nodes) {
066        this.nodes = nodes;
067    }
068
069    public List<Edge> getEdges() {
070        return edges;
071    }
072
073    public void setEdges(List<Edge> edges) {
074        this.edges = edges;
075    }
076
077    public List<Edge> getOutwardEdge(String nodeId) {
078        List<Edge> result = new ArrayList<>();
079        for (Edge edge : edges) {
080            if (nodeId.equals(edge.getSource())) {
081                result.add(edge);
082            }
083        }
084        return result;
085    }
086
087
088    public List<Edge> getInwardEdge(String nodeId) {
089        List<Edge> result = new ArrayList<>();
090        for (Edge edge : edges) {
091            if (nodeId.equals(edge.getTarget())) {
092                result.add(edge);
093            }
094        }
095        return result;
096    }
097
098    public void addNode(Node node) {
099        if (nodes == null) {
100            this.nodes = new ArrayList<>();
101        }
102
103        if (StringUtil.noText(node.getId())) {
104            node.setId(UUID.randomUUID().toString());
105        }
106
107        nodes.add(node);
108
109//        if (this.edges != null) {
110//            for (Edge edge : edges) {
111//                if (node.getId().equals(edge.getSource())) {
112//                    node.addOutwardEdge(edge);
113//                } else if (node.getId().equals(edge.getTarget())) {
114//                    node.addInwardEdge(edge);
115//                }
116//            }
117//        }
118    }
119
120
121    public Node getNodeById(String id) {
122        if (id == null || StringUtil.noText(id)) {
123            return null;
124        }
125
126        for (Node node : this.nodes) {
127            if (id.equals(node.getId())) {
128                return node;
129            }
130        }
131
132        return null;
133    }
134
135
136    public void addEdge(Edge edge) {
137        if (this.edges == null) {
138            this.edges = new ArrayList<>();
139        }
140        this.edges.add(edge);
141
142//        boolean findSource = false, findTarget = false;
143//        for (Node node : this.nodes) {
144//            if (node.getId().equals(edge.getSource())) {
145//                node.addOutwardEdge(edge);
146//                findSource = true;
147//            } else if (node.getId().equals(edge.getTarget())) {
148//                node.addInwardEdge(edge);
149//                findTarget = true;
150//            }
151//            if (findSource && findTarget) {
152//                break;
153//            }
154//        }
155    }
156
157
158    public Edge getEdgeById(String edgeId) {
159        for (Edge edge : this.edges) {
160            if (edgeId.equals(edge.getId())) {
161                return edge;
162            }
163        }
164        return null;
165    }
166
167    public List<Node> getStartNodes() {
168        if (nodes == null || nodes.isEmpty()) {
169            return null;
170        }
171
172        List<Node> result = new ArrayList<>();
173
174        for (Node node : nodes) {
175//            if (CollectionUtil.noItems(node.getInwardEdges())) {
176//                result.add(node);
177//            }
178            List<Edge> inwardEdge = getInwardEdge(node.getId());
179            if (inwardEdge == null || inwardEdge.isEmpty()) {
180                result.add(node);
181            }
182        }
183        return result;
184    }
185
186
187    public List<Parameter> getStartParameters() {
188        List<Node> startNodes = this.getStartNodes();
189        if (startNodes == null || startNodes.isEmpty()) {
190            return Collections.emptyList();
191        }
192
193        List<Parameter> parameters = new ArrayList<>();
194        for (Node node : startNodes) {
195            List<Parameter> nodeParameters = node.getParameters();
196            if (nodeParameters != null) parameters.addAll(nodeParameters);
197        }
198        return parameters;
199    }
200
201
202    @Override
203    public String toString() {
204        return "ChainDefinition{" +
205                "id='" + id + '\'' +
206                ", name='" + name + '\'' +
207                ", description='" + description + '\'' +
208                ", nodes=" + nodes +
209                ", edges=" + edges +
210                '}';
211    }
212}