| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- package matcher
- import (
- "fmt"
- "strings"
- "github.com/opencost/opencost/pkg/filter21/ast"
- "github.com/opencost/opencost/pkg/log"
- )
- // StringMatcherFactory leverages a single StringSliceFieldMapper[T] to generate instances of
- // StringSliceMatcher[T].
- type StringSliceMatcherFactory[T any] struct {
- fieldMapper SliceFieldMapper[T]
- }
- // NewStringSliceMatcherFactory creates a new StringMatcher factory for a given T type.
- func NewStringSliceMatcherFactory[T any](fieldMapper SliceFieldMapper[T]) *StringSliceMatcherFactory[T] {
- return &StringSliceMatcherFactory[T]{
- fieldMapper: fieldMapper,
- }
- }
- // NewStringMatcher creates a new StringSliceMatcher using the provided op, field ident, and value comparison.
- func (smf *StringSliceMatcherFactory[T]) NewStringSliceMatcher(op ast.FilterOp, ident ast.Identifier, value string) *StringSliceMatcher[T] {
- return &StringSliceMatcher[T]{
- Op: op,
- Identifier: ident,
- Value: value,
- fieldMapper: smf.fieldMapper,
- }
- }
- // StringSliceProperty is the lowest-level type of filter. It represents
- // a filter operation (equality, inequality, etc.) on a property that contains a string slice
- type StringSliceMatcher[T any] struct {
- Op ast.FilterOp
- Identifier ast.Identifier
- Value string
- fieldMapper SliceFieldMapper[T]
- }
- func (ssp *StringSliceMatcher[T]) String() string {
- return fmt.Sprintf(`(%s %s "%s")`, ssp.Op, ssp.Identifier.String(), ssp.Value)
- }
- func (ssp *StringSliceMatcher[T]) Matches(that T) bool {
- thatSlice, err := ssp.fieldMapper(that, ssp.Identifier)
- if err != nil {
- log.Errorf("Filter: StringSliceMatcher: could not retrieve field %s: %s", ssp.Identifier.String(), err.Error())
- return false
- }
- switch ssp.Op {
- case ast.FilterOpContains:
- if len(thatSlice) == 0 {
- return ssp.Value == ""
- }
- for _, s := range thatSlice {
- if s == ssp.Value {
- return true
- }
- }
- case ast.FilterOpContainsPrefix:
- for _, s := range thatSlice {
- if strings.HasPrefix(s, ssp.Value) {
- return true
- }
- }
- return false
- case ast.FilterOpContainsSuffix:
- for _, s := range thatSlice {
- if strings.HasSuffix(s, ssp.Value) {
- return true
- }
- }
- return false
- default:
- log.Errorf("Filter: StringSliceMatcher: Unhandled filter op. This is a filter implementation error and requires immediate patching. Op: %s", ssp.Op)
- return false
- }
- return false
- }
|