forked from fabric8-services/fabric8-wit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
criteria.go
237 lines (192 loc) · 5.97 KB
/
criteria.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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
package criteria
// Expression is used to express conditions for selecting an entity
type Expression interface {
// Accept calls the visitor callback of the appropriate type
Accept(visitor ExpressionVisitor) interface{}
// SetAnnotation puts the given annotation on the expression
SetAnnotation(key string, value interface{})
// Annotation reads back values set with SetAnnotation
Annotation(key string) interface{}
// Returns the parent expression or nil
Parent() Expression
setParent(parent Expression)
}
// IterateParents calls f for every member of the parent chain
// Stops iterating if f returns false
func IterateParents(exp Expression, f func(Expression) bool) {
if exp != nil {
exp = exp.Parent()
}
for exp != nil {
if !f(exp) {
return
}
exp = exp.Parent()
}
}
// BinaryExpression represents expressions with 2 children
// This could be generalized to n-ary expressions, but that is not necessary right now
type BinaryExpression interface {
Expression
Left() Expression
Right() Expression
}
// ExpressionVisitor is an implementation of the visitor pattern for expressions
type ExpressionVisitor interface {
Field(t *FieldExpression) interface{}
And(a *AndExpression) interface{}
Or(a *OrExpression) interface{}
Equals(e *EqualsExpression) interface{}
Parameter(v *ParameterExpression) interface{}
Literal(c *LiteralExpression) interface{}
Not(e *NotExpression) interface{}
IsNull(e *IsNullExpression) interface{}
}
type expression struct {
parent Expression
annotations map[string]interface{}
}
func (exp *expression) SetAnnotation(key string, value interface{}) {
if exp.annotations == nil {
exp.annotations = map[string]interface{}{}
}
exp.annotations[key] = value
}
func (exp *expression) Annotation(key string) interface{} {
return exp.annotations[key]
}
func (exp *expression) Parent() Expression {
result := exp.parent
return result
}
func (exp *expression) setParent(parent Expression) {
exp.parent = parent
}
// access a Field
// FieldExpression represents access to a field of the tested object
type FieldExpression struct {
expression
FieldName string
}
// Accept implements ExpressionVisitor
func (t *FieldExpression) Accept(visitor ExpressionVisitor) interface{} {
return visitor.Field(t)
}
// Field constructs a FieldExpression
func Field(id string) Expression {
return &FieldExpression{expression{}, id}
}
// Parameter (free variable of the expression)
// A ParameterExpression represents a parameter to be passed upon evaluation of the expression
type ParameterExpression struct {
expression
}
// Accept implements ExpressionVisitor
func (t *ParameterExpression) Accept(visitor ExpressionVisitor) interface{} {
return visitor.Parameter(t)
}
// Parameter constructs a value expression.
func Parameter() Expression {
return &ParameterExpression{}
}
// literal value
// A LiteralExpression represents a single constant value in the expression, think "5" or "asdf"
// the type of literals is not restricted at this level, but compilers or interpreters will have limitations on what they handle
type LiteralExpression struct {
expression
Value interface{}
}
// Accept implements ExpressionVisitor
func (t *LiteralExpression) Accept(visitor ExpressionVisitor) interface{} {
return visitor.Literal(t)
}
// Literal constructs a literal expression
func Literal(value interface{}) Expression {
return &LiteralExpression{expression{}, value}
}
// binaryExpression is an "abstract" type for binary expressions.
type binaryExpression struct {
expression
left Expression
right Expression
}
// Left implements BinaryExpression
func (exp *binaryExpression) Left() Expression {
return exp.left
}
// Right implements BinaryExpression
func (exp *binaryExpression) Right() Expression {
return exp.right
}
// make sure the children have the correct parent
func reparent(parent BinaryExpression) Expression {
parent.Left().setParent(parent)
parent.Right().setParent(parent)
return parent
}
// And
// AndExpression represents the conjunction operation of two terms
type AndExpression struct {
binaryExpression
}
// Accept implements ExpressionVisitor
func (t *AndExpression) Accept(visitor ExpressionVisitor) interface{} {
return visitor.And(t)
}
// And constructs an AndExpression
func And(left Expression, right Expression) Expression {
return reparent(&AndExpression{binaryExpression{expression{}, left, right}})
}
// Or
// OrExpression represents the disjunction operation of two terms
type OrExpression struct {
binaryExpression
}
// Accept implements ExpressionVisitor
func (t *OrExpression) Accept(visitor ExpressionVisitor) interface{} {
return visitor.Or(t)
}
// Or constructs an OrExpression
func Or(left Expression, right Expression) Expression {
return reparent(&OrExpression{binaryExpression{expression{}, left, right}})
}
// ==
// EqualsExpression represents the equality operator
type EqualsExpression struct {
binaryExpression
}
// Accept implements ExpressionVisitor
func (t *EqualsExpression) Accept(visitor ExpressionVisitor) interface{} {
return visitor.Equals(t)
}
// Equals constructs an EqualsExpression
func Equals(left Expression, right Expression) Expression {
return reparent(&EqualsExpression{binaryExpression{expression{}, left, right}})
}
// IS NULL
// IsNullExpression represents the IS operator with NULL value
type IsNullExpression struct {
expression
FieldName string
}
// IsNull constructs an NullExpression
func IsNull(name string) Expression {
return &IsNullExpression{expression{}, name}
}
// Accept implements ExpressionVisitor
func (t *IsNullExpression) Accept(visitor ExpressionVisitor) interface{} {
return visitor.IsNull(t)
}
// Not
// NotExpression represents the negation operator
type NotExpression struct {
binaryExpression
}
// Accept implements ExpressionVisitor
func (t *NotExpression) Accept(visitor ExpressionVisitor) interface{} {
return visitor.Not(t)
}
// Not constructs a NotExpression
func Not(left Expression, right Expression) Expression {
return reparent(&NotExpression{binaryExpression{expression{}, left, right}})
}