Skip to content

Commit

Permalink
Merge pull request #8 from sidhant92/nested_key
Browse files Browse the repository at this point in the history
Nested Field Support
  • Loading branch information
sidhant92 authored Feb 23, 2023
2 parents 512a0ed + 6324782 commit fb590a9
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 24 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Parentheses, `(` and `)`, can be used for grouping.
#### Usage Notes
* Phrases that includes quotes, like `content = "It's a wonderful day"`
* Phrases that includes quotes, like `attribute = 'She said "Hello World"'`
* For nested keys in data map you can use the dot notation, like `person.age`

## Usage
```
Expand Down Expand Up @@ -127,7 +128,7 @@ res, err := evaluator.Evaluate("name = sid AND (age = 25 OR num = 44)", data)
assert.Nil(t, err)
assert.True(t, res)
```
App Version Comparison
Semantic Version Comparison
```
data := map[string]interface{}{
"app_version": "1.5.9",
Expand Down
1 change: 0 additions & 1 deletion internal/parser/antlr/antlr_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,6 @@ func TestStringList2(t *testing.T) {
assert.Equal(t, res.(domain.InNode).Items[2].Value, "ab\"c")
}


func TestInvalidExpression(t *testing.T) {
_, err := parser.Parse("a")
assert.NotNil(t, err)
Expand Down
20 changes: 20 additions & 0 deletions internal/util/value_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,30 @@ package util
import (
"github.com/hashicorp/go-version"
"github.com/sidhant92/bool-parser-go/pkg/constant"
"log"
"strconv"
"strings"
)

func GetValueFromMap(key string, data map[string]interface{}) interface{} {
keys := strings.Split(key, ".")
size := len(keys)
value, ok := data[keys[0]]
if size == 1 {
if ok {
return value
} else {
return nil
}
}
nestedMap, ok := value.(map[string]interface{})
if ok {
return GetValueFromMap(keys[1], nestedMap)
}
log.Printf("could not find key %s for the data %s", key, data)
return nil
}

func ConvertValue(value string, dataType constant.DataType) (interface{}, error) {
switch dataType {
case constant.INTEGER:
Expand Down
34 changes: 13 additions & 21 deletions pkg/application/boolean_expression_evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package application
import (
"errors"
"github.com/sidhant92/bool-parser-go/internal/service"
"github.com/sidhant92/bool-parser-go/internal/util"
"github.com/sidhant92/bool-parser-go/pkg/constant"
"github.com/sidhant92/bool-parser-go/pkg/domain"
errors2 "github.com/sidhant92/bool-parser-go/pkg/error"
"github.com/sidhant92/bool-parser-go/pkg/parser"
"log"
)

type BooleanExpressionEvaluator struct {
Expand Down Expand Up @@ -41,18 +41,18 @@ func (b *BooleanExpressionEvaluator) evaluateNode(node domain.Node, data map[str
}

func (b *BooleanExpressionEvaluator) evaluateComparisonNode(node domain.ComparisonNode, data map[string]interface{}) (bool, error) {
if b.checkFieldDataMissing(node.Field, data) {
return false, nil
fieldData := util.GetValueFromMap(node.Field, data)
if fieldData == nil {
return false, errors2.KEY_DATA_NOT_PRESENT
}
fieldData := data[node.Field]
return b.OperatorService.Evaluate(node.Operator, node.DataType, fieldData, node.Value)
}

func (b *BooleanExpressionEvaluator) evaluateNumericRangeNode(node domain.NumericRangeNode, data map[string]interface{}) (bool, error) {
if b.checkFieldDataMissing(node.Field, data) {
return false, nil
fieldData := util.GetValueFromMap(node.Field, data)
if fieldData == nil {
return false, errors2.KEY_DATA_NOT_PRESENT
}
fieldData := data[node.Field]
leftRes, err := b.OperatorService.Evaluate(constant.GREATER_THAN_EQUAL, node.FromDataType, fieldData, node.FromValue)
if err != nil {
return false, err
Expand All @@ -65,10 +65,10 @@ func (b *BooleanExpressionEvaluator) evaluateNumericRangeNode(node domain.Numeri
}

func (b *BooleanExpressionEvaluator) evaluateInNode(node domain.InNode, data map[string]interface{}) (bool, error) {
if b.checkFieldDataMissing(node.Field, data) {
return false, nil
fieldData := util.GetValueFromMap(node.Field, data)
if fieldData == nil {
return false, errors2.KEY_DATA_NOT_PRESENT
}
fieldData := data[node.Field]
dataType := node.Items[0].DataType
var values []interface{}
for _, item := range node.Items {
Expand All @@ -85,10 +85,10 @@ func (b *BooleanExpressionEvaluator) evaluateUnaryNode(node domain.UnaryNode, da
if node.DataType == constant.BOOLEAN {
return node.Value.(bool), nil
}
if b.checkFieldDataMissing(node.Value.(string), data) {
return false, nil
fieldData := util.GetValueFromMap(node.Value.(string), data)
if fieldData == nil {
return false, errors2.KEY_DATA_NOT_PRESENT
}
fieldData := data[node.Value.(string)]
val, ok := fieldData.(bool)
if ok {
return val, nil
Expand Down Expand Up @@ -127,14 +127,6 @@ func (b *BooleanExpressionEvaluator) evaluateBooleanNode(node domain.BooleanNode
}
}

func (b *BooleanExpressionEvaluator) checkFieldDataMissing(field string, data map[string]interface{}) bool {
if _, ok := data[field]; ok {
return false
}
log.Println("required field data is missing")
return true
}

func NewBooleanExpressionEvaluator(parser parser.Parser) BooleanExpressionEvaluator {
return BooleanExpressionEvaluator{parser, service.NewOperatorService()}
}
24 changes: 23 additions & 1 deletion pkg/application/boolean_expression_evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,28 @@ func TestNumericGreaterThanCorrectExpression(t *testing.T) {
assert.True(t, res)
}

func TestNestedField(t *testing.T) {
data := map[string]interface{}{
"person": map[string]interface{}{
"age": 24,
},
}
res, err := evaluator.Evaluate("person.age > 20", data)
assert.Nil(t, err)
assert.True(t, res)
}

func TestMissingNestedField(t *testing.T) {
data := map[string]interface{}{
"person": map[string]interface{}{
"age": 24,
},
}
res, err := evaluator.Evaluate("person.agee > 20", data)
assert.ErrorIs(t, err, errors2.KEY_DATA_NOT_PRESENT)
assert.False(t, res)
}

func TestNumericGreaterThanIncorrectExpression(t *testing.T) {
data := map[string]interface{}{
"age": 26,
Expand Down Expand Up @@ -321,7 +343,7 @@ func TestKeyMissing(t *testing.T) {
"agee": 34,
}
res, err := evaluator.Evaluate("age = 24", data)
assert.Nil(t, err)
assert.ErrorIs(t, err, errors2.KEY_DATA_NOT_PRESENT)
assert.False(t, res)
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/error/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ import "errors"
var INVALID_DATA_TYPE = errors.New("invalid data type")

var INVALID_UNARY_OPERAND = errors.New("invalid unary operand")

var KEY_DATA_NOT_PRESENT = errors.New("key data not present")

0 comments on commit fb590a9

Please sign in to comment.