package workflow import ( "errors" ) type Step interface { Name() string } type Document struct { Workflow Workflow } type Workflow struct { Entry []Step Flows map[string][]Step } type fullStep struct { Name string If *string Do *string Then *string Else *string Options []OptionStep Collect []fullStep } type workflow struct { Entry []fullStep Flows map[string][]fullStep } func (wf *Workflow) UnmarshalYAML(unmarshal func(interface{}) error) error { w := workflow{} err := unmarshal(&w) if err != nil { return err } wf.Entry, err = decideSteps(w.Entry) if err != nil { return err } wf.Flows = make(map[string][]Step) for k, s := range w.Flows { wf.Flows[k], err = decideSteps(s) if err != nil { return err } } return nil } func decideSteps(s []fullStep) ([]Step, error) { arr := make([]Step, len(s)) var err error = nil for k, step := range s { arr[k], err = decideStep(step) if err != nil { return nil, err } } return arr, nil } func decideStep(s fullStep) (Step, error) { if s.Collect != nil { steps, err := decideSteps(s.Collect) if err != nil { return nil, err } return CollectStep{s.Name, steps}, nil } if s.If != nil { if s.Do != nil { return IfDoStep{s.Name, *s.If, *s.Do}, nil } if s.Then != nil || s.Else != nil { return IfJumpStep{s.Name, *s.If, s.Then, s.Else}, nil } return nil, errors.New("if step should either have `do`, `then`, or `else`") } if s.Options != nil { return OptionsStep{s.Name, s.Options}, nil } if s.Do != nil { return NormalStep{s.Name, *s.Do}, nil } return nil, errors.New("couldn't find any type of step that matched given map") }