-
Notifications
You must be signed in to change notification settings - Fork 0
/
filter.go
184 lines (150 loc) · 3.32 KB
/
filter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package tagger
import (
"fmt"
"strings"
)
// TODO: Investigate negate/invert filter and it's sql equivalent
// Filter provides an interface to filter files based on their tags
type Filter interface {
fmt.Stringer
// TODO: This interface might not if databases engines want to optimize filtering
Matches(t []Tag) bool
}
// NameFilter filters tags on their names
type NameFilter struct {
Name string
}
// Matches check if the filter matches the given tags
func (n NameFilter) Matches(tags []Tag) bool {
for _, tag := range tags {
if tag.Name() == n.Name {
return true
}
}
return false
}
// Comparator describes a way to compare two integer values
type Comparator int
// Definitions of various comparinson operators
const (
Invalid Comparator = iota
Equals
NotEquals
LessThan
GreaterThan
LessThanOrEqual
GreaterThanOrEqual
)
func ComparatorFromString(val string) Comparator {
switch val {
case "==":
return Equals
case "!=":
return NotEquals
case "<":
return LessThan
case ">":
return GreaterThan
case "<=":
return LessThanOrEqual
case ">=":
return GreaterThanOrEqual
default:
return Invalid
}
}
// ComparinsonFilter filters value tags based on their value
type ComparinsonFilter struct {
Name string
Value int
Function Comparator
}
// Matches check if the filter matches the given tags
func (c ComparinsonFilter) Matches(tags []Tag) bool {
for _, tag := range tags {
if tag.Name() == c.Name {
if !tag.HasValue() {
return false
}
switch c.Function {
case Equals:
return tag.Value() == c.Value
case NotEquals:
return tag.Value() != c.Value
case LessThan:
return tag.Value() < c.Value
case GreaterThan:
return tag.Value() > c.Value
case LessThanOrEqual:
return tag.Value() <= c.Value
case GreaterThanOrEqual:
return tag.Value() >= c.Value
}
}
}
return false
}
// AndFilter allows the joining of two or more filters, all which must match
type AndFilter struct {
Filters []Filter
}
// Matches check if the filter matches the given tags
func (a AndFilter) Matches(tags []Tag) bool {
for _, filter := range a.Filters {
if !filter.Matches(tags) {
return false
}
}
return true
}
// OrFilter allows the joining of two or more filters, one of which must match
type OrFilter struct {
Filters []Filter
}
// Matches check if the filter matches the given tags
func (o OrFilter) Matches(tags []Tag) bool {
for _, filter := range o.Filters {
if filter.Matches(tags) {
return true
}
}
return false
}
// Debuggg
func (c Comparator) String() string {
switch c {
case Equals:
return "=="
case NotEquals:
return "!="
case LessThan:
return "<"
case GreaterThan:
return ">"
case LessThanOrEqual:
return "<="
case GreaterThanOrEqual:
return ">="
}
return "INVALID"
}
func (n NameFilter) String() string {
return fmt.Sprintf("%s", n.Name)
}
func (c ComparinsonFilter) String() string {
return fmt.Sprintf("%s %s %d", c.Name, c.Function, c.Value)
}
func (a AndFilter) String() string {
subs := make([]string, 0)
for _, f := range a.Filters {
subs = append(subs, f.String())
}
return fmt.Sprintf("(%s)", strings.Join(subs, ", "))
}
func (a OrFilter) String() string {
subs := make([]string, 0)
for _, f := range a.Filters {
subs = append(subs, f.String())
}
return fmt.Sprintf("(%s)", strings.Join(subs, ", "))
}