2017-11-10 07:05:28 +00:00
|
|
|
package context
|
|
|
|
|
2017-11-27 16:05:04 +00:00
|
|
|
import (
|
|
|
|
"reflect"
|
|
|
|
"sync"
|
|
|
|
)
|
2017-11-27 10:51:03 +00:00
|
|
|
|
2017-11-10 07:05:28 +00:00
|
|
|
type ContextKey string
|
|
|
|
|
|
|
|
func (c ContextKey) String() string {
|
|
|
|
return string(c)
|
|
|
|
}
|
2017-11-27 10:51:03 +00:00
|
|
|
|
|
|
|
func NewContext(parent Context) Context {
|
|
|
|
c := &defaultContext{
|
2017-11-27 10:58:54 +00:00
|
|
|
Context: parent,
|
2017-11-27 10:51:03 +00:00
|
|
|
}
|
2017-11-27 16:05:04 +00:00
|
|
|
c.attributes = make(map[interface{}]interface{})
|
2017-11-27 10:51:03 +00:00
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
|
|
|
type Context interface {
|
2017-11-27 11:01:36 +00:00
|
|
|
Parent() Context
|
2017-11-27 16:05:04 +00:00
|
|
|
SetAttribute(key interface{}, value interface{})
|
|
|
|
GetAttribute(key interface{}) (value interface{})
|
|
|
|
RemoveAttribute(key interface{})
|
|
|
|
ContainsAttribute(key interface{}) (exist bool)
|
2017-11-27 10:51:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type defaultContext struct {
|
2017-11-27 10:58:54 +00:00
|
|
|
Context
|
2017-11-27 16:05:04 +00:00
|
|
|
attributes map[interface{}]interface{}
|
2017-11-27 10:51:03 +00:00
|
|
|
|
|
|
|
mtx sync.RWMutex
|
|
|
|
}
|
|
|
|
|
2017-11-27 11:01:36 +00:00
|
|
|
func (dc *defaultContext) Parent() Context {
|
|
|
|
return dc.Context
|
|
|
|
}
|
|
|
|
|
2017-11-27 16:05:04 +00:00
|
|
|
func (dc *defaultContext) SetAttribute(key interface{}, value interface{}) {
|
2017-11-27 10:51:03 +00:00
|
|
|
dc.checkInitialized()
|
|
|
|
|
2017-11-27 16:05:04 +00:00
|
|
|
if key == nil {
|
|
|
|
panic("nil key")
|
|
|
|
}
|
|
|
|
if !reflect.TypeOf(key).Comparable() {
|
|
|
|
panic("key is not comparable")
|
|
|
|
}
|
|
|
|
|
2017-11-27 10:51:03 +00:00
|
|
|
dc.mtx.Lock()
|
|
|
|
defer dc.mtx.Unlock()
|
|
|
|
|
|
|
|
dc.attributes[key] = value
|
|
|
|
}
|
|
|
|
|
2017-11-27 16:05:04 +00:00
|
|
|
func (dc *defaultContext) GetAttribute(key interface{}) (value interface{}) {
|
2017-11-27 10:51:03 +00:00
|
|
|
dc.checkInitialized()
|
|
|
|
|
|
|
|
dc.mtx.RLock()
|
|
|
|
defer dc.mtx.RUnlock()
|
|
|
|
|
|
|
|
if _, ok := dc.attributes[key]; ok {
|
|
|
|
return dc.attributes[key]
|
|
|
|
}
|
|
|
|
|
2017-11-27 10:58:54 +00:00
|
|
|
if nil == dc.Context {
|
2017-11-27 10:51:03 +00:00
|
|
|
return nil
|
|
|
|
}
|
2017-11-27 10:58:54 +00:00
|
|
|
return dc.Context.GetAttribute(key)
|
2017-11-27 10:51:03 +00:00
|
|
|
}
|
|
|
|
|
2017-11-27 16:05:04 +00:00
|
|
|
func (dc *defaultContext) RemoveAttribute(key interface{}) {
|
2017-11-27 10:51:03 +00:00
|
|
|
dc.checkInitialized()
|
|
|
|
|
|
|
|
dc.mtx.Lock()
|
|
|
|
defer dc.mtx.Unlock()
|
|
|
|
|
|
|
|
if _, ok := dc.attributes[key]; ok {
|
|
|
|
delete(dc.attributes, key)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-11-27 10:58:54 +00:00
|
|
|
if nil == dc.Context {
|
2017-11-27 10:51:03 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-11-27 10:58:54 +00:00
|
|
|
dc.Context.RemoveAttribute(key)
|
2017-11-27 10:51:03 +00:00
|
|
|
}
|
|
|
|
|
2017-11-27 16:05:04 +00:00
|
|
|
func (dc *defaultContext) ContainsAttribute(key interface{}) (exist bool) {
|
2017-11-27 10:51:03 +00:00
|
|
|
dc.checkInitialized()
|
|
|
|
|
|
|
|
dc.mtx.RLock()
|
|
|
|
defer dc.mtx.RUnlock()
|
|
|
|
|
|
|
|
if _, ok := dc.attributes[key]; ok {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2017-11-27 10:58:54 +00:00
|
|
|
if nil == dc.Context {
|
2017-11-27 10:51:03 +00:00
|
|
|
return false
|
|
|
|
}
|
2017-11-27 10:58:54 +00:00
|
|
|
return dc.Context.ContainsAttribute(key)
|
2017-11-27 10:51:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (dc *defaultContext) checkInitialized() {
|
|
|
|
if nil == dc.attributes {
|
|
|
|
panic("Attribute Manager: must be initialized")
|
|
|
|
}
|
|
|
|
}
|