di-go/annotation/annotation.go
2019-11-11 23:22:27 +09:00

143 lines
3.2 KiB
Go

package annotation
import (
"encoding/json"
"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[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]string, error) {
ss := make(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) {
ss[aName] = aAttributes
} else {
ss[aName] = ""
}
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 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 "" != attributes {
_json := fmt.Sprintf("{%s}", attributes)
if err := json.Unmarshal([]byte(_json), i); nil != err {
return nil, nil, err
}
}
return def.t, i, nil
}