-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathnode.go
More file actions
113 lines (103 loc) · 2.83 KB
/
node.go
File metadata and controls
113 lines (103 loc) · 2.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package ddt
import (
"encoding/json"
"errors"
"github.com/sgrodriguez/ddt/compare"
"github.com/sgrodriguez/ddt/function"
"github.com/sgrodriguez/ddt/value"
)
// Comparer interface
type Comparer interface {
Compare(a, b interface{}) bool
}
// Node Type
type Node struct {
Children []*Node `json:"-"`
ID int `json:"id"`
ParentID int `json:"parentId"`
PreProcessFn function.PreProcessFn `json:"-"`
PreProcessArgs []*value.Value `json:"preProcessFnArgs,omitempty"`
Comparer Comparer `json:"comparer,omitempty"`
ValueToCompare *value.Value `json:"valueToCompare,omitempty"`
Result *value.Value `json:"result,omitempty"`
}
// NextNode ...
func (n *Node) NextNode(input interface{}) (interface{}, error) {
if len(n.Children) == 0 {
return n.Result.Value, nil
}
resValue, err := getValueToCompare(input, n.PreProcessFn, n.PreProcessArgs)
if err != nil {
return nil, err
}
for _, c := range n.Children {
if c.Comparer.Compare(resValue, c.ValueToCompare.Value) {
return c.NextNode(input)
}
}
return nil, errors.New("value not found when comparing with all children nodes")
}
func getValueToCompare(input interface{}, fn function.PreProcessFn, args []*value.Value) (interface{}, error) {
if !fn.Empty() {
resValue, err := fn.Function(input, value.GetValueInterfaces(args)...)
if err != nil {
return nil, err
}
return resValue, nil
}
// pre processing the input value not need it.
return input, nil
}
// MarshalJSON ...
func (n *Node) MarshalJSON() ([]byte, error) {
type NodeAlias Node
return json.Marshal(&struct {
PreProcessFn string `json:"preProcessFnName"`
*NodeAlias
}{
PreProcessFn: n.PreProcessFn.Name,
NodeAlias: (*NodeAlias)(n),
})
}
// UnmarshalJSON ...
func (n *Node) UnmarshalJSON(data []byte) error {
type NodeAlias Node
nodeAlias := &struct {
PreProcessFn string `json:"preProcessFnName"`
Comparer json.RawMessage `json:"comparer,omitempty"`
*NodeAlias
}{
NodeAlias: (*NodeAlias)(n),
}
if err := json.Unmarshal(data, nodeAlias); err != nil {
return err
}
n.PreProcessFn = function.PreProcessFn{Name: nodeAlias.PreProcessFn}
if nodeAlias.Comparer != nil {
comp, err := createComparatorFromJSON(nodeAlias.Comparer)
if err != nil {
return err
}
n.Comparer = comp
}
return nil
}
// CreateComparatorFromJSON ...
func createComparatorFromJSON(message json.RawMessage) (Comparer, error) {
aux := &struct {
Comp string `json:"type"`
Equal bool `json:"equal"`
}{}
if err := json.Unmarshal(message, aux); err != nil {
return nil, err
}
switch aux.Comp {
case "eq":
return &compare.Equal{}, nil
case "lt":
return &compare.Lesser{Equal: aux.Equal}, nil
case "gt":
return &compare.Greater{Equal: aux.Equal}, nil
}
return nil, errors.New("invalid comparer")
}