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  }