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  }