1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.core.jpa.criteria;
17
18 import java.math.BigDecimal;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.LinkedHashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import javax.persistence.Query;
27
28 import org.kuali.rice.core.jpa.criteria.QueryByCriteria.QueryByCriteriaType;
29
30
31
32
33
34
35
36
37 @SuppressWarnings("unchecked")
38 public class Criteria {
39
40 private Integer searchLimit;
41
42 private String entityName;
43
44 private String alias;
45
46 private int bindParamCount;
47
48 private boolean distinct = false;
49
50 protected List tokens = new ArrayList();
51
52 private List orderByTokens = new ArrayList();
53
54 protected Map<String, Object> params = new LinkedHashMap<String, Object>();
55
56 public Criteria(String entityName) {
57 this(entityName, "a");
58 }
59
60 public Criteria(String entityName, String alias) {
61 this.entityName = entityName;
62 this.alias = alias;
63 }
64
65 public void between(String attribute, Object value1, Object value2) {
66 String fixedAttr = fixAttr(attribute);
67 tokens.add(" (" + alias + "." + attribute + " BETWEEN :" + fixedAttr + "-b1 AND :" + fixedAttr + "-b2) ");
68 params.put(fixedAttr+ "-b1", value1);
69 params.put(fixedAttr+ "-b2", value2);
70 }
71
72
73
74
75
76
77
78 private String fixAttr(String string) {
79 return string.replace(".", "_");
80 }
81
82 public void eq(String attribute, Object value) {
83 String fixedAttr = fixAttr(attribute);
84 tokens.add(alias + "." + attribute + " = :" + fixedAttr + " ");
85 params.put(fixedAttr, value);
86 }
87
88 public void gt(String attribute, Object value) {
89 String fixedAttr = fixAttr(attribute);
90 tokens.add(alias + "." + attribute + " > :" + fixedAttr + " ");
91 params.put(fixedAttr, value);
92 }
93
94 public void gte(String attribute, Object value) {
95 String fixedAttr = fixAttr(attribute);
96 tokens.add(alias + "." + attribute + " >= :" + fixedAttr + " ");
97 params.put(fixedAttr, value);
98 }
99
100 public void like(String attribute, Object value) {
101 String fixedAttr = fixAttr(attribute);
102 if (attribute.contains("__JPA_ALIAS__")) {
103 String bind = "BIND_PARAM_" + (++bindParamCount);
104 tokens.add(attribute + " LIKE :" + bind + " ");
105 params.put(bind, value);
106 } else {
107 tokens.add(alias + "." + attribute + " LIKE :" + stripFunctions(fixedAttr) + " ");
108 params.put(fixedAttr, value);
109 }
110 }
111
112 public void notLike(String attribute, Object value) {
113 String fixedAttr = fixAttr(attribute);
114 tokens.add(alias + "." + attribute + " NOT LIKE :" + fixedAttr + " ");
115 params.put(fixedAttr, value);
116 }
117
118 public void lt(String attribute, Object value) {
119 String fixedAttr = fixAttr(attribute);
120 tokens.add(alias + "." + attribute + " < :" + fixedAttr + " ");
121 params.put(fixedAttr, value);
122 }
123
124 public void lte(String attribute, Object value) {
125 String fixedAttr = fixAttr(attribute);
126 tokens.add(alias + "." + attribute + " <= :" + fixedAttr + " ");
127 params.put(fixedAttr, value);
128 }
129
130 public void ne(String attribute, Object value) {
131 String fixedAttr = fixAttr(attribute);
132 tokens.add(alias + "." + attribute + " != :" + fixedAttr + " ");
133 params.put(fixedAttr, value);
134 }
135
136 public void isNull(String attribute) {
137 tokens.add(alias + "." + attribute + " IS NULL ");
138 }
139
140 public void rawJpql(String jpql) {
141 tokens.add(" " + jpql + " ");
142 }
143
144 public void in(String attribute, List values) {
145 String in = "";
146 for (Object object : values) {
147 in += "'"+object + "',";
148 }
149 if (!"".equals(in)) {
150 in = in.substring(0, in.length()-1);
151 }
152 tokens.add(alias + "." + attribute + " IN (" + in + ") ");
153 }
154
155 public void notIn(String attribute, List values) {
156 String in = "";
157 for (Object object : values) {
158 in += "'"+object + "',";
159 }
160 if (!"".equals(in)) {
161 in = in.substring(in.length()-1);
162 }
163 tokens.add(alias + "." + attribute + " NOT IN (" + in + ") ");
164 }
165
166 public void orderBy(String attribute, boolean sortAscending) {
167 String sort = (sortAscending ? "ASC" : "DESC");
168 orderByTokens.add(alias + "." + attribute + " " + sort + " ");
169 }
170
171 public void and(Criteria and) {
172 tokens.add(new AndCriteria(and));
173 }
174
175 public void or(Criteria or) {
176 tokens.add(new OrCriteria(or));
177 }
178
179 public String toQuery(QueryByCriteriaType type) {
180 String queryType = type.toString();
181 if (type.equals(QueryByCriteriaType.SELECT)) {
182 if(distinct){
183 queryType += " " + "DISTINCT";
184 }
185
186 queryType += " " + alias;
187 }
188 String queryString = queryType + " FROM " + entityName + " AS " + alias;
189 if (!tokens.isEmpty()) {
190 queryString += " WHERE " + buildWhere();
191 }
192 if (!orderByTokens.isEmpty()) {
193 queryString += " ORDER BY ";
194 int count = 0;
195 for (Iterator iterator = orderByTokens.iterator(); iterator.hasNext();) {
196 Object token = (Object) iterator.next();
197 if (count == 0) {
198 count++;
199 } else {
200 queryString += ", ";
201 }
202 queryString += (String) token;
203 }
204 }
205 return fix(queryString);
206 }
207
208 public String toCountQuery() {
209 String queryString = "SELECT COUNT(*) FROM " + entityName + " AS " + alias;
210 if (!tokens.isEmpty()) {
211 queryString += " WHERE " + buildWhere();
212 }
213 return fix(queryString);
214 }
215
216 private String fix(String queryString) {
217 queryString = queryString.replaceAll("__JPA_ALIAS__", alias);
218 return queryString;
219 }
220
221 private String buildWhere() {
222 String queryString = "";
223 int i = 0;
224 for (Iterator iterator = tokens.iterator(); iterator.hasNext();) {
225 Object token = (Object) iterator.next();
226 if (token instanceof Criteria) {
227 String logic = "";
228 if (i>0 && token instanceof AndCriteria) {
229 logic = " AND ";
230 } else if (i>0 && token instanceof OrCriteria) {
231 logic = " OR ";
232 }
233 queryString += logic + " (" + ((Criteria) token).buildWhere() + ") ";
234 } else {
235 if(i>0){
236 queryString += " AND " + (String) token;
237 }else{
238 queryString += (String) token;
239 }
240 }
241 i++;
242 }
243 return queryString;
244 }
245
246
247 void prepareParameters(Query query) {
248 prepareParameters(query, tokens, params);
249 }
250
251 void prepareParameters(Query query, List tokens, Map<String, Object> params) {
252 for (Map.Entry<String, Object> param : params.entrySet()) {
253 Object value = param.getValue();
254 if (value instanceof BigDecimal) {
255 value = new Long(((BigDecimal)value).longValue());
256 }
257 if (value instanceof String) {
258 value = ((String)value).replaceAll("\\*", "%");
259 }
260 query.setParameter(param.getKey(), value);
261 }
262 for (Iterator iterator = tokens.iterator(); iterator.hasNext();) {
263 Object token = (Object) iterator.next();
264 if (token instanceof Criteria) {
265 prepareParameters(query, ((Criteria)token).tokens, ((Criteria)token).params);
266 }
267 }
268 }
269
270 private class AndCriteria extends Criteria {
271 public AndCriteria(Criteria and) {
272 super(and.entityName, and.alias);
273 this.tokens = new ArrayList(and.tokens);
274 this.params = new HashMap(and.params);
275 }
276 }
277
278 private class OrCriteria extends Criteria {
279 public OrCriteria(Criteria or) {
280 super(or.entityName, or.alias);
281 this.tokens = new ArrayList(or.tokens);
282 this.params = new HashMap(or.params);
283 }
284 }
285
286 public Integer getSearchLimit() {
287 return this.searchLimit;
288 }
289
290 public void setSearchLimit(Integer searchLimit) {
291 this.searchLimit = searchLimit;
292 }
293
294
295 public void notNull(String attribute) {
296 tokens.add(alias + "." + attribute + " IS NOT NULL ");
297 }
298
299 public void distinct(boolean distinct){
300 this.distinct = distinct;
301 }
302
303
304
305
306
307
308
309
310 public void notBetween(String attribute, Object value1,
311 Object value2) {
312 String fixedAttr = fixAttr(attribute);
313 tokens.add(" (" + alias + "." + attribute + " NOT BETWEEN :" + fixedAttr + "-b1 AND :" + fixedAttr + "-b2) ");
314 params.put(fixedAttr + "-b1", value1);
315 params.put(fixedAttr + "-b2", value2);
316 }
317
318
319
320
321
322
323
324 public void in(String match, Criteria subQuery, String attribute) {
325 if("a".equals(subQuery.alias)){
326 subQuery.alias="b";
327 }
328 String whereClause = "";
329 if(subQuery.tokens.isEmpty()){
330 whereClause = "WHERE ";
331 }else{
332 whereClause = "AND ";
333 }
334 whereClause += subQuery.alias+"."+attribute + " = " + alias+"."+match;
335
336 tokens.add("EXISTS (" + subQuery.toQuery(QueryByCriteriaType.SELECT) + whereClause + " ) ");
337
338 }
339
340 private String stripFunctions(String attribute) {
341 int index = attribute.lastIndexOf('(');
342 if(index != -1) {
343 return attribute.substring(index+1, attribute.indexOf(')'));
344 }
345
346 return attribute;
347 }
348
349 public String getAlias() {
350 return this.alias;
351 }
352
353 }