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
|
|
|
|
}
|