github.com/isyscore/isc-gobase@v1.5.3-0.20231218061332-cbc7451899e9/validate/matcher/blackWhiteMatch.go (about)

     1  package matcher
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/antonmedv/expr/compiler"
     8  	"github.com/antonmedv/expr/parser"
     9  	"github.com/isyscore/isc-gobase/logger"
    10  )
    11  
    12  type BlackWhiteMatch struct {
    13  	BlackMsg string
    14  	WhiteMsg string
    15  }
    16  
    17  func (blackWhiteMatch *BlackWhiteMatch) SetBlackMsg(format string, a ...any) {
    18  	blackWhiteMatch.BlackMsg = fmt.Sprintf(format, a...)
    19  }
    20  
    21  func (blackWhiteMatch *BlackWhiteMatch) SetWhiteMsg(format string, a ...any) {
    22  	blackWhiteMatch.WhiteMsg = fmt.Sprintf(format, a...)
    23  }
    24  
    25  func (blackWhiteMatch *BlackWhiteMatch) GetWhitMsg() string {
    26  	return blackWhiteMatch.WhiteMsg
    27  }
    28  
    29  func (blackWhiteMatch *BlackWhiteMatch) GetBlackMsg() string {
    30  	return blackWhiteMatch.BlackMsg
    31  }
    32  
    33  func addMatcher(objectTypeFullName string, objectFieldName string, matcher Matcher, errMsg string, accept bool) {
    34  	fieldMatcherMap, c1 := MatchMap[objectTypeFullName]
    35  
    36  	if !c1 {
    37  		fieldMap := make(map[string]*FieldMatcher)
    38  		var matchers []*Matcher
    39  		if matcher != nil {
    40  			matchers = append(matchers, &matcher)
    41  		}
    42  
    43  		if errMsg != "" {
    44  			errMsgData := errMsgChange(errMsg)
    45  			tree, err := parser.Parse(errMsgData)
    46  			if err != nil {
    47  				logger.Error("errMsg[%v] parse error: %v", errMsg, err.Error())
    48  				return
    49  			}
    50  
    51  			program, err := compiler.Compile(tree, nil)
    52  			if err != nil {
    53  				logger.Error("errMsg[%v] compile error: %v", errMsg, err.Error())
    54  				return
    55  			}
    56  
    57  			fieldMap[objectFieldName] = &FieldMatcher{FieldName: objectFieldName, ErrMsgProgram: program, Matchers: matchers, Accept: accept}
    58  		} else {
    59  			fieldMap[objectFieldName] = &FieldMatcher{FieldName: objectFieldName, Matchers: matchers, Accept: accept}
    60  		}
    61  
    62  		MatchMap[objectTypeFullName] = fieldMap
    63  	} else {
    64  		fieldMatcher, c2 := fieldMatcherMap[objectFieldName]
    65  		if !c2 {
    66  			var matchers []*Matcher
    67  			if matcher != nil {
    68  				matchers = append(matchers, &matcher)
    69  			}
    70  
    71  			if errMsg != "" {
    72  				tree, err := parser.Parse(errMsgChange(errMsg))
    73  				if err != nil {
    74  					logger.Error("errMsg[%v] parse error: %v", errMsg, err.Error())
    75  					return
    76  				}
    77  
    78  				program, err := compiler.Compile(tree, nil)
    79  				if err != nil {
    80  					logger.Error("errMsg[%v] compile error: %v", errMsg, err.Error())
    81  					return
    82  				}
    83  
    84  				fieldMatcherMap[objectFieldName] = &FieldMatcher{FieldName: objectFieldName, ErrMsgProgram: program, Matchers: matchers, Accept: accept}
    85  			} else {
    86  				fieldMatcherMap[objectFieldName] = &FieldMatcher{FieldName: objectFieldName, Matchers: matchers, Accept: accept}
    87  			}
    88  		} else {
    89  			if matcher != nil {
    90  				fieldMatcher.Matchers = append(fieldMatcher.Matchers, &matcher)
    91  			}
    92  			fieldMatcher.Accept = accept
    93  		}
    94  	}
    95  }
    96  
    97  // 将#root和#current转换为root和#current,相当于移除井号
    98  func rmvWell(expression string) string {
    99  	if strings.Contains(expression, "#root.") {
   100  		expression = strings.ReplaceAll(expression, "#root.", "root.")
   101  	}
   102  
   103  	if strings.Contains(expression, "#current") {
   104  		expression = strings.ReplaceAll(expression, "#current", "current")
   105  	}
   106  	return expression
   107  }
   108  
   109  var currentKey = "#current"
   110  var rootKey = "#root"
   111  
   112  func errMsgChange(errMsg string) string {
   113  	var matchKeys []string
   114  	var chgMsg strings.Builder
   115  	chgMsg.WriteString("sprintf(\"")
   116  
   117  	var b strings.Builder
   118  	b.Grow(len(errMsg))
   119  
   120  	matchIndex := 0
   121  	matchLength := 0
   122  	for infoIndex, data := range errMsg {
   123  		c := string(data)
   124  		if c == "#" {
   125  			if findCurrentKey(infoIndex, 0, errMsg) {
   126  				matchIndex = 0
   127  				matchLength = len(currentKey)
   128  				b.WriteString("%v")
   129  				matchKeys = append(matchKeys, "current")
   130  				continue
   131  			} else if find, size, wordKey := findRootKey(infoIndex, 0, errMsg); find {
   132  				matchIndex = 0
   133  				matchLength = size
   134  				b.WriteString("%v")
   135  				matchKeys = append(matchKeys, "root"+wordKey)
   136  				continue
   137  			}
   138  		} else if matchIndex+1 < matchLength {
   139  			matchIndex++
   140  			continue
   141  		} else {
   142  			b.WriteString(c)
   143  		}
   144  	}
   145  
   146  	chgMsg.WriteString(b.String())
   147  	chgMsg.WriteString("\"")
   148  
   149  	matchKeysSize := len(matchKeys)
   150  	if matchKeysSize > 0 {
   151  		chgMsg.WriteString(", ")
   152  	}
   153  
   154  	for i, data := range matchKeys {
   155  		if i+1 < matchKeysSize {
   156  			chgMsg.WriteString(data)
   157  			chgMsg.WriteString(", ")
   158  		} else {
   159  			chgMsg.WriteString(data)
   160  		}
   161  	}
   162  	chgMsg.WriteString(")")
   163  
   164  	return chgMsg.String()
   165  }
   166  
   167  func findCurrentKey(infoIndex, matchIndex int, info string) bool {
   168  	if matchIndex >= len(currentKey) {
   169  		return true
   170  	}
   171  	if info[infoIndex:infoIndex+1] == currentKey[matchIndex:matchIndex+1] {
   172  		return findCurrentKey(infoIndex+1, matchIndex+1, info)
   173  	}
   174  	return false
   175  }
   176  
   177  func findRootKey(infoIndex, matchIndex int, info string) (bool, int, string) {
   178  	if matchIndex >= len(rootKey) {
   179  		nextKeyLength := nextMatchKeyLength(info[infoIndex:])
   180  		if nextKeyLength > 0 {
   181  			return true, len(rootKey) + nextKeyLength, info[infoIndex : infoIndex+nextKeyLength]
   182  		}
   183  		return false, 0, ""
   184  	}
   185  	if info[infoIndex:infoIndex+1] == rootKey[matchIndex:matchIndex+1] {
   186  		return findRootKey(infoIndex+1, matchIndex+1, info)
   187  	}
   188  	return false, 0, ""
   189  }
   190  
   191  // 下一个英文的单词长度
   192  // 97 ~ 122
   193  // 65 ~ 90
   194  func nextMatchKeyLength(errMsg string) int {
   195  	spaceIndex := strings.Index(strings.TrimSpace(errMsg), " ")
   196  	toMatchMsg := errMsg
   197  	if spaceIndex > 0 {
   198  		toMatchMsg = errMsg[:spaceIndex]
   199  	}
   200  	var index = 0
   201  	for _, c := range toMatchMsg {
   202  		// 判断是否是英文字符:a~z、A~Z和点号"."
   203  		if (c >= 97 && c <= 122) || (c >= 65 && c <= 90) || c == 46 {
   204  			index++
   205  			continue
   206  		} else {
   207  			return index
   208  		}
   209  	}
   210  	return index
   211  }