-
Notifications
You must be signed in to change notification settings - Fork 0
/
bean_factory_validator.go
121 lines (112 loc) · 4.39 KB
/
bean_factory_validator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package pp_ioc
import (
"github.com/pkg/errors"
logCtx "github.com/wlad031/pp-logging"
"reflect"
"strings"
)
type beanFactoryValidator struct {
logger logCtx.NamedLogger
}
func newBeanFactoryValidator() *beanFactoryValidator {
return &beanFactoryValidator{
logger: logCtx.Get("IOC.BeanFactoryValidator"),
}
}
func (v *beanFactoryValidator) validate(beanFactory *beanFactory) error {
if beanFactory.factoryFunction == nil {
return errors.New("Invalid factory function: nil")
}
factoryValue := reflect.ValueOf(beanFactory.factoryFunction)
if factoryValue.Kind() != reflect.Func {
return errors.New("Invalid factory function: not a function")
}
for i := 0; i < beanFactory.type_.NumIn(); i++ {
beanFactory._inParamTypes = append(beanFactory._inParamTypes, beanFactory.type_.In(i))
}
for i := 0; i < beanFactory.type_.NumOut(); i++ {
beanFactory._outParamTypes = append(beanFactory._outParamTypes, beanFactory.type_.Out(i))
}
for _, paramType := range beanFactory._inParamTypes {
if paramType.Kind() != reflect.Struct &&
paramType.Kind() != reflect.Interface &&
paramType.Kind() != reflect.Ptr &&
!(paramType.Kind() == reflect.Ptr &&
paramType.Elem().Kind() != reflect.Struct &&
paramType.Kind() != reflect.Interface) {
return errors.New("Invalid factory function: only struct/interface or " +
"*struct/*interface IN params allowed")
}
if paramType.Kind() == reflect.Struct ||
(paramType.Kind() == reflect.Ptr && paramType.Elem().Kind() == reflect.Struct) {
if paramType.Kind() == reflect.Ptr {
paramType = paramType.Elem()
}
for i := 0; i < paramType.NumField(); i++ {
fieldType := paramType.Field(i)
switch fieldType.Type.Kind() {
case reflect.Bool:
case reflect.Int:
case reflect.Int8:
case reflect.Int16:
case reflect.Int32:
case reflect.Int64:
case reflect.Uint:
case reflect.Uint8:
case reflect.Uint16:
case reflect.Uint32:
case reflect.Uint64:
case reflect.Float32:
case reflect.Float64:
case reflect.String:
if e := validateValue(fieldType); e != nil {
return errors.Wrap(e, "Invalid value field")
}
continue
case reflect.Uintptr:
case reflect.Interface:
case reflect.Struct:
case reflect.Ptr:
default:
continue
// FIXME:
// return errors.New("Invalid factory function: invalid in-struct field type")
}
}
}
}
numOut := len(beanFactory._outParamTypes)
if numOut != 1 && numOut != 2 {
return errors.New("Invalid factory function: " +
"invalid number of OUT parameters (must be 1 or 2)")
}
outParamType := beanFactory._outParamTypes[0]
if outParamType.Kind() != reflect.Interface &&
outParamType.Kind() != reflect.Struct &&
!(outParamType.Kind() == reflect.Ptr &&
outParamType.Elem().Kind() != reflect.Interface &&
outParamType/*FIXME: .Elem()*/.Kind() != reflect.Struct) {
return errors.New("Invalid factory function: invalid type (" +
outParamType.Kind().String() +
") of the first OUT parameters " +
"(must be interface/struct or *interface/*struct)")
}
if numOut == 2 {
if beanFactory.type_.Out(1).Kind() != reflect.Interface ||
!beanFactory.type_.Out(1).Implements(reflect.TypeOf((*error)(nil)).Elem()) {
return errors.New("Invalid factory function: invalid type of " +
"the second OUT parameter (must implement 'error')")
}
}
return nil
}
func validateValue(field reflect.StructField) error {
tag := field.Tag.Get("value")
if tag == "" {
return nil // FIXME: not correct behaviour
}
if !(strings.HasPrefix(tag, ValueTagPrefix) && strings.HasSuffix(tag, ValueTagSuffix)) {
return errors.New("Invalid value tag format")
}
return nil
}