package annotation import ( "fmt" "reflect" "strings" ) const ( AnnotationTag = "annotation" AnnotationMetaTag = "annotation-meta" AnnotationChar = "@" AnnotationStartChar = "(" AnnotationEndChar = ")" AnnotationSpliter = ";" AnnotationAttributeSpliter = "," AnnotationKeyValueSpliter = "=" ) 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 } func newAnnotation(name string, attributes map[string]string) (Annotation, error) { def, ok := annotationRegistry[name] if !ok { return 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 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 }