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