di-go/annotation/annotation.go
2019-11-11 22:52:10 +09:00

254 lines
5.6 KiB
Go

package annotation
import (
"fmt"
"reflect"
"strings"
)
const (
AnnotationTag = "annotation"
AnnotationMetaTag = "@annotation"
AnnotationChar = "@"
AnnotationStartChar = "("
AnnotationEndChar = ")"
AnnotationSpliter = ";"
AnnotationAttributeSpliter = ","
AnnotationAttributeStartChar = "'"
AnnotationAttributeEndChar = "'"
AnnotationKeyValueSpliter = "="
AnnotationAttributeArrayStartChar = "["
AnnotationAttributeArrayEndChar = "]"
AnnotationAttributeArrayItemSpliter = ","
AnnotationAttributeMapStartChar = "{"
AnnotationAttributeMapEndChar = "}"
AnnotationAttributeMapKeyValueSpliter = ":"
AnnotationAttributeMapItemSpliter = ","
)
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
// }
// @Inject(name? string)
// @Resource(name? string)
func ParseAnnotation(tag reflect.StructTag) (map[reflect.Type]Annotation, error) {
s := strings.Trim(tag.Get(AnnotationTag), " ")
if "" == s {
return nil, nil
}
annotations, err := splitAnnotation(s)
if nil != err {
return nil, err
}
if nil == annotations || 0 == len(annotations) {
return nil, nil
}
rKVs := make(map[reflect.Type]Annotation, 0)
for name, attributes := range annotations {
t, annotation, err := newAnnotation(name, attributes)
if nil != err {
return nil, err
}
rKVs[t] = annotation
}
return rKVs, nil
}
func splitAnnotation(s string) (map[string]map[string]string, error) {
ss := make(map[string]map[string]string, 0)
ts := s
for {
as := strings.Index(ts, AnnotationChar)
if -1 == as {
break
}
aas := strings.Index(ts, AnnotationStartChar)
aae := strings.Index(ts, AnnotationEndChar)
aName := ts[as:aas]
aAttributes := ts[aas+1 : aae]
if 0 < len(aAttributes) {
attributes, err := splitAnnotationAttribute(aAttributes)
if nil != err {
return nil, err
}
ss[aName] = attributes
} else {
ss[aName] = nil
}
if len(ts) <= (aae + 1) {
break
}
ts = ts[aae+1:]
}
return ss, nil
}
func splitAnnotationAttribute(s string) (map[string]string, error) {
ss := make(map[string]string, 0)
ts := s
for {
as := strings.Index(ts, AnnotationKeyValueSpliter)
if -1 == as {
break
}
aName := ts[:as]
aas := strings.Index(ts[as:], AnnotationAttributeStartChar)
aae := strings.Index(ts[as+aas+1:], AnnotationAttributeEndChar)
if -1 == aas && -1 == aae {
ss[aName] = ts[as+1 : len(ts)]
} else if -1 != aas && -1 != aae {
ss[aName] = ts[as+aas+1 : as+aas+aae+1]
} else {
return nil, fmt.Errorf("not valid string %s", ts)
}
asi := strings.Index(ts[as+aae:], AnnotationAttributeSpliter)
if -1 == asi {
break
}
if len(ts) <= (as + aae + asi + 1) {
break
}
ts = strings.TrimSpace(ts[as+aae+asi+1:])
}
return ss, nil
}
func newAnnotation(name string, attributes map[string]string) (reflect.Type, Annotation, error) {
def, ok := annotationRegistry[name]
if !ok {
return nil, 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 def.t, 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
// }