149 lines
2.9 KiB
Go
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
|
|
}
|