package annotation import ( "fmt" "log" "reflect" "strings" cur "git.loafle.net/commons/util-go/reflect" ) type AnnotationFieldMeta struct { fieldName string options anotationMetaOptions } 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) { META_LOOP: for k, v := range attributes { meta := def.fields[k] if nil == meta { log.Printf("Attribute[%s] of Type[%s] is not exist", k, def.rt.Name()) continue META_LOOP } f := rv.FieldByName(meta.fieldName) 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) } 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) }