gopkg/middleware/apollo/search.go

282 lines
6.4 KiB
Go
Raw Normal View History

2021-11-24 23:04:26 +08:00
// Package apollo...
//
// Description : apollo...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-11-24 10:26 下午
package apollo
import (
"encoding/json"
"errors"
2021-11-25 11:29:53 +08:00
"fmt"
2021-11-25 12:22:26 +08:00
"regexp"
"strings"
"sync"
"git.zhangdeman.cn/zhangdeman/gopkg/convert"
2021-11-24 23:04:26 +08:00
"git.zhangdeman.cn/zhangdeman/gopkg/util"
)
const (
// OperateTypeIs 固定值
OperateTypeIs = "is"
// OperateTypeIn 在指定枚举值中
OperateTypeIn = "in"
// OperateTypeNotIn 不在指定枚举值中
OperateTypeNotIn = "not_in"
// OperateGt 大于
OperateGt = "gt"
// OperateGte 大于等于
OperateGte = "gte"
// OperateLt 小于
OperateLt = "lt"
// OperateLte 小于等于
OperateLte = "lte"
2021-11-25 12:22:26 +08:00
// OperateTypeContains 包含
OperateTypeContains = "contains"
// OperateTypeRegular 正则匹配
OperateTypeRegular = "regular"
)
var (
// hasCompilerRegula 已编译正则,不进行重复编辑
hasCompilerRegula map[string]*regexp.Regexp
// regulaLock 编译正则用的锁
regulaLock *sync.RWMutex
2021-11-24 23:04:26 +08:00
)
2021-11-25 12:22:26 +08:00
func init() {
regulaLock = &sync.RWMutex{}
hasCompilerRegula = make(map[string]*regexp.Regexp)
}
2021-11-24 23:04:26 +08:00
// Rule 数据过滤规则
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:32 下午 2021/11/24
type Rule struct {
Name string `json:"name"` // 规则名称
ConditionList []Condition `json:"condition_list"` // 条件列表
Data map[string]interface{} `json:"data"` // 满足条件时返回的数据
}
// Condition 条件处理
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:27 下午 2021/11/24
type Condition struct {
InputKey string `json:"input_key"` // 从输入数据中读取的key
Operate string `json:"operate"` // 操作
TargetValue string `json:"target_value"` // 目标值
}
// Search 搜索key并按照指定条件过滤
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:01 下午 2021/11/24
func Search(key string, inputData map[string]interface{}, receiver interface{}) error {
if nil == receiver {
return errors.New("receiver is nil")
}
if nil == inputData {
inputData = make(map[string]interface{})
}
var (
readResult string
err error
formatResult []Rule
)
if readResult = Client.GetStringValue(key, ""); len(readResult) == 0 {
return errors.New("key is not found : " + key)
}
if err = json.Unmarshal([]byte(readResult), &formatResult); nil != err {
return errors.New("parse read config fail : " + err.Error())
}
for _, rule := range formatResult {
if checkRule(rule, inputData) {
byteData, mErr := json.Marshal(rule.Data)
if nil != mErr {
return mErr
}
// 命中规则, 返回数据
return util.JSONUnmarshalWithNumber(byteData, receiver)
}
}
return nil
}
// checkRule 检测数据是否命中规则
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:59 下午 2021/11/24
func checkRule(rule Rule, inputData map[string]interface{}) bool {
2021-11-25 11:29:53 +08:00
for _, cond := range rule.ConditionList {
val, exist := inputData[cond.InputKey]
if !exist {
// 输入的key 不存在, 不符合规则
return false
}
switch cond.Operate {
case OperateTypeIs:
if !is(val, cond.TargetValue) {
return false
}
2021-11-25 12:22:26 +08:00
case OperateTypeIn:
if !in(val, cond.TargetValue) {
return false
}
case OperateTypeNotIn:
if !notIn(val, cond.TargetValue) {
return false
}
case OperateTypeContains:
if !contains(val, cond.TargetValue) {
return false
}
case OperateGt:
if !compareNumber(val, cond.TargetValue, OperateGt) {
return false
}
case OperateGte:
if !compareNumber(val, cond.TargetValue, OperateGte) {
return false
}
case OperateLt:
if !compareNumber(val, cond.TargetValue, OperateLt) {
return false
}
case OperateLte:
if !compareNumber(val, cond.TargetValue, OperateLte) {
return false
}
2021-11-25 11:29:53 +08:00
default:
return false
}
}
2021-11-24 23:04:26 +08:00
return true
}
2021-11-25 11:29:53 +08:00
// is 判断是否相等
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:28 上午 2021/11/25
func is(inputVal interface{}, targetValue string) bool {
return fmt.Sprintf("%v", inputVal) == targetValue
}
2021-11-25 12:22:26 +08:00
// in ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:47 上午 2021/11/25
func in(inputValue interface{}, targetValue string) bool {
if nil == inputValue {
return false
}
inputStr := fmt.Sprintf("%v", inputValue)
targetList := strings.Split(targetValue, ",")
for _, item := range targetList {
if inputStr == item {
return true
}
}
return false
}
// notIn ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:47 上午 2021/11/25
func notIn(inputValue interface{}, targetValue string) bool {
if nil == inputValue {
return false
}
inputStr := fmt.Sprintf("%v", inputValue)
targetList := strings.Split(targetValue, ",")
for _, item := range targetList {
if inputStr == item {
return false
}
}
return true
}
// compareNumber ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:56 上午 2021/11/25
func compareNumber(inputValue interface{}, targetValue string, operateType string) bool {
if inputValue == nil || len(targetValue) == 0 {
return false
}
var (
err error
inputFloat float64
targetFloat float64
)
if err = convert.ConvertAssign(&inputFloat, inputValue); nil != err {
return false
}
if err = convert.ConvertAssign(&targetFloat, targetValue); nil != err {
return false
}
switch operateType {
case OperateGt:
return inputFloat > targetFloat
case OperateGte:
return inputFloat >= targetFloat
case OperateLt:
return inputFloat < targetFloat
case OperateLte:
return inputFloat <= targetFloat
}
return false
}
// contains ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:03 下午 2021/11/25
func contains(inputValue interface{}, targetValue string) bool {
return strings.Contains(fmt.Sprintf("%v", inputValue), targetValue)
}
// regula 正则匹配
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:15 下午 2021/11/25
func regula(inputValue interface{}, targetValue string) bool {
var (
reg *regexp.Regexp
err error
)
regulaLock.Lock()
if _, exist := hasCompilerRegula[targetValue]; !exist {
if reg, err = regexp.Compile(targetValue); nil != err {
regulaLock.Unlock()
return false
}
hasCompilerRegula[targetValue] = reg
} else {
reg = hasCompilerRegula[targetValue]
}
regulaLock.Unlock()
// 判断是否匹配到数据
result := reg.FindAllStringSubmatch(fmt.Sprintf("%v", inputValue), -1)
return len(result) > 0
}