mcmp: make InheritedValue a function, not a method, and add Parent method to support it

This commit is contained in:
Brian Picciano 2019-06-23 11:17:48 -06:00
parent 6cd61c60f7
commit 752e266685
2 changed files with 47 additions and 31 deletions

View File

@ -69,20 +69,6 @@ func (c *Component) Value(key interface{}) interface{} {
return value return value
} }
// InheritedValue returns the value which has been set for the given key. It first
// looks for the key on the receiver Component. If not found, it will look on
// its parent Component, and so on, until the key is found. If the key is not
// found on the root Component then false is returned.
func (c *Component) InheritedValue(key interface{}) (interface{}, bool) {
value, ok := c.value(key)
if ok {
return value, ok
} else if c.parent == nil {
return nil, false
}
return c.parent.InheritedValue(key)
}
// Values returns all key/value pairs which have been set via SetValue. // Values returns all key/value pairs which have been set via SetValue.
func (c *Component) Values() map[interface{}]interface{} { func (c *Component) Values() map[interface{}]interface{} {
c.l.RLock() c.l.RLock()
@ -137,6 +123,13 @@ func (c *Component) Children() []*Component {
return children return children
} }
// Parent returns the Component from which this one was created via the Child
// method. This returns nil if this Component was not created via Child (and is
// therefore the root Component).
func (c *Component) Parent() *Component {
return c.parent
}
// Name returns the name this Component was created with (via the Child method), // Name returns the name this Component was created with (via the Child method),
// or false if this Component was not created via Child (and is therefore the // or false if this Component was not created via Child (and is therefore the
// root Component). // root Component).
@ -216,3 +209,17 @@ func BreadthFirstVisit(c *Component, callback func(*Component) bool) {
queue = queue[1:] queue = queue[1:]
} }
} }
// InheritedValue returns the value which has been set for the given key. It
// first looks for the key on the receiver Component. If not found, it will look
// on its parent Component, and so on, until the key is found. If the key is not
// found on any Components, up to the root Component, then false is returned.
func InheritedValue(c *Component, key interface{}) (interface{}, bool) {
if c.HasValue(key) {
return c.kv[key], true
} else if parent := c.Parent(); parent == nil {
return nil, false
} else {
return InheritedValue(parent, key)
}
}

View File

@ -53,23 +53,6 @@ func TestComponent(t *T) {
assertValue(child, "bar", 2), assertValue(child, "bar", 2),
) )
assertInheritedValue := func(c *Component, key, expectedValue interface{}) massert.Assertion {
val, ok := c.InheritedValue(key)
return massert.All(
massert.Equal(expectedValue, val),
massert.Equal(expectedValue != nil, ok),
)
}
// test that InheritedValue does what it's supposed to
massert.Require(t,
assertInheritedValue(c, "foo", 1),
assertInheritedValue(child, "foo", 1),
assertInheritedValue(c, "bar", nil),
assertInheritedValue(child, "bar", 2),
assertInheritedValue(c, "xxx", nil),
assertInheritedValue(child, "xxx", nil),
)
} }
func TestBreadFirstVisit(t *T) { func TestBreadFirstVisit(t *T) {
cmp := new(Component) cmp := new(Component)
@ -103,3 +86,29 @@ func TestBreadFirstVisit(t *T) {
) )
} }
} }
func TestInheritedValue(t *T) {
assertInheritedValue := func(c *Component, key, expectedValue interface{}) massert.Assertion {
val, ok := InheritedValue(c, key)
return massert.All(
massert.Equal(expectedValue, val),
massert.Equal(expectedValue != nil, ok),
)
}
c := new(Component)
c.SetValue("foo", 1)
child := c.Child("child")
child.SetValue("bar", 2)
// test that InheritedValue does what it's supposed to
massert.Require(t,
assertInheritedValue(c, "foo", 1),
assertInheritedValue(child, "foo", 1),
assertInheritedValue(c, "bar", nil),
assertInheritedValue(child, "bar", 2),
assertInheritedValue(c, "xxx", nil),
assertInheritedValue(child, "xxx", nil),
)
}