package filters import ( "errors" "fmt" "regexp" "strconv" "time" cache "github.com/patrickmn/go-cache" ) var matchCache = cache.New(5*time.Minute, 1*time.Minute) type matcherT interface { setOperator(operator string) GetOperator() string Compare(valA, valB interface{}) bool } type abstractMatcher struct { matcherT Operator string } func (matcher *abstractMatcher) GetOperator() string { return matcher.Operator } type equalMatcher struct { abstractMatcher } func (matcher *equalMatcher) Compare(valA, valB interface{}) bool { return valA == valB } type notEqualMatcher struct { abstractMatcher } func (matcher *notEqualMatcher) Compare(valA, valB interface{}) bool { return valA != valB } type moreThanMatcher struct { abstractMatcher } func (matcher *moreThanMatcher) Compare(valA, valB interface{}) bool { if valA == nil || valA == "" || valB == nil || valB == "" { return false } if intA, ok := valA.(int); ok { if intB, ok := valB.(int); ok { return intA > intB } } if atoiA, err := strconv.Atoi(valA.(string)); err == nil { if atoiB, err := strconv.Atoi(valB.(string)); err == nil { return atoiA > atoiB } } return string(valA.(string)) > string(valB.(string)) } type lessThanMatcher struct { abstractMatcher } func (matcher *lessThanMatcher) Compare(valA, valB interface{}) bool { if valA == nil || valA == "" || valB == nil || valB == "" { return false } if intA, ok := valA.(int); ok { if intB, ok := valB.(int); ok { return intA < intB } } if atoiA, err := strconv.Atoi(valA.(string)); err == nil { if atoiB, err := strconv.Atoi(valB.(string)); err == nil { return atoiA < atoiB } } return string(valA.(string)) < string(valB.(string)) } type regexpMatcher struct { abstractMatcher } func (matcher *regexpMatcher) Compare(valA, valB interface{}) bool { r, found := matchCache.Get(valB.(string)) if !found { var err error r, err = regexp.Compile("(?i)" + valB.(string)) if err != nil { return false } matchCache.Set(valB.(string), r, 1*time.Minute) } return r.(*regexp.Regexp).MatchString(valA.(string)) } type negativeRegexMatcher struct { abstractMatcher } func (matcher *negativeRegexMatcher) Compare(valA, valB interface{}) bool { r := regexpMatcher{} return !r.Compare(valA, valB) } func newMatcher(matchType string) (matcherT, error) { if m, found := matcherConfig[matchType]; found { return m, nil } e := fmt.Sprintf("%s not matched with any know match type", matchType) return nil, errors.New(e) }