1
2
3
4
5
6 package pt.digitalis.dif.model.dataset;
7
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12
13 import pt.digitalis.dif.model.sql.SQLDataSet;
14 import pt.digitalis.dif.utils.ObjectFormatter;
15 import pt.digitalis.utils.common.CollectionUtils;
16 import pt.digitalis.utils.common.IBeanAttributes;
17
18
19
20
21
22
23
24
25
26 public class QueryPart<T extends IBeanAttributes> implements IQueryPart<T> {
27
28
29 private static final String JOINS_NOT_SUPPORTED = "Joins not supported";
30
31
32 private final boolean allowJoins;
33
34
35 protected IDataSet<T> dataSet;
36
37
38 private List<String> fields = new ArrayList<String>();
39
40
41 private List<Filter> filters = new ArrayList<Filter>();
42
43
44 private final boolean flatMode;
45
46
47
48
49
50 private String fullPath = "";
51
52
53 private Map<String, Join<T>> joins = new HashMap<String, Join<T>>();
54
55
56
57
58 private String path = "";
59
60
61
62
63
64 private String prefix = "";
65
66
67 protected Query<T> query;
68
69
70
71
72
73
74
75
76
77
78 public QueryPart(IDataSet<T> dataSet, Query<T> query, boolean flatMode, boolean allowJoins)
79 {
80 this.dataSet = dataSet;
81 this.query = query;
82 this.flatMode = flatMode;
83 this.allowJoins = allowJoins;
84 }
85
86
87
88
89 public Query<T> addField(String fieldName) throws DataSetException
90 {
91 if ("id".equals(fieldName))
92 fieldName = getDataSet().getIDFieldName();
93
94 if (!getFields().contains(fieldName))
95 {
96
97 if (!flatMode && fieldName != null && fieldName.contains(".")
98
99 && !fieldName.toLowerCase().startsWith("id.")
100
101 && !((fieldName.split("\\.").length >= 2) && fieldName.indexOf(".id") == fieldName.indexOf('.')))
102 {
103 QueryPart<T> queryPart = this;
104
105 String[] parts = fieldName.split("\\.", 2);
106 String fullPath = parts[0];
107 String path = parts[0];
108 String alias = parts[0];
109
110 queryPart = queryPart.getOrAddJoin(path, alias, fullPath, false).getQueryPart();
111
112 while (parts[1].contains("."))
113 {
114 parts = parts[1].split("\\.", 2);
115
116 fullPath += "." + parts[0];
117 path = path.replace(".", "_") + "." + parts[0];
118 alias += "_" + parts[0];
119
120 queryPart = queryPart.getOrAddJoin(path, alias, fullPath, false).getQueryPart();
121 }
122
123 }
124
125 fields.add(fieldName);
126 }
127
128 return query;
129 }
130
131
132
133
134 public Query<T> addFields(String fieldNames) throws DataSetException
135 {
136 if (fieldNames != null)
137 {
138 String[] fields = fieldNames.split(",");
139
140 for (String fieldName: fields)
141 this.addField(fieldName.trim());
142 }
143
144 return query;
145 }
146
147
148
149
150 public Query<T> addFilter(Filter filter) throws DataSetException
151 {
152 if (prefix.equals("") && "id".equals(filter.getAttributeName()) && getDataSet().isCompositeID())
153 {
154 String[] fields = getDataSet().getIDFieldName().split(",");
155 String[] values = filter.getValue().split(":");
156
157 for (int i = 0; i < fields.length; i++)
158 this.addFilter(new Filter("id." + fields[i], filter.getType(), values[i]));
159
160 return query;
161 }
162 else
163 {
164
165
166 if (filter.getType() != FilterType.SQL)
167 {
168
169 if (filter.getAttributeName() == null)
170 throw new InvalidFieldName(filter.getAttributeName());
171
172
173
174
175 if (!(this.getDataSet() instanceof HibernateDataSet))
176 {
177
178
179 if (this.getDataSet() instanceof SQLDataSet && filter.getAttributeName().contains(".")
180 || !this.getAttributesDefinition().isEmpty()
181 && this.getAttributesDefinition().get(filter.getAttributeName().split("\\.")[0]) == null)
182 throw new InvalidFieldName(filter.getAttributeName());
183 }
184 }
185
186
187 if (!allowJoins && filter.getAttributeName() != null && filter.getAttributeName().contains("."))
188 AbstractDataSet.throwUnsuportedOperationException(JOINS_NOT_SUPPORTED);
189
190 if (prefix.equals("") && "id".equals(filter.getAttributeName()) && !getDataSet().isCompositeID())
191 filter.setAttributeName(getDataSet().getIDFieldName());
192
193
194 if (!flatMode && filter.getAttributeName() != null
195 && filter.getAttributeName().contains(".")
196
197 && !filter.getAttributeName().toLowerCase().startsWith("id.")
198
199 && !((filter.getAttributeName().split("\\.").length >= 2)
200 && filter.getAttributeName().indexOf(".id") == filter.getAttributeName().indexOf('.') && getJoins()
201 .containsKey(filter.getAttributeName().split("\\.")[0])))
202 {
203 Filter parsedFilter = new Filter(filter.getAttributeName(), filter.getType(), filter.getValue(),
204 filter.getValue2());
205
206 String[] parts = filter.getAttributeName().split("\\.", 2);
207 parsedFilter.setAttributeName(parts[1]);
208
209 String fullPath = parts[0];
210 String path = parts[0];
211 String alias = parts[0];
212
213 if (!prefix.equals(""))
214 {
215 fullPath = this.fullPath + "." + path;
216 path = prefix + "." + path;
217 alias = prefix + "_" + alias;
218 }
219
220 getOrAddJoin(path, alias, fullPath, false).getQueryPart().addFilter(parsedFilter);
221 }
222 else
223 filters.add(filter);
224
225 return query;
226 }
227 }
228
229
230
231
232 public Query<T> addFilters(List<Filter> filters) throws DataSetException
233 {
234 for (Filter filter: filters)
235 addFilter(filter);
236
237 return query;
238 }
239
240
241
242
243 public Query<T> addJoin(String join, JoinType joinType) throws DataSetException
244 {
245
246 addJoin(join, joinType, false);
247
248 return query;
249 }
250
251
252
253
254
255 public Query<T> addJoin(String join, JoinType joinType, boolean eagerJoin) throws DataSetException
256 {
257 QueryPart<? extends IBeanAttributes> queryPart;
258
259 String[] parts = join.split("\\.", 2);
260 String fullPath = parts[0];
261 String path = parts[0];
262 String alias = parts[0];
263
264 queryPart = query;
265
266 if (parts.length > 1)
267 {
268 queryPart = queryPart.getOrAddJoin(path, alias, fullPath, eagerJoin).getQueryPart();
269
270 while (parts[1].contains("."))
271 {
272 parts = parts[1].split("\\.", 2);
273
274 fullPath += "." + parts[0];
275 path = path.replace(".", "_") + "." + parts[0];
276 alias += "_" + parts[0];
277
278 queryPart = queryPart.getOrAddJoin(path, alias, fullPath, eagerJoin).getQueryPart();
279 }
280
281 fullPath += "." + parts[1];
282 path = path.replace(".", "_") + "." + parts[1];
283 alias += "_" + parts[1];
284 }
285
286 queryPart.getOrAddJoin(path, alias, fullPath, joinType, eagerJoin);
287
288 return query;
289 }
290
291
292
293
294 public Query<T> between(String attribute, String first, String last) throws DataSetException
295 {
296 this.addFilter(new Filter(attribute, FilterType.BETWEEN, first, last));
297
298 return query;
299 }
300
301
302
303
304 public Query<T> equals(String attribute, String value) throws DataSetException
305 {
306 this.addFilter(new Filter(attribute, FilterType.EQUALS, value));
307
308 return query;
309 }
310
311
312
313
314 public Map<String, AttributeDefinition> getAttributesDefinition()
315 {
316 return this.getDataSet().getAttributesDefinition();
317 }
318
319
320
321
322
323
324 public IDataSet<T> getDataSet()
325 {
326 return dataSet;
327 }
328
329
330
331
332 public List<String> getFields()
333 {
334 return fields;
335 }
336
337
338
339
340 public List<Filter> getFilters()
341 {
342 return filters;
343 }
344
345
346
347
348 public String getFullPath()
349 {
350 return fullPath;
351 }
352
353
354
355
356 public Map<String, Join<T>> getJoins()
357 {
358 return joins;
359 }
360
361
362
363
364
365
366
367
368
369
370
371
372
373 public Join<T> getOrAddJoin(String joinName, String alias, String fullPath, boolean eager) throws DataSetException
374 {
375 return getOrAddJoin(joinName, alias, fullPath, JoinType.NORMAL, eager);
376 }
377
378
379
380
381
382
383
384
385
386
387
388
389
390 public Join<T> getOrAddJoin(String joinName, String alias, String fullPath, JoinType joinType)
391 throws DataSetException
392 {
393 return getOrAddJoin(joinName, alias, fullPath, joinType, false);
394 }
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410 public Join<T> getOrAddJoin(String joinName, String alias, String fullPath, JoinType joinType, boolean eager)
411 throws DataSetException
412 {
413 if (!allowJoins)
414 AbstractDataSet.throwUnsuportedOperationException(JOINS_NOT_SUPPORTED);
415
416 Join<T> join = getJoins().get(joinName);
417
418 if (join == null)
419 {
420 QueryPart<T> joinQueryPart = new QueryPart<T>(getDataSet(), query, flatMode, allowJoins);
421 joinQueryPart.setPath(joinName);
422 joinQueryPart.setPrefix(alias);
423 joinQueryPart.setFullPath(fullPath);
424
425 join = new Join<T>(joinName, joinType, joinQueryPart);
426 joins.put(joinName, join);
427 join.setEager(eager);
428 }
429 else
430 {
431 if (joinType != JoinType.NORMAL)
432 join.setJoinType(joinType);
433
434 if (eager && !join.isEager())
435 join.setEager(true);
436 }
437
438 return join;
439 }
440
441
442
443
444 public String getPath()
445 {
446 return path;
447 }
448
449
450
451
452 public String getPrefix()
453 {
454 return prefix;
455 }
456
457
458
459
460 public Query<T> graterOrEqualsThan(String attribute, String value) throws DataSetException
461 {
462 this.addFilter(new Filter(attribute, FilterType.GRATER_OR_EQUALS_THAN, value));
463
464 return query;
465 }
466
467
468
469
470 public Query<T> graterThan(String attribute, String value) throws DataSetException
471 {
472 this.addFilter(new Filter(attribute, FilterType.GRATER_THAN, value));
473
474 return query;
475 }
476
477
478
479
480 public Query<T> in(String attribute, List<? extends Object> valueList) throws DataSetException
481 {
482 this.addFilter(new Filter(attribute, FilterType.IN, CollectionUtils.listToCommaSeparatedString(valueList)));
483
484 return query;
485 }
486
487
488
489
490 public Query<T> in(String attribute, String valueList) throws DataSetException
491 {
492 this.addFilter(new Filter(attribute, FilterType.IN, valueList));
493
494 return query;
495 }
496
497
498
499
500 public Query<T> isNotNull(String attribute) throws DataSetException
501 {
502 this.addFilter(new Filter(attribute, FilterType.IS_NOT_NULL));
503
504 return query;
505 }
506
507
508
509
510 public Query<T> isNull(String attribute) throws DataSetException
511 {
512 this.addFilter(new Filter(attribute, FilterType.IS_NULL));
513
514 return query;
515 }
516
517
518
519
520 public Query<T> lesserOrEqualsThan(String attribute, String value) throws DataSetException
521 {
522 this.addFilter(new Filter(attribute, FilterType.LESSER_OR_EQUALS_THAN, value));
523
524 return query;
525 }
526
527
528
529
530 public Query<T> lesserThan(String attribute, String value) throws DataSetException
531 {
532 this.addFilter(new Filter(attribute, FilterType.LESSER_THAN, value));
533
534 return query;
535 }
536
537
538
539
540 public Query<T> like(String attribute, String expression) throws DataSetException
541 {
542 this.addFilter(new Filter(attribute, FilterType.LIKE, expression));
543
544 return query;
545 }
546
547
548
549
550 public Query<T> notBetween(String attribute, String first, String last) throws DataSetException
551 {
552 this.addFilter(new Filter(attribute, FilterType.NOT_BETWEEN, first, last));
553
554 return query;
555 }
556
557
558
559
560 public Query<T> notEquals(String attribute, String value) throws DataSetException
561 {
562 this.addFilter(new Filter(attribute, FilterType.NOT_EQUALS, value));
563
564 return query;
565 }
566
567
568
569
570 public Query<T> notIn(String attribute, List<Object> valueList) throws DataSetException
571 {
572 this.addFilter(new Filter(attribute, FilterType.NOT_IN, CollectionUtils.listToCommaSeparatedString(valueList)));
573
574 return query;
575 }
576
577
578
579
580 public Query<T> notIn(String attribute, String valueList) throws DataSetException
581 {
582 this.addFilter(new Filter(attribute, FilterType.NOT_IN, valueList));
583
584 return query;
585 }
586
587
588
589
590 public Query<T> notLike(String attribute, String expression) throws DataSetException
591 {
592 this.addFilter(new Filter(attribute, FilterType.NOT_LIKE, expression));
593
594 return query;
595 }
596
597
598
599
600 public Query<T> removeFilters() throws DataSetException
601 {
602 this.filters.clear();
603
604 for (Join<T> join: this.getJoins().values())
605 {
606 join.getQueryPart().removeFilters();
607 }
608
609 return query;
610 }
611
612
613
614
615 public void setFullPath(String fullPath)
616 {
617 this.fullPath = fullPath;
618 }
619
620
621
622
623 public void setPath(String path)
624 {
625 this.path = path;
626 }
627
628
629
630
631 public void setPrefix(String prefix)
632 {
633 this.prefix = prefix;
634 }
635
636
637
638
639 @Override
640 public String toString()
641 {
642 ObjectFormatter formatter = new ObjectFormatter();
643 formatter.addItem("DataSet", getDataSet());
644
645 formatter.addItem("Prefix", prefix);
646 formatter.addItem("Path", path);
647 formatter.addItem("Fields", getFields());
648 formatter.addItem("Filters", getFilters());
649 formatter.addItem("Joins", getJoins());
650
651 return formatter.getFormatedObject();
652 }
653 }