di/annotation/annotation.go
crusader 1a82266014 ing
2018-03-15 22:19:44 +09:00

149 lines
2.9 KiB
Go

package annotation
import (
"fmt"
"reflect"
"strings"
)
const (
AnnotationTag = "annotation"
AnnotationMetaTag = "annotation-meta"
AnnotationChar = "@"
AnnotationStartChar = "("
AnnotationEndChar = ")"
AnnotationSpliter = ";"
AnnotationAttributeSpliter = ","
AnnotationKeyValueSpliter = "="
)
type Annotation interface {
}
// @Inject(name? string)
// @Resource(name? string)
func ParseAnnotation(tag reflect.StructTag) (map[string]Annotation, error) {
s := strings.Trim(tag.Get(AnnotationTag), " ")
if "" == s {
return nil, nil
}
annotations := strings.Split(s, AnnotationSpliter)
if nil == annotations || 0 == len(annotations) {
return nil, nil
}
rKVs := make(map[string]Annotation, 0)
for _, a := range annotations {
a = strings.Trim(a, " ")
if "" == a {
continue
}
aName, attributes, err := parseAnnotationItem(a)
if nil != err {
return nil, err
}
if "" == aName {
continue
}
annotation, err := newAnnotation(aName, attributes)
if nil != err {
return nil, err
}
rKVs[aName] = annotation
}
return rKVs, nil
}
func newAnnotation(name string, attributes map[string]string) (Annotation, error) {
def, ok := annotationRegistry[name]
if !ok {
return nil, fmt.Errorf("There is no annotation[%s]", name)
}
v := reflect.New(def.rt)
i := v.Interface().(Annotation)
if nil != attributes {
setMetaAttributes(def, v.Elem(), attributes)
}
return i, nil
}
func parseAnnotationItem(a string) (name string, attributes map[string]string, err error) {
s := strings.Trim(a, " ")
if "" == s {
return
}
i := strings.Index(s, AnnotationChar)
if -1 == i {
err = fmt.Errorf("Syntax error: annotation must be started %s", AnnotationChar)
return
}
aStart := strings.Index(s, AnnotationStartChar)
if -1 == aStart {
// This is pure annotation ex)@Resource
name = s
return
}
name = s[:aStart]
aEnd := strings.Index(s, AnnotationEndChar)
if -1 == aEnd {
// This is syntax error ex)@Resource(
err = fmt.Errorf("Syntax error: annotation must be ended %s", AnnotationEndChar)
return
}
if 1 >= aEnd-aStart {
return
}
attr := s[aStart+1 : aEnd]
attr = strings.Trim(attr, " ")
if "" == attr {
return
}
attrs, pErr := parseAttributeString(s[aStart+1 : aEnd])
if nil != pErr {
err = pErr
return
}
attributes = attrs
return
}
func parseAttributeString(s string) (map[string]string, error) {
attr := strings.Trim(s, " ")
if "" == attr {
return nil, nil
}
kvs := strings.Split(attr, AnnotationAttributeSpliter)
if nil == kvs || 0 == len(kvs) {
return nil, nil
}
rKVs := make(map[string]string)
for i := 0; i < len(kvs); i++ {
s := strings.Trim(kvs[i], " ")
if "" == s {
continue
}
kv := strings.Split(s, AnnotationKeyValueSpliter)
k := strings.Trim(kv[0], " ")
v := strings.Trim(kv[1], " ")
rKVs[k] = v
}
return rKVs, nil
}