2017-11-27 05:53:04 +00:00
|
|
|
package context
|
|
|
|
|
2017-11-27 09:41:29 +00:00
|
|
|
import "sync"
|
|
|
|
|
2017-11-27 10:13:19 +00:00
|
|
|
type Attributer interface {
|
|
|
|
Attributes() Attributes
|
|
|
|
}
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
type Attributes interface {
|
|
|
|
initialize()
|
|
|
|
Set(key string, value interface{})
|
|
|
|
Get(key string) (value interface{})
|
|
|
|
Remove(key string)
|
2017-11-27 05:53:04 +00:00
|
|
|
Contains(key string) (exist bool)
|
|
|
|
Destroy()
|
|
|
|
}
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
func NewAttributes(parent Attributes) Attributes {
|
|
|
|
am := &attributes{
|
|
|
|
Parent: parent,
|
|
|
|
}
|
|
|
|
am.initialize()
|
|
|
|
|
|
|
|
return am
|
|
|
|
}
|
|
|
|
|
|
|
|
type attributes struct {
|
|
|
|
Parent Attributes
|
|
|
|
values map[string]interface{}
|
2017-11-27 09:41:29 +00:00
|
|
|
|
|
|
|
mtx sync.RWMutex
|
2017-11-27 05:53:04 +00:00
|
|
|
}
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
func (am *attributes) initialize() {
|
2017-11-27 09:41:29 +00:00
|
|
|
if nil != am.Parent {
|
2017-11-27 09:57:43 +00:00
|
|
|
am.Parent.initialize()
|
2017-11-27 09:41:29 +00:00
|
|
|
}
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
if nil == am.values {
|
2017-11-27 05:57:26 +00:00
|
|
|
am.Destroy()
|
2017-11-27 05:53:04 +00:00
|
|
|
}
|
2017-11-27 09:57:43 +00:00
|
|
|
am.values = make(map[string]interface{})
|
2017-11-27 05:53:04 +00:00
|
|
|
}
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
func (am *attributes) Set(key string, value interface{}) {
|
2017-11-27 09:41:29 +00:00
|
|
|
am.checkInitialized()
|
|
|
|
|
|
|
|
am.mtx.Lock()
|
|
|
|
defer am.mtx.Unlock()
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
am.values[key] = value
|
2017-11-27 05:53:04 +00:00
|
|
|
}
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
func (am *attributes) Get(key string) (value interface{}) {
|
2017-11-27 09:41:29 +00:00
|
|
|
am.checkInitialized()
|
|
|
|
|
|
|
|
am.mtx.RLock()
|
|
|
|
defer am.mtx.RUnlock()
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
if _, ok := am.values[key]; ok {
|
|
|
|
return am.values[key]
|
2017-11-27 05:53:04 +00:00
|
|
|
}
|
|
|
|
|
2017-11-27 09:41:29 +00:00
|
|
|
if nil == am.Parent {
|
2017-11-27 05:53:04 +00:00
|
|
|
return nil
|
|
|
|
}
|
2017-11-27 09:57:43 +00:00
|
|
|
return am.Parent.Get(key)
|
2017-11-27 05:53:04 +00:00
|
|
|
}
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
func (am *attributes) Remove(key string) {
|
2017-11-27 09:41:29 +00:00
|
|
|
am.checkInitialized()
|
|
|
|
|
|
|
|
am.mtx.Lock()
|
|
|
|
defer am.mtx.Unlock()
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
if _, ok := am.values[key]; ok {
|
|
|
|
delete(am.values, key)
|
2017-11-27 09:41:29 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if nil == am.Parent {
|
2017-11-27 05:53:04 +00:00
|
|
|
return
|
|
|
|
}
|
2017-11-27 09:41:29 +00:00
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
am.Parent.Remove(key)
|
2017-11-27 05:53:04 +00:00
|
|
|
}
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
func (am *attributes) Contains(key string) (exist bool) {
|
2017-11-27 09:41:29 +00:00
|
|
|
am.checkInitialized()
|
|
|
|
|
|
|
|
am.mtx.RLock()
|
|
|
|
defer am.mtx.RUnlock()
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
if _, ok := am.values[key]; ok {
|
2017-11-27 09:41:29 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
if nil == am.Parent {
|
2017-11-27 05:53:04 +00:00
|
|
|
return false
|
|
|
|
}
|
2017-11-27 09:41:29 +00:00
|
|
|
return am.Parent.Contains(key)
|
2017-11-27 05:53:04 +00:00
|
|
|
}
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
func (am *attributes) Destroy() {
|
|
|
|
if nil != am.values {
|
|
|
|
am.values = nil
|
2017-11-27 05:53:04 +00:00
|
|
|
}
|
2017-11-27 09:41:29 +00:00
|
|
|
|
|
|
|
if nil != am.Parent {
|
|
|
|
am.Parent.Destroy()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-27 09:57:43 +00:00
|
|
|
func (am *attributes) checkInitialized() {
|
|
|
|
if nil == am.values {
|
2017-11-27 09:41:29 +00:00
|
|
|
panic("Attribute Manager: must be initialized")
|
|
|
|
}
|
2017-11-27 05:53:04 +00:00
|
|
|
}
|