diff --git a/annotation/annotation.go b/annotation/annotation.go index ab68cc1..0e08579 100644 --- a/annotation/annotation.go +++ b/annotation/annotation.go @@ -7,19 +7,64 @@ import ( ) const ( - AnnotationTag = "annotation" - AnnotationMetaTag = "@annotation" - AnnotationChar = "@" - AnnotationStartChar = "(" - AnnotationEndChar = ")" - AnnotationSpliter = ";" - AnnotationAttributeSpliter = "," - AnnotationKeyValueSpliter = "=" + 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[string]Annotation, error) { @@ -28,34 +73,88 @@ func ParseAnnotation(tag reflect.StructTag) (map[string]Annotation, error) { return nil, nil } - annotations := strings.Split(s, AnnotationSpliter) + annotations, err := splitAnnotation(s) + if nil != err { + return nil, err + } + 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) + for name, attributes := range annotations { + annotation, err := newAnnotation(name, attributes) if nil != err { return nil, err } - if "" == aName { - continue - } - annotation, err := newAnnotation(aName, attributes) - if nil != err { - return nil, err - } - rKVs[aName] = annotation + rKVs[name] = 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) (Annotation, error) { def, ok := annotationRegistry[name] if !ok { @@ -71,78 +170,78 @@ func newAnnotation(name string, attributes map[string]string) (Annotation, error return i, nil } -func parseAnnotationItem(a string) (name string, attributes map[string]string, err error) { - s := strings.Trim(a, " ") - if "" == s { - return - } +// 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 - } +// 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 - } +// aStart := strings.Index(s, AnnotationStartChar) +// if -1 == aStart { +// // This is pure annotation ex)@Resource +// name = s +// return +// } - name = s[:aStart] +// 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 - } +// 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 - } +// if 1 >= aEnd-aStart { +// return +// } - attr := s[aStart+1 : aEnd] - attr = strings.Trim(attr, " ") +// attr := s[aStart+1 : aEnd] +// attr = strings.Trim(attr, " ") - if "" == attr { - return - } +// if "" == attr { +// return +// } - attrs, pErr := parseAttributeString(s[aStart+1 : aEnd]) - if nil != pErr { - err = pErr - return - } +// attrs, pErr := parseAttributeString(s[aStart+1 : aEnd]) +// if nil != pErr { +// err = pErr +// return +// } - attributes = attrs +// attributes = attrs - return -} +// return +// } -func parseAttributeString(s string) (map[string]string, error) { - attr := strings.Trim(s, " ") - if "" == attr { - return nil, nil - } +// 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 - } +// 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 - } +// 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 -} +// return rKVs, nil +// } diff --git a/annotation/annotation_test.go b/annotation/annotation_test.go new file mode 100644 index 0000000..cccdb0c --- /dev/null +++ b/annotation/annotation_test.go @@ -0,0 +1,20 @@ +package annotation + +import ( + "log" + "testing" +) + +func TestSplitAnnotation(t *testing.T) { + s := "@overflow:RequestMapping(method='POST', entry='/account/signin', params='[signinID, signinPW]');@overflow:RequestMapping1(method='POST1', entry='/account/signin1', params='[signinID1, signinPW1]')" + ss, _ := splitAnnotation(s) + + log.Printf("%v", ss) +} + +func TestSplitAnnotationAttribute(t *testing.T) { + s := "method='POST', entry='/account/signin', params='[signinID, signinPW]'" + ss, _ := splitAnnotationAttribute(s) + + log.Printf("%v", ss) +} diff --git a/annotation/meta.go b/annotation/meta.go index c7f3e80..69610bb 100644 --- a/annotation/meta.go +++ b/annotation/meta.go @@ -1,6 +1,8 @@ package annotation import ( + "fmt" + "log" "reflect" "strings" @@ -77,11 +79,95 @@ func parseAnnotationMeta(tag reflect.StructTag) (string, 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) - f.Set(reflect.ValueOf(v)) + 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) +} diff --git a/registry/definition.go b/registry/definition.go index e85269c..c50b10e 100644 --- a/registry/definition.go +++ b/registry/definition.go @@ -28,7 +28,7 @@ func (td *TypeDefinition) GetAnnotation(name string) cda.Annotation { return td.TypeAnnotations[name] } -func (td *TypeDefinition) GetAnnotationByType(at reflect.Type, includeEmbedding bool) cda.Annotation { +func (td *TypeDefinition) GetTypeAnnotationByType(at reflect.Type, includeEmbedding bool) cda.Annotation { if nil == td.TypeAnnotations { return nil } diff --git a/registry/registry.go b/registry/registry.go index 095cdaf..cc407ba 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -25,7 +25,6 @@ type ComponentRegistry interface { GetInstance(t reflect.Type) (interface{}, error) GetInstances(ts []reflect.Type) ([]interface{}, error) GetInstanceByName(name string) (interface{}, error) - // GetInstancesByAnnotationName(n string) ([]interface{}, error) GetInstancesByAnnotationType(t reflect.Type) ([]interface{}, error) GetTypeAnnotation(instanceType reflect.Type, annotationType reflect.Type) cda.Annotation @@ -78,7 +77,7 @@ func (cr *defaultComponentRegistry) RegisterType(t reflect.Type) { name := td.TypeName - if a := td.GetAnnotationByType(cdia.ComponentAnnotationType, true); nil != a { + if a := td.GetTypeAnnotationByType(cdia.ComponentAnnotationType, true); nil != a { ca := a.(*cdia.ComponentAnnotation) if "" != strings.Trim(ca.Name, " ") { name = ca.Name @@ -251,7 +250,7 @@ func (cr *defaultComponentRegistry) GetInstancesByAnnotationType(t reflect.Type) instances := make([]interface{}, 0) for _, td := range cr.definitionByType { - if nil != td.GetAnnotationByType(t, true) { + if nil != td.GetTypeAnnotationByType(t, true) { if i, err = cr.GetInstance(td.Type); nil != err { return nil, err } @@ -271,7 +270,7 @@ func (cr *defaultComponentRegistry) GetTypeAnnotation(instanceType reflect.Type, return nil } - return def.GetAnnotationByType(annotationType, false) + return def.GetTypeAnnotationByType(annotationType, false) } func GetMethodAnnotation(instanceType reflect.Type, annotationType reflect.Type, methodName string) cda.Annotation { return registry.GetMethodAnnotation(instanceType, annotationType, methodName) @@ -387,7 +386,7 @@ func parseMethodAnnotation(f *reflect.StructField, td *TypeDefinition) bool { if nil == td.MethodAnnotations { td.MethodAnnotations = make(map[string]map[string]cda.Annotation, 0) } - td.MethodAnnotations[f.Name] = as + td.MethodAnnotations[f.Name[1:]] = as return true } return false diff --git a/registry/registry_test.go b/registry/registry_test.go index 856be4f..3f64d4c 100644 --- a/registry/registry_test.go +++ b/registry/registry_test.go @@ -50,7 +50,7 @@ func TestRegisterType(t *testing.T) { } type AService struct { - annotation.TypeAnnotation `annotation:"@Component(name=dkdkdf)"` + annotation.TypeAnnotation `annotation:"@Component(name='dkdkdf', methods='[1, 2]')"` NameA string }