You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
219 lines
3.9 KiB
219 lines
3.9 KiB
package specifications |
|
|
|
const ( |
|
GROUP_AND = "AND" |
|
GROUP_OR = "OR" |
|
GROUP_NOT = "NOT" |
|
) |
|
|
|
const ( |
|
OP_EQ = "=" |
|
OP_NEQ = "!=" |
|
OP_GT = ">" |
|
OP_GTE = ">=" |
|
OP_LT = "<" |
|
OP_LTE = "<=" |
|
OP_IN = "IN" |
|
OP_NIN = "NOT IN" |
|
) |
|
|
|
type Condition struct { |
|
Field string `json:"field"` |
|
Operator string `json:"operator"` |
|
Value interface{} `json:"value"` |
|
} |
|
|
|
type LogicalGroup struct { |
|
Operator string `json:"operator"` |
|
Conditions []Condition `json:"conditions"` |
|
Spec *Spec `json:"spec"` |
|
} |
|
|
|
type Spec struct { |
|
Condition *Condition `json:"condition,omitempty"` |
|
LogicalGroup *LogicalGroup `json:"logicalGroup,omitempty"` |
|
} |
|
|
|
func And(conditions ...*Spec) *Spec { |
|
if len(conditions) == 0 { |
|
return nil |
|
} |
|
if len(conditions) == 1 { |
|
return conditions[0] |
|
} |
|
|
|
var flatConditions []Condition |
|
var nestedSpecs []*Spec |
|
|
|
for _, spec := range conditions { |
|
if spec.Condition != nil { |
|
flatConditions = append(flatConditions, *spec.Condition) |
|
} else { |
|
nestedSpecs = append(nestedSpecs, spec) |
|
} |
|
} |
|
|
|
result := &Spec{ |
|
LogicalGroup: &LogicalGroup{ |
|
Operator: GROUP_AND, |
|
Conditions: flatConditions, |
|
}, |
|
} |
|
|
|
if len(nestedSpecs) == 1 { |
|
result.LogicalGroup.Spec = nestedSpecs[0] |
|
} else if len(nestedSpecs) > 1 { |
|
result.LogicalGroup.Spec = And(nestedSpecs...) |
|
} |
|
|
|
return result |
|
} |
|
|
|
func Or(conditions ...*Spec) *Spec { |
|
if len(conditions) == 0 { |
|
return nil |
|
} |
|
if len(conditions) == 1 { |
|
return conditions[0] |
|
} |
|
|
|
var flatConditions []Condition |
|
var nestedSpecs []*Spec |
|
|
|
for _, spec := range conditions { |
|
if spec.Condition != nil { |
|
flatConditions = append(flatConditions, *spec.Condition) |
|
} else { |
|
nestedSpecs = append(nestedSpecs, spec) |
|
} |
|
} |
|
|
|
result := &Spec{ |
|
LogicalGroup: &LogicalGroup{ |
|
Operator: GROUP_OR, |
|
Conditions: flatConditions, |
|
}, |
|
} |
|
|
|
if len(nestedSpecs) == 1 { |
|
result.LogicalGroup.Spec = nestedSpecs[0] |
|
} else if len(nestedSpecs) > 1 { |
|
result.LogicalGroup.Spec = Or(nestedSpecs...) |
|
} |
|
|
|
return result |
|
} |
|
|
|
func Not(condition *Spec) *Spec { |
|
return &Spec{ |
|
LogicalGroup: &LogicalGroup{ |
|
Operator: GROUP_NOT, |
|
Spec: condition, |
|
}, |
|
} |
|
} |
|
|
|
func Eq(field string, value interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_EQ, |
|
Value: value, |
|
}, |
|
} |
|
} |
|
|
|
func Neq(field string, value interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_NEQ, |
|
Value: value, |
|
}, |
|
} |
|
} |
|
|
|
func Gt(field string, value interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_GT, |
|
Value: value, |
|
}, |
|
} |
|
} |
|
|
|
func Gte(field string, value interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_GTE, |
|
Value: value, |
|
}, |
|
} |
|
} |
|
|
|
func Lt(field string, value interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_LT, |
|
Value: value, |
|
}, |
|
} |
|
} |
|
|
|
func Lte(field string, value interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_LTE, |
|
Value: value, |
|
}, |
|
} |
|
} |
|
|
|
func In(field string, values []interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_IN, |
|
Value: values, |
|
}, |
|
} |
|
} |
|
|
|
func Nin(field string, values []interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_NIN, |
|
Value: values, |
|
}, |
|
} |
|
} |
|
|
|
func GetConditions(spec *Spec) []Condition { |
|
var conditions []Condition |
|
flattenConditions(spec, &conditions) |
|
return conditions |
|
} |
|
|
|
func flattenConditions(spec *Spec, conditions *[]Condition) { |
|
if spec == nil { |
|
return |
|
} |
|
|
|
if spec.Condition != nil { |
|
*conditions = append(*conditions, *spec.Condition) |
|
} |
|
|
|
if spec.LogicalGroup != nil { |
|
for _, cond := range spec.LogicalGroup.Conditions { |
|
*conditions = append(*conditions, cond) |
|
} |
|
if spec.LogicalGroup.Spec != nil { |
|
flattenConditions(spec.LogicalGroup.Spec, conditions) |
|
} |
|
} |
|
} |