github.com/alkemics/goflow@v0.2.1/yaml.go (about) 1 package goflow 2 3 import ( 4 "os" 5 6 "gopkg.in/yaml.v2" 7 ) 8 9 // Load will decode the yaml file at yamlFilename into a GraphRenderer, installing all 10 // the wrappers. 11 // 12 // Even if a wrapper returns an error, this function will go through all the wrappers. 13 func Load(yamlFilename string, wrappers []GraphWrapper) (GraphRenderer, error) { 14 file, err := os.Open(yamlFilename) 15 if err != nil { 16 return nil, Error{ 17 Filename: yamlFilename, 18 Err: err, 19 } 20 } 21 defer file.Close() 22 23 var g graphLoader 24 if err := yaml.NewDecoder(file).Decode(&g); err != nil { 25 return nil, ParseYAMLError(err) 26 } 27 28 if err := file.Close(); err != nil { 29 return nil, Error{ 30 Filename: yamlFilename, 31 Err: err, 32 } 33 } 34 35 graph, err := loadGraph(g, wrappers) 36 if err != nil { 37 return nil, Error{ 38 Filename: yamlFilename, 39 Err: err, 40 } 41 } 42 43 return graph, nil 44 } 45 46 func loadGraph(g graphLoader, wrappers []GraphWrapper) (GraphRenderer, error) { 47 var wrapped GraphRenderer = g 48 49 errs := make([]error, 0) 50 for _, w := range wrappers { 51 w, err := w(g.Unmarshal, wrapped) 52 if err != nil { 53 errs = append(errs, err) 54 } 55 if w != nil { 56 wrapped = w 57 } 58 } 59 60 if len(errs) > 0 { 61 return nil, MultiError{Errs: errs} 62 } 63 64 return wrapped, nil 65 } 66 67 type graphLoader struct { 68 NameVal string 69 PkgVal string 70 NodesVal []nodeLoader 71 Unmarshal func(interface{}) error 72 } 73 74 func (g graphLoader) Name() string { return g.NameVal } 75 func (g graphLoader) Pkg() string { return g.PkgVal } 76 func (g graphLoader) Imports() []Import { return nil } 77 func (g graphLoader) Doc() string { return "" } 78 func (g graphLoader) Dependencies() []Field { return nil } 79 func (g graphLoader) Inputs() []Field { return nil } 80 func (g graphLoader) Outputs() []Field { return nil } 81 func (g graphLoader) Nodes() []NodeRenderer { 82 nodes := make([]NodeRenderer, len(g.NodesVal)) 83 for i, n := range g.NodesVal { 84 nodes[i] = n 85 } 86 return nodes 87 } 88 89 func (g *graphLoader) UnmarshalYAML(unmarshal func(interface{}) error) error { 90 var gl struct { 91 Name string `yaml:"name"` 92 Pkg string `yaml:"package"` 93 Nodes []nodeLoader `yaml:"nodes"` 94 } 95 if err := unmarshal(&gl); err != nil { 96 return err 97 } 98 g.NameVal = gl.Name 99 g.PkgVal = gl.Pkg 100 if g.PkgVal == "" { 101 g.PkgVal = "graphs" 102 } 103 g.NodesVal = gl.Nodes 104 g.Unmarshal = func(v interface{}) error { 105 return ParseYAMLError(unmarshal(v)) 106 } 107 return nil 108 } 109 110 type nodeLoader struct { 111 IDVal string 112 Unmarshal func(interface{}) error 113 } 114 115 func (n nodeLoader) ID() string { return n.IDVal } 116 func (n nodeLoader) Doc() string { return "" } 117 func (n nodeLoader) Previous() []string { return nil } 118 func (n nodeLoader) Imports() []Import { return nil } 119 func (n nodeLoader) Dependencies() []Field { return nil } 120 func (n nodeLoader) Inputs() []Field { return nil } 121 func (n nodeLoader) Outputs() []Field { return nil } 122 func (n nodeLoader) Run(inputs, outputs []Field) (string, error) { return "", nil } 123 124 func (n nodeLoader) UnmarshalFunc() func(interface{}) error { 125 return n.Unmarshal 126 } 127 128 func (n *nodeLoader) UnmarshalYAML(unmarshal func(interface{}) error) error { 129 var nl struct { 130 ID string `yaml:"id"` 131 } 132 if err := unmarshal(&nl); err != nil { 133 return err 134 } 135 n.IDVal = nl.ID 136 n.Unmarshal = func(v interface{}) error { 137 return ParseYAMLError(unmarshal(v)) 138 } 139 return nil 140 }