package annotation import ( "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[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 // } // @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]map[string]string, error) { ss := make(map[string]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) { attributes, err := splitAnnotationAttribute(aAttributes) if nil != err { return nil, err } ss[aName] = attributes } else { ss[aName] = nil } 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) ss[aName] = ts[as+aas+1 : as+aas+aae+1] 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 map[string]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 nil != attributes { setMetaAttributes(def, v.Elem(), attributes) } return def.t, 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 // }