-
Notifications
You must be signed in to change notification settings - Fork 9
/
ExpressionEvaluater.go
96 lines (90 loc) · 2.79 KB
/
ExpressionEvaluater.go
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
package helper
import (
"fmt"
"github.com/Knetic/govaluate"
"strconv"
)
type ConditionObject struct {
ConditionType ConditionType `json:"conditionType"` //TRIGGER, SKIP, PASS, FAIL
ConditionOnVariable string `json:"conditionOnVariable"` //name of variable
ConditionalOperator string `json:"conditionalOperator"`
ConditionalValue string `json:"conditionalValue"`
typecastConditionalValue interface{}
}
func ShouldTriggerStage(conditions []*ConditionObject, variables []*VariableObject) (bool, error) {
conditionType := conditions[0].ConditionType //assuming list has min 1
status := true
for _, condition := range conditions {
result, err := evaluateExpression(condition, variables)
if err != nil {
return false, err
}
status = status && result
}
if conditionType == TRIGGER {
return status, nil // trigger if all success
} else {
return !status, nil //skip if all ture
}
}
func StageIsSuccess(conditions []*ConditionObject, variables []*VariableObject) (bool, error) {
conditionType := conditions[0].ConditionType //assuming list has min 1
status := true
for _, condition := range conditions {
result, err := evaluateExpression(condition, variables)
if err != nil {
return false, err
}
status = status && result
}
if conditionType == PASS {
return status, nil // success if all success
} else {
return !status, nil //fail if all success
}
}
func evaluateExpression(condition *ConditionObject, variables []*VariableObject) (status bool, err error) {
variableMap := make(map[string]*VariableObject)
for _, variable := range variables {
variableMap[variable.Name] = variable
}
variableOperand := variableMap[condition.ConditionOnVariable]
if variableOperand.TypedValue == nil {
converted, err := TypeConverter(variableOperand.Value, variableOperand.Format)
if err != nil {
return false, err
}
variableOperand.TypedValue = converted
}
refOperand, err := TypeConverter(condition.ConditionalValue, variableOperand.Format)
if err != nil {
return false, err
}
expression, err := govaluate.NewEvaluableExpression(fmt.Sprintf("variableOperand %s refOperand", condition.ConditionalOperator))
if err != nil {
return false, err
}
parameters := make(map[string]interface{}, 8)
parameters["variableOperand"] = variableOperand.TypedValue
parameters["refOperand"] = refOperand
result, err := expression.Evaluate(parameters)
if err != nil {
return false, err
}
status = result.(bool)
return status, nil
}
func TypeConverter(value string, format Format) (interface{}, error) {
switch format {
case STRING:
return value, nil
case NUMBER:
return strconv.ParseFloat(value, 8)
case BOOL:
return strconv.ParseBool(value)
case DATE:
return value, nil
default:
return nil, fmt.Errorf("unsupported datatype")
}
}