Skip to content

Commit

Permalink
Replace MergeInto with Patch & Replace rules
Browse files Browse the repository at this point in the history
  • Loading branch information
Galaco committed Jan 4, 2019
1 parent 049ba58 commit d4f3dde
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 13 deletions.
40 changes: 31 additions & 9 deletions keyvalue.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
)

const reservedKeyPatch = "patch"
const reservedKeyReplace = "replace"

// A KeyValue object, that may hold multiple Values
type KeyValue struct {
Expand Down Expand Up @@ -139,37 +140,58 @@ func (node *KeyValue) Parent() *KeyValue {
return node.parent
}

func (node *KeyValue) Patch(parent *KeyValue) (merged KeyValue, err error) {
merged = *parent
if node.Key() != merged.Key() {
// "patch" is a special key that can appear at the root of a keyvalue
// it does what it sounds like, its ony real purpose is to patch another tree
// with its own values
if node.Key() != reservedKeyPatch || node.Parent() == nil || node.Parent().Key() != tokenRootNodeKey {
return merged,errors.New("cannot merge mismatched root nodes")
}
node.key = merged.Key()
}

err = recursiveMerge(node, &merged, false)

return merged,err
}

// MergeInto merges this KeyValue tree into another.
// The resultant tree will contain all nodes in the same tree from both
// this and the target.
// In the case where a key exists in both trees, this key's value will
// replace the parent's value
func (node *KeyValue) MergeInto(parent *KeyValue) (merged KeyValue, err error) {
func (node *KeyValue) Replace(parent *KeyValue) (merged KeyValue, err error) {
merged = *parent
if node.Key() != merged.Key() {
// "patch" is a special key that can appear at the root of a keyvalue
// it does what it sounds like, its ony real purpose is to patch another tree
// with its own values
if node.Key() != reservedKeyPatch || node.Parent() == nil || node.Parent().Key() != tokenRootNodeKey {
// "replace" is a special key that can appear at the root of a keyvalue
// it does what it sounds like, its ony real purpose is to replace another tree's values
// with its own values if found, else add them.
if node.Key() != reservedKeyReplace || node.Parent() == nil || node.Parent().Key() != tokenRootNodeKey {
return merged,errors.New("cannot merge mismatched root nodes")
}
node.key = merged.Key()
}

err = recursiveMerge(node, &merged)
err = recursiveMerge(node, &merged, true)

return merged,err
}

// recursiveMerge merge a into b
// if a.Key() == b.Key(), a will replace b
func recursiveMerge(a *KeyValue, b *KeyValue) (err error) {
// if a.Key() == b.Key() && shouldReplace, a will replace b unless they have children, then
// recurse downwards.
func recursiveMerge(a *KeyValue, b *KeyValue, shouldReplace bool) (err error) {
// Bottem level node on parent tree
if b.HasChildren() == false {
// only option is to replace b with a, and types must match
if a.Key() != b.Key() {
return errors.New("mismatched types on keyvalue")
}
if shouldReplace == false {
return nil
}
b.valueType = a.valueType
b.value = a.value
return nil
Expand Down Expand Up @@ -200,7 +222,7 @@ func recursiveMerge(a *KeyValue, b *KeyValue) (err error) {
return err
}
} else {
err = recursiveMerge(children[idx], childB)
err = recursiveMerge(children[idx], childB, shouldReplace)
if err != nil {
return err
}
Expand Down
8 changes: 4 additions & 4 deletions keyvalue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func TestKeyValue_AsFloat(t *testing.T) {

func TestKeyValue_MergeInto(t *testing.T) {
a := &KeyValue{
key: "foo",
key: "replace",
valueType: ValueArray,
value: []interface{}{
&KeyValue{
Expand Down Expand Up @@ -212,7 +212,7 @@ func TestKeyValue_MergeInto(t *testing.T) {
},
}

result,err := a.MergeInto(b)
result,err := a.Replace(b)
if err != nil {
t.Error(err)
}
Expand Down Expand Up @@ -246,7 +246,7 @@ func TestKeyValue_MergeInto(t *testing.T) {

func TestKeyValue_RemoveChild(t *testing.T) {
a := &KeyValue{
key: "foo",
key: "replace",
valueType: ValueArray,
value: []interface{}{
&KeyValue{
Expand Down Expand Up @@ -293,7 +293,7 @@ func TestKeyValue_RemoveChild(t *testing.T) {
},
}

result,err := a.MergeInto(b)
result,err := a.Replace(b)
if err != nil {
t.Error(err)
}
Expand Down

0 comments on commit d4f3dde

Please sign in to comment.