forked from jamessimone/apex-dml-mocking
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Query.cls
186 lines (157 loc) · 5.44 KB
/
Query.cls
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
public virtual class Query {
public enum Operator {
EQUALS,
NOT_EQUALS,
LESS_THAN,
LESS_THAN_OR_EQUAL,
GREATER_THAN,
GREATER_THAN_OR_EQUAL,
ALIKE, // like is a reserved word
NOT_LIKE
}
public final Operator operator;
private final String field;
private final Schema.SObjectField fieldToken;
private final Object predicate;
private final Map<String, Object> bindVars = new Map<String, Object>();
private static final String BIND_VAR_MERGE = 'bindVar{0}';
private static Integer BIND_VAR_NUMBER = 0;
public Query usingParent(Schema.SObjectField parentField) {
return this.usingParent(new List<Schema.SObjectField>{ parentField });
}
public Query usingParent(List<SObjectField> parentFields) {
parentFields.add(this.fieldToken);
return new ParentQuery(parentFields, this.operator, this.predicate);
}
public static Query equals(SObjectField field, Object predicate) {
return new Query(field, Operator.EQUALS, predicate);
}
public static Query notEquals(SObjectField field, Object predicate) {
return new Query(field, Operator.NOT_EQUALS, predicate);
}
public static Query lessThan(SObjectField field, Object predicate) {
return new Query(field, Operator.LESS_THAN, predicate);
}
public static Query lessThanOrEqual(SObjectField field, Object predicate) {
return new Query(field, Operator.LESS_THAN_OR_EQUAL, predicate);
}
public static Query greaterThan(SObjectField field, Object predicate) {
return new Query(field, Operator.GREATER_THAN, predicate);
}
public static Query greaterThanOrEqual(SObjectField field, Object predicate) {
return new Query(field, Operator.GREATER_THAN_OR_EQUAL, predicate);
}
// like is a reserved keyword
public static Query likeQuery(SObjectField field, Object predicate) {
return new Query(field, Operator.ALIKE, predicate);
}
public static Query notLike(SObjectField field, Object predicate) {
return new Query(field, Operator.NOT_LIKE, predicate);
}
// or is a reserved keyword
public static Query orQuery(Query innerQuery, Query secondInnerQuery) {
return orQuery(new List<Query>{ innerQuery, secondInnerQuery });
}
public static Query orQuery(List<Query> innerQueries) {
return new OrQuery(innerQueries);
}
private class OrQuery extends Query {
private final List<Query> queries;
private final String orDelimiter = ' OR ';
public OrQuery(List<Query> queries) {
super();
this.queries = queries;
}
public override String toString() {
String baseString = '(';
for (Query innerQuery : this.queries) {
baseString += innerQuery.toString() + this.orDelimiter;
this.bindVars.putAll(innerQuery.getBindVars());
}
return baseString.removeEnd(this.orDelimiter) + ')';
}
}
private class ParentQuery extends Query {
private ParentQuery(List<SObjectField> parentFields, Operator operator, Object predicate) {
super(getBuiltUpParentFieldName(parentFields), operator, predicate);
}
}
protected Query() {
}
private Query(String fieldName, Operator operator, Object predicate) {
this.field = fieldName;
this.operator = operator;
this.predicate = predicate;
}
private Query(SObjectField fieldToken, Operator operator, Object predicate) {
this(fieldToken.getDescribe().getName(), operator, predicate);
this.fieldToken = fieldToken;
}
public Map<String, Object> getBindVars() {
return this.bindVars;
}
public virtual override String toString() {
String predicateValue = this.getPredicate(this.predicate);
if (this.operator == Query.Operator.NOT_LIKE) {
// who knows why this is the format they wanted
return String.format(this.getOperator(), new List<String>{ this.field }) + ' ' + predicateValue;
}
return this.field + ' ' + this.getOperator() + ' ' + predicateValue;
}
public Boolean equals(Object thatObject) {
if (thatObject instanceof Query) {
Query that = (Query) thatObject;
return this.toString() == that.toString();
}
return false;
}
private String getOperator() {
String returnVal = '';
switch on this.operator {
when EQUALS {
returnVal = '=';
}
when NOT_EQUALS {
returnVal = '!=';
}
when LESS_THAN {
returnVal = '<';
}
when LESS_THAN_OR_EQUAL {
returnVal = '<=';
}
when GREATER_THAN {
returnVal = '>';
}
when GREATER_THAN_OR_EQUAL {
returnVal = '>=';
}
when ALIKE {
returnVal = 'like';
}
when NOT_LIKE {
returnVal = 'not {0} like';
}
}
return returnVal;
}
private String getPredicate(Object predicate) {
if (predicate == null || predicate instanceof Boolean) {
return '' + predicate;
}
String predicateKey = String.format(BIND_VAR_MERGE, new List<String>{ BIND_VAR_NUMBER.format() });
BIND_VAR_NUMBER++;
this.bindVars.put(predicateKey, predicate);
return ':' + predicateKey;
}
private static String getBuiltUpParentFieldName(List<SObjectField> parentFields) {
String builtUpFieldName = '';
for (Integer index = 0; index < parentFields.size(); index++) {
Schema.DescribeFieldResult parentFieldDescribe = parentFields[index].getDescribe();
builtUpFieldName += index == parentFields.size() - 1
? parentFieldDescribe.getName()
: parentFieldDescribe.getRelationshipName() + '.';
}
return builtUpFieldName;
}
}