From 08db48ce48181aaef8fd84ab252e99a14d341564 Mon Sep 17 00:00:00 2001 From: crusader Date: Thu, 23 Aug 2018 15:13:22 +0900 Subject: [PATCH] ing --- definition.go | 9 ++ registry.go | 292 +++++++++++++++++++++++++++++++++++++++++++++----- type.go | 10 +- 3 files changed, 279 insertions(+), 32 deletions(-) diff --git a/definition.go b/definition.go index 90d9eff..7a61556 100644 --- a/definition.go +++ b/definition.go @@ -6,3 +6,12 @@ type Definition struct { t reflect.Type rt reflect.Type } + +type TypeDefinition struct { + t reflect.Type + rt reflect.Type + + typeAnnotation map[reflect.Type]Annotation + fieldAnnotation map[string]map[reflect.Type]Annotation + methodAnnotation map[string]map[reflect.Type]Annotation +} diff --git a/registry.go b/registry.go index 93dabb3..d0f9e55 100644 --- a/registry.go +++ b/registry.go @@ -6,18 +6,26 @@ import ( "reflect" "strings" - cur "git.loafle.net/overflow/util-go/reflect" + our "git.loafle.net/overflow/util-go/reflect" ) type Registry interface { Register(t reflect.Type) error - Get(f *reflect.StructField) (map[reflect.Type]Annotation, error) + GetTypeAnnotation(t reflect.Type, at reflect.Type) (Annotation, error) + GetTypeAnnotations(t reflect.Type) (map[reflect.Type]Annotation, error) + GetFieldAnnotation(t reflect.Type, name string, at reflect.Type) (Annotation, error) + GetFieldAnnotations(t reflect.Type, name string) (map[reflect.Type]Annotation, error) + GetAllFieldAnnotations(t reflect.Type) (map[string]map[reflect.Type]Annotation, error) + GetMethodAnnotation(t reflect.Type, name string, at reflect.Type) (Annotation, error) + GetMethodAnnotations(t reflect.Type, name string) (map[reflect.Type]Annotation, error) + GetAllMethodAnnotations(t reflect.Type) (map[string]map[reflect.Type]Annotation, error) } func New(parent Registry) Registry { r := &AnnotationRegistry{ - parent: parent, - definitions: make(map[string]*Definition, 0), + parent: parent, + definitions: make(map[string]*Definition, 0), + typeDefinitions: make(map[reflect.Type]*TypeDefinition, 0), } if nil == r.parent { r.parent = SystemRegistry @@ -26,20 +34,22 @@ func New(parent Registry) Registry { } var SystemRegistry = &AnnotationRegistry{ - parent: nil, - definitions: make(map[string]*Definition, 0), + parent: nil, + definitions: make(map[string]*Definition, 0), + typeDefinitions: make(map[reflect.Type]*TypeDefinition, 0), } type AnnotationRegistry struct { - parent Registry - definitions map[string]*Definition + parent Registry + definitions map[string]*Definition + typeDefinitions map[reflect.Type]*TypeDefinition } func Register(t reflect.Type) error { return SystemRegistry.Register(t) } func (r *AnnotationRegistry) Register(t reflect.Type) error { - rt, _, _ := cur.GetTypeInfo(t) + rt, _, _ := our.GetTypeInfo(t) fields := findAnnotatedFields(t, AnnotationType, false) switch len(fields) { @@ -68,10 +78,35 @@ func (r *AnnotationRegistry) Register(t reflect.Type) error { return nil } -func Get(f *reflect.StructField) (map[reflect.Type]Annotation, error) { - return SystemRegistry.Get(f) +func findAnnotatedFields(t reflect.Type, ft reflect.Type, deep bool) map[string]*reflect.StructField { + fields := make(map[string]*reflect.StructField, 0) + + rt, _, _ := our.GetTypeInfo(t) + if reflect.Struct != rt.Kind() { + return fields + } + +LOOP: + for i := 0; i < rt.NumField(); i++ { + f := rt.Field(i) + + if f.Anonymous { + if f.Type == ft { + fields[f.Name] = &f + continue LOOP + } + if deep { + _fields := findAnnotatedFields(f.Type, ft, deep) + for _n, _f := range _fields { + fields[_n] = _f + } + } + } + } + return fields } -func (r *AnnotationRegistry) Get(f *reflect.StructField) (map[reflect.Type]Annotation, error) { + +func (r *AnnotationRegistry) getAnnotation(f *reflect.StructField) (map[reflect.Type]Annotation, error) { annotations := make(map[reflect.Type]Annotation, 0) tag := strings.TrimSpace(f.Tag.Get(AnnotationTag)) @@ -129,12 +164,20 @@ func (r *AnnotationRegistry) Get(f *reflect.StructField) (map[reflect.Type]Annot return annotations, nil } -func findAnnotatedFields(t reflect.Type, ft reflect.Type, deep bool) map[string]*reflect.StructField { - fields := make(map[string]*reflect.StructField, 0) - - rt, _, _ := cur.GetTypeInfo(t) +func (r *AnnotationRegistry) getTypeDefinition(t reflect.Type) (*TypeDefinition, error) { + rt, _, _ := our.GetTypeInfo(t) if reflect.Struct != rt.Kind() { - return fields + return nil, fmt.Errorf("type[%s] is not struct", rt.Name()) + } + + td, ok := r.typeDefinitions[t] + if ok { + return td, nil + } + + td = &TypeDefinition{ + t: t, + rt: rt, } LOOP: @@ -142,17 +185,214 @@ LOOP: f := rt.Field(i) if f.Anonymous { - if f.Type == ft { - fields[f.Name] = &f - continue LOOP - } - if deep { - _fields := findAnnotatedFields(f.Type, ft, deep) - for _n, _f := range _fields { - fields[_n] = _f + if f.Type == TypeAnnotationType { + if 0 < len(td.typeAnnotation) { + return nil, fmt.Errorf("TypeAnnotation of type[%s] be defined one more time", rt.Name()) } + as, err := r.getAnnotation(&f) + if nil != err { + return nil, err + } + if 0 == len(as) { + continue LOOP + } + td.typeAnnotation = as + } + } else { + if f.Type == MethodAnnotationType { + as, err := r.getAnnotation(&f) + if nil != err { + return nil, err + } + if 0 == len(as) { + continue LOOP + } + if 0 == len(td.methodAnnotation) { + td.methodAnnotation = make(map[string]map[reflect.Type]Annotation, 0) + } + td.methodAnnotation[f.Name] = as + continue LOOP + } else { + as, err := r.getAnnotation(&f) + if nil != err { + return nil, err + } + if 0 == len(as) { + continue LOOP + } + if 0 == len(td.fieldAnnotation) { + td.fieldAnnotation = make(map[string]map[reflect.Type]Annotation, 0) + } + td.fieldAnnotation[f.Name] = as + continue LOOP } } } - return fields + + r.typeDefinitions[t] = td + + return td, nil +} + +func GetTypeAnnotation(t reflect.Type, at reflect.Type) (Annotation, error) { + return SystemRegistry.GetTypeAnnotation(t, at) +} +func (r *AnnotationRegistry) GetTypeAnnotation(t reflect.Type, at reflect.Type) (Annotation, error) { + td, err := r.getTypeDefinition(t) + if nil != err { + return nil, err + } + + if 0 == len(td.typeAnnotation) { + return nil, fmt.Errorf("TypeAnnotation of type[%s] is not exist", td.rt.Name()) + } + + a, ok := td.typeAnnotation[at] + if !ok { + return nil, fmt.Errorf("Annotation[%s] of type[%s] is not exist", at.Name(), td.rt.Name()) + } + + return a, nil +} + +func GetTypeAnnotations(t reflect.Type) (map[reflect.Type]Annotation, error) { + return SystemRegistry.GetTypeAnnotations(t) +} +func (r *AnnotationRegistry) GetTypeAnnotations(t reflect.Type) (map[reflect.Type]Annotation, error) { + td, err := r.getTypeDefinition(t) + if nil != err { + return nil, err + } + + if 0 == len(td.typeAnnotation) { + return nil, fmt.Errorf("TypeAnnotation of type[%s] is not exist", td.rt.Name()) + } + + return td.typeAnnotation, nil +} + +func GetFieldAnnotation(t reflect.Type, name string, at reflect.Type) (Annotation, error) { + return SystemRegistry.GetFieldAnnotation(t, name, at) +} +func (r *AnnotationRegistry) GetFieldAnnotation(t reflect.Type, name string, at reflect.Type) (Annotation, error) { + td, err := r.getTypeDefinition(t) + if nil != err { + return nil, err + } + + if 0 == len(td.fieldAnnotation) { + return nil, fmt.Errorf("FieldAnnotation of type[%s] is not exist", td.rt.Name()) + } + + as, ok := td.fieldAnnotation[name] + if !ok || 0 == len(as) { + return nil, fmt.Errorf("Field[%s] Annotation of type[%s] is not exist", name, td.rt.Name()) + } + + a, ok := as[at] + if !ok { + return nil, fmt.Errorf("Annotation[%s] of field[%s] in type[%s] is not exist", at.Name(), name, td.rt.Name()) + } + + return a, nil +} + +func GetFieldAnnotations(t reflect.Type, name string) (map[reflect.Type]Annotation, error) { + return SystemRegistry.GetFieldAnnotations(t, name) +} +func (r *AnnotationRegistry) GetFieldAnnotations(t reflect.Type, name string) (map[reflect.Type]Annotation, error) { + td, err := r.getTypeDefinition(t) + if nil != err { + return nil, err + } + + if 0 == len(td.fieldAnnotation) { + return nil, fmt.Errorf("FieldAnnotation of type[%s] is not exist", td.rt.Name()) + } + + as, ok := td.fieldAnnotation[name] + if !ok || 0 == len(as) { + return nil, fmt.Errorf("Field[%s] Annotation of type[%s] is not exist", name, td.rt.Name()) + } + + return as, nil +} + +func GetAllFieldAnnotations(t reflect.Type) (map[string]map[reflect.Type]Annotation, error) { + return SystemRegistry.GetAllFieldAnnotations(t) +} +func (r *AnnotationRegistry) GetAllFieldAnnotations(t reflect.Type) (map[string]map[reflect.Type]Annotation, error) { + td, err := r.getTypeDefinition(t) + if nil != err { + return nil, err + } + + if 0 == len(td.fieldAnnotation) { + return nil, fmt.Errorf("FieldAnnotation of type[%s] is not exist", td.rt.Name()) + } + + return td.fieldAnnotation, nil +} + +func GetMethodAnnotation(t reflect.Type, name string, at reflect.Type) (Annotation, error) { + return SystemRegistry.GetMethodAnnotation(t, name, at) +} +func (r *AnnotationRegistry) GetMethodAnnotation(t reflect.Type, name string, at reflect.Type) (Annotation, error) { + td, err := r.getTypeDefinition(t) + if nil != err { + return nil, err + } + + if 0 == len(td.methodAnnotation) { + return nil, fmt.Errorf("MethodAnnotation of type[%s] is not exist", td.rt.Name()) + } + + as, ok := td.methodAnnotation[name] + if !ok || 0 == len(as) { + return nil, fmt.Errorf("Method[%s] Annotation of type[%s] is not exist", name, td.rt.Name()) + } + + a, ok := as[at] + if !ok { + return nil, fmt.Errorf("Annotation[%s] of method[%s] in type[%s] is not exist", at.Name(), name, td.rt.Name()) + } + + return a, nil +} + +func GetMethodAnnotations(t reflect.Type, name string) (map[reflect.Type]Annotation, error) { + return SystemRegistry.GetMethodAnnotations(t, name) +} +func (r *AnnotationRegistry) GetMethodAnnotations(t reflect.Type, name string) (map[reflect.Type]Annotation, error) { + td, err := r.getTypeDefinition(t) + if nil != err { + return nil, err + } + + if 0 == len(td.methodAnnotation) { + return nil, fmt.Errorf("MethodAnnotation of type[%s] is not exist", td.rt.Name()) + } + + as, ok := td.methodAnnotation[name] + if !ok || 0 == len(as) { + return nil, fmt.Errorf("Method[%s] Annotation of type[%s] is not exist", name, td.rt.Name()) + } + + return as, nil +} + +func GetAllMethodAnnotations(t reflect.Type) (map[string]map[reflect.Type]Annotation, error) { + return SystemRegistry.GetAllMethodAnnotations(t) +} +func (r *AnnotationRegistry) GetAllMethodAnnotations(t reflect.Type) (map[string]map[reflect.Type]Annotation, error) { + td, err := r.getTypeDefinition(t) + if nil != err { + return nil, err + } + + if 0 == len(td.methodAnnotation) { + return nil, fmt.Errorf("MethodAnnotation of type[%s] is not exist", td.rt.Name()) + } + + return td.methodAnnotation, nil } diff --git a/type.go b/type.go index 6ec55c9..cc7f9f5 100644 --- a/type.go +++ b/type.go @@ -11,18 +11,16 @@ type Annotation interface { var TypeAnnotationType = reflect.TypeOf((*TypeAnnotation)(nil)).Elem() +const TypeAnnotationName = "TypeAnnotation" + type TypeAnnotation interface { Annotation } -var ConstructorAnnotationType = reflect.TypeOf((*ConstructorAnnotation)(nil)).Elem() - -type ConstructorAnnotation interface { - Annotation -} - var MethodAnnotationType = reflect.TypeOf((*MethodAnnotation)(nil)).Elem() +const MethodAnnotationName = "MethodAnnotation" + type MethodAnnotation interface { Annotation }