Skip to content

Commit

Permalink
Support for regex MatchString function (#284)
Browse files Browse the repository at this point in the history
* Fix for String In issue

* added check for isvalid condition

* removed extra nil check and len check

* Antlr4.9 and go runtime changes

* Update ANTLR.md

* updated with review comments

* remove rule entry changes

* removing rule entry from knowledgebase library

* added comments

* updated with review comments

* updated go.mod

* Added UUID import

* Minor comment changes

* reverted back

* minor code comment changes

* Support for regex match string function
  • Loading branch information
jinagamvasubabu authored Feb 21, 2022
1 parent 7934a3b commit 167f0b2
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 7 deletions.
21 changes: 21 additions & 0 deletions docs/cn/Function_cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,27 @@ rule TrimText "Do something when Fact.Text is 'ABC'" {
}
```
### string.MatchString() string
`MatchString` MatchString reports whether the string s contains any match of the regular expression pattern. Similar to golang [MatchString](https://pkg.go.dev/regexp#MatchString)
#### Returns
* True if the `regexPattern` matches the string s
* False if the `regexPattern` doesn't match the string s
#### Example
```Shell
rule MatchStringText "Return true when regex pattern matches the string" {
when
Fact.Text.MatchString("B([a-z]+)ck")
then
Fact.DoSomething();
}
```
### array.Len() int
`Len` 返回数据或者切片的长度.
Expand Down
21 changes: 21 additions & 0 deletions docs/de/Function_de.md
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,27 @@ rule TrimText "Do something when Fact.Text is 'ABC'" {
}
```
### string.MatchString() string
`MatchString` MatchString reports whether the string s contains any match of the regular expression pattern. Similar to golang [MatchString](https://pkg.go.dev/regexp#MatchString)
#### Returns
* True if the `regexPattern` matches the string s
* False if the `regexPattern` doesn't match the string s
#### Example
```Shell
rule MatchStringText "Return true when regex pattern matches the string" {
when
Fact.Text.MatchString("B([a-z]+)ck")
then
Fact.DoSomething();
}
```
### array.Len() int
`Len` will return the length of the array/slice.
Expand Down
21 changes: 21 additions & 0 deletions docs/en/Function_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,27 @@ rule TrimText "Do something when Fact.Text is 'ABC'" {
}
```
### string.MatchString() string
`MatchString` MatchString reports whether the string s contains any match of the regular expression pattern. Similar to golang [MatchString](https://pkg.go.dev/regexp#MatchString)
#### Returns
* True if the `regexPattern` matches the string s
* False if the `regexPattern` doesn't match the string s
#### Example
```Shell
rule MatchStringText "Return true when regex pattern matches the string" {
when
Fact.Text.MatchString("B([a-z]+)ck")
then
Fact.DoSomething();
}
```
### array.Len() int
`Len` will return the length of the array/slice.
Expand Down
20 changes: 20 additions & 0 deletions docs/id/Function_id.md
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,26 @@ rule TrimText "Do something when Fact.Text is 'ABC'" {
}
```
### string.MatchString() string
`MatchString` MatchString reports whether the string s contains any match of the regular expression pattern. Similar to golang [MatchString](https://pkg.go.dev/regexp#MatchString)
#### Returns
* True if the `regexPattern` matches the string s
* False if the `regexPattern` doesn't match the string s
#### Example
```Shell
rule MatchStringText "Return true when regex pattern matches the string" {
when
Fact.Text.MatchString("B([a-z]+)ck")
then
Fact.DoSomething();
}
```
### array.Len() int
`Len` will return the length of the array/slice.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,28 @@ import (
)

const (
Rule1 = `
rule ColorCheck "test 1" {
strInConditionRule = `
rule StrInConditionCheck "test 1" {
when
Color.Name.In("Black", "Yellow")
then
Color.Message = "Its either black or yellow!!!";
Retract("ColorCheck");
Retract("StrInConditionCheck");
}
`
strMatchStringConditionRule = `
rule strMatchStringConditionCheck "test 2" {
when
Color.Name.MatchString("B([a-z]+)ck")
then
Color.Message = "yes its Black!!!";
Retract("strMatchStringConditionCheck");
}
`
)

type Color struct {
Name string
Name string
Message string
}

Expand All @@ -45,19 +54,40 @@ func TestStringInExample(t *testing.T) {
Name: "Black",
Message: "",
}

dataContext := ast.NewDataContext()
err := dataContext.Add("Color", color)
assert.NoError(t, err)

// Prepare knowledgebase library and load it with our rule.
lib := ast.NewKnowledgeLibrary()
rb := builder.NewRuleBuilder(lib)
err = rb.BuildRuleFromResource("Test", "0.1.1", pkg.NewBytesResource([]byte(Rule1)))
err = rb.BuildRuleFromResource("Test", "0.1.1", pkg.NewBytesResource([]byte(strInConditionRule)))
assert.NoError(t, err)
kb := lib.NewKnowledgeBaseInstance("Test", "0.1.1")
eng1 := &engine.GruleEngine{MaxCycle: 1}
err = eng1.Execute(dataContext, kb)
assert.NoError(t, err)
assert.Equal(t, "Its either black or yellow!!!", color.Message)
}

func TestStringMatchStringExample(t *testing.T) {
color := &Color{
Name: "Black",
Message: "",
}

dataContext := ast.NewDataContext()
err := dataContext.Add("Color", color)
assert.NoError(t, err)

// Prepare knowledgebase library and load it with our rule.
lib := ast.NewKnowledgeLibrary()
rb := builder.NewRuleBuilder(lib)
err = rb.BuildRuleFromResource("Test", "0.1.1", pkg.NewBytesResource([]byte(strMatchStringConditionRule)))
assert.NoError(t, err)
kb := lib.NewKnowledgeBaseInstance("Test", "0.1.1")
eng1 := &engine.GruleEngine{MaxCycle: 1}
err = eng1.Execute(dataContext, kb)
assert.NoError(t, err)
assert.Equal(t, "yes its Black!!!", color.Message)
}
14 changes: 13 additions & 1 deletion model/DataAccessLayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ package model
import (
"fmt"
"reflect"
"regexp"
"strings"

"github.com/hyperjumptech/grule-rule-engine/pkg"
)

Expand Down Expand Up @@ -220,6 +220,18 @@ func StrIn(str string, arg []reflect.Value) (reflect.Value, error) {
return reflect.ValueOf(false), nil
}

// StrMatchRegexPattern reports whether the string s contains any match of the regular expression pattern.
func StrMatchRegexPattern(str string, arg []reflect.Value) (reflect.Value, error) {
if arg == nil || len(arg) != 1 || arg[0].Kind() != reflect.String {
return reflect.ValueOf(nil), fmt.Errorf("function StrMatchRegexPattern requires 1 string argument")
}
m, err := regexp.MatchString(arg[0].String(), str)
if err != nil {
return reflect.ValueOf(nil), fmt.Errorf("function StrMatchRegexPattern requires valid regex pattern")
}
return reflect.ValueOf(m), nil
}

// ArrMapLen will return the size of underlying map, array or slice
func ArrMapLen(arr reflect.Value, arg []reflect.Value) (reflect.Value, error) {
if arg != nil && len(arg) != 0 {
Expand Down
27 changes: 27 additions & 0 deletions model/DataAccessLayer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,4 +181,31 @@ func TestStrIn_Accepts_Empty_Arguments(t *testing.T) {
b := "Black"
_, err := StrIn(b, []reflect.Value{})
assert.NoError(t, err)
}


func TestStrMatchRegexPattern_Valid_Regex_Pattern(t *testing.T) {
regex := "p([a-z]+)ch"
str := "peach"

val, err := StrMatchRegexPattern(str, []reflect.Value{reflect.ValueOf(regex)})
assert.NoError(t, err)
assert.True(t, val.Bool())
}

func TestStrMatchRegexPattern_InValid_Regex_Pattern(t *testing.T) {
regex := "p([a-z]ch"
str := "peach"

_, err := StrMatchRegexPattern(str, []reflect.Value{reflect.ValueOf(regex)})
assert.Error(t, err)
}

func TestStrMatchRegexPattern_Not_Match(t *testing.T) {
regex := "p([a-z]+)ch"
str := "pe1ch"

val, err := StrMatchRegexPattern(str, []reflect.Value{reflect.ValueOf(regex)})
assert.NoError(t, err)
assert.False(t, val.Bool())
}
2 changes: 2 additions & 0 deletions model/GoDataAccessLayer.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ func (node *GoValueNode) CallFunction(funcName string, args ...reflect.Value) (r
strfunc = StrTrim
case "Len":
strfunc = StrLen
case "MatchString":
strfunc = StrMatchRegexPattern
}
if strfunc != nil {
val, err := strfunc(node.thisValue.String(), args)
Expand Down

0 comments on commit 167f0b2

Please sign in to comment.