github.com/isyscore/isc-gobase@v1.5.3-0.20231218061332-cbc7451899e9/validate/matcher/customize.go (about) 1 package matcher 2 3 import ( 4 "github.com/isyscore/isc-gobase/constants" 5 "github.com/isyscore/isc-gobase/logger" 6 "reflect" 7 "strings" 8 ) 9 10 type CustomizeMatch struct { 11 BlackWhiteMatch 12 13 expression string 14 funValue reflect.Value 15 } 16 17 var funMap = make(map[string]any) 18 19 type MatchJudge func(any) bool 20 21 func (customizeMatch *CustomizeMatch) Match(parameterMap map[string]interface{}, object any, field reflect.StructField, fieldValue any) bool { 22 defer func() { 23 if err := recover(); err != nil { 24 logger.Error("call match err: %v", err) 25 return 26 } 27 }() 28 29 var in []reflect.Value 30 if customizeMatch.funValue.Type().NumIn() == 1 { 31 in = make([]reflect.Value, 1) 32 inKind0 := customizeMatch.funValue.Type().In(0).Kind() 33 if inKind0 == reflect.ValueOf(object).Kind() { 34 in[0] = reflect.ValueOf(object) 35 } else if inKind0 == reflect.ValueOf(fieldValue).Kind() { 36 in[0] = reflect.ValueOf(fieldValue) 37 } else { 38 logger.Error("the value don't match parameter of fun") 39 return false 40 } 41 } else if customizeMatch.funValue.Type().NumIn() == 2 { 42 in = make([]reflect.Value, 2) 43 inKind0 := customizeMatch.funValue.Type().In(0).Kind() 44 inKind1 := customizeMatch.funValue.Type().In(1).Kind() 45 46 if inKind0 == reflect.ValueOf(object).Kind() { 47 in[0] = reflect.ValueOf(object) 48 if inKind1 == reflect.ValueOf(fieldValue).Kind() { 49 in[1] = reflect.ValueOf(fieldValue) 50 } else if inKind1 == reflect.ValueOf(parameterMap).Kind() { 51 in[1] = reflect.ValueOf(parameterMap) 52 } else { 53 logger.Error("参数2 没有找到匹配的类型的值,只可为属性的类型或者map[string]interface{}的类型") 54 return false 55 } 56 } else if inKind0 == reflect.ValueOf(fieldValue).Kind() { 57 in[0] = reflect.ValueOf(fieldValue) 58 if inKind1 == reflect.ValueOf(object).Kind() { 59 in[1] = reflect.ValueOf(object) 60 } else if inKind1 == reflect.ValueOf(parameterMap).Kind() { 61 in[1] = reflect.ValueOf(parameterMap) 62 } else { 63 logger.Error("参数2 没有找到匹配的类型的值,只可为属性所在的对象的类型或者map[string]interface{}的类型") 64 return false 65 } 66 } else { 67 logger.Error("没有找到匹配的类型的值") 68 return false 69 } 70 } else if customizeMatch.funValue.Type().NumIn() == 3 { 71 in = make([]reflect.Value, 3) 72 inKind0 := customizeMatch.funValue.Type().In(0).Kind() 73 inKind1 := customizeMatch.funValue.Type().In(1).Kind() 74 inKind2 := customizeMatch.funValue.Type().In(2).Kind() 75 76 if inKind0 == reflect.ValueOf(object).Kind() && inKind1 == reflect.ValueOf(fieldValue).Kind() { 77 in[0] = reflect.ValueOf(object) 78 in[1] = reflect.ValueOf(fieldValue) 79 } else if inKind0 == reflect.ValueOf(fieldValue).Kind() && inKind1 == reflect.ValueOf(object).Kind() { 80 in[0] = reflect.ValueOf(fieldValue) 81 in[1] = reflect.ValueOf(object) 82 } 83 84 if inKind2 == reflect.ValueOf(parameterMap).Kind() { 85 in[2] = reflect.ValueOf(parameterMap) 86 } else { 87 logger.Error("参数3不是map[string]interface{}类型,参数无法注入") 88 return false 89 } 90 } 91 92 retValues := customizeMatch.funValue.Call(in) 93 if len(retValues) == 1 { 94 if retValues[0].Bool() { 95 customizeMatch.SetBlackMsg("属性 %v 的值 %v 命中禁用条件回调 [%v] ", field.Name, fieldValue, customizeMatch.expression) 96 } else { 97 customizeMatch.SetWhiteMsg("属性 %v 的值 %v 没命中只允许条件回调 [%v] ", field.Name, fieldValue, customizeMatch.expression) 98 } 99 return retValues[0].Bool() 100 } else { 101 kind0 := retValues[0].Kind() 102 kind1 := retValues[1].Kind() 103 104 if kind0 == reflect.Bool { 105 if retValues[0].Bool() { 106 customizeMatch.SetBlackMsg(retValues[1].String()) 107 } else { 108 customizeMatch.SetWhiteMsg(retValues[1].String()) 109 } 110 return retValues[0].Bool() 111 } else if kind1 == reflect.Bool { 112 if retValues[1].Bool() { 113 customizeMatch.SetBlackMsg(retValues[0].String()) 114 } else { 115 customizeMatch.SetWhiteMsg(retValues[0].String()) 116 } 117 return retValues[1].Bool() 118 } else { 119 return retValues[0].Bool() 120 } 121 } 122 } 123 124 func (customizeMatch *CustomizeMatch) IsEmpty() bool { 125 return customizeMatch.expression == "" 126 } 127 128 func BuildCustomizeMatcher(objectTypeFullName string, _ reflect.Kind, objectFieldName string, tagName string, subCondition string, errMsg string) { 129 if constants.MATCH != tagName { 130 return 131 } 132 133 if !strings.Contains(subCondition, constants.Customize) { 134 return 135 } 136 137 index := strings.Index(subCondition, "=") 138 expression := subCondition[index+1:] 139 140 if expression == "" { 141 return 142 } 143 144 fun, contain := funMap[expression] 145 if !contain { 146 logger.Warn("the name of fun not find, funName is [%v]", expression) 147 return 148 } 149 addMatcher(objectTypeFullName, objectFieldName, &CustomizeMatch{funValue: reflect.ValueOf(fun), expression: expression}, errMsg, true) 150 } 151 152 func RegisterCustomize(funName string, fun interface{}) { 153 funValue := reflect.ValueOf(fun) 154 if funValue.Kind() != reflect.Func { 155 logger.Warn("fun is not fun[%v] type", funName) 156 return 157 } 158 159 if funValue.Type().NumIn() > 3 { 160 logger.Warn("the num of fun[%v] argument need to be less than or equal to 3", funName) 161 return 162 } 163 164 if funValue.Type().NumOut() > 2 { 165 logger.Warn("the num of fun[%v] return need to be less than or equal to 2", funName) 166 return 167 } 168 169 if funValue.Type().NumOut() == 0 { 170 logger.Warn("the type of fun[%v] return must be bool", funName) 171 return 172 } else if funValue.Type().NumOut() == 1 { 173 if funValue.Type().Out(0).Kind() != reflect.Bool { 174 logger.Warn("the type of fun[%v] return must be bool", funName) 175 return 176 } 177 } else if funValue.Type().NumOut() == 2 { 178 kind0 := funValue.Type().Out(0).Kind() 179 kind1 := funValue.Type().Out(1).Kind() 180 181 if kind0 != reflect.Bool && kind0 != reflect.String { 182 logger.Warn("return type of fun[%v] return must be bool or string", funName) 183 return 184 } 185 186 if kind1 != reflect.Bool && kind1 != reflect.String { 187 logger.Warn("return type of fun[%v] return must be bool or string", funName) 188 return 189 } 190 } 191 192 funMap[funName] = fun 193 }