Multiple implementations of the same back-end application. The aim is to provide quick, side-by-side comparisons of different technologies (languages, frameworks, libraries) while preserving consistent business logic across all implementations.
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

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