mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-03 22:45:13 +08:00
210 lines
4.7 KiB
Go
210 lines
4.7 KiB
Go
package blueprint
|
||
|
||
import (
|
||
"fmt"
|
||
)
|
||
|
||
type prePortNode struct {
|
||
node *execNode // 上个结点
|
||
outPortId int // 对应上一个结点的OutPortId
|
||
}
|
||
|
||
type execNode struct {
|
||
Id string
|
||
execNode IInnerExecNode
|
||
|
||
nextNode []*execNode
|
||
nextIdx int
|
||
|
||
preInPort []*prePortNode // Port的上一个结点
|
||
inPortDefaultValue map[string]any
|
||
|
||
variableName string // 如果是变量,则有变量名
|
||
beConnect bool // 是否有被连线
|
||
isEntrance bool // 是否是入口结点
|
||
}
|
||
|
||
// HasBeConnectLine 是否有被连线
|
||
func (en *execNode) HasBeConnectLine() bool {
|
||
return en.beConnect
|
||
}
|
||
|
||
// HasInPortExec 有前置执行入口
|
||
func (en *execNode) HasInPortExec() bool {
|
||
return en.execNode.IsInPortExec(0)
|
||
}
|
||
|
||
// HasOutPortExec 有前置执行入口
|
||
func (en *execNode) HasOutPortExec() bool {
|
||
return en.execNode.IsOutPortExec(0)
|
||
}
|
||
|
||
func (en *execNode) GetInPortDefaultValue(index int) any {
|
||
key := fmt.Sprintf("%d", index)
|
||
v, ok := en.inPortDefaultValue[key]
|
||
if !ok {
|
||
return nil
|
||
}
|
||
return v
|
||
}
|
||
|
||
func (en *execNode) GetInPortDefaultIntArrayValue(index int) []int64 {
|
||
val := en.GetInPortDefaultValue(index)
|
||
if val == nil {
|
||
return nil
|
||
}
|
||
|
||
var arrayInt []int64
|
||
arrayVal := val.([]any)
|
||
for i := range arrayVal {
|
||
if intVal, ok := arrayVal[i].(float64); ok {
|
||
arrayInt = append(arrayInt, int64(intVal))
|
||
}
|
||
}
|
||
return arrayInt
|
||
}
|
||
|
||
func (en *execNode) GetInPortDefaultStringArrayValue(index int) []string {
|
||
val := en.GetInPortDefaultValue(index)
|
||
if val == nil {
|
||
return nil
|
||
}
|
||
|
||
return val.([]string)
|
||
}
|
||
|
||
func (en *execNode) Next() *execNode {
|
||
if en.nextIdx >= len(en.nextNode) {
|
||
return nil
|
||
}
|
||
|
||
return en.nextNode[en.nextIdx]
|
||
}
|
||
|
||
func (en *execNode) exec(gr *Graph) (int, error) {
|
||
e, ok := en.execNode.(IExecNode)
|
||
if !ok {
|
||
return -1, fmt.Errorf("exec node %s not exec", en.execNode.GetName())
|
||
}
|
||
|
||
node, ok := en.execNode.(IBaseExecNode)
|
||
if !ok {
|
||
return -1, fmt.Errorf("exec node %s not exec", en.execNode.GetName())
|
||
}
|
||
|
||
// 执行完,要恢复上下文,结点的BaseExecNode会被执行时修改
|
||
ctx, exNode := node.getExecNodeInfo()
|
||
defer func() {
|
||
node.setExecNodeInfo(ctx, exNode)
|
||
}()
|
||
|
||
if err := node.initExecNode(gr, en); err != nil {
|
||
return -1, err
|
||
}
|
||
|
||
//defer func() {
|
||
inPort, outPort := node.GetPorts()
|
||
debugString := "inPort:"
|
||
for i := 0; i < len(inPort); i++ {
|
||
debugString += fmt.Sprintf("%+v,", inPort[i])
|
||
}
|
||
debugString += " outPort:"
|
||
for i := 0; i < len(outPort); i++ {
|
||
debugString += fmt.Sprintf("%+v,", outPort[i])
|
||
}
|
||
|
||
fmt.Printf("exec node %s,%s\n", en.execNode.GetName(), debugString)
|
||
//}()
|
||
|
||
return e.Exec()
|
||
}
|
||
|
||
func (en *execNode) doSetInPort(gr *Graph, index int, inPort IPort) error {
|
||
// 找到当前Node的InPort的index的前一个结点
|
||
preNode := en.preInPort[index]
|
||
// 如果前一个结点为空,则填充默认值
|
||
if preNode == nil {
|
||
err := inPort.setAnyVale(en.GetInPortDefaultValue(index))
|
||
if err != nil {
|
||
return err
|
||
}
|
||
return nil
|
||
}
|
||
|
||
if _, ok := gr.context[preNode.node.Id]; !ok ||
|
||
(!preNode.node.HasBeConnectLine() && !preNode.node.isEntrance) {
|
||
// 如果前一个结点没有执行过,则递归执行前一个结点
|
||
err := preNode.node.Do(gr)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
// 判断上一个结点是否已经执行过
|
||
if _, ok := gr.context[preNode.node.Id]; ok {
|
||
outPort := gr.GetNodeOutPortValue(preNode.node.Id, preNode.outPortId)
|
||
if outPort == nil {
|
||
return fmt.Errorf("pre node %s out port index %d not found", preNode.node.Id, preNode.outPortId)
|
||
}
|
||
|
||
inPort.SetValue(outPort)
|
||
return nil
|
||
}
|
||
|
||
return fmt.Errorf("pre node %s not exec", preNode.node.Id)
|
||
}
|
||
|
||
func (en *execNode) Do(gr *Graph, outPortArgs ...any) error {
|
||
// 重新初始化上下文
|
||
inPorts, outPorts := en.execNode.CloneInOutPort()
|
||
gr.context[en.Id] = &ExecContext{
|
||
InputPorts: inPorts,
|
||
OutputPorts: outPorts,
|
||
}
|
||
|
||
startOutIdx := en.execNode.GetOutPortParamStartIndex()
|
||
for i := 0; i < len(outPortArgs); i++ {
|
||
if i >= len(outPorts) {
|
||
return fmt.Errorf("args %d not found in node %s", i, en.execNode.GetName())
|
||
}
|
||
|
||
if err := outPorts[i+startOutIdx].setAnyVale(outPortArgs[i]); err != nil {
|
||
return fmt.Errorf("args %d set value error: %w", i, err)
|
||
}
|
||
}
|
||
|
||
// 处理InPort结点值
|
||
var err error
|
||
for portId := range inPorts {
|
||
if en.execNode.IsInPortExec(portId) {
|
||
continue
|
||
}
|
||
|
||
err = en.doSetInPort(gr, portId, inPorts[portId])
|
||
if err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
// 设置执行器相关的上下文信息
|
||
// 如果是变量设置变量名
|
||
// 执行本结点
|
||
nextIndex, err := en.exec(gr)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
if nextIndex == -1 || en.nextNode == nil {
|
||
return nil
|
||
}
|
||
|
||
if nextIndex < 0 || nextIndex >= len(en.nextNode) {
|
||
return fmt.Errorf("next index %d not found", nextIndex)
|
||
}
|
||
|
||
if en.nextNode[nextIndex] == nil {
|
||
return nil
|
||
}
|
||
return en.nextNode[nextIndex].Do(gr)
|
||
}
|