1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.efaps.db;
22
23 import java.io.StringReader;
24 import java.sql.ResultSet;
25 import java.sql.SQLException;
26 import java.sql.Statement;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.UUID;
32
33 import org.apache.commons.dbutils.handlers.ArrayListHandler;
34 import org.efaps.admin.common.MsgPhrase;
35 import org.efaps.admin.datamodel.Attribute;
36 import org.efaps.admin.datamodel.AttributeSet;
37 import org.efaps.admin.datamodel.Type;
38 import org.efaps.beans.ValueList;
39 import org.efaps.beans.valueparser.ParseException;
40 import org.efaps.beans.valueparser.ValueParser;
41 import org.efaps.ci.CIAttribute;
42 import org.efaps.db.print.OneSelect;
43 import org.efaps.db.print.Phrase;
44 import org.efaps.db.transaction.ConnectionResource;
45 import org.efaps.db.wrapper.SQLPart;
46 import org.efaps.db.wrapper.SQLSelect;
47 import org.efaps.util.EFapsException;
48 import org.infinispan.Cache;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52
53
54
55
56
57
58
59 public abstract class AbstractPrintQuery
60 {
61
62
63
64
65 private static final Logger LOG = LoggerFactory.getLogger(PrintQuery.class);
66
67
68
69
70 private final Map<String, OneSelect> selectStmt2OneSelect = new HashMap<String, OneSelect>();
71
72
73
74
75 private final Map<String, OneSelect> attr2OneSelect = new HashMap<String, OneSelect>();
76
77
78
79
80
81
82 private final Map<String, Integer> sqlTable2Index = new HashMap<String, Integer>();
83
84
85
86
87 private final Map<String, Phrase> key2Phrase = new HashMap<String, Phrase>();
88
89
90
91
92 private final List<OneSelect> allSelects = new ArrayList<OneSelect>();
93
94
95
96
97 private int tableIndex = 0;
98
99
100
101
102
103
104
105 private boolean enforceSorted;
106
107
108
109
110 private int typeColumnIndex = 0;
111
112
113
114
115
116
117
118
119
120 public AbstractPrintQuery addAttribute(final CIAttribute... _attributes)
121 throws EFapsException
122 {
123 if (isMarked4execute()) {
124 for (final CIAttribute attr : _attributes) {
125 addAttribute(attr.name);
126 }
127 }
128 return this;
129 }
130
131
132
133
134
135
136
137
138 public AbstractPrintQuery addAttribute(final Attribute... _attributes)
139 {
140 if (isMarked4execute()) {
141 for (final Attribute attr : _attributes) {
142 final OneSelect oneselect = new OneSelect(this, attr);
143 this.allSelects.add(oneselect);
144 this.attr2OneSelect.put(attr.getName(), oneselect);
145 }
146 }
147 return this;
148 }
149
150
151
152
153
154
155 protected void addOneSelect(final OneSelect _oneSelect)
156 {
157 this.allSelects.add(_oneSelect);
158 }
159
160
161
162
163
164
165 protected List<OneSelect> getAllSelects()
166 {
167 return this.allSelects;
168 }
169
170
171
172
173
174
175
176 public Attribute getAttribute4Attribute(final String _attributeName)
177 {
178 final OneSelect oneselect = this.attr2OneSelect.get(_attributeName);
179 return oneselect == null ? null : oneselect.getAttribute();
180 }
181
182
183
184
185
186
187
188
189 public List<Instance> getInstances4Attribute(final String _attributeName)
190 throws EFapsException
191 {
192 final OneSelect oneselect = this.attr2OneSelect.get(_attributeName);
193 return oneselect == null ? null : oneselect.getInstances();
194 }
195
196
197
198
199
200
201
202
203
204 public <T> T getAttribute(final CIAttribute _attribute)
205 throws EFapsException
206 {
207 return this.<T>getAttribute(_attribute.name);
208 }
209
210
211
212
213
214
215
216
217
218 @SuppressWarnings("unchecked")
219 public <T> T getAttribute(final String _attributeName)
220 throws EFapsException
221 {
222 final OneSelect oneselect = this.attr2OneSelect.get(_attributeName);
223 return oneselect == null ? null : (T) oneselect.getObject();
224 }
225
226
227
228
229
230
231
232
233
234 @SuppressWarnings("unchecked")
235 public <T> T getAttribute(final Attribute _attribute)
236 throws EFapsException
237 {
238 return (T) getAttribute(_attribute.getName());
239 }
240
241
242
243
244
245
246
247
248
249 public abstract Type getMainType();
250
251
252
253
254
255
256 public abstract List<Instance> getInstanceList();
257
258
259
260
261
262
263 public abstract Instance getCurrentInstance();
264
265
266
267
268
269
270
271
272
273 public AbstractPrintQuery addAttributeSet(final String _setName)
274 throws EFapsException
275 {
276 final Type type = getMainType();
277 if (type != null) {
278 final AttributeSet set = AttributeSet.find(type.getName(), _setName);
279 addAttributeSet(set);
280 }
281 return this;
282 }
283
284
285
286
287
288
289
290
291
292
293 public AbstractPrintQuery addAttributeSet(final AttributeSet _set)
294 throws EFapsException
295 {
296 final String key = "linkfrom[" + _set.getName() + "#" + _set.getAttributeName() + "]";
297 final OneSelect oneselect = new OneSelect(this, key);
298 this.allSelects.add(oneselect);
299 this.attr2OneSelect.put(_set.getAttributeName(), oneselect);
300 oneselect.analyzeSelectStmt();
301 for (final String setAttrName : _set.getSetAttributes()) {
302 if (!setAttrName.equals(_set.getAttributeName())) {
303 oneselect.getFromSelect().addOneSelect(new OneSelect(this, _set.getAttribute(setAttrName)));
304 }
305 }
306 oneselect.getFromSelect().getMainOneSelect().setAttribute(_set.getAttribute(_set.getAttributeName()));
307 return this;
308 }
309
310
311
312
313
314
315
316
317
318 @SuppressWarnings("unchecked")
319 public <T> T getAttributeSet(final String _setName)
320 throws EFapsException
321 {
322 final OneSelect oneselect = this.attr2OneSelect.get(_setName);
323 Map<String, Object> ret = null;
324 if (oneselect == null || oneselect.getFromSelect() == null) {
325 LOG.error("Could not get an AttributeSet for the name: '{}' in PrintQuery '{]'", _setName, this);
326 } else if (oneselect.getFromSelect().hasResult()) {
327 ret = new HashMap<String, Object>();
328
329 boolean first = true;
330 for (final OneSelect onsel : oneselect.getFromSelect().getAllSelects()) {
331 if (first) {
332 first = false;
333 } else {
334 final ArrayList<Object> list = new ArrayList<Object>();
335 final Object object = onsel.getObject();
336 if (object instanceof List<?>) {
337 list.addAll((List<?>) object);
338 } else {
339 list.add(object);
340 }
341 ret.put(onsel.getAttribute().getName(), list);
342 }
343 }
344 }
345 return (T) ret;
346 }
347
348
349
350
351
352
353
354
355
356 public AbstractPrintQuery addAttribute(final String... _attrNames)
357 throws EFapsException
358 {
359 final Type type = getMainType();
360 if (type != null) {
361 for (final String attrName : _attrNames) {
362 final Attribute attr = type.getAttribute(attrName);
363 if (attr == null) {
364 final AttributeSet set = AttributeSet.find(type.getName(), attrName);
365 if (set != null) {
366 addAttributeSet(set);
367 }
368 } else {
369 addAttribute(attr);
370 }
371 }
372 }
373 return this;
374 }
375
376
377
378
379
380
381
382
383
384
385
386
387 public AbstractPrintQuery addPhrase(final String _key,
388 final String _phraseStmt)
389 throws EFapsException
390 {
391 ValueList list = null;
392
393 final ValueParser parser = new ValueParser(new StringReader(_phraseStmt));
394 try {
395 list = parser.ExpressionString();
396 } catch (final ParseException e) {
397 throw new EFapsException(PrintQuery.class.toString(), e);
398 }
399 final Phrase phrase = new Phrase(_key, _phraseStmt, list);
400 this.key2Phrase.put(_key, phrase);
401
402 for (final String selectStmt : list.getExpressions()) {
403 final OneSelect oneselect = new OneSelect(this, selectStmt);
404 this.allSelects.add(oneselect);
405 phrase.addSelect(oneselect);
406 oneselect.analyzeSelectStmt();
407 }
408 return this;
409 }
410
411
412
413
414
415
416
417
418 public String getPhrase(final String _key)
419 throws EFapsException
420 {
421 final Phrase phrase = this.key2Phrase.get(_key);
422 return phrase == null ? null : phrase.getPhraseValue(getCurrentInstance());
423 }
424
425
426
427
428
429
430 public AbstractPrintQuery addMsgPhrase(final MsgPhrase... _msgPhrase)
431 throws EFapsException
432 {
433 return addMsgPhrase(null, _msgPhrase);
434 }
435
436
437
438
439
440
441 public AbstractPrintQuery addMsgPhrase(final SelectBuilder _selectBldr,
442 final MsgPhrase... _msgPhrase)
443 throws EFapsException
444 {
445 String baseSel;
446 if (_selectBldr == null) {
447 baseSel = "";
448 } else {
449 baseSel = _selectBldr.toString() + ".";
450 }
451 for (final MsgPhrase phrase : _msgPhrase) {
452 for (final String selectStmt : phrase.getArguments()) {
453 addSelect(baseSel + selectStmt);
454 }
455 }
456 return this;
457 }
458
459 public AbstractPrintQuery addMsgPhrase(final String... _msgPhrase)
460 throws EFapsException
461 {
462 final List<MsgPhrase> msgphrases = new ArrayList<>();
463 for (final String phraseStr : _msgPhrase) {
464 msgphrases.add(MsgPhrase.get(phraseStr));
465 }
466 return addMsgPhrase(msgphrases.toArray(new MsgPhrase[msgphrases.size()]));
467 }
468
469 public AbstractPrintQuery addMsgPhrase(final UUID... _msgPhrase)
470 throws EFapsException
471 {
472 return addMsgPhrase(null, _msgPhrase);
473 }
474
475 public AbstractPrintQuery addMsgPhrase(final SelectBuilder _selectBldr,
476 final UUID... _msgPhrase)
477 throws EFapsException
478 {
479 final List<MsgPhrase> msgphrases = new ArrayList<>();
480 for (final UUID phraseUUID : _msgPhrase) {
481 msgphrases.add(MsgPhrase.get(phraseUUID));
482 }
483 return addMsgPhrase(_selectBldr, msgphrases.toArray(new MsgPhrase[msgphrases.size()]));
484 }
485
486
487
488
489
490
491
492
493 public String getMsgPhrase(final String _msgPhrase)
494 throws EFapsException
495 {
496 return getMsgPhrase(MsgPhrase.get(_msgPhrase));
497 }
498
499
500
501
502
503
504
505
506 public String getMsgPhrase(final UUID _msgPhrase)
507 throws EFapsException
508 {
509 return getMsgPhrase(null, MsgPhrase.get(_msgPhrase));
510 }
511
512
513
514
515
516
517
518
519 public String getMsgPhrase(final SelectBuilder _selectBldr,
520 final UUID _msgPhrase)
521 throws EFapsException
522 {
523 return getMsgPhrase(_selectBldr, MsgPhrase.get(_msgPhrase));
524 }
525
526
527
528
529
530
531
532
533 public String getMsgPhrase(final MsgPhrase _msgPhrase)
534 throws EFapsException
535 {
536 return getMsgPhrase(null, _msgPhrase);
537 }
538
539
540
541
542
543
544
545
546 public String getMsgPhrase(final SelectBuilder _selectBldr,
547 final MsgPhrase _msgPhrase)
548 throws EFapsException
549 {
550 final List<Object> objects = new ArrayList<>();
551 String baseSel;
552 if (_selectBldr == null) {
553 baseSel = "";
554 } else {
555 baseSel = _selectBldr.toString() + ".";
556 }
557 boolean isNotNull = true;
558 for (final String select : _msgPhrase.getArguments()) {
559 final Object tmpObj = getSelect(baseSel + select);
560 isNotNull = isNotNull && tmpObj != null;
561 objects.add(tmpObj);
562 }
563 return isNotNull ? _msgPhrase.format(objects.toArray()) : null;
564 }
565
566
567
568
569
570
571
572
573
574
575
576
577
578 public AbstractPrintQuery addSelect(final SelectBuilder... _selectBldrs)
579 throws EFapsException
580 {
581 if (isMarked4execute()) {
582 for (final SelectBuilder selectBldr : _selectBldrs) {
583 addSelect(selectBldr.toString());
584 }
585 }
586 return this;
587 }
588
589
590
591
592
593
594
595
596
597
598
599
600
601 public AbstractPrintQuery addSelect(final String... _selectStmts)
602 throws EFapsException
603 {
604 if (isMarked4execute()) {
605 for (final String selectStmt : _selectStmts) {
606 final OneSelect oneselect = new OneSelect(this, selectStmt);
607 this.allSelects.add(oneselect);
608 this.selectStmt2OneSelect.put(selectStmt, oneselect);
609 oneselect.analyzeSelectStmt();
610 }
611 }
612 return this;
613 }
614
615
616
617
618
619
620
621
622
623 @SuppressWarnings("unchecked")
624 public <T> T getSelect(final String _selectStmt)
625 throws EFapsException
626 {
627 final OneSelect oneselect = this.selectStmt2OneSelect.get(_selectStmt);
628 return oneselect == null ? null : (T) oneselect.getObject();
629 }
630
631
632
633
634
635
636
637
638
639 @SuppressWarnings("unchecked")
640 public <T> T getSelect(final SelectBuilder _selectBldr)
641 throws EFapsException
642 {
643 final OneSelect oneselect = this.selectStmt2OneSelect.get(_selectBldr.toString());
644 return oneselect == null ? null : (T) oneselect.getObject();
645 }
646
647
648
649
650
651
652
653 public Attribute getAttribute4Select(final String _selectStmt)
654 {
655 final OneSelect oneselect = this.selectStmt2OneSelect.get(_selectStmt);
656 return oneselect == null ? null : oneselect.getAttribute();
657 }
658
659
660
661
662
663
664
665
666
667 public List<Instance> getInstances4Select(final String _selectStmt)
668 throws EFapsException
669 {
670 final OneSelect oneselect = this.selectStmt2OneSelect.get(_selectStmt);
671 return oneselect == null ? new ArrayList<Instance>() : oneselect.getInstances();
672 }
673
674
675
676
677
678
679
680
681 public boolean isList4Select(final String _selectStmt)
682 throws EFapsException
683 {
684 final OneSelect oneselect = this.selectStmt2OneSelect.get(_selectStmt);
685 return oneselect == null ? false : oneselect.isMultiple();
686 }
687
688
689
690
691
692
693 public boolean isEnforceSorted()
694 {
695 return this.enforceSorted;
696 }
697
698
699
700
701
702
703
704 public void setEnforceSorted(final boolean _enforceSorted)
705 {
706 this.enforceSorted = _enforceSorted;
707 }
708
709
710
711
712
713
714
715 public void dryRun()
716 throws EFapsException
717 {
718 final String sql = createSQLStatement();
719 LOG.debug("DryRun SQL", sql);
720 }
721
722
723
724
725
726
727
728 public boolean execute()
729 throws EFapsException
730 {
731 return executeWithoutAccessCheck();
732 }
733
734
735
736
737
738
739
740 public boolean executeWithoutAccessCheck()
741 throws EFapsException
742 {
743 boolean ret = false;
744 if (isMarked4execute()) {
745 if (getInstanceList().size() > 0) {
746 ret = executeOneCompleteStmt(createSQLStatement(), this.allSelects);
747 }
748 if (ret) {
749 for (final OneSelect onesel : this.allSelects) {
750 if (onesel.getFromSelect() != null) {
751 onesel.getFromSelect().execute(onesel);
752 }
753 }
754 }
755 }
756 return ret;
757 }
758
759
760
761
762
763
764
765 protected String createSQLStatement()
766 throws EFapsException
767 {
768
769 final SQLSelect select = new SQLSelect()
770 .column(0, "ID")
771 .from(getMainType().getMainTable().getSqlTable(), 0);
772 for (final OneSelect oneSel : this.allSelects) {
773 oneSel.append2SQLFrom(select);
774 }
775
776 int colIndex = select.getColumns().size() + 1;
777
778 if (getMainType().getMainTable().getSqlColType() != null) {
779 select.column(0, getMainType().getMainTable().getSqlColType());
780 this.typeColumnIndex = colIndex;
781 colIndex++;
782 }
783
784 for (final OneSelect onesel : this.allSelects) {
785 if (onesel.getValueSelect() != null) {
786 colIndex += onesel.append2SQLSelect(select, colIndex);
787 }
788 }
789
790 select.addPart(SQLPart.WHERE).addColumnPart(0, "ID").addPart(SQLPart.IN).addPart(SQLPart.PARENTHESIS_OPEN);
791
792 int i = 0;
793 for (final Instance instance : getInstanceList()) {
794 if (Context.getDbType().getMaxExpressions() > -1 && i > Context.getDbType().getMaxExpressions()) {
795 select.addPart(SQLPart.PARENTHESIS_CLOSE)
796 .addPart(SQLPart.OR)
797 .addColumnPart(0, "ID").addPart(SQLPart.IN).addPart(SQLPart.PARENTHESIS_OPEN);
798 i = 0;
799 }
800 if (i > 0) {
801 select.addPart(SQLPart.COMMA);
802 }
803 select.addValuePart(instance.getId());
804 i++;
805 }
806 select.addPart(SQLPart.PARENTHESIS_CLOSE);
807
808 for (final OneSelect oneSel : this.allSelects) {
809 oneSel.append2SQLWhere(select);
810 }
811
812 return select.getSQL();
813 }
814
815
816
817
818
819
820
821
822
823
824
825 @SuppressWarnings("unchecked")
826 protected boolean executeOneCompleteStmt(final String _complStmt,
827 final List<OneSelect> _oneSelects)
828 throws EFapsException
829 {
830 boolean ret = false;
831 ConnectionResource con = null;
832 try {
833 AbstractPrintQuery.LOG.debug("Executing SQL: {}", _complStmt);
834
835 List<Object[]> rows = null;
836 boolean cached = false;
837 if (isCacheEnabled()) {
838 final QueryKey querykey = QueryKey.get(getKey(), _complStmt);
839 final Cache<QueryKey, Object> cache = QueryCache.getSqlCache();
840 if (cache.containsKey(querykey)) {
841 final Object object = cache.get(querykey);
842 if (object instanceof List) {
843 rows = (List<Object[]>) object;
844 }
845 cached = true;
846 }
847 }
848
849 if (!cached) {
850 con = Context.getThreadContext().getConnectionResource();
851 final Statement stmt = con.getConnection().createStatement();
852 final ResultSet rs = stmt.executeQuery(_complStmt);
853 final ArrayListHandler handler = new ArrayListHandler(Context.getDbType().getRowProcessor());
854 rows = handler.handle(rs);
855 rs.close();
856 stmt.close();
857 con.commit();
858
859 if (isCacheEnabled()) {
860 QueryCache.put((ICacheDefinition) this, QueryKey.get(getKey(), _complStmt), rows);
861 }
862 }
863
864 for (final Object[] row : rows) {
865 for (final OneSelect onesel : _oneSelects) {
866 onesel.addObject(row);
867 }
868 ret = true;
869 }
870
871 final List<Instance> tmpList = new ArrayList<Instance>();
872 final Map<Instance, Integer> sortMap = new HashMap<Instance, Integer>();
873 int i = 0;
874 for (final Object[] row : rows) {
875 final Instance instance;
876 if (getMainType().getMainTable().getSqlColType() != null) {
877 instance = Instance.get(Type.get((Long) row[this.typeColumnIndex - 1]), (Long) row[0]);
878 } else {
879 instance = Instance.get(getMainType(), (Long) row[0]);
880 }
881 sortMap.put(instance, i);
882 tmpList.add(instance);
883 i++;
884 }
885
886 if (this.enforceSorted) {
887 for (final OneSelect onesel : _oneSelects) {
888 onesel.sortByInstanceList(getInstanceList(), sortMap);
889 }
890 } else {
891 getInstanceList().clear();
892 getInstanceList().addAll(tmpList);
893 }
894 } catch (final SQLException e) {
895 throw new EFapsException(InstanceQuery.class, "executeOneCompleteStmt", e);
896 } finally {
897 if (con != null && con.isOpened()) {
898 con.abort();
899 }
900 }
901 return ret;
902 }
903
904
905
906
907
908
909
910
911
912
913 public Integer getTableIndex(final String _tableName,
914 final String _column,
915 final int _relIndex,
916 final Long _clazzId)
917 {
918 return this.sqlTable2Index.get(_relIndex + "__" + _tableName + "__" + _column
919 + (_clazzId == null ? "" : "__" + _clazzId));
920 }
921
922
923
924
925
926
927
928
929
930
931
932 public Integer getNewTableIndex(final String _tableName,
933 final String _column,
934 final Integer _relIndex,
935 final Long _clazzId)
936 {
937 this.tableIndex++;
938 this.sqlTable2Index.put(_relIndex + "__" + _tableName + "__" + _column
939 + (_clazzId == null ? "" : "__" + _clazzId), this.tableIndex);
940 return this.tableIndex;
941 }
942
943
944
945
946
947
948
949 public boolean isMarked4execute()
950 {
951 return !getInstanceList().isEmpty();
952 }
953
954
955
956
957 public abstract boolean isCacheEnabled();
958
959
960
961
962 public String getKey()
963 {
964 return QueryCache.DEFAULTKEY;
965 }
966
967 }