Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

flogo expressions support for rule conditions #71

Merged
merged 13 commits into from
Apr 28, 2020
7 changes: 6 additions & 1 deletion common/model/tuple.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -273,3 +274,7 @@ func (t *tupleImpl) isKeyProp(propName string) bool {
}
return found
}

func (t *tupleImpl) GetMap() map[string]interface{} {
return t.tuples
}
2 changes: 1 addition & 1 deletion common/model/tuplekey.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package model

import (
"fmt"
"reflect"
"github.com/project-flogo/core/data/coerce"
"reflect"
)

// TupleKey primary key of a tuple
Expand Down
11 changes: 5 additions & 6 deletions common/model/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,18 @@ type MutableRule interface {
SetAction(actionFn ActionFunction)
SetPriority(priority int)
SetContext(ctx RuleContext)
AddExprCondition(conditionName string, cExpr string, ctx RuleContext) error
AddIdrsToRule(idrs []TupleType)
}

//Condition interface to maintain/get various condition properties
type Condition interface {
GetName() string
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
Expand Down Expand Up @@ -71,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
Expand All @@ -92,16 +93,14 @@ 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 {
GetTuple() Tuple
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{})
37 changes: 27 additions & 10 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,19 @@ 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
type ConditionDescriptor struct {
Name string
Identifiers []string
Evaluator model.ConditionEvaluator
Expression string
}

func (c *RuleDescriptor) UnmarshalJSON(d []byte) error {
Expand All @@ -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 {
Expand All @@ -52,13 +55,22 @@ 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
}

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 {
Expand All @@ -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 {
Expand All @@ -91,22 +104,26 @@ 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
}

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
}
Expand Down
23 changes: 0 additions & 23 deletions config/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
*/
71 changes: 37 additions & 34 deletions examples/flogo/simple/flogo.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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"
}
}
]
Expand Down Expand Up @@ -92,22 +84,18 @@
}
],
"output": [
{
"name": "outputData",
"type": "any"
}
{
"name": "outputData",
"type": "any"
}
]
},
"rules": [
{
"name": "n1.name == Bob",
"conditions": [
{
"name": "c1",
"identifiers": [
"n1"
],
"evaluator": "checkForBob"
"expression" : "$.n1.name == 'Bob'"
}
],
"actionFunction": "checkForBobAction"
Expand All @@ -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"
}
]
}
Expand Down
25 changes: 25 additions & 0 deletions examples/flogo/simple/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
10 changes: 7 additions & 3 deletions rete/filternode.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
Loading