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.
247 lines
5.3 KiB
247 lines
5.3 KiB
package specifications |
|
|
|
import ( |
|
) |
|
|
|
// Condition represents a single condition in the specification |
|
type Condition struct { |
|
Field string `json:"field"` |
|
Operator string `json:"operator"` |
|
Value interface{} `json:"value"` |
|
} |
|
|
|
// LogicalGroup represents a logical group of conditions (AND, OR, NOT) |
|
type LogicalGroup struct { |
|
Operator string `json:"operator"` // "AND", "OR", "NOT" |
|
Conditions []Condition `json:"conditions"` // For AND/OR |
|
Spec *Spec `json:"spec"` // For NOT |
|
} |
|
|
|
// Spec represents a specification that can be either a single condition or a logical group |
|
type Spec struct { |
|
Condition *Condition `json:"condition,omitempty"` |
|
LogicalGroup *LogicalGroup `json:"logicalGroup,omitempty"` |
|
} |
|
|
|
// SpecHelper provides methods to build specifications |
|
type SpecHelper struct{} |
|
|
|
// NewSpecHelper creates a new SpecHelper instance |
|
func NewSpecHelper() *SpecHelper { |
|
return &SpecHelper{} |
|
} |
|
|
|
// Logical group operators |
|
const ( |
|
GROUP_AND = "AND" |
|
GROUP_OR = "OR" |
|
GROUP_NOT = "NOT" |
|
) |
|
|
|
// Comparison operators |
|
const ( |
|
OP_EQ = "=" |
|
OP_NEQ = "!=" |
|
OP_GT = ">" |
|
OP_GTE = ">=" |
|
OP_LT = "<" |
|
OP_LTE = "<=" |
|
OP_IN = "IN" |
|
OP_NIN = "NOT IN" |
|
) |
|
|
|
// Logical group helpers |
|
func (h *SpecHelper) And(conditions ...*Spec) *Spec { |
|
return &Spec{ |
|
LogicalGroup: &LogicalGroup{ |
|
Operator: GROUP_AND, |
|
Conditions: h.extractConditions(conditions), |
|
}, |
|
} |
|
} |
|
|
|
func (h *SpecHelper) Or(conditions ...*Spec) *Spec { |
|
return &Spec{ |
|
LogicalGroup: &LogicalGroup{ |
|
Operator: GROUP_OR, |
|
Conditions: h.extractConditions(conditions), |
|
}, |
|
} |
|
} |
|
|
|
func (h *SpecHelper) Not(condition *Spec) *Spec { |
|
return &Spec{ |
|
LogicalGroup: &LogicalGroup{ |
|
Operator: GROUP_NOT, |
|
Spec: condition, |
|
}, |
|
} |
|
} |
|
|
|
// Condition helpers |
|
func (h *SpecHelper) Eq(field string, value interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_EQ, |
|
Value: value, |
|
}, |
|
} |
|
} |
|
|
|
func (h *SpecHelper) Neq(field string, value interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_NEQ, |
|
Value: value, |
|
}, |
|
} |
|
} |
|
|
|
func (h *SpecHelper) Gt(field string, value interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_GT, |
|
Value: value, |
|
}, |
|
} |
|
} |
|
|
|
func (h *SpecHelper) Gte(field string, value interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_GTE, |
|
Value: value, |
|
}, |
|
} |
|
} |
|
|
|
func (h *SpecHelper) Lt(field string, value interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_LT, |
|
Value: value, |
|
}, |
|
} |
|
} |
|
|
|
func (h *SpecHelper) Lte(field string, value interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_LTE, |
|
Value: value, |
|
}, |
|
} |
|
} |
|
|
|
func (h *SpecHelper) In(field string, values []interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_IN, |
|
Value: values, |
|
}, |
|
} |
|
} |
|
|
|
func (h *SpecHelper) Nin(field string, values []interface{}) *Spec { |
|
return &Spec{ |
|
Condition: &Condition{ |
|
Field: field, |
|
Operator: OP_NIN, |
|
Value: values, |
|
}, |
|
} |
|
} |
|
|
|
// extractConditions extracts conditions from specs for logical groups |
|
func (h *SpecHelper) extractConditions(specs []*Spec) []Condition { |
|
var conditions []Condition |
|
for _, spec := range specs { |
|
if spec.Condition != nil { |
|
conditions = append(conditions, *spec.Condition) |
|
} |
|
} |
|
return conditions |
|
} |
|
|
|
// GetConditions returns all conditions from a spec (flattened) |
|
func (h *SpecHelper) GetConditions(spec *Spec) []Condition { |
|
var conditions []Condition |
|
h.flattenConditions(spec, &conditions) |
|
return conditions |
|
} |
|
|
|
// flattenConditions recursively flattens conditions from a spec |
|
func (h *SpecHelper) flattenConditions(spec *Spec, conditions *[]Condition) { |
|
if spec == nil { |
|
return |
|
} |
|
|
|
if spec.Condition != nil { |
|
*conditions = append(*conditions, *spec.Condition) |
|
} |
|
|
|
if spec.LogicalGroup != nil { |
|
if spec.LogicalGroup.Operator == GROUP_AND || spec.LogicalGroup.Operator == GROUP_OR { |
|
for _, cond := range spec.LogicalGroup.Conditions { |
|
*conditions = append(*conditions, cond) |
|
} |
|
} else if spec.LogicalGroup.Operator == GROUP_NOT && spec.LogicalGroup.Spec != nil { |
|
h.flattenConditions(spec.LogicalGroup.Spec, conditions) |
|
} |
|
} |
|
} |
|
|
|
// Global Spec helper instance |
|
var SpecBuilder = NewSpecHelper() |
|
|
|
// Convenience functions that use the global Spec instance |
|
func And(conditions ...*Spec) *Spec { |
|
return SpecBuilder.And(conditions...) |
|
} |
|
|
|
func Or(conditions ...*Spec) *Spec { |
|
return SpecBuilder.Or(conditions...) |
|
} |
|
|
|
func Not(condition *Spec) *Spec { |
|
return SpecBuilder.Not(condition) |
|
} |
|
|
|
func Eq(field string, value interface{}) *Spec { |
|
return SpecBuilder.Eq(field, value) |
|
} |
|
|
|
func Neq(field string, value interface{}) *Spec { |
|
return SpecBuilder.Neq(field, value) |
|
} |
|
|
|
func Gt(field string, value interface{}) *Spec { |
|
return SpecBuilder.Gt(field, value) |
|
} |
|
|
|
func Gte(field string, value interface{}) *Spec { |
|
return SpecBuilder.Gte(field, value) |
|
} |
|
|
|
func Lt(field string, value interface{}) *Spec { |
|
return SpecBuilder.Lt(field, value) |
|
} |
|
|
|
func Lte(field string, value interface{}) *Spec { |
|
return SpecBuilder.Lte(field, value) |
|
} |
|
|
|
func In(field string, values []interface{}) *Spec { |
|
return SpecBuilder.In(field, values) |
|
} |
|
|
|
func Nin(field string, values []interface{}) *Spec { |
|
return SpecBuilder.Nin(field, values) |
|
} |