From fa5167ce1626a4f922cc9e4b3496a6666812505d Mon Sep 17 00:00:00 2001 From: "balamg@yahoo.com" Date: Thu, 4 Oct 2018 00:52:24 +0530 Subject: [PATCH 1/9] expr based condition --- common/model/types.go | 4 +- rete/filternode.go | 10 +- rete/joinnode.go | 15 ++- ruleapi/condition.go | 15 ++- ruleapi/exprcondition.go | 63 +++++++++++++ ruleapi/rule.go | 186 ++++++++++++++++++++++++++++++++++++- ruleapi/tests/cn_1_test.go | 98 +++++++++++++++++++ 7 files changed, 381 insertions(+), 10 deletions(-) create mode 100644 ruleapi/exprcondition.go create mode 100644 ruleapi/tests/cn_1_test.go diff --git a/common/model/types.go b/common/model/types.go index 2258a93..ee2f0e9 100644 --- a/common/model/types.go +++ b/common/model/types.go @@ -26,16 +26,18 @@ type MutableRule interface { SetAction(actionFn ActionFunction) SetPriority(priority int) SetContext(ctx RuleContext) + AddExprCondition (conditionName string, cExpr string, ctx RuleContext) (error) } //Condition interface to maintain/get various condition properties type Condition interface { GetName() string - GetEvaluator() ConditionEvaluator + //GetEvaluator() ConditionEvaluator GetRule() Rule GetIdentifiers() []TupleType GetContext() RuleContext String() string + Evaluate(string, string, map[TupleType]Tuple, RuleContext) (bool, error) } // RuleSession to maintain rules and assert tuples against those rules diff --git a/rete/filternode.go b/rete/filternode.go index 0781935..251d32a 100644 --- a/rete/filternode.go +++ b/rete/filternode.go @@ -94,9 +94,13 @@ func (fn *filterNodeImpl) assertObjects(ctx context.Context, handles []reteHandl } tupleMap := convertToTupleMap(tuples) cv := fn.conditionVar - toPropagate := cv.GetEvaluator()(cv.GetName(), cv.GetRule().GetName(), tupleMap, cv.GetContext()) - if toPropagate { - fn.nodeLinkVar.propagateObjects(ctx, handles) + toPropagate, err := cv.Evaluate(cv.GetName(), cv.GetRule().GetName(), tupleMap, cv.GetContext()) + if err == nil { + if toPropagate { + fn.nodeLinkVar.propagateObjects(ctx, handles) + } + } else { + //todo } } } diff --git a/rete/joinnode.go b/rete/joinnode.go index 6f533e1..fe4d5e8 100644 --- a/rete/joinnode.go +++ b/rete/joinnode.go @@ -164,6 +164,8 @@ func (jn *joinNodeImpl) assertObjects(ctx context.Context, handles []reteHandle, func (jn *joinNodeImpl) assertFromRight(ctx context.Context, handles []reteHandle, joinedHandles []reteHandle) { + var err error + //TODO: other stuff. right now focus on tuple table jn.joinRightObjects(handles, joinedHandles) tupleTableRow := newJoinTableRow(handles) @@ -181,7 +183,10 @@ func (jn *joinNodeImpl) assertFromRight(ctx context.Context, handles []reteHandl } else { tupleMap := copyIntoTupleMap(joinedHandles) cv := jn.conditionVar - toPropagate = cv.GetEvaluator()(cv.GetName(), cv.GetRule().GetName(), tupleMap, cv.GetContext()) + toPropagate, err = cv.Evaluate(cv.GetName(), cv.GetRule().GetName(), tupleMap, cv.GetContext()) + if err != nil { + //todo + } } if toPropagate { jn.nodeLinkVar.propagateObjects(ctx, joinedHandles) @@ -212,6 +217,9 @@ func (jn *joinNodeImpl) joinRightObjects(rightHandles []reteHandle, joinedHandle } func (jn *joinNodeImpl) assertFromLeft(ctx context.Context, handles []reteHandle, joinedHandles []reteHandle) { + + var err error + jn.joinLeftObjects(handles, joinedHandles) //TODO: other stuff. right now focus on tuple table tupleTableRow := newJoinTableRow(handles) @@ -229,7 +237,10 @@ func (jn *joinNodeImpl) assertFromLeft(ctx context.Context, handles []reteHandle } else { tupleMap := copyIntoTupleMap(joinedHandles) cv := jn.conditionVar - toPropagate = cv.GetEvaluator()(cv.GetName(), cv.GetRule().GetName(), tupleMap, cv.GetContext()) + toPropagate, err = cv.Evaluate(cv.GetName(), cv.GetRule().GetName(), tupleMap, cv.GetContext()) + if err != nil { + //todo + } } if toPropagate { jn.nodeLinkVar.propagateObjects(ctx, joinedHandles) diff --git a/ruleapi/condition.go b/ruleapi/condition.go index 7ae71e3..33f9c8d 100644 --- a/ruleapi/condition.go +++ b/ruleapi/condition.go @@ -34,9 +34,9 @@ func (cnd *conditionImpl) GetContext() model.RuleContext { return cnd.ctx } -func (cnd *conditionImpl) GetEvaluator() model.ConditionEvaluator { - return cnd.cfn -} +//func (cnd *conditionImpl) GetEvaluator() model.ConditionEvaluator { +// return cnd.cfn +//} func (cnd *conditionImpl) String() string { return "[Condition: name:" + cnd.name + ", idrs: TODO]" @@ -52,3 +52,12 @@ func (cnd *conditionImpl) GetRule() model.Rule { func (cnd *conditionImpl) GetTupleTypeAlias() []model.TupleType { return cnd.identifiers } + +func (cnd *conditionImpl) Evaluate (condName string, ruleNm string, tuples map[model.TupleType]model.Tuple, ctx model.RuleContext) (bool, error) { + result := false + if cnd.cfn != nil { + result = cnd.cfn (condName, ruleNm, tuples, ctx) + } + + return result, nil +} diff --git a/ruleapi/exprcondition.go b/ruleapi/exprcondition.go new file mode 100644 index 0000000..8f0697e --- /dev/null +++ b/ruleapi/exprcondition.go @@ -0,0 +1,63 @@ +package ruleapi + +import ( + "github.com/project-flogo/rules/common/model" +) + + +type exprConditionImpl struct { + name string + rule model.Rule + identifiers []model.TupleType + cExpr string + ctx model.RuleContext +} + +func newExprCondition(name string, rule model.Rule, identifiers []model.TupleType, cExpr string, ctx model.RuleContext) model.Condition { + c := exprConditionImpl{} + c.initExprConditionImpl(name, rule, identifiers, cExpr, ctx) + return &c +} + +func (cnd *exprConditionImpl) initExprConditionImpl(name string, rule model.Rule, identifiers []model.TupleType, cExpr string, ctx model.RuleContext) { + cnd.name = name + cnd.rule = rule + cnd.identifiers = append(cnd.identifiers, identifiers...) + cnd.cExpr = cExpr + cnd.ctx = ctx +} + +func (cnd *exprConditionImpl) GetIdentifiers() []model.TupleType { + return cnd.identifiers +} +func (cnd *exprConditionImpl) GetContext() model.RuleContext { + return cnd.ctx +} + +func (cnd *exprConditionImpl) GetEvaluator() model.ConditionEvaluator { + return nil +} + +func (cnd *exprConditionImpl) String() string { + return "[Condition: name:" + cnd.name + ", idrs: TODO]" +} + +func (cnd *exprConditionImpl) GetName() string { + return cnd.name +} + +func (cnd *exprConditionImpl) GetRule() model.Rule { + return cnd.rule +} +func (cnd *exprConditionImpl) GetTupleTypeAlias() []model.TupleType { + return cnd.identifiers +} + +func (cnd *exprConditionImpl) Evaluate (condName string, ruleNm string, tuples map[model.TupleType]model.Tuple, ctx model.RuleContext) (bool, error) { + result := false + if cnd.cExpr != "" { + //todo + } + + return result, nil +} \ No newline at end of file diff --git a/ruleapi/rule.go b/ruleapi/rule.go index c4fc1af..a63b924 100644 --- a/ruleapi/rule.go +++ b/ruleapi/rule.go @@ -4,6 +4,9 @@ import ( "fmt" "strings" + "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression" + "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression/expr" + "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/funcexprtype" "github.com/project-flogo/rules/common/model" ) @@ -73,6 +76,23 @@ func (rule *ruleImpl) addCond(conditionName string, idrs []model.TupleType, cfn } } +func (rule *ruleImpl) addExprCond(conditionName string, idrs []model.TupleType, cExpr string, ctx model.RuleContext) { + condition := newExprCondition(conditionName, rule, idrs, cExpr, ctx) + rule.conditions = append(rule.conditions, condition) + + for _, cidr := range idrs { + if len(rule.identifiers) == 0 { + rule.identifiers = append(rule.identifiers, cidr) + } else { + for _, ridr := range rule.identifiers { + if cidr != ridr { + rule.identifiers = append(rule.identifiers, cidr) + break + } + } + } + } +} func (rule *ruleImpl) GetPriority() int { return rule.priority @@ -103,7 +123,7 @@ func (rule *ruleImpl) SetAction(actionFn model.ActionFunction) { rule.actionFn = actionFn } -func (rule *ruleImpl) AddCondition(conditionName string, idrs []string, cFn model.ConditionEvaluator, ctx model.RuleContext) (err error) { +func (rule *ruleImpl) AddCondition2(conditionName string, idrs []string, cFn model.ConditionEvaluator, ctx model.RuleContext) (err error) { typeDeps := []model.TupleType{} for _, idr := range idrs { aliasProp := strings.Split(string(idr), ".") @@ -138,6 +158,170 @@ func (rule *ruleImpl) AddCondition(conditionName string, idrs []string, cFn mode return err } +func (rule *ruleImpl) AddCondition(conditionName string, idrs []string, cFn model.ConditionEvaluator, ctx model.RuleContext) (err error) { + typeDeps, err := rule.addDeps(idrs) + if err != nil { + return err + } + rule.addCond(conditionName, typeDeps, cFn, ctx, true) + return err +} + +func (rule *ruleImpl) addDeps(idrs []string) ([]model.TupleType, error) { + typeDeps := []model.TupleType{} + for _, idr := range idrs { + aliasProp := strings.Split(string(idr), ".") + alias := model.TupleType(aliasProp[0]) + + if model.GetTupleDescriptor(model.TupleType(alias)) == nil { + return typeDeps, fmt.Errorf("Tuple type not found [%s]", string(alias)) + } + + exists, _ := model.Contains(typeDeps, alias) + if !exists { + typeDeps = append(typeDeps, alias) + } + if len(aliasProp) == 2 { //specifically 2, else do not consider + prop := aliasProp[1] + + td := model.GetTupleDescriptor(model.TupleType(alias)) + if prop != "none" && td.GetProperty(prop) == nil { //"none" is a special case + return typeDeps, fmt.Errorf("TupleType property not found [%s]", prop) + } + + propMap, found := rule.deps[alias] + if !found { + propMap = map[string]bool{} + rule.deps[alias] = propMap + } + propMap[prop] = true + } + } + + return typeDeps, nil +} + func (rule *ruleImpl) GetDeps() map[model.TupleType]map[string]bool { return rule.deps } + +func (rule *ruleImpl) AddExprCondition(conditionName string, cstr string, ctx model.RuleContext) error { + + e, err := expression.ParseExpression(cstr) + if err != nil { + return err + } + exprn := e.(*expr.Expression) + refs, err := getRefs(exprn) + if err != nil { + return err + } + + err = validateRefs(refs) + if err != nil { + return err + } + + typeDeps, err := rule.addDeps(refs) + if err != nil { + return err + } + rule.addExprCond(conditionName, typeDeps, cstr, ctx) + return err + +} + +//func parseRefs(refs map[string]bool) (map[string]map[string]bool, error) { +// +// aliasAndRefs := make(map[string]map[string]bool) +// +// for val, _ := range refs { +// +// vals := strings.Split(val, ".") +// +// td := model.GetTupleDescriptor(model.TupleType(vals[0])) +// if td == nil { +// return aliasAndRefs, fmt.Errorf("Invalid TupleType [%s]", vals[0]) +// } +// +// prop := td.GetProperty(vals[1]) +// if prop == nil { +// return aliasAndRefs, fmt.Errorf("Property [%s] not found in TupleType [%s]", vals[1], vals[0]) +// } +// +// propsMap, found := aliasAndRefs[vals[0]] +// if !found { +// propsMap = make(map[string]bool) +// aliasAndRefs[vals[0]] = propsMap +// } +// +// propsMap[vals[1]] = true +// +// } +// +// return aliasAndRefs, nil +//} + +func validateRefs(refs []string) (error) { + for _, ref := range refs { + vals := strings.Split(ref, ".") + td := model.GetTupleDescriptor(model.TupleType(vals[0])) + if td == nil { + return fmt.Errorf("Invalid TupleType [%s]", vals[0]) + } + prop := td.GetProperty(vals[1]) + if prop == nil { + return fmt.Errorf("Property [%s] not found in TupleType [%s]", vals[1], vals[0]) + } + } + return nil +} + +func getRefs(e *expr.Expression) ([]string, error) { + refs := make(map[string]bool) + keys := []string{} + + err := getRefRecursively(e, refs) + if err != nil { + return keys, err + } + + for key, _ := range refs { + keys = append (keys, key) + } + return keys, err +} + +func getRefRecursively(e *expr.Expression, refs map[string]bool) error { + + if e == nil { + return nil + } + err := getRefsInternal(e.Left, refs) + if err != nil { + return err + } + err = getRefsInternal(e.Right, refs) + if err != nil { + return err + } + return nil +} + +func getRefsInternal(e *expr.Expression, refs map[string]bool) error { + if e.Type == funcexprtype.EXPRESSION { + getRefRecursively(e, refs) + } else if e.Type == funcexprtype.REF || e.Type == funcexprtype.ARRAYREF { + value := e.Value.(string) + if strings.Index(value, "$") == 0 { + value = value[1:len(value)] + split := strings.Split(value, ".") + if split != nil && len(split) != 2 { + return fmt.Errorf("Invalid tokens [%s]", value) + } + + refs[value] = true + } + } + return nil +} diff --git a/ruleapi/tests/cn_1_test.go b/ruleapi/tests/cn_1_test.go new file mode 100644 index 0000000..0a631ca --- /dev/null +++ b/ruleapi/tests/cn_1_test.go @@ -0,0 +1,98 @@ +package tests + +import ( + "testing" + "github.com/TIBCOSoftware/flogo-lib/core/data" + "fmt" + "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression/expr" + "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/funcexprtype" + "strings" + "github.com/project-flogo/rules/ruleapi" +) + +func Test_1_Con(t *testing.T) { + + createRuleSession() + + //a1, _ := data.NewAttribute("name", data.TypeString, "n1") + //a2, _ := data.NewAttribute("age2", data.TypeInteger, 10) + //a3, _ := data.NewAttribute("age", data.TypeInteger, 10) + // + //attr := []*data.Attribute{a1, a2, a3} + // + //simpleScope := data.NewSimpleScope(attr, nil) + // + ////fmt.Printf("bc index %d\n", strings.Index("abc", "bc")) + // + //r := data.GetBasicResolver() + // + //e, err := expression.ParseExpression(`($.age == $.age2) && ($.age2 == 11)`) + //exprn := e.(*expr.Expression) + //getRefs(exprn) + //if err == nil { + // v, err2 := e.EvalWithScope(simpleScope, r) + // if err2 != nil { + // t.Error(err2) + // } else { + // t.Logf("Value: %t\n", v) + // } + //} else { + // t.Error(err) + //} + + r1 := ruleapi.NewRule("r1") + err := r1.AddExprCondition("c1", "($t1.p1 == $t2.p2) && ($t1.p3 > $t2.p2)", nil) + if err != nil { + t.Errorf("error: %s\n", err) + } + + +} + +func getRefs(e *expr.Expression) (map[string]bool, error) { + refs := make(map[string]bool) + err := getRefRecursively(e, refs) + return refs, err +} + +func getRefRecursively (e *expr.Expression, refs map[string]bool) (error) { + + if e == nil { + return nil + } + err := getRefsInternal(e.Left, refs) + if err != nil { + return err + } + err = getRefsInternal(e.Right, refs) + if err != nil { + return err + } + return nil +} + +func getRefsInternal(e *expr.Expression, refs map[string]bool) (error) { + if e.Type == funcexprtype.EXPRESSION { + getRefRecursively(e, refs) + } else if e.Type == funcexprtype.ARRAYREF { + value := e.Value.(string) + + split := strings.Split(value, ".") + if split != nil && len(split) != 2 { + return fmt.Errorf("Invalid tokens [%s]", value) + } + + refs[value] = true + } + return nil +} + +type RuleExpressionResolver struct { + +} + +func (r *RuleExpressionResolver) Resolve(toResolve string, scope data.Scope) (value interface{}, err error) { + fmt.Printf("Resolve: [%s]\n", toResolve) + return nil, nil +} + From c4a62bf778f249fda4ddb264f901c81d4616383c Mon Sep 17 00:00:00 2001 From: "balamg@yahoo.com" Date: Sat, 20 Oct 2018 19:35:34 +0530 Subject: [PATCH 2/9] expr based condition --- ruleapi/exprcondition.go | 23 ++++++++- ruleapi/tests/cn_1_test.go | 99 ++++++++++++++++++-------------------- 2 files changed, 69 insertions(+), 53 deletions(-) diff --git a/ruleapi/exprcondition.go b/ruleapi/exprcondition.go index 8f0697e..721579f 100644 --- a/ruleapi/exprcondition.go +++ b/ruleapi/exprcondition.go @@ -2,6 +2,9 @@ package ruleapi import ( "github.com/project-flogo/rules/common/model" + "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression" + "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression/expr" + "github.com/TIBCOSoftware/flogo-lib/core/data" ) @@ -56,8 +59,26 @@ func (cnd *exprConditionImpl) GetTupleTypeAlias() []model.TupleType { func (cnd *exprConditionImpl) Evaluate (condName string, ruleNm string, tuples map[model.TupleType]model.Tuple, ctx model.RuleContext) (bool, error) { result := false if cnd.cExpr != "" { - //todo + e, err := expression.ParseExpression(cnd.cExpr) + exprn := e.(*expr.Expression) + if err != nil { + return result, err + } + td := TuplePropertyResolver{} + res, err := exprn.EvalWithScope(nil, &td) + + result = res.(bool) } return result, nil +} + +type TuplePropertyResolver struct { + +} + +func (t *TuplePropertyResolver) Resolve(toResolve string, scope data.Scope) (value interface{}, err error) { + + + return nil, nil } \ No newline at end of file diff --git a/ruleapi/tests/cn_1_test.go b/ruleapi/tests/cn_1_test.go index 0a631ca..eb69a50 100644 --- a/ruleapi/tests/cn_1_test.go +++ b/ruleapi/tests/cn_1_test.go @@ -2,11 +2,6 @@ package tests import ( "testing" - "github.com/TIBCOSoftware/flogo-lib/core/data" - "fmt" - "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression/expr" - "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/funcexprtype" - "strings" "github.com/project-flogo/rules/ruleapi" ) @@ -48,51 +43,51 @@ func Test_1_Con(t *testing.T) { } - -func getRefs(e *expr.Expression) (map[string]bool, error) { - refs := make(map[string]bool) - err := getRefRecursively(e, refs) - return refs, err -} - -func getRefRecursively (e *expr.Expression, refs map[string]bool) (error) { - - if e == nil { - return nil - } - err := getRefsInternal(e.Left, refs) - if err != nil { - return err - } - err = getRefsInternal(e.Right, refs) - if err != nil { - return err - } - return nil -} - -func getRefsInternal(e *expr.Expression, refs map[string]bool) (error) { - if e.Type == funcexprtype.EXPRESSION { - getRefRecursively(e, refs) - } else if e.Type == funcexprtype.ARRAYREF { - value := e.Value.(string) - - split := strings.Split(value, ".") - if split != nil && len(split) != 2 { - return fmt.Errorf("Invalid tokens [%s]", value) - } - - refs[value] = true - } - return nil -} - -type RuleExpressionResolver struct { - -} - -func (r *RuleExpressionResolver) Resolve(toResolve string, scope data.Scope) (value interface{}, err error) { - fmt.Printf("Resolve: [%s]\n", toResolve) - return nil, nil -} +// +//func getRefs(e *expr.Expression) (map[string]bool, error) { +// refs := make(map[string]bool) +// err := getRefRecursively(e, refs) +// return refs, err +//} +// +//func getRefRecursively (e *expr.Expression, refs map[string]bool) (error) { +// +// if e == nil { +// return nil +// } +// err := getRefsInternal(e.Left, refs) +// if err != nil { +// return err +// } +// err = getRefsInternal(e.Right, refs) +// if err != nil { +// return err +// } +// return nil +//} + +//func getRefsInternal(e *expr.Expression, refs map[string]bool) (error) { +// if e.Type == funcexprtype.EXPRESSION { +// getRefRecursively(e, refs) +// } else if e.Type == funcexprtype.ARRAYREF { +// value := e.Value.(string) +// +// split := strings.Split(value, ".") +// if split != nil && len(split) != 2 { +// return fmt.Errorf("Invalid tokens [%s]", value) +// } +// +// refs[value] = true +// } +// return nil +//} + +//type RuleExpressionResolver struct { +// +//} +// +//func (r *RuleExpressionResolver) Resolve(toResolve string, scope data.Scope) (value interface{}, err error) { +// fmt.Printf("Resolve: [%s]\n", toResolve) +// return nil, nil +//} From be0d36d55c443d0379be4b5633046198f070c83d Mon Sep 17 00:00:00 2001 From: "balamg@yahoo.com" Date: Sun, 21 Oct 2018 17:25:46 +0530 Subject: [PATCH 3/9] expr based condition --- common/model/types.go | 1 - ruleapi/exprcondition.go | 68 ++++++++++++++++++++----- ruleapi/rule.go | 31 ------------ ruleapi/tests/cn_1_test.go | 93 ---------------------------------- ruleapi/tests/common.go | 3 ++ ruleapi/tests/expr_1_test.go | 44 ++++++++++++++++ ruleapi/tests/expr_2_test.go | 45 ++++++++++++++++ ruleapi/tests/expr_3_test.go | 44 ++++++++++++++++ ruleapi/tests/expr_4_test.go | 44 ++++++++++++++++ ruleapi/tests/rtctxn_1_test.go | 2 +- 10 files changed, 236 insertions(+), 139 deletions(-) delete mode 100644 ruleapi/tests/cn_1_test.go create mode 100644 ruleapi/tests/expr_1_test.go create mode 100644 ruleapi/tests/expr_2_test.go create mode 100644 ruleapi/tests/expr_3_test.go create mode 100644 ruleapi/tests/expr_4_test.go diff --git a/common/model/types.go b/common/model/types.go index ee2f0e9..ca04954 100644 --- a/common/model/types.go +++ b/common/model/types.go @@ -32,7 +32,6 @@ type MutableRule interface { //Condition interface to maintain/get various condition properties type Condition interface { GetName() string - //GetEvaluator() ConditionEvaluator GetRule() Rule GetIdentifiers() []TupleType GetContext() RuleContext diff --git a/ruleapi/exprcondition.go b/ruleapi/exprcondition.go index 721579f..7f92408 100644 --- a/ruleapi/exprcondition.go +++ b/ruleapi/exprcondition.go @@ -1,18 +1,19 @@ package ruleapi import ( - "github.com/project-flogo/rules/common/model" + "github.com/TIBCOSoftware/flogo-lib/core/data" "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression" "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression/expr" - "github.com/TIBCOSoftware/flogo-lib/core/data" + "github.com/project-flogo/rules/common/model" + "reflect" + "strings" ) - type exprConditionImpl struct { name string rule model.Rule identifiers []model.TupleType - cExpr string + cExpr string ctx model.RuleContext } @@ -56,7 +57,7 @@ func (cnd *exprConditionImpl) GetTupleTypeAlias() []model.TupleType { return cnd.identifiers } -func (cnd *exprConditionImpl) Evaluate (condName string, ruleNm string, tuples map[model.TupleType]model.Tuple, ctx model.RuleContext) (bool, error) { +func (cnd *exprConditionImpl) Evaluate(condName string, ruleNm string, tuples map[model.TupleType]model.Tuple, ctx model.RuleContext) (bool, error) { result := false if cnd.cExpr != "" { e, err := expression.ParseExpression(cnd.cExpr) @@ -64,21 +65,62 @@ func (cnd *exprConditionImpl) Evaluate (condName string, ruleNm string, tuples m if err != nil { return result, err } - td := TuplePropertyResolver{} - res, err := exprn.EvalWithScope(nil, &td) - - result = res.(bool) + td := tuplePropertyResolver{} + scope := tupleScope{tuples} + res, err := exprn.EvalWithData(tuples, &scope, &td) + if err != nil { + return false, err + } else if reflect.TypeOf(res).Kind() == reflect.Bool { + result = res.(bool) + } } return result, nil } -type TuplePropertyResolver struct { +////////////////////////////////////////////////////////// +type tupleScope struct { + tuples map[model.TupleType]model.Tuple +} +func (ts *tupleScope) GetAttr(name string) (attr *data.Attribute, exists bool) { + return nil, false } -func (t *TuplePropertyResolver) Resolve(toResolve string, scope data.Scope) (value interface{}, err error) { +// SetAttrValue sets the value of the specified attribute +func (ts *tupleScope) SetAttrValue(name string, value interface{}) error { + return nil +} +/////////////////////////////////////////////////////////// +type tuplePropertyResolver struct { +} - return nil, nil -} \ No newline at end of file +func (t *tuplePropertyResolver) Resolve(toResolve string, scope data.Scope) (value interface{}, err error) { + + toResolve = toResolve[1:] + aliasAndProp := strings.Split(toResolve, ".") + + ts := scope.(*tupleScope) + var v interface{} + if ts != nil { + tuple := ts.tuples[model.TupleType(aliasAndProp[0])].(model.Tuple) + if tuple != nil { + + p := tuple.GetTupleDescriptor().GetProperty(aliasAndProp[1]) + switch p.PropType { + case data.TypeString: + v, err = tuple.GetString(aliasAndProp[1]) + case data.TypeInteger: + v, err = tuple.GetInt(aliasAndProp[1]) + case data.TypeLong: + v, err = tuple.GetLong(aliasAndProp[1]) + case data.TypeDouble: + v, err = tuple.GetDouble(aliasAndProp[1]) + case data.TypeBoolean: + v, err = tuple.GetBool(aliasAndProp[1]) + } + } + } + return v, err +} diff --git a/ruleapi/rule.go b/ruleapi/rule.go index a63b924..1681246 100644 --- a/ruleapi/rule.go +++ b/ruleapi/rule.go @@ -231,37 +231,6 @@ func (rule *ruleImpl) AddExprCondition(conditionName string, cstr string, ctx mo } -//func parseRefs(refs map[string]bool) (map[string]map[string]bool, error) { -// -// aliasAndRefs := make(map[string]map[string]bool) -// -// for val, _ := range refs { -// -// vals := strings.Split(val, ".") -// -// td := model.GetTupleDescriptor(model.TupleType(vals[0])) -// if td == nil { -// return aliasAndRefs, fmt.Errorf("Invalid TupleType [%s]", vals[0]) -// } -// -// prop := td.GetProperty(vals[1]) -// if prop == nil { -// return aliasAndRefs, fmt.Errorf("Property [%s] not found in TupleType [%s]", vals[1], vals[0]) -// } -// -// propsMap, found := aliasAndRefs[vals[0]] -// if !found { -// propsMap = make(map[string]bool) -// aliasAndRefs[vals[0]] = propsMap -// } -// -// propsMap[vals[1]] = true -// -// } -// -// return aliasAndRefs, nil -//} - func validateRefs(refs []string) (error) { for _, ref := range refs { vals := strings.Split(ref, ".") diff --git a/ruleapi/tests/cn_1_test.go b/ruleapi/tests/cn_1_test.go deleted file mode 100644 index eb69a50..0000000 --- a/ruleapi/tests/cn_1_test.go +++ /dev/null @@ -1,93 +0,0 @@ -package tests - -import ( - "testing" - "github.com/project-flogo/rules/ruleapi" -) - -func Test_1_Con(t *testing.T) { - - createRuleSession() - - //a1, _ := data.NewAttribute("name", data.TypeString, "n1") - //a2, _ := data.NewAttribute("age2", data.TypeInteger, 10) - //a3, _ := data.NewAttribute("age", data.TypeInteger, 10) - // - //attr := []*data.Attribute{a1, a2, a3} - // - //simpleScope := data.NewSimpleScope(attr, nil) - // - ////fmt.Printf("bc index %d\n", strings.Index("abc", "bc")) - // - //r := data.GetBasicResolver() - // - //e, err := expression.ParseExpression(`($.age == $.age2) && ($.age2 == 11)`) - //exprn := e.(*expr.Expression) - //getRefs(exprn) - //if err == nil { - // v, err2 := e.EvalWithScope(simpleScope, r) - // if err2 != nil { - // t.Error(err2) - // } else { - // t.Logf("Value: %t\n", v) - // } - //} else { - // t.Error(err) - //} - - r1 := ruleapi.NewRule("r1") - err := r1.AddExprCondition("c1", "($t1.p1 == $t2.p2) && ($t1.p3 > $t2.p2)", nil) - if err != nil { - t.Errorf("error: %s\n", err) - } - - -} -// -//func getRefs(e *expr.Expression) (map[string]bool, error) { -// refs := make(map[string]bool) -// err := getRefRecursively(e, refs) -// return refs, err -//} -// -//func getRefRecursively (e *expr.Expression, refs map[string]bool) (error) { -// -// if e == nil { -// return nil -// } -// err := getRefsInternal(e.Left, refs) -// if err != nil { -// return err -// } -// err = getRefsInternal(e.Right, refs) -// if err != nil { -// return err -// } -// return nil -//} - -//func getRefsInternal(e *expr.Expression, refs map[string]bool) (error) { -// if e.Type == funcexprtype.EXPRESSION { -// getRefRecursively(e, refs) -// } else if e.Type == funcexprtype.ARRAYREF { -// value := e.Value.(string) -// -// split := strings.Split(value, ".") -// if split != nil && len(split) != 2 { -// return fmt.Errorf("Invalid tokens [%s]", value) -// } -// -// refs[value] = true -// } -// return nil -//} - -//type RuleExpressionResolver struct { -// -//} -// -//func (r *RuleExpressionResolver) Resolve(toResolve string, scope data.Scope) (value interface{}, err error) { -// fmt.Printf("Resolve: [%s]\n", toResolve) -// return nil, nil -//} - diff --git a/ruleapi/tests/common.go b/ruleapi/tests/common.go index b051379..4e4e8f5 100644 --- a/ruleapi/tests/common.go +++ b/ruleapi/tests/common.go @@ -33,6 +33,7 @@ func trueCondition(ruleName string, condName string, tuples map[model.TupleType] } func emptyAction(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { + } func printTuples(t *testing.T, oprn string, tupleMap map[string]map[string]model.Tuple) { @@ -58,3 +59,5 @@ type txnCtx struct { Testing *testing.T TxnCnt int } + +type TestKey struct{} \ No newline at end of file diff --git a/ruleapi/tests/expr_1_test.go b/ruleapi/tests/expr_1_test.go new file mode 100644 index 0000000..36a6656 --- /dev/null +++ b/ruleapi/tests/expr_1_test.go @@ -0,0 +1,44 @@ +package tests + +import ( + "testing" + "github.com/project-flogo/rules/ruleapi" + "github.com/project-flogo/rules/common/model" + "golang.org/x/net/context" +) + +//1 condition, 1 expression +func Test_1_Expr(t *testing.T) { + + rs, _ := createRuleSession() + r1 := ruleapi.NewRule("r1") + r1.AddExprCondition("c1", "$t1.p1 > $t2.p1", nil) + r1.SetAction(a1) + rs.AddRule(r1) + + rs.Start(nil) + + var ctx context.Context + + t1, _ := model.NewTupleWithKeyValues("t1", "t1") + t1.SetInt(nil,"p1", 2) + t1.SetDouble(nil,"p2", 1.3) + t1.SetString(nil,"p3", "t3") + + ctx = context.WithValue(context.TODO(), TestKey{}, t) + rs.Assert(ctx, t1) + + t2, _ := model.NewTupleWithKeyValues("t2", "t2") + t2.SetInt(nil,"p1", 1) + t2.SetDouble(nil,"p2", 1.1) + t2.SetString(nil,"p3", "t3") + + ctx = context.WithValue(context.TODO(), TestKey{}, t) + rs.Assert(ctx, t2) + rs.Unregister() +} + +func a1(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { + t := ctx.Value(TestKey{}).(*testing.T) + t.Logf("Test_1_Expr executed!") +} \ No newline at end of file diff --git a/ruleapi/tests/expr_2_test.go b/ruleapi/tests/expr_2_test.go new file mode 100644 index 0000000..1997dc8 --- /dev/null +++ b/ruleapi/tests/expr_2_test.go @@ -0,0 +1,45 @@ +package tests + +import ( + "testing" + "github.com/project-flogo/rules/ruleapi" + "github.com/project-flogo/rules/common/model" + "golang.org/x/net/context" +) + +//2 conditions, 1 expr each +func Test_2_Expr(t *testing.T) { + + rs, _ := createRuleSession() + r1 := ruleapi.NewRule("r1") + r1.AddExprCondition("c1", "$t1.p1 > $t2.p1", nil) + r1.AddExprCondition("c2", "$t1.p1 == 2", nil) + r1.SetAction(a2) + rs.AddRule(r1) + + rs.Start(nil) + + var ctx context.Context + + t1, _ := model.NewTupleWithKeyValues("t1", "t1") + t1.SetInt(nil,"p1", 2) + t1.SetDouble(nil,"p2", 1.3) + t1.SetString(nil,"p3", "t3") + + ctx = context.WithValue(context.TODO(), TestKey{}, t) + rs.Assert(ctx, t1) + + t2, _ := model.NewTupleWithKeyValues("t2", "t2") + t2.SetInt(nil,"p1", 1) + t2.SetDouble(nil,"p2", 1.1) + t2.SetString(nil,"p3", "t3") + + ctx = context.WithValue(context.TODO(), TestKey{}, t) + rs.Assert(ctx, t2) + rs.Unregister() +} + +func a2(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { + t := ctx.Value(TestKey{}).(*testing.T) + t.Logf("Test_2_Expr executed!") +} \ No newline at end of file diff --git a/ruleapi/tests/expr_3_test.go b/ruleapi/tests/expr_3_test.go new file mode 100644 index 0000000..3a97575 --- /dev/null +++ b/ruleapi/tests/expr_3_test.go @@ -0,0 +1,44 @@ +package tests + +import ( + "testing" + "github.com/project-flogo/rules/ruleapi" + "github.com/project-flogo/rules/common/model" + "golang.org/x/net/context" +) + +//1 conditions, 2 expr +func Test_3_Expr(t *testing.T) { + + rs, _ := createRuleSession() + r1 := ruleapi.NewRule("r1") + r1.AddExprCondition("c1", "($t1.p1 > $t2.p1) && ($t1.p2 > $t2.p2)", nil) + r1.SetAction(a3) + rs.AddRule(r1) + + rs.Start(nil) + + var ctx context.Context + + t1, _ := model.NewTupleWithKeyValues("t1", "t1") + t1.SetInt(nil,"p1", 2) + t1.SetDouble(nil,"p2", 1.3) + t1.SetString(nil,"p3", "t3") + + ctx = context.WithValue(context.TODO(), TestKey{}, t) + rs.Assert(ctx, t1) + + t2, _ := model.NewTupleWithKeyValues("t2", "t2") + t2.SetInt(nil,"p1", 1) + t2.SetDouble(nil,"p2", 1.1) + t2.SetString(nil,"p3", "t3") + + ctx = context.WithValue(context.TODO(), TestKey{}, t) + rs.Assert(ctx, t2) + rs.Unregister() +} + +func a3(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { + t := ctx.Value(TestKey{}).(*testing.T) + t.Logf("Test_3_Expr executed!") +} \ No newline at end of file diff --git a/ruleapi/tests/expr_4_test.go b/ruleapi/tests/expr_4_test.go new file mode 100644 index 0000000..547f62b --- /dev/null +++ b/ruleapi/tests/expr_4_test.go @@ -0,0 +1,44 @@ +package tests + +import ( + "testing" + "github.com/project-flogo/rules/ruleapi" + "github.com/project-flogo/rules/common/model" + "golang.org/x/net/context" +) + +//1 conditions, 3 expr +func Test_4_Expr(t *testing.T) { + + rs, _ := createRuleSession() + r1 := ruleapi.NewRule("r1") + r1.AddExprCondition("c1", "($t1.p1 > $t2.p1) && (($t1.p2 > $t2.p2) && ($t1.p3 == $t2.p3))", nil) + r1.SetAction(a4) + rs.AddRule(r1) + + rs.Start(nil) + + var ctx context.Context + + t1, _ := model.NewTupleWithKeyValues("t1", "t1") + t1.SetInt(nil,"p1", 2) + t1.SetDouble(nil,"p2", 1.3) + t1.SetString(nil,"p3", "t3") + + ctx = context.WithValue(context.TODO(), TestKey{}, t) + rs.Assert(ctx, t1) + + t2, _ := model.NewTupleWithKeyValues("t2", "t2") + t2.SetInt(nil,"p1", 1) + t2.SetDouble(nil,"p2", 1.1) + t2.SetString(nil,"p3", "t3") + + ctx = context.WithValue(context.TODO(), TestKey{}, t) + rs.Assert(ctx, t2) + rs.Unregister() +} + +func a4(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { + t := ctx.Value(TestKey{}).(*testing.T) + t.Logf("Test_4_Expr executed!") +} \ No newline at end of file diff --git a/ruleapi/tests/rtctxn_1_test.go b/ruleapi/tests/rtctxn_1_test.go index 28ac038..6333aaf 100644 --- a/ruleapi/tests/rtctxn_1_test.go +++ b/ruleapi/tests/rtctxn_1_test.go @@ -14,7 +14,7 @@ func Test_T1(t *testing.T) { rs, _ := createRuleSession() rule := ruleapi.NewRule("R1") - rule.AddCondition("R1_c1", []string{"t1.none"}, trueCondition, nil) + rule.AddCondition("R1_c1", []string{"t1.none"}, trueCondition, t) rule.SetAction(emptyAction) rule.SetPriority(1) rs.AddRule(rule) From 1a28a292070b41c8b3692f531c776926134cee59 Mon Sep 17 00:00:00 2001 From: "balamg@yahoo.com" Date: Tue, 23 Oct 2018 14:19:17 +0530 Subject: [PATCH 4/9] expr based condition --- ruleapi/tests/expr_1_test.go | 55 ++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/ruleapi/tests/expr_1_test.go b/ruleapi/tests/expr_1_test.go index 36a6656..57557d0 100644 --- a/ruleapi/tests/expr_1_test.go +++ b/ruleapi/tests/expr_1_test.go @@ -5,6 +5,7 @@ import ( "github.com/project-flogo/rules/ruleapi" "github.com/project-flogo/rules/common/model" "golang.org/x/net/context" + "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression" ) //1 condition, 1 expression @@ -12,7 +13,7 @@ func Test_1_Expr(t *testing.T) { rs, _ := createRuleSession() r1 := ruleapi.NewRule("r1") - r1.AddExprCondition("c1", "$t1.p1 > $t2.p1", nil) + r1.AddExprCondition("c1", "$t2.p2 > $t1.p1", nil) r1.SetAction(a1) rs.AddRule(r1) @@ -21,7 +22,7 @@ func Test_1_Expr(t *testing.T) { var ctx context.Context t1, _ := model.NewTupleWithKeyValues("t1", "t1") - t1.SetInt(nil,"p1", 2) + t1.SetInt(nil,"p1", 1) t1.SetDouble(nil,"p2", 1.3) t1.SetString(nil,"p3", "t3") @@ -30,7 +31,7 @@ func Test_1_Expr(t *testing.T) { t2, _ := model.NewTupleWithKeyValues("t2", "t2") t2.SetInt(nil,"p1", 1) - t2.SetDouble(nil,"p2", 1.1) + t2.SetDouble(nil,"p2", 1.0001) t2.SetString(nil,"p3", "t3") ctx = context.WithValue(context.TODO(), TestKey{}, t) @@ -41,4 +42,52 @@ func Test_1_Expr(t *testing.T) { func a1(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { t := ctx.Value(TestKey{}).(*testing.T) t.Logf("Test_1_Expr executed!") +} + +func Test_Eval (t *testing.T) { + expr, _ := expression.ParseExpression("1 == 1.23") + i, err := expr.Eval() + if err != nil { + t.Fatalf("error %s\n", err) + } + res := i.(bool) + if res { + t.Errorf("Expected false, got : %t\n ", res) + } +} + +func Test_Eval2 (t *testing.T) { + expr, _ := expression.ParseExpression("1 < 1.23") + i, err := expr.Eval() + if err != nil { + t.Fatalf("error %s\n", err) + } + res := i.(bool) + if !res { + t.Errorf("Expected true, got : %t\n ", res) + } +} + +func Test_Eval3 (t *testing.T) { + expr, _ := expression.ParseExpression("1.23 == 1") + i, err := expr.Eval() + if err != nil { + t.Fatalf("error %s\n", err) + } + res := i.(bool) + if res { + t.Errorf("Expected false, got : %t\n ", res) + } +} + +func Test_Eval4 (t *testing.T) { + expr, _ := expression.ParseExpression("1.23 > 1") + i, err := expr.Eval() + if err != nil { + t.Fatalf("error %s\n", err) + } + res := i.(bool) + if !res { + t.Errorf("Expected true, got : %t\n ", res) + } } \ No newline at end of file From 98283b6a75c17a3ef9fa60394a26054c8b670660 Mon Sep 17 00:00:00 2001 From: "balamg@yahoo.com" Date: Tue, 23 Oct 2018 14:20:16 +0530 Subject: [PATCH 5/9] expr based condition --- ruleapi/tests/expr_5_test.go | 44 ++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 ruleapi/tests/expr_5_test.go diff --git a/ruleapi/tests/expr_5_test.go b/ruleapi/tests/expr_5_test.go new file mode 100644 index 0000000..4fdfc77 --- /dev/null +++ b/ruleapi/tests/expr_5_test.go @@ -0,0 +1,44 @@ +package tests + +import ( + "testing" + "github.com/project-flogo/rules/ruleapi" + "github.com/project-flogo/rules/common/model" + "golang.org/x/net/context" +) + +//1 arithmetic operation +func Test_5_Expr(t *testing.T) { + + rs, _ := createRuleSession() + r1 := ruleapi.NewRule("r1") + r1.AddExprCondition("c1", "(($t1.p1 + $t2.p1) == 5) && (($t1.p2 > $t2.p2) && ($t1.p3 == $t2.p3))", nil) + r1.SetAction(a5) + rs.AddRule(r1) + + rs.Start(nil) + + var ctx context.Context + + t1, _ := model.NewTupleWithKeyValues("t1", "t1") + t1.SetInt(nil,"p1", 2) + t1.SetDouble(nil,"p2", 1.3) + t1.SetString(nil,"p3", "t3") + + ctx = context.WithValue(context.TODO(), TestKey{}, t) + rs.Assert(ctx, t1) + + t2, _ := model.NewTupleWithKeyValues("t2", "t2") + t2.SetInt(nil,"p1", 1) + t2.SetDouble(nil,"p2", 1.1) + t2.SetString(nil,"p3", "t3") + + ctx = context.WithValue(context.TODO(), TestKey{}, t) + rs.Assert(ctx, t2) + rs.Unregister() +} + +func a5(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { + t := ctx.Value(TestKey{}).(*testing.T) + t.Logf("Test_5_Expr executed!") +} \ No newline at end of file From b8a741d920c21fe833c645302a2790a8c8410da9 Mon Sep 17 00:00:00 2001 From: "balamg@yahoo.com" Date: Tue, 5 Mar 2019 16:22:30 +0530 Subject: [PATCH 6/9] Refactored to use the new expression API of project-flogo/core --- common/model/tuple.go | 7 +- common/model/tuplekey.go | 2 +- ruleapi/exprcondition.go | 92 +++++++++++++++---------- ruleapi/rule.go | 130 +++++++++++++++++++---------------- ruleapi/tests/expr_1_test.go | 116 ++++++++++++++++--------------- ruleapi/tests/expr_2_test.go | 22 +++--- ruleapi/tests/expr_3_test.go | 20 +++--- ruleapi/tests/expr_4_test.go | 20 +++--- ruleapi/tests/expr_5_test.go | 20 +++--- 9 files changed, 233 insertions(+), 196 deletions(-) diff --git a/common/model/tuple.go b/common/model/tuple.go index d7e3bd3..700b0d6 100644 --- a/common/model/tuple.go +++ b/common/model/tuple.go @@ -23,6 +23,7 @@ type Tuple interface { GetBool(name string) (val bool, err error) //GetDateTime(name string) time.Time GetKey() TupleKey + GetMap() map[string]interface{} } //MutableTuple mutable part of the tuple @@ -210,7 +211,7 @@ func (t *tupleImpl) initTupleWithKeyValues(td *TupleDescriptor, values ...interf t.key = tk //populate the tuple key fields with the key values for _, keyProp := range td.GetKeyProps() { - t.tuples [keyProp] = tk.GetValue(keyProp) + t.tuples[keyProp] = tk.GetValue(keyProp) } return err } @@ -273,3 +274,7 @@ func (t *tupleImpl) isKeyProp(propName string) bool { } return found } + +func (t *tupleImpl) GetMap() map[string]interface{} { + return t.tuples +} diff --git a/common/model/tuplekey.go b/common/model/tuplekey.go index 996e2e3..7a12d62 100644 --- a/common/model/tuplekey.go +++ b/common/model/tuplekey.go @@ -2,8 +2,8 @@ package model import ( "fmt" - "reflect" "github.com/project-flogo/core/data/coerce" + "reflect" ) // TupleKey primary key of a tuple diff --git a/ruleapi/exprcondition.go b/ruleapi/exprcondition.go index 7f92408..26734b0 100644 --- a/ruleapi/exprcondition.go +++ b/ruleapi/exprcondition.go @@ -1,14 +1,24 @@ package ruleapi import ( - "github.com/TIBCOSoftware/flogo-lib/core/data" - "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression" - "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression/expr" + "github.com/project-flogo/core/data" + "github.com/project-flogo/core/data/expression" + "github.com/project-flogo/core/data/expression/script" + "github.com/project-flogo/core/data/resolve" "github.com/project-flogo/rules/common/model" "reflect" - "strings" ) +var td tuplePropertyResolver +var resolver resolve.CompositeResolver +var factory expression.Factory + +func init() { + td = tuplePropertyResolver{} + resolver = resolve.NewCompositeResolver(map[string]resolve.Resolver{".": &td}) + factory = script.NewExprFactory(resolver) +} + type exprConditionImpl struct { name string rule model.Rule @@ -60,14 +70,14 @@ func (cnd *exprConditionImpl) GetTupleTypeAlias() []model.TupleType { func (cnd *exprConditionImpl) Evaluate(condName string, ruleNm string, tuples map[model.TupleType]model.Tuple, ctx model.RuleContext) (bool, error) { result := false if cnd.cExpr != "" { - e, err := expression.ParseExpression(cnd.cExpr) - exprn := e.(*expr.Expression) + //e, err := expression.ParseExpression(cnd.cExpr) + exprn, err := factory.NewExpr(cnd.cExpr) if err != nil { return result, err } - td := tuplePropertyResolver{} + scope := tupleScope{tuples} - res, err := exprn.EvalWithData(tuples, &scope, &td) + res, err := exprn.Eval(&scope) if err != nil { return false, err } else if reflect.TypeOf(res).Kind() == reflect.Bool { @@ -83,8 +93,12 @@ type tupleScope struct { tuples map[model.TupleType]model.Tuple } -func (ts *tupleScope) GetAttr(name string) (attr *data.Attribute, exists bool) { - return nil, false +func (ts *tupleScope) GetValue(name string) (value interface{}, exists bool) { + return false, true +} + +func (ts *tupleScope) SetValue(name string, value interface{}) error { + return nil } // SetAttrValue sets the value of the specified attribute @@ -96,31 +110,39 @@ func (ts *tupleScope) SetAttrValue(name string, value interface{}) error { type tuplePropertyResolver struct { } -func (t *tuplePropertyResolver) Resolve(toResolve string, scope data.Scope) (value interface{}, err error) { +//func (t *tuplePropertyResolver) Resolve(toResolve string, scope data.Scope) (value interface{}, err error) { +func (t *tuplePropertyResolver) Resolve(scope data.Scope, item string, field string) (interface{}, error) { + //toResolve = toResolve[1:] + //aliasAndProp := strings.Split(toResolve, ".") + // + //var v interface{} + //if ts != nil { + // tuple := ts.tuples[model.TupleType(aliasAndProp[0])].(model.Tuple) + // if tuple != nil { + // + // p := tuple.GetTupleDescriptor().GetProperty(aliasAndProp[1]) + // switch p.PropType { + // case data.TypeString: + // v, err = tuple.GetString(aliasAndProp[1]) + // case data.TypeInteger: + // v, err = tuple.GetInt(aliasAndProp[1]) + // case data.TypeLong: + // v, err = tuple.GetLong(aliasAndProp[1]) + // case data.TypeDouble: + // v, err = tuple.GetDouble(aliasAndProp[1]) + // case data.TypeBoolean: + // v, err = tuple.GetBool(aliasAndProp[1]) + // } + // } + //} + //return v, err + ts := scope.(*tupleScope) + tuple := ts.tuples[model.TupleType(field)] + m := tuple.GetMap() + return m, nil - toResolve = toResolve[1:] - aliasAndProp := strings.Split(toResolve, ".") +} - ts := scope.(*tupleScope) - var v interface{} - if ts != nil { - tuple := ts.tuples[model.TupleType(aliasAndProp[0])].(model.Tuple) - if tuple != nil { - - p := tuple.GetTupleDescriptor().GetProperty(aliasAndProp[1]) - switch p.PropType { - case data.TypeString: - v, err = tuple.GetString(aliasAndProp[1]) - case data.TypeInteger: - v, err = tuple.GetInt(aliasAndProp[1]) - case data.TypeLong: - v, err = tuple.GetLong(aliasAndProp[1]) - case data.TypeDouble: - v, err = tuple.GetDouble(aliasAndProp[1]) - case data.TypeBoolean: - v, err = tuple.GetBool(aliasAndProp[1]) - } - } - } - return v, err +func (*tuplePropertyResolver) GetResolverInfo() *resolve.ResolverInfo { + return resolve.NewResolverInfo(false, false) } diff --git a/ruleapi/rule.go b/ruleapi/rule.go index 1681246..18aee4d 100644 --- a/ruleapi/rule.go +++ b/ruleapi/rule.go @@ -2,11 +2,9 @@ package ruleapi import ( "fmt" + "regexp" "strings" - "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression" - "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression/expr" - "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/funcexprtype" "github.com/project-flogo/rules/common/model" ) @@ -207,17 +205,15 @@ func (rule *ruleImpl) GetDeps() map[model.TupleType]map[string]bool { func (rule *ruleImpl) AddExprCondition(conditionName string, cstr string, ctx model.RuleContext) error { - e, err := expression.ParseExpression(cstr) - if err != nil { - return err - } - exprn := e.(*expr.Expression) - refs, err := getRefs(exprn) - if err != nil { - return err - } + //e, err := expression.ParseExpression(cstr) + //if err != nil { + // return err + //} + //exprn := e.(*expr.Expression) + //refs, err := getRefs(exprn) + refs := getRefs(cstr) - err = validateRefs(refs) + err := validateRefs(refs) if err != nil { return err } @@ -227,12 +223,13 @@ func (rule *ruleImpl) AddExprCondition(conditionName string, cstr string, ctx mo return err } rule.addExprCond(conditionName, typeDeps, cstr, ctx) - return err + return nil } -func validateRefs(refs []string) (error) { +func validateRefs(refs []string) error { for _, ref := range refs { + ref := strings.TrimPrefix(ref, "$.") vals := strings.Split(ref, ".") td := model.GetTupleDescriptor(model.TupleType(vals[0])) if td == nil { @@ -246,51 +243,62 @@ func validateRefs(refs []string) (error) { return nil } -func getRefs(e *expr.Expression) ([]string, error) { - refs := make(map[string]bool) - keys := []string{} - - err := getRefRecursively(e, refs) - if err != nil { - return keys, err - } - - for key, _ := range refs { - keys = append (keys, key) - } - return keys, err -} - -func getRefRecursively(e *expr.Expression, refs map[string]bool) error { - - if e == nil { - return nil - } - err := getRefsInternal(e.Left, refs) - if err != nil { - return err - } - err = getRefsInternal(e.Right, refs) - if err != nil { - return err - } - return nil -} - -func getRefsInternal(e *expr.Expression, refs map[string]bool) error { - if e.Type == funcexprtype.EXPRESSION { - getRefRecursively(e, refs) - } else if e.Type == funcexprtype.REF || e.Type == funcexprtype.ARRAYREF { - value := e.Value.(string) - if strings.Index(value, "$") == 0 { - value = value[1:len(value)] - split := strings.Split(value, ".") - if split != nil && len(split) != 2 { - return fmt.Errorf("Invalid tokens [%s]", value) - } - - refs[value] = true - } +// +//func getRefs(e *expr.Expression) ([]string, error) { +// refs := make(map[string]bool) +// keys := []string{} +// +// err := getRefRecursively(e, refs) +// if err != nil { +// return keys, err +// } +// +// for key, _ := range refs { +// keys = append (keys, key) +// } +// return keys, err +//} +// +//func getRefRecursively(e *expr.Expression, refs map[string]bool) error { +// +// if e == nil { +// return nil +// } +// err := getRefsInternal(e.Left, refs) +// if err != nil { +// return err +// } +// err = getRefsInternal(e.Right, refs) +// if err != nil { +// return err +// } +// return nil +//} +// +//func getRefsInternal(e *expr.Expression, refs map[string]bool) error { +// if e.Type == funcexprtype.EXPRESSION { +// getRefRecursively(e, refs) +// } else if e.Type == funcexprtype.REF || e.Type == funcexprtype.ARRAYREF { +// value := e.Value.(string) +// if strings.Index(value, "$") == 0 { +// value = value[1:len(value)] +// split := strings.Split(value, ".") +// if split != nil && len(split) != 2 { +// return fmt.Errorf("Invalid tokens [%s]", value) +// } +// +// refs[value] = true +// } +// } +// return nil +//} + +func getRefs(cstr string) []string { + keys2 := []string{} + re := regexp.MustCompile(`\$\.(\w+\.\w+)`) + keys := re.FindAllStringSubmatch(cstr, -1) + for _, k := range keys { + keys2 = append(keys2, k[1]) } - return nil + return keys2 } diff --git a/ruleapi/tests/expr_1_test.go b/ruleapi/tests/expr_1_test.go index 57557d0..66c46c3 100644 --- a/ruleapi/tests/expr_1_test.go +++ b/ruleapi/tests/expr_1_test.go @@ -1,11 +1,10 @@ package tests import ( - "testing" - "github.com/project-flogo/rules/ruleapi" "github.com/project-flogo/rules/common/model" + "github.com/project-flogo/rules/ruleapi" "golang.org/x/net/context" - "github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/expression" + "testing" ) //1 condition, 1 expression @@ -13,7 +12,7 @@ func Test_1_Expr(t *testing.T) { rs, _ := createRuleSession() r1 := ruleapi.NewRule("r1") - r1.AddExprCondition("c1", "$t2.p2 > $t1.p1", nil) + r1.AddExprCondition("c1", "$.t2.p2 > $.t1.p1", nil) r1.SetAction(a1) rs.AddRule(r1) @@ -22,17 +21,17 @@ func Test_1_Expr(t *testing.T) { var ctx context.Context t1, _ := model.NewTupleWithKeyValues("t1", "t1") - t1.SetInt(nil,"p1", 1) - t1.SetDouble(nil,"p2", 1.3) - t1.SetString(nil,"p3", "t3") + t1.SetInt(nil, "p1", 1) + t1.SetDouble(nil, "p2", 1.3) + t1.SetString(nil, "p3", "t3") ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t1) t2, _ := model.NewTupleWithKeyValues("t2", "t2") - t2.SetInt(nil,"p1", 1) - t2.SetDouble(nil,"p2", 1.0001) - t2.SetString(nil,"p3", "t3") + t2.SetInt(nil, "p1", 1) + t2.SetDouble(nil, "p2", 1.0001) + t2.SetString(nil, "p3", "t3") ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t2) @@ -44,50 +43,53 @@ func a1(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[m t.Logf("Test_1_Expr executed!") } -func Test_Eval (t *testing.T) { - expr, _ := expression.ParseExpression("1 == 1.23") - i, err := expr.Eval() - if err != nil { - t.Fatalf("error %s\n", err) - } - res := i.(bool) - if res { - t.Errorf("Expected false, got : %t\n ", res) - } -} - -func Test_Eval2 (t *testing.T) { - expr, _ := expression.ParseExpression("1 < 1.23") - i, err := expr.Eval() - if err != nil { - t.Fatalf("error %s\n", err) - } - res := i.(bool) - if !res { - t.Errorf("Expected true, got : %t\n ", res) - } -} - -func Test_Eval3 (t *testing.T) { - expr, _ := expression.ParseExpression("1.23 == 1") - i, err := expr.Eval() - if err != nil { - t.Fatalf("error %s\n", err) - } - res := i.(bool) - if res { - t.Errorf("Expected false, got : %t\n ", res) - } -} - -func Test_Eval4 (t *testing.T) { - expr, _ := expression.ParseExpression("1.23 > 1") - i, err := expr.Eval() - if err != nil { - t.Fatalf("error %s\n", err) - } - res := i.(bool) - if !res { - t.Errorf("Expected true, got : %t\n ", res) - } -} \ No newline at end of file +// +// These standalone tests are not relevant anymore as the expression API has changed +// +//func Test_Eval (t *testing.T) { +// expr, _ := expression.ParseExpression("1 == 1.23") +// i, err := expr.Eval() +// if err != nil { +// t.Fatalf("error %s\n", err) +// } +// res := i.(bool) +// if res { +// t.Errorf("Expected false, got : %t\n ", res) +// } +//} +// +//func Test_Eval2 (t *testing.T) { +// expr, _ := expression.ParseExpression("1 < 1.23") +// i, err := expr.Eval() +// if err != nil { +// t.Fatalf("error %s\n", err) +// } +// res := i.(bool) +// if !res { +// t.Errorf("Expected true, got : %t\n ", res) +// } +//} +// +//func Test_Eval3 (t *testing.T) { +// expr, _ := expression.ParseExpression("1.23 == 1") +// i, err := expr.Eval() +// if err != nil { +// t.Fatalf("error %s\n", err) +// } +// res := i.(bool) +// if res { +// t.Errorf("Expected false, got : %t\n ", res) +// } +//} +// +//func Test_Eval4 (t *testing.T) { +// expr, _ := expression.ParseExpression("1.23 > 1") +// i, err := expr.Eval() +// if err != nil { +// t.Fatalf("error %s\n", err) +// } +// res := i.(bool) +// if !res { +// t.Errorf("Expected true, got : %t\n ", res) +// } +//} diff --git a/ruleapi/tests/expr_2_test.go b/ruleapi/tests/expr_2_test.go index 1997dc8..3be99f6 100644 --- a/ruleapi/tests/expr_2_test.go +++ b/ruleapi/tests/expr_2_test.go @@ -1,10 +1,10 @@ package tests import ( - "testing" - "github.com/project-flogo/rules/ruleapi" "github.com/project-flogo/rules/common/model" + "github.com/project-flogo/rules/ruleapi" "golang.org/x/net/context" + "testing" ) //2 conditions, 1 expr each @@ -12,8 +12,8 @@ func Test_2_Expr(t *testing.T) { rs, _ := createRuleSession() r1 := ruleapi.NewRule("r1") - r1.AddExprCondition("c1", "$t1.p1 > $t2.p1", nil) - r1.AddExprCondition("c2", "$t1.p1 == 2", nil) + r1.AddExprCondition("c1", "$.t1.p1 > $.t2.p1", nil) + r1.AddExprCondition("c2", "$.t1.p1 == 2", nil) r1.SetAction(a2) rs.AddRule(r1) @@ -22,17 +22,17 @@ func Test_2_Expr(t *testing.T) { var ctx context.Context t1, _ := model.NewTupleWithKeyValues("t1", "t1") - t1.SetInt(nil,"p1", 2) - t1.SetDouble(nil,"p2", 1.3) - t1.SetString(nil,"p3", "t3") + t1.SetInt(nil, "p1", 2) + t1.SetDouble(nil, "p2", 1.3) + t1.SetString(nil, "p3", "t3") ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t1) t2, _ := model.NewTupleWithKeyValues("t2", "t2") - t2.SetInt(nil,"p1", 1) - t2.SetDouble(nil,"p2", 1.1) - t2.SetString(nil,"p3", "t3") + t2.SetInt(nil, "p1", 1) + t2.SetDouble(nil, "p2", 1.1) + t2.SetString(nil, "p3", "t3") ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t2) @@ -42,4 +42,4 @@ func Test_2_Expr(t *testing.T) { func a2(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { t := ctx.Value(TestKey{}).(*testing.T) t.Logf("Test_2_Expr executed!") -} \ No newline at end of file +} diff --git a/ruleapi/tests/expr_3_test.go b/ruleapi/tests/expr_3_test.go index 3a97575..8012566 100644 --- a/ruleapi/tests/expr_3_test.go +++ b/ruleapi/tests/expr_3_test.go @@ -1,10 +1,10 @@ package tests import ( - "testing" - "github.com/project-flogo/rules/ruleapi" "github.com/project-flogo/rules/common/model" + "github.com/project-flogo/rules/ruleapi" "golang.org/x/net/context" + "testing" ) //1 conditions, 2 expr @@ -12,7 +12,7 @@ func Test_3_Expr(t *testing.T) { rs, _ := createRuleSession() r1 := ruleapi.NewRule("r1") - r1.AddExprCondition("c1", "($t1.p1 > $t2.p1) && ($t1.p2 > $t2.p2)", nil) + r1.AddExprCondition("c1", "($.t1.p1 > $.t2.p1) && ($.t1.p2 > $.t2.p2)", nil) r1.SetAction(a3) rs.AddRule(r1) @@ -21,17 +21,17 @@ func Test_3_Expr(t *testing.T) { var ctx context.Context t1, _ := model.NewTupleWithKeyValues("t1", "t1") - t1.SetInt(nil,"p1", 2) - t1.SetDouble(nil,"p2", 1.3) - t1.SetString(nil,"p3", "t3") + t1.SetInt(nil, "p1", 2) + t1.SetDouble(nil, "p2", 1.3) + t1.SetString(nil, "p3", "t3") ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t1) t2, _ := model.NewTupleWithKeyValues("t2", "t2") - t2.SetInt(nil,"p1", 1) - t2.SetDouble(nil,"p2", 1.1) - t2.SetString(nil,"p3", "t3") + t2.SetInt(nil, "p1", 1) + t2.SetDouble(nil, "p2", 1.1) + t2.SetString(nil, "p3", "t3") ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t2) @@ -41,4 +41,4 @@ func Test_3_Expr(t *testing.T) { func a3(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { t := ctx.Value(TestKey{}).(*testing.T) t.Logf("Test_3_Expr executed!") -} \ No newline at end of file +} diff --git a/ruleapi/tests/expr_4_test.go b/ruleapi/tests/expr_4_test.go index 547f62b..936942e 100644 --- a/ruleapi/tests/expr_4_test.go +++ b/ruleapi/tests/expr_4_test.go @@ -1,10 +1,10 @@ package tests import ( - "testing" - "github.com/project-flogo/rules/ruleapi" "github.com/project-flogo/rules/common/model" + "github.com/project-flogo/rules/ruleapi" "golang.org/x/net/context" + "testing" ) //1 conditions, 3 expr @@ -12,7 +12,7 @@ func Test_4_Expr(t *testing.T) { rs, _ := createRuleSession() r1 := ruleapi.NewRule("r1") - r1.AddExprCondition("c1", "($t1.p1 > $t2.p1) && (($t1.p2 > $t2.p2) && ($t1.p3 == $t2.p3))", nil) + r1.AddExprCondition("c1", "($.t1.p1 > $.t2.p1) && (($.t1.p2 > $.t2.p2) && ($.t1.p3 == $.t2.p3))", nil) r1.SetAction(a4) rs.AddRule(r1) @@ -21,17 +21,17 @@ func Test_4_Expr(t *testing.T) { var ctx context.Context t1, _ := model.NewTupleWithKeyValues("t1", "t1") - t1.SetInt(nil,"p1", 2) - t1.SetDouble(nil,"p2", 1.3) - t1.SetString(nil,"p3", "t3") + t1.SetInt(nil, "p1", 2) + t1.SetDouble(nil, "p2", 1.3) + t1.SetString(nil, "p3", "t3") ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t1) t2, _ := model.NewTupleWithKeyValues("t2", "t2") - t2.SetInt(nil,"p1", 1) - t2.SetDouble(nil,"p2", 1.1) - t2.SetString(nil,"p3", "t3") + t2.SetInt(nil, "p1", 1) + t2.SetDouble(nil, "p2", 1.1) + t2.SetString(nil, "p3", "t3") ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t2) @@ -41,4 +41,4 @@ func Test_4_Expr(t *testing.T) { func a4(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { t := ctx.Value(TestKey{}).(*testing.T) t.Logf("Test_4_Expr executed!") -} \ No newline at end of file +} diff --git a/ruleapi/tests/expr_5_test.go b/ruleapi/tests/expr_5_test.go index 4fdfc77..5676e2b 100644 --- a/ruleapi/tests/expr_5_test.go +++ b/ruleapi/tests/expr_5_test.go @@ -1,10 +1,10 @@ package tests import ( - "testing" - "github.com/project-flogo/rules/ruleapi" "github.com/project-flogo/rules/common/model" + "github.com/project-flogo/rules/ruleapi" "golang.org/x/net/context" + "testing" ) //1 arithmetic operation @@ -12,7 +12,7 @@ func Test_5_Expr(t *testing.T) { rs, _ := createRuleSession() r1 := ruleapi.NewRule("r1") - r1.AddExprCondition("c1", "(($t1.p1 + $t2.p1) == 5) && (($t1.p2 > $t2.p2) && ($t1.p3 == $t2.p3))", nil) + r1.AddExprCondition("c1", "(($.t1.p1 + $.t2.p1) == 5) && (($.t1.p2 > $.t2.p2) && ($.t1.p3 == $.t2.p3))", nil) r1.SetAction(a5) rs.AddRule(r1) @@ -21,17 +21,17 @@ func Test_5_Expr(t *testing.T) { var ctx context.Context t1, _ := model.NewTupleWithKeyValues("t1", "t1") - t1.SetInt(nil,"p1", 2) - t1.SetDouble(nil,"p2", 1.3) - t1.SetString(nil,"p3", "t3") + t1.SetInt(nil, "p1", 1) + t1.SetDouble(nil, "p2", 1.3) + t1.SetString(nil, "p3", "t3") ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t1) t2, _ := model.NewTupleWithKeyValues("t2", "t2") - t2.SetInt(nil,"p1", 1) - t2.SetDouble(nil,"p2", 1.1) - t2.SetString(nil,"p3", "t3") + t2.SetInt(nil, "p1", 4) + t2.SetDouble(nil, "p2", 1.1) + t2.SetString(nil, "p3", "t3") ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t2) @@ -41,4 +41,4 @@ func Test_5_Expr(t *testing.T) { func a5(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { t := ctx.Value(TestKey{}).(*testing.T) t.Logf("Test_5_Expr executed!") -} \ No newline at end of file +} From 6af83a6fbae60c139401083db746c9cee0b50f7e Mon Sep 17 00:00:00 2001 From: bg Date: Thu, 4 Jul 2019 19:48:00 +0530 Subject: [PATCH 7/9] fixed compilation errors in tests --- ruleapi/exprcondition.go | 2 +- ruleapi/tests/expr_1_test.go | 2 +- ruleapi/tests/expr_2_test.go | 2 +- ruleapi/tests/expr_3_test.go | 2 +- ruleapi/tests/expr_4_test.go | 2 +- ruleapi/tests/expr_5_test.go | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ruleapi/exprcondition.go b/ruleapi/exprcondition.go index 26734b0..9b979ff 100644 --- a/ruleapi/exprcondition.go +++ b/ruleapi/exprcondition.go @@ -133,7 +133,7 @@ func (t *tuplePropertyResolver) Resolve(scope data.Scope, item string, field str // case data.TypeBoolean: // v, err = tuple.GetBool(aliasAndProp[1]) // } - // } + // }` //} //return v, err ts := scope.(*tupleScope) diff --git a/ruleapi/tests/expr_1_test.go b/ruleapi/tests/expr_1_test.go index 66c46c3..41f4435 100644 --- a/ruleapi/tests/expr_1_test.go +++ b/ruleapi/tests/expr_1_test.go @@ -1,9 +1,9 @@ package tests import ( + "context" "github.com/project-flogo/rules/common/model" "github.com/project-flogo/rules/ruleapi" - "golang.org/x/net/context" "testing" ) diff --git a/ruleapi/tests/expr_2_test.go b/ruleapi/tests/expr_2_test.go index 3be99f6..c27581e 100644 --- a/ruleapi/tests/expr_2_test.go +++ b/ruleapi/tests/expr_2_test.go @@ -1,9 +1,9 @@ package tests import ( + "context" "github.com/project-flogo/rules/common/model" "github.com/project-flogo/rules/ruleapi" - "golang.org/x/net/context" "testing" ) diff --git a/ruleapi/tests/expr_3_test.go b/ruleapi/tests/expr_3_test.go index 8012566..f8a49e1 100644 --- a/ruleapi/tests/expr_3_test.go +++ b/ruleapi/tests/expr_3_test.go @@ -1,9 +1,9 @@ package tests import ( + "context" "github.com/project-flogo/rules/common/model" "github.com/project-flogo/rules/ruleapi" - "golang.org/x/net/context" "testing" ) diff --git a/ruleapi/tests/expr_4_test.go b/ruleapi/tests/expr_4_test.go index 936942e..d4d7bfe 100644 --- a/ruleapi/tests/expr_4_test.go +++ b/ruleapi/tests/expr_4_test.go @@ -1,9 +1,9 @@ package tests import ( + "context" "github.com/project-flogo/rules/common/model" "github.com/project-flogo/rules/ruleapi" - "golang.org/x/net/context" "testing" ) diff --git a/ruleapi/tests/expr_5_test.go b/ruleapi/tests/expr_5_test.go index 5676e2b..53c8668 100644 --- a/ruleapi/tests/expr_5_test.go +++ b/ruleapi/tests/expr_5_test.go @@ -1,9 +1,9 @@ package tests import ( + "context" "github.com/project-flogo/rules/common/model" "github.com/project-flogo/rules/ruleapi" - "golang.org/x/net/context" "testing" ) From b45a266b02d3627460c668bce3a0fec6f41c61d2 Mon Sep 17 00:00:00 2001 From: bg Date: Wed, 31 Jul 2019 19:46:57 +0530 Subject: [PATCH 8/9] fix go mod --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index cfa514a..1e5d07f 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,5 @@ require ( github.com/aws/aws-sdk-go v1.18.3 github.com/gorilla/websocket v1.4.0 github.com/oklog/ulid v1.3.1 - github.com/project-flogo/core v0.9.0-alpha.6 + github.com/project-flogo/core v0.9.2 ) From f66fa9608d235089bd41cefdc06dc71daea93712 Mon Sep 17 00:00:00 2001 From: bg Date: Fri, 2 Aug 2019 12:59:02 +0530 Subject: [PATCH 9/9] flogo/flogo.json support for expression based conditions --- common/model/types.go | 10 ++--- config/config.go | 37 +++++++++++----- config/manager.go | 23 ---------- examples/flogo/simple/flogo.json | 71 ++++++++++++++++-------------- examples/flogo/simple/functions.go | 25 +++++++++++ rete/network.go | 6 +++ ruleapi/condition.go | 9 +++- ruleapi/exprcondition.go | 13 +++++- ruleapi/rule.go | 24 ++++++++++ ruleapi/rulesession.go | 14 +++++- ruleapi/tests/expr_1_test.go | 61 +++++-------------------- ruleapi/tests/expr_2_test.go | 10 +++++ ruleapi/tests/expr_3_test.go | 10 +++++ ruleapi/tests/expr_4_test.go | 10 +++++ ruleapi/tests/expr_5_test.go | 10 +++++ 15 files changed, 205 insertions(+), 128 deletions(-) diff --git a/common/model/types.go b/common/model/types.go index ca04954..eb2807d 100644 --- a/common/model/types.go +++ b/common/model/types.go @@ -26,7 +26,8 @@ type MutableRule interface { SetAction(actionFn ActionFunction) SetPriority(priority int) SetContext(ctx RuleContext) - AddExprCondition (conditionName string, cExpr string, ctx RuleContext) (error) + AddExprCondition(conditionName string, cExpr string, ctx RuleContext) error + AddIdrsToRule(idrs []TupleType) } //Condition interface to maintain/get various condition properties @@ -72,7 +73,6 @@ type RuleSession interface { //RtcTransactionHandler RegisterRtcTransactionHandler(txnHandler RtcTransactionHandler, handlerCtx interface{}) - } //ConditionEvaluator is a function pointer for handling condition evaluations on the server side @@ -93,10 +93,9 @@ type ValueChangeListener interface { type RtcTxn interface { //map of type and map of key/tuple - GetRtcAdded () map[string]map[string]Tuple + GetRtcAdded() map[string]map[string]Tuple GetRtcModified() map[string]map[string]RtcModified GetRtcDeleted() map[string]map[string]Tuple - } type RtcModified interface { @@ -104,5 +103,4 @@ type RtcModified interface { GetModifiedProps() map[string]bool } -type RtcTransactionHandler func (ctx context.Context, rs RuleSession, txn RtcTxn, txnContext interface{}) - +type RtcTransactionHandler func(ctx context.Context, rs RuleSession, txn RtcTxn, txnContext interface{}) diff --git a/config/config.go b/config/config.go index ec9429e..85836be 100644 --- a/config/config.go +++ b/config/config.go @@ -23,10 +23,11 @@ type RuleSessionDescriptor struct { // RuleDescriptor defines a rule type RuleDescriptor struct { - Name string - Conditions []*ConditionDescriptor - ActionFunc model.ActionFunction - Priority int + Name string + Conditions []*ConditionDescriptor + ActionFunc model.ActionFunction + Priority int + Identifiers []string } // ConditionDescriptor defines a condition in a rule @@ -34,6 +35,7 @@ type ConditionDescriptor struct { Name string Identifiers []string Evaluator model.ConditionEvaluator + Expression string } func (c *RuleDescriptor) UnmarshalJSON(d []byte) error { @@ -42,6 +44,7 @@ func (c *RuleDescriptor) UnmarshalJSON(d []byte) error { Conditions []*ConditionDescriptor `json:"conditions"` ActionFuncId string `json:"actionFunction"` Priority int `json:"priority"` + Identifiers []string `json:"identifiers"` }{} if err := json.Unmarshal(d, ser); err != nil { @@ -52,6 +55,7 @@ func (c *RuleDescriptor) UnmarshalJSON(d []byte) error { c.Conditions = ser.Conditions c.ActionFunc = GetActionFunction(ser.ActionFuncId) c.Priority = ser.Priority + c.Identifiers = ser.Identifiers return nil } @@ -59,6 +63,14 @@ func (c *RuleDescriptor) UnmarshalJSON(d []byte) error { func (c *RuleDescriptor) MarshalJSON() ([]byte, error) { buffer := bytes.NewBufferString("{") buffer.WriteString("\"name\":" + "\"" + c.Name + "\",") + if c.Identifiers != nil { + buffer.WriteString("\"identifiers\":[") + for _, id := range c.Identifiers { + buffer.WriteString("\"" + id + "\",") + } + buffer.Truncate(buffer.Len() - 1) + buffer.WriteString("],") + } buffer.WriteString("\"conditions\":[") for _, condition := range c.Conditions { @@ -82,6 +94,7 @@ func (c *ConditionDescriptor) UnmarshalJSON(d []byte) error { Name string `json:"name"` Identifiers []string `json:"identifiers"` EvaluatorId string `json:"evaluator"` + Expression string `json:"expression"` }{} if err := json.Unmarshal(d, ser); err != nil { @@ -91,6 +104,7 @@ func (c *ConditionDescriptor) UnmarshalJSON(d []byte) error { c.Name = ser.Name c.Identifiers = ser.Identifiers c.Evaluator = GetConditionEvaluator(ser.EvaluatorId) + c.Expression = ser.Expression return nil } @@ -98,15 +112,18 @@ func (c *ConditionDescriptor) UnmarshalJSON(d []byte) error { func (c *ConditionDescriptor) MarshalJSON() ([]byte, error) { buffer := bytes.NewBufferString("{") buffer.WriteString("\"name\":" + "\"" + c.Name + "\",") - buffer.WriteString("\"identifiers\":[") - for _, id := range c.Identifiers { - buffer.WriteString("\"" + id + "\",") + if c.Identifiers != nil { + buffer.WriteString("\"identifiers\":[") + for _, id := range c.Identifiers { + buffer.WriteString("\"" + id + "\",") + } + buffer.Truncate(buffer.Len() - 1) + buffer.WriteString("],") } - buffer.Truncate(buffer.Len() - 1) - buffer.WriteString("],") conditionEvaluatorID := GetConditionEvaluatorID(c.Evaluator) - buffer.WriteString("\"evaluator\":\"" + conditionEvaluatorID + "\"}") + buffer.WriteString("\"evaluator\":\"" + conditionEvaluatorID + "\",") + buffer.WriteString("\"expression\":\"" + c.Expression + "\"}") return buffer.Bytes(), nil } diff --git a/config/manager.go b/config/manager.go index ccb6054..25d43be 100644 --- a/config/manager.go +++ b/config/manager.go @@ -57,26 +57,3 @@ func (m *ResourceManager) GetRuleActionDescriptor(uri string) (*RuleActionDescri return nil, errors.New("cannot find RuleSession: " + uri) } - -//ioMetadata support -/* -type ActionResource struct { - IOMetadata *metadata.IOMetadata `json:"metadata"` -} - -type ResManager struct { - IOMetadata *metadata.IOMetadata -} - -func (m *ResManager) LoadResource(resConfig *resource.Config) (*resource.Resource, error) { - - var res *ActionResource - err := json.Unmarshal(resConfig.Data, &res) - if err != nil { - return nil, fmt.Errorf("error unmarshalling metadata resource with id '%s', %s", resConfig.ID, err.Error()) - } - - m.IOMetadata = res.IOMetadata - return resource.New("ruleaction", m.IOMetadata), nil -} -*/ diff --git a/examples/flogo/simple/flogo.json b/examples/flogo/simple/flogo.json index 41e8ca1..71beff9 100644 --- a/examples/flogo/simple/flogo.json +++ b/examples/flogo/simple/flogo.json @@ -4,6 +4,13 @@ "version": "0.0.1", "description": "Sample Flogo App", "appModel": "1.0.0", + "properties": [ + { + "name": "name", + "type": "string", + "value": "testprop" + } + ], "triggers": [ { "id": "receive_http_message", @@ -12,32 +19,17 @@ "port": "7777" }, "handlers": [ - { - "settings": { - "method": "GET", - "path": "/test/n1" - }, - "actions": [ - { - "id": "simple_rule", - "input": { - "tupletype": "n1", - "values": "=$.queryParams" - } - } - ] - }, { "settings": { "method": "GET", - "path": "/test/n2" + "path": "/test/:tupleType" }, "actions": [ { "id": "simple_rule", "input": { - "tupletype": "n2", - "values": "=$.queryParams" + "tupletype": "=$.pathParams.tupleType", + "values": "=$.queryParams" } } ] @@ -92,10 +84,10 @@ } ], "output": [ - { - "name": "outputData", - "type": "any" - } + { + "name": "outputData", + "type": "any" + } ] }, "rules": [ @@ -103,11 +95,7 @@ "name": "n1.name == Bob", "conditions": [ { - "name": "c1", - "identifiers": [ - "n1" - ], - "evaluator": "checkForBob" + "expression" : "$.n1.name == 'Bob'" } ], "actionFunction": "checkForBobAction" @@ -116,22 +104,37 @@ "name": "n1.name == Bob \u0026\u0026 n1.name == n2.name", "conditions": [ { - "name": "c1", "identifiers": [ "n1" ], "evaluator": "checkForBob" }, { - "name": "c2", - "identifiers": [ - "n1", - "n2" - ], - "evaluator": "checkSameNamesCondition" + "expression" : "($.n1.name == 'Bob') \u0026\u0026 ($.n1.name == $.n2.name)" } ], "actionFunction": "checkSameNamesAction" + }, + { + "name": "env variable example", + "conditions": [ + { + "expression" : "($.n1.name == $env['name'])" + } + ], + "actionFunction": "envVarExampleAction" + }, + { + "name": "flogo property example", + "identifiers": [ + "n1" + ], + "conditions": [ + { + "expression" : "('testprop' == $property['name'])" + } + ], + "actionFunction": "propertyExampleAction" } ] } diff --git a/examples/flogo/simple/functions.go b/examples/flogo/simple/functions.go index ffc838c..f23073f 100644 --- a/examples/flogo/simple/functions.go +++ b/examples/flogo/simple/functions.go @@ -12,6 +12,8 @@ import ( func init() { config.RegisterActionFunction("checkForBobAction", checkForBobAction) config.RegisterActionFunction("checkSameNamesAction", checkSameNamesAction) + config.RegisterActionFunction("envVarExampleAction", envVarExampleAction) + config.RegisterActionFunction("propertyExampleAction", propertyExampleAction) config.RegisterConditionEvaluator("checkForBob", checkForBob) config.RegisterConditionEvaluator("checkSameNamesCondition", checkSameNamesCondition) @@ -72,3 +74,26 @@ func StartupRSFunction(ctx context.Context, rs model.RuleSession, startupCtx map rs.Assert(nil, t3) return nil } + +func envVarExampleAction(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { + fmt.Printf("Rule fired: [%s]\n", ruleName) + t1 := tuples["n1"] + if t1 == nil { + fmt.Println("Should not get nil tuples here in JoinCondition! This is an error") + return + } else { + nm, _ := t1.GetString("name") + fmt.Printf("n1.name is [%s]\n", nm) + } +} +func propertyExampleAction(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { + fmt.Printf("Rule fired: [%s]\n", ruleName) + t1 := tuples["n1"] + if t1 == nil { + fmt.Println("Should not get nil tuples here ! This is an error") + return + } else { + nm, _ := t1.GetString("name") + fmt.Printf("n1.name is [%s]\n", nm) + } +} diff --git a/rete/network.go b/rete/network.go index 52dc416..4fef2d2 100644 --- a/rete/network.go +++ b/rete/network.go @@ -99,6 +99,7 @@ func (nw *reteNetworkImpl) AddRule(rule model.Rule) (err error) { classNodeLinksOfRule := list.New() conditions := rule.GetConditions() + noIdrConditionCnt := 0 if len(conditions) == 0 { identifierVar := pickIdentifier(rule.GetIdentifiers()) nw.createClassFilterNode(rule, nodesOfRule, classNodeLinksOfRule, identifierVar, nil, nodeSet) @@ -106,6 +107,7 @@ func (nw *reteNetworkImpl) AddRule(rule model.Rule) (err error) { for i := 0; i < len(conditions); i++ { if conditions[i].GetIdentifiers() == nil || len(conditions[i].GetIdentifiers()) == 0 { conditionSetNoIdr.PushBack(conditions[i]) + noIdrConditionCnt++ } else if len(conditions[i].GetIdentifiers()) == 1 && !contains(nodeSet, conditions[i].GetIdentifiers()[0]) { cond := conditions[i] @@ -115,6 +117,10 @@ func (nw *reteNetworkImpl) AddRule(rule model.Rule) (err error) { } } } + if len(rule.GetConditions()) != 0 && noIdrConditionCnt == len(rule.GetConditions()) { + idr := pickIdentifier(rule.GetIdentifiers()) + nw.createClassFilterNode(rule, nodesOfRule, classNodeLinksOfRule, idr, nil, nodeSet) + } nw.buildNetwork(rule, nodesOfRule, classNodeLinksOfRule, conditionSet, nodeSet, conditionSetNoIdr) diff --git a/ruleapi/condition.go b/ruleapi/condition.go index 33f9c8d..df49f43 100644 --- a/ruleapi/condition.go +++ b/ruleapi/condition.go @@ -2,6 +2,7 @@ package ruleapi import ( "github.com/project-flogo/rules/common/model" + "strconv" ) type conditionImpl struct { @@ -20,6 +21,10 @@ func newCondition(name string, rule model.Rule, identifiers []model.TupleType, c } func (cnd *conditionImpl) initConditionImpl(name string, rule model.Rule, identifiers []model.TupleType, cfn model.ConditionEvaluator, ctx model.RuleContext) { + if name == "" { + cndIdx := len(rule.GetConditions()) + 1 + name = "c_" + strconv.Itoa(cndIdx) + } cnd.name = name cnd.rule = rule cnd.identifiers = append(cnd.identifiers, identifiers...) @@ -53,10 +58,10 @@ func (cnd *conditionImpl) GetTupleTypeAlias() []model.TupleType { return cnd.identifiers } -func (cnd *conditionImpl) Evaluate (condName string, ruleNm string, tuples map[model.TupleType]model.Tuple, ctx model.RuleContext) (bool, error) { +func (cnd *conditionImpl) Evaluate(condName string, ruleNm string, tuples map[model.TupleType]model.Tuple, ctx model.RuleContext) (bool, error) { result := false if cnd.cfn != nil { - result = cnd.cfn (condName, ruleNm, tuples, ctx) + result = cnd.cfn(condName, ruleNm, tuples, ctx) } return result, nil diff --git a/ruleapi/exprcondition.go b/ruleapi/exprcondition.go index 9b979ff..872826c 100644 --- a/ruleapi/exprcondition.go +++ b/ruleapi/exprcondition.go @@ -7,6 +7,7 @@ import ( "github.com/project-flogo/core/data/resolve" "github.com/project-flogo/rules/common/model" "reflect" + "strconv" ) var td tuplePropertyResolver @@ -15,7 +16,13 @@ var factory expression.Factory func init() { td = tuplePropertyResolver{} - resolver = resolve.NewCompositeResolver(map[string]resolve.Resolver{".": &td}) + //resolver = resolve.NewCompositeResolver(map[string]resolve.Resolver{".": &td}) + resolver = resolve.NewCompositeResolver(map[string]resolve.Resolver{ + ".": &td, + "env": &resolve.EnvResolver{}, + "property": &resolve.PropertyResolver{}, + "loop": &resolve.LoopResolver{}, + }) factory = script.NewExprFactory(resolver) } @@ -34,6 +41,10 @@ func newExprCondition(name string, rule model.Rule, identifiers []model.TupleTyp } func (cnd *exprConditionImpl) initExprConditionImpl(name string, rule model.Rule, identifiers []model.TupleType, cExpr string, ctx model.RuleContext) { + if name == "" { + cndIdx := len(rule.GetConditions()) + 1 + name = "c_" + strconv.Itoa(cndIdx) + } cnd.name = name cnd.rule = rule cnd.identifiers = append(cnd.identifiers, identifiers...) diff --git a/ruleapi/rule.go b/ruleapi/rule.go index 18aee4d..9bd2d30 100644 --- a/ruleapi/rule.go +++ b/ruleapi/rule.go @@ -74,6 +74,30 @@ func (rule *ruleImpl) addCond(conditionName string, idrs []model.TupleType, cfn } } + +func (rule *ruleImpl) AddIdrsToRule(idrs []model.TupleType) { + for _, cidr := range idrs { + //TODO: configure the rulesession + if model.GetTupleDescriptor(cidr) == nil { + return + } + if len(rule.identifiers) == 0 { + rule.identifiers = append(rule.identifiers, cidr) + } else { + found := false + for _, ridr := range rule.identifiers { + if cidr == ridr { + found = true + break + } + } + if !found { + rule.identifiers = append(rule.identifiers, cidr) + } + } + } +} + func (rule *ruleImpl) addExprCond(conditionName string, idrs []model.TupleType, cExpr string, ctx model.RuleContext) { condition := newExprCondition(conditionName, rule, idrs, cExpr, ctx) rule.conditions = append(rule.conditions, condition) diff --git a/ruleapi/rulesession.go b/ruleapi/rulesession.go index 6df0fc9..68424f0 100644 --- a/ruleapi/rulesession.go +++ b/ruleapi/rulesession.go @@ -56,7 +56,19 @@ func GetOrCreateRuleSessionFromConfig(name string, jsonConfig string) (model.Rul rule.SetPriority(ruleCfg.Priority) for _, condCfg := range ruleCfg.Conditions { - rule.AddCondition(condCfg.Name, condCfg.Identifiers, condCfg.Evaluator, nil) + if condCfg.Expression == "" { + rule.AddCondition(condCfg.Name, condCfg.Identifiers, condCfg.Evaluator, nil) + } else { + rule.AddExprCondition(condCfg.Name, condCfg.Expression, nil) + } + } + //now add explicit rule identifiers if any + if ruleCfg.Identifiers != nil { + idrs := []model.TupleType{} + for _, idr := range ruleCfg.Identifiers { + idrs = append(idrs, model.TupleType(idr)) + } + rule.AddIdrsToRule(idrs) } rs.AddRule(rule) diff --git a/ruleapi/tests/expr_1_test.go b/ruleapi/tests/expr_1_test.go index 41f4435..478cfa6 100644 --- a/ruleapi/tests/expr_1_test.go +++ b/ruleapi/tests/expr_1_test.go @@ -10,10 +10,13 @@ import ( //1 condition, 1 expression func Test_1_Expr(t *testing.T) { + actionCount := map[string]int{"count": 0} rs, _ := createRuleSession() r1 := ruleapi.NewRule("r1") r1.AddExprCondition("c1", "$.t2.p2 > $.t1.p1", nil) r1.SetAction(a1) + r1.SetContext(actionCount) + rs.AddRule(r1) rs.Start(nil) @@ -36,60 +39,16 @@ func Test_1_Expr(t *testing.T) { ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t2) rs.Unregister() + count := actionCount["count"] + if count != 1 { + t.Errorf("expected [%d], got [%d]\n", 1, count) + } } func a1(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { t := ctx.Value(TestKey{}).(*testing.T) t.Logf("Test_1_Expr executed!") + actionCount := ruleCtx.(map[string]int) + count := actionCount["count"] + actionCount["count"] = count + 1 } - -// -// These standalone tests are not relevant anymore as the expression API has changed -// -//func Test_Eval (t *testing.T) { -// expr, _ := expression.ParseExpression("1 == 1.23") -// i, err := expr.Eval() -// if err != nil { -// t.Fatalf("error %s\n", err) -// } -// res := i.(bool) -// if res { -// t.Errorf("Expected false, got : %t\n ", res) -// } -//} -// -//func Test_Eval2 (t *testing.T) { -// expr, _ := expression.ParseExpression("1 < 1.23") -// i, err := expr.Eval() -// if err != nil { -// t.Fatalf("error %s\n", err) -// } -// res := i.(bool) -// if !res { -// t.Errorf("Expected true, got : %t\n ", res) -// } -//} -// -//func Test_Eval3 (t *testing.T) { -// expr, _ := expression.ParseExpression("1.23 == 1") -// i, err := expr.Eval() -// if err != nil { -// t.Fatalf("error %s\n", err) -// } -// res := i.(bool) -// if res { -// t.Errorf("Expected false, got : %t\n ", res) -// } -//} -// -//func Test_Eval4 (t *testing.T) { -// expr, _ := expression.ParseExpression("1.23 > 1") -// i, err := expr.Eval() -// if err != nil { -// t.Fatalf("error %s\n", err) -// } -// res := i.(bool) -// if !res { -// t.Errorf("Expected true, got : %t\n ", res) -// } -//} diff --git a/ruleapi/tests/expr_2_test.go b/ruleapi/tests/expr_2_test.go index c27581e..5f5d7fe 100644 --- a/ruleapi/tests/expr_2_test.go +++ b/ruleapi/tests/expr_2_test.go @@ -10,11 +10,14 @@ import ( //2 conditions, 1 expr each func Test_2_Expr(t *testing.T) { + actionCount := map[string]int{"count": 0} rs, _ := createRuleSession() r1 := ruleapi.NewRule("r1") r1.AddExprCondition("c1", "$.t1.p1 > $.t2.p1", nil) r1.AddExprCondition("c2", "$.t1.p1 == 2", nil) r1.SetAction(a2) + r1.SetContext(actionCount) + rs.AddRule(r1) rs.Start(nil) @@ -37,9 +40,16 @@ func Test_2_Expr(t *testing.T) { ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t2) rs.Unregister() + count := actionCount["count"] + if count != 1 { + t.Errorf("expected [%d], got [%d]\n", 1, count) + } } func a2(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { t := ctx.Value(TestKey{}).(*testing.T) t.Logf("Test_2_Expr executed!") + actionCount := ruleCtx.(map[string]int) + count := actionCount["count"] + actionCount["count"] = count + 1 } diff --git a/ruleapi/tests/expr_3_test.go b/ruleapi/tests/expr_3_test.go index f8a49e1..37d6361 100644 --- a/ruleapi/tests/expr_3_test.go +++ b/ruleapi/tests/expr_3_test.go @@ -10,10 +10,13 @@ import ( //1 conditions, 2 expr func Test_3_Expr(t *testing.T) { + actionCount := map[string]int{"count": 0} rs, _ := createRuleSession() r1 := ruleapi.NewRule("r1") r1.AddExprCondition("c1", "($.t1.p1 > $.t2.p1) && ($.t1.p2 > $.t2.p2)", nil) r1.SetAction(a3) + r1.SetContext(actionCount) + rs.AddRule(r1) rs.Start(nil) @@ -36,9 +39,16 @@ func Test_3_Expr(t *testing.T) { ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t2) rs.Unregister() + count := actionCount["count"] + if count != 1 { + t.Errorf("expected [%d], got [%d]\n", 1, count) + } } func a3(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { t := ctx.Value(TestKey{}).(*testing.T) t.Logf("Test_3_Expr executed!") + actionCount := ruleCtx.(map[string]int) + count := actionCount["count"] + actionCount["count"] = count + 1 } diff --git a/ruleapi/tests/expr_4_test.go b/ruleapi/tests/expr_4_test.go index d4d7bfe..c3cd7f8 100644 --- a/ruleapi/tests/expr_4_test.go +++ b/ruleapi/tests/expr_4_test.go @@ -10,10 +10,13 @@ import ( //1 conditions, 3 expr func Test_4_Expr(t *testing.T) { + actionCount := map[string]int{"count": 0} rs, _ := createRuleSession() r1 := ruleapi.NewRule("r1") r1.AddExprCondition("c1", "($.t1.p1 > $.t2.p1) && (($.t1.p2 > $.t2.p2) && ($.t1.p3 == $.t2.p3))", nil) r1.SetAction(a4) + r1.SetContext(actionCount) + rs.AddRule(r1) rs.Start(nil) @@ -36,9 +39,16 @@ func Test_4_Expr(t *testing.T) { ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t2) rs.Unregister() + count := actionCount["count"] + if count != 1 { + t.Errorf("expected [%d], got [%d]\n", 1, count) + } } func a4(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { t := ctx.Value(TestKey{}).(*testing.T) t.Logf("Test_4_Expr executed!") + actionCount := ruleCtx.(map[string]int) + count := actionCount["count"] + actionCount["count"] = count + 1 } diff --git a/ruleapi/tests/expr_5_test.go b/ruleapi/tests/expr_5_test.go index 53c8668..411a50b 100644 --- a/ruleapi/tests/expr_5_test.go +++ b/ruleapi/tests/expr_5_test.go @@ -10,10 +10,13 @@ import ( //1 arithmetic operation func Test_5_Expr(t *testing.T) { + actionCount := map[string]int{"count": 0} rs, _ := createRuleSession() r1 := ruleapi.NewRule("r1") r1.AddExprCondition("c1", "(($.t1.p1 + $.t2.p1) == 5) && (($.t1.p2 > $.t2.p2) && ($.t1.p3 == $.t2.p3))", nil) r1.SetAction(a5) + r1.SetContext(actionCount) + rs.AddRule(r1) rs.Start(nil) @@ -36,9 +39,16 @@ func Test_5_Expr(t *testing.T) { ctx = context.WithValue(context.TODO(), TestKey{}, t) rs.Assert(ctx, t2) rs.Unregister() + count := actionCount["count"] + if count != 1 { + t.Errorf("expected [%d], got [%d]\n", 1, count) + } } func a5(ctx context.Context, rs model.RuleSession, ruleName string, tuples map[model.TupleType]model.Tuple, ruleCtx model.RuleContext) { t := ctx.Value(TestKey{}).(*testing.T) t.Logf("Test_5_Expr executed!") + actionCount := ruleCtx.(map[string]int) + count := actionCount["count"] + actionCount["count"] = count + 1 }