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 }