Skip to content

Commit 42381d7

Browse files
committed
Add NewInherit
1 parent d0d944d commit 42381d7

File tree

2 files changed

+69
-4
lines changed

2 files changed

+69
-4
lines changed

jsonlogic.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,23 @@ var (
1111

1212
// JSONLogic is an evaluator of json logic with a set of operations.
1313
type JSONLogic struct {
14-
ops map[string]Operation
14+
parent *JSONLogic
15+
ops map[string]Operation
1516
}
1617

1718
type Applier func(logic, data interface{}) (res interface{}, err error)
1819

1920
type Operation func(apply Applier, params []interface{}, data interface{}) (interface{}, error)
2021

21-
// New creates a JSONLogic with standard operations.
22+
// NewInherit creates a child JSONLogic instance.
23+
func NewInherit(parent *JSONLogic) *JSONLogic {
24+
return &JSONLogic{
25+
parent: parent,
26+
ops: make(map[string]Operation),
27+
}
28+
}
29+
30+
// New creates a root (no parent) JSONLogic with standard operations.
2231
func New() *JSONLogic {
2332
ret := NewEmpty()
2433
// Data access.
@@ -59,6 +68,7 @@ func New() *JSONLogic {
5968
return ret
6069
}
6170

71+
// NewEmpty creates a root (no parent) JSONLogic with no operation.
6272
func NewEmpty() *JSONLogic {
6373
return &JSONLogic{
6474
ops: make(map[string]Operation),
@@ -112,7 +122,14 @@ func (jl *JSONLogic) Apply(logic, data interface{}) (res interface{}, err error)
112122
}
113123
}()
114124

115-
opFn := jl.ops[op]
125+
var opFn Operation
126+
for inst := jl; inst != nil; inst = inst.parent {
127+
var ok bool
128+
opFn, ok = inst.ops[op]
129+
if ok {
130+
break
131+
}
132+
}
116133
if opFn == nil {
117134
return nil, fmt.Errorf("Apply: operator %q not found", op)
118135
}
@@ -126,6 +143,7 @@ func AddOperation(name string, op Operation) {
126143
}
127144

128145
// AddOperation adds a named operation to JSONLogic instance.
146+
// Can override parent's same name operation.
129147
func (jl *JSONLogic) AddOperation(name string, op Operation) {
130148
jl.ops[name] = op
131149
}
@@ -138,7 +156,8 @@ func Clone() *JSONLogic {
138156
// Clone clones a JSONLogic instance.
139157
func (jl *JSONLogic) Clone() *JSONLogic {
140158
ret := &JSONLogic{
141-
ops: make(map[string]Operation),
159+
parent: jl.parent,
160+
ops: make(map[string]Operation),
142161
}
143162
for k, v := range jl.ops {
144163
ret.ops[k] = v

jsonlogic_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package jsonlogic
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestNewInherit(t *testing.T) {
10+
assert := assert.New(t)
11+
12+
parent := NewEmpty()
13+
parent.AddOperation("xxx", func(apply Applier, params []interface{}, data interface{}) (interface{}, error) {
14+
return "parent", nil
15+
})
16+
17+
child := NewInherit(parent)
18+
child.AddOperation("xxx", func(apply Applier, params []interface{}, data interface{}) (interface{}, error) {
19+
return "child", nil
20+
})
21+
22+
notFoundChild := NewInherit(parent)
23+
notFoundChild.AddOperation("xxx", nil)
24+
25+
logic := map[string]interface{}{
26+
"xxx": nil,
27+
}
28+
29+
{
30+
res, err := child.Apply(logic, nil)
31+
assert.NoError(err)
32+
assert.Equal("child", res)
33+
}
34+
35+
{
36+
_, err := notFoundChild.Apply(logic, nil)
37+
assert.Error(err)
38+
}
39+
40+
{
41+
res, err := parent.Apply(logic, nil)
42+
assert.NoError(err)
43+
assert.Equal("parent", res)
44+
}
45+
46+
}

0 commit comments

Comments
 (0)