2018-04-03 09:02:31 +00:00
|
|
|
package annotation
|
|
|
|
|
|
|
|
import (
|
2018-04-10 12:08:21 +00:00
|
|
|
"fmt"
|
|
|
|
"log"
|
2018-04-03 09:02:31 +00:00
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
cur "git.loafle.net/commons/util-go/reflect"
|
|
|
|
)
|
|
|
|
|
|
|
|
type AnnotationFieldMeta struct {
|
|
|
|
fieldName string
|
|
|
|
options anotationMetaOptions
|
|
|
|
}
|
|
|
|
|
2019-11-06 13:15:02 +00:00
|
|
|
|
|
|
|
|
2018-04-03 09:02:31 +00:00
|
|
|
type anotationMetaOptions string
|
|
|
|
|
|
|
|
func (o anotationMetaOptions) Contains(optionName string) bool {
|
|
|
|
if len(o) == 0 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
s := string(o)
|
|
|
|
for s != "" {
|
|
|
|
var next string
|
|
|
|
i := strings.Index(s, AnnotationAttributeSpliter)
|
|
|
|
if i >= 0 {
|
|
|
|
s, next = s[:i], s[i+1:]
|
|
|
|
}
|
|
|
|
if s == optionName {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
s = next
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func getMetaFields(t reflect.Type) map[string]*AnnotationFieldMeta {
|
|
|
|
fields := make(map[string]*AnnotationFieldMeta, 0)
|
|
|
|
rt, _, _ := cur.GetTypeInfo(t)
|
|
|
|
if reflect.Struct != rt.Kind() {
|
|
|
|
return fields
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < rt.NumField(); i++ {
|
|
|
|
f := rt.Field(i)
|
|
|
|
|
|
|
|
if f.Anonymous {
|
|
|
|
pFields := getMetaFields(f.Type)
|
|
|
|
for k, v := range pFields {
|
|
|
|
fields[k] = v
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
name, metaOptions := parseAnnotationMeta(f.Tag)
|
|
|
|
if "" == name {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
fields[name] = &AnnotationFieldMeta{
|
|
|
|
fieldName: f.Name,
|
|
|
|
options: metaOptions,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return fields
|
|
|
|
}
|
|
|
|
|
|
|
|
func parseAnnotationMeta(tag reflect.StructTag) (string, anotationMetaOptions) {
|
|
|
|
s := strings.Trim(tag.Get(AnnotationMetaTag), " ")
|
|
|
|
if "" == s {
|
|
|
|
return "", ""
|
|
|
|
}
|
|
|
|
|
|
|
|
if idx := strings.Index(s, AnnotationAttributeSpliter); idx != -1 {
|
|
|
|
return s[:idx], anotationMetaOptions(s[idx+1:])
|
|
|
|
}
|
|
|
|
|
|
|
|
return s, anotationMetaOptions("")
|
|
|
|
}
|
|
|
|
|
|
|
|
func setMetaAttributes(def *AnnotationDefinition, rv reflect.Value, attributes map[string]string) {
|
2018-04-10 12:08:21 +00:00
|
|
|
META_LOOP:
|
2018-04-03 09:02:31 +00:00
|
|
|
for k, v := range attributes {
|
|
|
|
meta := def.fields[k]
|
2018-04-10 12:08:21 +00:00
|
|
|
if nil == meta {
|
|
|
|
log.Printf("Attribute[%s] of Type[%s] is not exist", k, def.rt.Name())
|
|
|
|
continue META_LOOP
|
|
|
|
}
|
2018-04-03 09:02:31 +00:00
|
|
|
f := rv.FieldByName(meta.fieldName)
|
|
|
|
|
2018-04-10 12:08:21 +00:00
|
|
|
switch f.Type().Kind() {
|
|
|
|
case reflect.Array:
|
|
|
|
log.Printf("Array not support")
|
|
|
|
case reflect.Slice:
|
|
|
|
s, err := convertSlice(v, f.Type())
|
|
|
|
if nil != err {
|
|
|
|
continue META_LOOP
|
|
|
|
}
|
|
|
|
f.Set(reflect.ValueOf(s))
|
|
|
|
case reflect.Map:
|
|
|
|
s, err := convertMap(v, f.Type())
|
|
|
|
if nil != err {
|
|
|
|
continue META_LOOP
|
|
|
|
}
|
|
|
|
f.Set(reflect.ValueOf(s))
|
|
|
|
case reflect.Struct:
|
|
|
|
log.Printf("Struct not support")
|
|
|
|
case reflect.Ptr:
|
|
|
|
log.Printf("Pointer not support")
|
|
|
|
default:
|
|
|
|
f.Set(reflect.ValueOf(v))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func convertSlice(s string, t reflect.Type) (interface{}, error) {
|
|
|
|
ts := s
|
|
|
|
|
|
|
|
as := strings.Index(ts, AnnotationAttributeArrayStartChar)
|
|
|
|
if -1 == as {
|
|
|
|
return nil, fmt.Errorf("Value is not contain %s", AnnotationAttributeArrayStartChar)
|
|
|
|
}
|
|
|
|
ts = ts[as+1:]
|
|
|
|
ae := strings.Index(ts, AnnotationAttributeArrayEndChar)
|
|
|
|
if -1 == ae {
|
|
|
|
return nil, fmt.Errorf("Value is not contain %s", AnnotationAttributeArrayEndChar)
|
|
|
|
}
|
|
|
|
ts = ts[:ae]
|
|
|
|
|
|
|
|
is := strings.Split(ts, AnnotationAttributeArrayItemSpliter)
|
|
|
|
if nil == is || 0 == len(is) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, v := range is {
|
|
|
|
is[i] = strings.TrimSpace(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
return cur.ConvertToType(is, t)
|
|
|
|
}
|
|
|
|
|
|
|
|
func convertMap(s string, t reflect.Type) (interface{}, error) {
|
|
|
|
ts := s
|
|
|
|
|
|
|
|
as := strings.Index(ts, AnnotationAttributeMapStartChar)
|
|
|
|
if -1 == as {
|
|
|
|
return nil, fmt.Errorf("Value is not contain %s", AnnotationAttributeMapStartChar)
|
|
|
|
}
|
|
|
|
ts = ts[as+1:]
|
|
|
|
ae := strings.Index(ts, AnnotationAttributeMapEndChar)
|
|
|
|
if -1 == ae {
|
|
|
|
return nil, fmt.Errorf("Value is not contain %s", AnnotationAttributeMapEndChar)
|
2018-04-03 09:02:31 +00:00
|
|
|
}
|
2018-04-10 12:08:21 +00:00
|
|
|
ts = ts[:ae]
|
|
|
|
|
|
|
|
is := strings.Split(ts, AnnotationAttributeMapItemSpliter)
|
|
|
|
if nil == is || 0 == len(is) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
ms := make(map[string]string)
|
|
|
|
for _, s := range is {
|
|
|
|
kvs := strings.Split(s, AnnotationAttributeMapKeyValueSpliter)
|
|
|
|
if 2 != len(kvs) {
|
|
|
|
return nil, fmt.Errorf("Map Value format k:v but %s", s)
|
|
|
|
}
|
|
|
|
k := strings.TrimSpace(kvs[0])
|
|
|
|
v := strings.TrimSpace(kvs[1])
|
|
|
|
ms[k] = v
|
|
|
|
}
|
|
|
|
|
|
|
|
return cur.ConvertToType(ms, t)
|
2018-04-03 09:02:31 +00:00
|
|
|
}
|