123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- package rule
- import (
- "encoding/json"
- "git.sxidc.com/go-framework/baize/convenient/domain/query_rule/definition"
- "git.sxidc.com/go-framework/baize/framework/core/domain"
- "git.sxidc.com/go-framework/baize/framework/core/infrastructure"
- "git.sxidc.com/go-framework/baize/framework/core/infrastructure/database"
- "git.sxidc.com/go-framework/baize/framework/core/infrastructure/database/clause"
- "git.sxidc.com/go-framework/baize/framework/core/infrastructure/database/sql"
- "git.sxidc.com/go-framework/baize/framework/core/tag/rule"
- "git.sxidc.com/go-tools/utils/strutils"
- "github.com/pkg/errors"
- )
- const (
- LogicalOperatorAnd = "and"
- LogicalOperatorOr = "or"
- )
- func isSupportedLogicalOperator(logicalOperator string) bool {
- return logicalOperator == LogicalOperatorAnd || logicalOperator == LogicalOperatorOr
- }
- type Rule struct {
- LogicalOperator string `json:"logicalOperator"`
- Left *Rule `json:"left"`
- Right *Rule `json:"right"`
- FieldName string `json:"fieldName"`
- FieldType string `json:"fieldType"`
- Operator string `json:"operator"`
- Value any `json:"value"`
- }
- func (r Rule) check() error {
- if r.isNode() {
- return r.checkAsNode()
- } else {
- return r.checkAsLeaf()
- }
- }
- func (r Rule) checkAsNode() error {
- if !isSupportedLogicalOperator(r.LogicalOperator) {
- return errors.New("不支持的逻辑操作符")
- }
- if r.Left == nil {
- return errors.New("左结点为空")
- }
- if r.Right == nil {
- return errors.New("右结点为空")
- }
- if strutils.IsStringNotEmpty(r.Left.LogicalOperator) {
- err := r.Left.checkAsNode()
- if err != nil {
- return err
- }
- } else {
- err := r.Left.checkAsLeaf()
- if err != nil {
- return err
- }
- }
- if strutils.IsStringNotEmpty(r.Right.LogicalOperator) {
- err := r.Right.checkAsNode()
- if err != nil {
- return err
- }
- } else {
- err := r.Right.checkAsLeaf()
- if err != nil {
- return err
- }
- }
- return nil
- }
- func (r Rule) checkAsLeaf() error {
- if strutils.IsStringEmpty(r.FieldName) {
- return errors.New("字段名为空")
- }
- if !rule.IsSupportedType(r.FieldType) {
- return errors.New("字段类型不支持")
- }
- if !definition.IsSupportedOperator(r.Operator) {
- return errors.New("操作符不支持")
- }
- return nil
- }
- func (r Rule) isNode() bool {
- return strutils.IsStringNotEmpty(r.LogicalOperator)
- }
- func HasRule(dbSchema string, scope string, domainName string, i *infrastructure.Infrastructure) (bool, error) {
- dbExecutor := i.DBExecutor()
- return database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{
- TableName: domain.TableName(dbSchema, &Entity{}),
- Conditions: sql.NewConditions().
- Equal(ColumnScope, scope).
- Equal(ColumnDomainName, domainName).
- Equal(ColumnEnabled, true),
- })
- }
- func FormConditionClause(dbSchema string, scope string, domainName string, i *infrastructure.Infrastructure, ruleParams map[string]any) (clause.Clause, error) {
- r, err := getEnabledRule(dbSchema, scope, domainName, i)
- if err != nil {
- return nil, err
- }
- c, err := formConditionClause(domainName, r, ruleParams)
- if err != nil {
- return nil, err
- }
- return c, nil
- }
- func FormConditionClauseByRule(domainName string, r Rule, ruleParams map[string]any) (clause.Clause, error) {
- c, err := formConditionClause(domainName, r, ruleParams)
- if err != nil {
- return nil, err
- }
- return c, nil
- }
- const (
- modifyBranchRoot = "root"
- modifyBranchLeft = "left"
- modifyBranchRight = "right"
- )
- func ModifyLeafRuleStr(ruleStr string, leafRuleCallback func(leafRule *Rule) error) (string, error) {
- rootRule := new(Rule)
- err := json.Unmarshal([]byte(ruleStr), rootRule)
- if err != nil {
- return "", err
- }
- err = modifyLeafRule(nil, rootRule, modifyBranchRoot, leafRuleCallback)
- if err != nil {
- return "", err
- }
- newRuleStr, err := json.Marshal(rootRule)
- if err != nil {
- return "", err
- }
- return string(newRuleStr), nil
- }
- func modifyLeafRule(parentRule *Rule, r *Rule, branch string, leafRuleCallback func(leafRule *Rule) error) error {
- if r == nil {
- return nil
- }
- err := r.check()
- if err != nil {
- return err
- }
- if !r.isNode() {
- err := leafRuleCallback(r)
- if err != nil {
- return err
- }
- if parentRule == nil {
- return nil
- }
- switch branch {
- case modifyBranchRoot:
- return nil
- case modifyBranchLeft:
- parentRule.Left = r
- case modifyBranchRight:
- parentRule.Right = r
- default:
- return errors.New("不支持的分支类型: " + branch)
- }
- }
- err = modifyLeafRule(r, r.Left, modifyBranchLeft, leafRuleCallback)
- if err != nil {
- return err
- }
- err = modifyLeafRule(r, r.Right, modifyBranchRight, leafRuleCallback)
- if err != nil {
- return err
- }
- return nil
- }
- func modifyRule(rootRule *Rule, ruleCallback func(parentRule *Rule, r *Rule, branch string) error) error {
- if rootRule == nil {
- return nil
- }
- err := rootRule.check()
- if err != nil {
- return err
- }
- if !rootRule.isNode() {
- return ruleCallback(nil, rootRule, modifyBranchRoot)
- }
- err = ruleCallback(rootRule, rootRule.Left, modifyBranchLeft)
- if err != nil {
- return err
- }
- if rootRule.Left.isNode() {
- err := modifyRule(rootRule.Left, ruleCallback)
- if err != nil {
- return err
- }
- }
- err = ruleCallback(rootRule, rootRule.Right, modifyBranchRight)
- if err != nil {
- return err
- }
- if rootRule.Right.isNode() {
- err := modifyRule(rootRule.Right, ruleCallback)
- if err != nil {
- return err
- }
- }
- return nil
- }
- func getEnabledRule(dbSchema string, scope string, domainName string, i *infrastructure.Infrastructure) (Rule, error) {
- dbExecutor := i.DBExecutor()
- result, err := database.QueryOne(dbExecutor, &sql.QueryOneExecuteParams{
- TableName: domain.TableName(dbSchema, &Entity{}),
- Conditions: sql.NewConditions().
- Equal(ColumnScope, scope).
- Equal(ColumnDomainName, domainName).
- Equal(ColumnEnabled, true),
- })
- if err != nil {
- return Rule{}, err
- }
- r := new(Rule)
- err = json.Unmarshal([]byte(result.ColumnValueString(ColumnRule)), r)
- if err != nil {
- return Rule{}, err
- }
- return *r, nil
- }
- func formConditionClause(domainName string, r Rule, ruleParams map[string]any) (clause.Clause, error) {
- err := r.check()
- if err != nil {
- return nil, err
- }
- if strutils.IsStringEmpty(r.LogicalOperator) {
- columnName, err := definition.GetColumnName(domainName, r.FieldName)
- if err != nil {
- return nil, err
- }
- ruleValue := r.Value
- if ruleParams != nil {
- ruleParamValue, ok := ruleParams[columnName]
- if ok {
- ruleValue = ruleParamValue
- }
- }
- if ruleValue == nil {
- return nil, nil
- }
- conditions := clause.NewConditions()
- err = definition.AddCondition(conditions, r.Operator, columnName, ruleValue)
- if err != nil {
- return nil, err
- }
- return conditions.And(), nil
- }
- leftClause, err := formConditionClause(domainName, *r.Left, ruleParams)
- if err != nil {
- return nil, err
- }
- rightClause, err := formConditionClause(domainName, *r.Right, ruleParams)
- if err != nil {
- return nil, err
- }
- switch r.LogicalOperator {
- case LogicalOperatorAnd:
- return clause.NewConditionJoin(leftClause, rightClause).And(), nil
- case LogicalOperatorOr:
- return clause.NewConditionJoin(leftClause, rightClause).Or(), nil
- default:
- return clause.NewConditionJoin(leftClause, rightClause).And(), nil
- }
- }
|