github.com/alkemics/goflow@v0.2.1/wrappers/outputs/wrappers.go (about)

     1  package outputs
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strings"
     7  
     8  	"github.com/alkemics/goflow"
     9  )
    10  
    11  func Wrapper(unmarshal func(interface{}) error, graph goflow.GraphRenderer) (goflow.GraphRenderer, error) {
    12  	var outputs struct {
    13  		Outputs map[string]bindings
    14  	}
    15  	if err := unmarshal(&outputs); err != nil {
    16  		return nil, err
    17  	}
    18  
    19  	outputBuilders := make([]goflow.NodeRenderer, 0)
    20  	outputFields := make([]goflow.Field, 0, len(outputs.Outputs))
    21  	for output, bs := range outputs.Outputs {
    22  		fields := make([]goflow.Field, len(bs))
    23  		for i, binding := range bs {
    24  			fields[i] = goflow.Field{
    25  				Name: binding,
    26  				Type: "@any",
    27  			}
    28  		}
    29  
    30  		outputBuilderName := fmt.Sprintf("__output_%s_builder", output)
    31  
    32  		outputFields = append(outputFields, goflow.Field{
    33  			Name: fmt.Sprintf("%s.%s", outputBuilderName, output),
    34  			Type: "@any",
    35  		})
    36  
    37  		outputType := fmt.Sprintf("@from[%s]", strings.Join(goflow.FieldNames(fields), ","))
    38  
    39  		outputBuilders = append(outputBuilders, outputNode{
    40  			id: fmt.Sprintf("__output_%s_builder", output),
    41  			output: goflow.Field{
    42  				Name: output,
    43  				Type: outputType,
    44  			},
    45  			inputs: fields,
    46  		})
    47  	}
    48  
    49  	return graphRenderer{
    50  		GraphRenderer: graph,
    51  
    52  		outputs:        outputFields,
    53  		outputBuilders: outputBuilders,
    54  	}, nil
    55  }
    56  
    57  func NameWrapper(_ func(interface{}) error, graph goflow.GraphRenderer) (goflow.GraphRenderer, error) {
    58  	outputs := graph.Outputs()
    59  	renamedOutputs := make([]goflow.Field, len(outputs))
    60  	for i, output := range outputs {
    61  		if matches := outputBuilderRegex.FindStringSubmatch(output.Name); len(matches) > 0 {
    62  			output.Name = matches[1]
    63  		}
    64  		renamedOutputs[i] = output
    65  	}
    66  
    67  	sort.SliceStable(renamedOutputs, func(i, j int) bool {
    68  		return strings.Compare(renamedOutputs[i].Name, renamedOutputs[j].Name) <= 0
    69  	})
    70  
    71  	// Check if at most one error field is returned.
    72  	errorFieldNames := make([]string, 0, len(outputs))
    73  	for _, o := range outputs {
    74  		if o.Type == "error" {
    75  			errorFieldNames = append(errorFieldNames, o.Name)
    76  		}
    77  	}
    78  	if len(errorFieldNames) > 1 {
    79  		return nil, TooManyErrorOutputsError{
    80  			Names: errorFieldNames,
    81  		}
    82  	}
    83  
    84  	return nameGraphWrapper{
    85  		GraphRenderer: graph,
    86  		outputs:       renamedOutputs,
    87  	}, nil
    88  }