1
2
3
4
5
6
7
8
9
10
11
12 package org.displaytag.tags;
13
14 import java.io.ByteArrayOutputStream;
15 import java.io.IOException;
16 import java.io.StringWriter;
17 import java.io.Writer;
18 import java.util.Collection;
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.Map;
23
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26 import javax.servlet.jsp.JspException;
27 import javax.servlet.jsp.JspTagException;
28 import javax.servlet.jsp.JspWriter;
29
30 import org.apache.commons.beanutils.BeanUtils;
31 import org.apache.commons.collections.IteratorUtils;
32 import org.apache.commons.lang.ObjectUtils;
33 import org.apache.commons.lang.StringUtils;
34 import org.apache.commons.lang.math.LongRange;
35 import org.apache.commons.lang.math.NumberUtils;
36 import org.apache.commons.lang.math.Range;
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.displaytag.Messages;
40 import org.displaytag.decorator.TableDecorator;
41 import org.displaytag.exception.ExportException;
42 import org.displaytag.exception.FactoryInstantiationException;
43 import org.displaytag.exception.InvalidTagAttributeValueException;
44 import org.displaytag.exception.WrappedRuntimeException;
45 import org.displaytag.export.BinaryExportView;
46 import org.displaytag.export.ExportView;
47 import org.displaytag.export.ExportViewFactory;
48 import org.displaytag.export.TextExportView;
49 import org.displaytag.model.Cell;
50 import org.displaytag.model.Column;
51 import org.displaytag.model.HeaderCell;
52 import org.displaytag.model.Row;
53 import org.displaytag.model.TableModel;
54 import org.displaytag.pagination.PaginatedList;
55 import org.displaytag.pagination.PaginatedListSmartListHelper;
56 import org.displaytag.pagination.SmartListHelper;
57 import org.displaytag.properties.MediaTypeEnum;
58 import org.displaytag.properties.SortOrderEnum;
59 import org.displaytag.properties.TableProperties;
60 import org.displaytag.render.HtmlTableWriter;
61 import org.displaytag.util.CollectionUtil;
62 import org.displaytag.util.DependencyChecker;
63 import org.displaytag.util.Href;
64 import org.displaytag.util.ParamEncoder;
65 import org.displaytag.util.RequestHelper;
66 import org.displaytag.util.RequestHelperFactory;
67 import org.displaytag.util.TagConstants;
68
69
70
71
72
73
74
75
76
77
78
79 public class TableTag extends HtmlTableTag
80 {
81
82
83
84
85
86 public static final String PAGE_ATTRIBUTE_MEDIA = "mediaType";
87
88
89
90
91 public static final String FILTER_CONTENT_OVERRIDE_BODY =
92 "org.displaytag.filter.ResponseOverrideFilter.CONTENT_OVERRIDE_BODY";
93
94
95
96
97 private static final long serialVersionUID = 899149338534L;
98
99
100
101
102 private static Log log = LogFactory.getLog(TableTag.class);
103
104
105
106
107 private static RequestHelperFactory rhf;
108
109
110
111
112
113 protected Object list;
114
115
116
117
118
119
120
121 protected Object listAttribute;
122
123
124
125
126 private int rowNumber = 1;
127
128
129
130
131 private String name;
132
133
134
135
136 private int length;
137
138
139
140
141 private String decoratorName;
142
143
144
145
146 private int pagesize;
147
148
149
150
151 private boolean partialList;
152
153
154
155
156 private boolean export;
157
158
159
160
161 private int offset;
162
163
164
165
166 private Object size;
167
168
169
170
171 private String sizeObjectName;
172
173
174
175
176 private Boolean sortFullTable;
177
178
179
180
181 private boolean localSort = true;
182
183
184
185
186 private String requestUri;
187
188
189
190
191 private boolean dontAppendContext;
192
193
194
195
196 private int defaultSortedColumn = -1;
197
198
199
200
201 private SortOrderEnum defaultSortOrder;
202
203
204
205
206 private String excludedParams;
207
208
209
210
211 private String uid;
212
213
214
215
216 private String varTotals;
217
218
219
220
221
222
223 private TableModel tableModel;
224
225
226
227
228 private Row currentRow;
229
230
231
232
233
234
235
236
237 private SmartListHelper listHelper;
238
239
240
241
242 private Href baseHref;
243
244
245
246
247 private TableProperties properties;
248
249
250
251
252 private int pageNumber = 1;
253
254
255
256
257 private Iterator tableIterator;
258
259
260
261
262 private MediaTypeEnum currentMediaType;
263
264
265
266
267 private boolean doAfterBodyExecuted;
268
269
270
271
272 private ParamEncoder paramEncoder;
273
274
275
276
277 private String footer;
278
279
280
281
282 private boolean lastIteration;
283
284
285
286
287 private String caption;
288
289
290
291
292 private CaptionTag captionTag;
293
294
295
296
297
298
299
300 private Object filteredRows;
301
302
303
304
305
306 private PaginatedList paginatedList;
307
308
309
310
311
312 protected boolean isLastIteration()
313 {
314 return this.lastIteration;
315 }
316
317
318
319
320
321 public void setExcludedParams(String value)
322 {
323 this.excludedParams = value;
324 }
325
326
327
328
329
330 public void setFooter(String string)
331 {
332 this.footer = string;
333 this.tableModel.setFooter(this.footer);
334 }
335
336
337
338
339
340 public void setCaption(String string)
341 {
342 this.caption = string;
343 this.tableModel.setCaption(this.caption);
344 }
345
346
347
348
349
350 public void setCaptionTag(CaptionTag captionTag)
351 {
352 this.captionTag = captionTag;
353 }
354
355
356
357
358
359 public CaptionTag getCaptionTag()
360 {
361 return this.captionTag;
362 }
363
364
365
366
367
368 protected boolean isEmpty()
369 {
370 return this.currentRow == null;
371 }
372
373
374
375
376
377 public void setSize(Object size)
378 {
379 if (size instanceof String)
380 {
381 this.sizeObjectName = (String) size;
382 }
383 else
384 {
385 this.size = size;
386 }
387 }
388
389
390
391
392
393 public void setSizeObjectName(String sizeObjectName)
394 {
395 this.sizeObjectName = sizeObjectName;
396 }
397
398
399
400
401
402
403 public void setSort(String value) throws InvalidTagAttributeValueException
404 {
405 if (TableTagParameters.SORT_AMOUNT_PAGE.equals(value))
406 {
407 this.sortFullTable = Boolean.FALSE;
408 }
409 else if (TableTagParameters.SORT_AMOUNT_LIST.equals(value))
410 {
411 this.sortFullTable = Boolean.TRUE;
412 }
413 else if (TableTagParameters.SORT_AMOUNT_EXTERNAL.equals(value))
414 {
415 this.localSort = false;
416 }
417 else
418 {
419 throw new InvalidTagAttributeValueException(getClass(), "sort", value);
420 }
421 }
422
423
424
425
426
427 public void setRequestURI(String value)
428 {
429 this.requestUri = value;
430 }
431
432
433
434
435
436 public void setRequestURIcontext(boolean value)
437 {
438 this.dontAppendContext = !value;
439 }
440
441
442
443
444
445
446 public void setList(Object value)
447 {
448 this.listAttribute = value;
449 }
450
451
452
453
454
455
456 public void setName(Object value)
457 {
458 if (value instanceof String)
459 {
460
461 this.name = (String) value;
462 }
463 else
464 {
465
466 this.list = value;
467 }
468 }
469
470
471
472
473
474
475 public void setNameString(String value)
476 {
477 this.name = value;
478 }
479
480
481
482
483
484
485 public void setDefaultorder(String value) throws InvalidTagAttributeValueException
486 {
487 this.defaultSortOrder = SortOrderEnum.fromName(value);
488 if (this.defaultSortOrder == null)
489 {
490 throw new InvalidTagAttributeValueException(getClass(), "defaultorder", value);
491 }
492 }
493
494
495
496
497
498 public void setDecorator(String decorator)
499 {
500 this.decoratorName = decorator;
501 }
502
503
504
505
506
507 public void setExport(boolean value)
508 {
509 this.export = value;
510 }
511
512
513
514
515
516 public void setVarTotals(String varTotalsName)
517 {
518 this.varTotals = varTotalsName;
519 }
520
521
522
523
524
525 public String getVarTotals()
526 {
527 return this.varTotals;
528 }
529
530
531
532
533
534 public void setLength(int value)
535 {
536 this.length = value;
537 }
538
539
540
541
542
543 public void setDefaultsort(int value)
544 {
545
546 this.defaultSortedColumn = value - 1;
547 }
548
549
550
551
552
553 public void setPagesize(int value)
554 {
555 this.pagesize = value;
556 }
557
558
559
560
561
562
563 public void setPartialList(boolean partialList)
564 {
565 this.partialList = partialList;
566 }
567
568
569
570
571
572 public void setOffset(int value)
573 {
574 if (value < 1)
575 {
576
577 this.offset = 0;
578 }
579 else
580 {
581 this.offset = value - 1;
582 }
583 }
584
585
586
587
588
589 public void setUid(String value)
590 {
591 this.uid = value;
592 }
593
594
595
596
597
598 public String getUid()
599 {
600 return this.uid;
601 }
602
603
604
605
606
607 protected TableProperties getProperties()
608 {
609 return this.properties;
610 }
611
612
613
614
615
616
617 protected Href getBaseHref()
618 {
619 return this.baseHref;
620 }
621
622
623
624
625
626
627 public void addColumn(HeaderCell column)
628 {
629 if (log.isDebugEnabled())
630 {
631 log.debug("[" + getUid() + "] addColumn " + column);
632 }
633
634 if ((this.paginatedList != null) && (column.getSortable()))
635 {
636 String sortCriterion = paginatedList.getSortCriterion();
637
638 String sortProperty = column.getSortProperty();
639 if (sortProperty == null)
640 {
641 sortProperty = column.getBeanPropertyName();
642 }
643
644 if ((sortCriterion != null) && sortCriterion.equals(sortProperty))
645 {
646 this.tableModel.setSortedColumnNumber(this.tableModel.getNumberOfColumns());
647 column.setAlreadySorted();
648 }
649 }
650
651 this.tableModel.addColumnHeader(column);
652 }
653
654
655
656
657
658 public void addCell(Cell cell)
659 {
660
661 if (this.currentRow != null)
662 {
663 int columnNumber = this.currentRow.getCellList().size();
664 this.currentRow.addCell(cell);
665
666
667
668 if (columnNumber < tableModel.getHeaderCellList().size())
669 {
670 HeaderCell header = (HeaderCell) tableModel.getHeaderCellList().get(columnNumber);
671 header.addCell(new Column(header, cell, currentRow));
672 }
673 }
674 }
675
676
677
678
679
680 protected boolean isFirstIteration()
681 {
682 if (log.isDebugEnabled())
683 {
684 log.debug("["
685 + getUid()
686 + "] first iteration="
687 + (this.rowNumber == 1)
688 + " (row number="
689 + this.rowNumber
690 + ")");
691 }
692
693
694 return this.rowNumber == 1;
695 }
696
697
698
699
700
701
702
703
704 public int doStartTag() throws JspException
705 {
706 DependencyChecker.check();
707
708
709 ExportViewFactory.getInstance();
710
711 if (log.isDebugEnabled())
712 {
713 log.debug("[" + getUid() + "] doStartTag called");
714 }
715
716 this.properties = TableProperties.getInstance((HttpServletRequest) pageContext.getRequest());
717 this.tableModel = new TableModel(this.properties, pageContext.getResponse().getCharacterEncoding(), pageContext);
718
719
720 this.tableModel.setId(getUid());
721
722 initParameters();
723
724 this.tableModel.setMedia(this.currentMediaType);
725
726 Object previousMediaType = this.pageContext.getAttribute(PAGE_ATTRIBUTE_MEDIA);
727
728 if (previousMediaType == null || MediaTypeEnum.HTML.equals(previousMediaType))
729 {
730 if (log.isDebugEnabled())
731 {
732 log.debug("[" + getUid() + "] setting media [" + this.currentMediaType + "] in this.pageContext");
733 }
734 this.pageContext.setAttribute(PAGE_ATTRIBUTE_MEDIA, this.currentMediaType);
735 }
736
737 doIteration();
738
739
740
741 return 2;
742 }
743
744
745
746
747 public int doAfterBody()
748 {
749
750 this.doAfterBodyExecuted = true;
751
752 if (log.isDebugEnabled())
753 {
754 log.debug("[" + getUid() + "] doAfterBody called - iterating on row " + this.rowNumber);
755 }
756
757
758 this.rowNumber++;
759
760
761 return doIteration();
762 }
763
764
765
766
767
768 protected int doIteration()
769 {
770
771 if (log.isDebugEnabled())
772 {
773 log.debug("[" + getUid() + "] doIteration called");
774 }
775
776
777 if (this.currentRow != null)
778 {
779
780 this.tableModel.addRow(this.currentRow);
781 this.currentRow = null;
782 }
783
784 if (this.tableIterator.hasNext())
785 {
786
787 Object iteratedObject = this.tableIterator.next();
788 if (getUid() != null)
789 {
790 if ((iteratedObject != null))
791 {
792
793 if (log.isDebugEnabled())
794 {
795 log.debug("[" + getUid() + "] setting attribute \"" + getUid() + "\" in pageContext");
796 }
797 this.pageContext.setAttribute(getUid(), iteratedObject);
798
799 }
800 else
801 {
802
803 this.pageContext.removeAttribute(getUid());
804 }
805
806 this.pageContext.setAttribute(getUid() + TableTagExtraInfo.ROWNUM_SUFFIX, new Integer(this.rowNumber));
807 }
808
809
810 this.currentRow = new Row(iteratedObject, this.rowNumber);
811
812 this.lastIteration = !this.tableIterator.hasNext();
813
814
815
816 return 2;
817 }
818 this.lastIteration = true;
819
820 if (log.isDebugEnabled())
821 {
822 log.debug("[" + getUid() + "] doIteration() - iterator ended after " + (this.rowNumber - 1) + " rows");
823 }
824
825
826 return SKIP_BODY;
827 }
828
829
830
831
832
833 private void initParameters() throws JspTagException, FactoryInstantiationException
834 {
835
836 if (rhf == null)
837 {
838
839 rhf = this.properties.getRequestHelperFactoryInstance();
840 }
841
842 String fullName = getFullObjectName();
843
844
845 if (fullName != null)
846 {
847 this.list = evaluateExpression(fullName);
848 }
849 else if (this.list == null)
850 {
851
852 this.list = this.listAttribute;
853 }
854
855 if (this.list instanceof PaginatedList)
856 {
857 this.paginatedList = (PaginatedList) this.list;
858 this.list = this.paginatedList.getList();
859 }
860
861
862 this.tableModel.setLocalSort(this.localSort && (this.paginatedList == null));
863
864 RequestHelper requestHelper = rhf.getRequestHelperInstance(this.pageContext);
865
866 initHref(requestHelper);
867
868 Integer pageNumberParameter = requestHelper.getIntParameter(encodeParameter(TableTagParameters.PARAMETER_PAGE));
869 this.pageNumber = (pageNumberParameter == null) ? 1 : pageNumberParameter.intValue();
870
871 int sortColumn = -1;
872 if (!this.tableModel.isLocalSort())
873 {
874
875 String sortColumnName = requestHelper.getParameter(encodeParameter(TableTagParameters.PARAMETER_SORT));
876
877
878 String usename = requestHelper.getParameter(encodeParameter(TableTagParameters.PARAMETER_SORTUSINGNAME));
879
880 if (sortColumnName == null)
881 {
882 this.tableModel.setSortedColumnNumber(this.defaultSortedColumn);
883 }
884 else
885 {
886 if (usename != null)
887 {
888
889 this.tableModel.setSortedColumnName(sortColumnName);
890 }
891 else if (NumberUtils.isNumber(sortColumnName))
892 {
893 sortColumn = Integer.parseInt(sortColumnName);
894 this.tableModel.setSortedColumnNumber(sortColumn);
895 }
896 }
897 }
898 else if (this.paginatedList == null)
899 {
900 Integer sortColumnParameter = requestHelper
901 .getIntParameter(encodeParameter(TableTagParameters.PARAMETER_SORT));
902 sortColumn = (sortColumnParameter == null) ? this.defaultSortedColumn : sortColumnParameter.intValue();
903 this.tableModel.setSortedColumnNumber(sortColumn);
904 }
905 else
906 {
907 sortColumn = defaultSortedColumn;
908 }
909
910
911 boolean finalSortFull = this.properties.getSortFullList();
912
913
914 if (this.sortFullTable != null)
915 {
916 finalSortFull = this.sortFullTable.booleanValue();
917 }
918
919
920 if (!this.partialList || !finalSortFull)
921 {
922 this.tableModel.setSortFullTable(finalSortFull);
923 }
924
925 if (this.paginatedList == null)
926 {
927 SortOrderEnum paramOrder = SortOrderEnum.fromCode(requestHelper
928 .getIntParameter(encodeParameter(TableTagParameters.PARAMETER_ORDER)));
929
930
931 if (paramOrder == null)
932 {
933 paramOrder = this.defaultSortOrder;
934 }
935
936 boolean order = SortOrderEnum.DESCENDING != paramOrder;
937 this.tableModel.setSortOrderAscending(order);
938 }
939 else
940 {
941 SortOrderEnum direction = paginatedList.getSortDirection();
942 this.tableModel.setSortOrderAscending(direction == SortOrderEnum.ASCENDING);
943 }
944
945 Integer exportTypeParameter = requestHelper
946 .getIntParameter(encodeParameter(TableTagParameters.PARAMETER_EXPORTTYPE));
947
948 this.currentMediaType = (MediaTypeEnum) ObjectUtils.defaultIfNull(
949 MediaTypeEnum.fromCode(exportTypeParameter),
950 MediaTypeEnum.HTML);
951
952
953 if (this.partialList)
954 {
955 if ((this.sizeObjectName == null) && (this.size == null))
956 {
957
958 }
959 if (this.sizeObjectName != null)
960 {
961
962 this.size = evaluateExpression(this.sizeObjectName);
963 }
964 if (size == null)
965 {
966 throw new JspTagException(Messages.getString("MissingAttributeException.msg", new Object[]{"size"}));
967 }
968 else if (!(size instanceof Integer))
969 {
970 throw new JspTagException(Messages.getString(
971 "InvalidTypeException.msg",
972 new Object[]{"size", "Integer"}));
973 }
974 }
975
976
977 boolean wishOptimizedIteration = ((this.pagesize > 0
978 || this.offset > 0
979 || this.length > 0
980 ) && !partialList);
981
982
983 if (wishOptimizedIteration && (this.list instanceof Collection)
984 && ((sortColumn == -1
985 || !finalSortFull
986 ) && (this.currentMediaType == MediaTypeEnum.HTML
987 || !this.properties.getExportFullList())
988 ))
989 {
990 int start = 0;
991 int end = 0;
992 if (this.offset > 0)
993 {
994 start = this.offset;
995 }
996 if (length > 0)
997 {
998 end = start + this.length;
999 }
1000
1001 if (this.pagesize > 0)
1002 {
1003 int fullSize = ((Collection) this.list).size();
1004 start = (this.pageNumber - 1) * this.pagesize;
1005
1006
1007 if (start > fullSize)
1008 {
1009 int div = fullSize / this.pagesize;
1010 start = (fullSize % this.pagesize == 0) ? div : div + 1;
1011 }
1012
1013 end = start + this.pagesize;
1014 }
1015
1016
1017 filteredRows = new LongRange(start + 1, end);
1018 }
1019 else
1020 {
1021 filteredRows = new LongRange(1, Long.MAX_VALUE);
1022 }
1023
1024 this.tableIterator = IteratorUtils.getIterator(this.list);
1025 }
1026
1027
1028
1029
1030
1031
1032
1033 protected boolean isIncludedRow()
1034 {
1035 return ((Range) filteredRows).containsLong(this.rowNumber);
1036 }
1037
1038
1039
1040
1041
1042
1043 private String getFullObjectName()
1044 {
1045
1046 if (this.name == null)
1047 {
1048 return null;
1049 }
1050
1051 return this.name;
1052 }
1053
1054
1055
1056
1057
1058 protected void initHref(RequestHelper requestHelper)
1059 {
1060
1061 this.baseHref = requestHelper.getHref();
1062
1063 if (this.excludedParams != null)
1064 {
1065 String[] splittedExcludedParams = StringUtils.split(this.excludedParams);
1066
1067
1068 if (splittedExcludedParams.length == 1 && "*".equals(splittedExcludedParams[0]))
1069 {
1070
1071 if (this.paramEncoder == null)
1072 {
1073 this.paramEncoder = new ParamEncoder(getUid());
1074 }
1075
1076 Iterator paramsIterator = baseHref.getParameterMap().keySet().iterator();
1077 while (paramsIterator.hasNext())
1078 {
1079 String key = (String) paramsIterator.next();
1080
1081
1082 if (!this.paramEncoder.isParameterEncoded(key))
1083 {
1084 baseHref.removeParameter(key);
1085 }
1086 }
1087 }
1088 else
1089 {
1090 for (int j = 0; j < splittedExcludedParams.length; j++)
1091 {
1092 baseHref.removeParameter(splittedExcludedParams[j]);
1093 }
1094 }
1095 }
1096
1097 if (this.requestUri != null)
1098 {
1099
1100 String fullURI = requestUri;
1101 if (!this.dontAppendContext)
1102 {
1103 String contextPath = ((HttpServletRequest) this.pageContext.getRequest()).getContextPath();
1104
1105
1106
1107 if (!StringUtils.isEmpty(contextPath)
1108 && requestUri != null
1109 && requestUri.startsWith("/")
1110 && !requestUri.startsWith(contextPath))
1111 {
1112 fullURI = contextPath + this.requestUri;
1113 }
1114 }
1115
1116
1117 fullURI = ((HttpServletResponse) this.pageContext.getResponse()).encodeURL(fullURI);
1118
1119 baseHref.setFullUrl(fullURI);
1120
1121
1122
1123
1124 }
1125
1126 }
1127
1128
1129
1130
1131
1132
1133
1134
1135 public int doEndTag() throws JspException
1136 {
1137
1138 if (log.isDebugEnabled())
1139 {
1140 log.debug("[" + getUid() + "] doEndTag called");
1141 }
1142
1143 if (!this.doAfterBodyExecuted)
1144 {
1145 if (log.isDebugEnabled())
1146 {
1147 log.debug("[" + getUid() + "] tag body is empty.");
1148 }
1149
1150
1151 if (this.currentRow != null)
1152 {
1153
1154 this.tableModel.addRow(this.currentRow);
1155 }
1156
1157
1158 while (this.tableIterator.hasNext())
1159 {
1160 Object iteratedObject = this.tableIterator.next();
1161 this.rowNumber++;
1162
1163
1164 this.currentRow = new Row(iteratedObject, this.rowNumber);
1165
1166 this.tableModel.addRow(this.currentRow);
1167 }
1168 }
1169
1170
1171 if (this.tableModel.isEmpty())
1172 {
1173 describeEmptyTable();
1174 }
1175
1176 TableDecorator tableDecorator = this.properties.getDecoratorFactoryInstance().
1177 loadTableDecorator(this.pageContext, getConfiguredDecoratorName());
1178
1179 if (tableDecorator != null)
1180 {
1181 tableDecorator.init(this.pageContext, this.list, this.tableModel);
1182 this.tableModel.setTableDecorator(tableDecorator);
1183 }
1184
1185 setupViewableData();
1186
1187
1188
1189 if (this.paginatedList == null && this.tableModel.isLocalSort())
1190 {
1191 if (!this.tableModel.isSortFullTable())
1192 {
1193 this.tableModel.sortPageList();
1194 }
1195 }
1196
1197
1198 int returnValue = EVAL_PAGE;
1199
1200
1201
1202 Object previousMediaType = this.pageContext.getAttribute(PAGE_ATTRIBUTE_MEDIA);
1203 if (MediaTypeEnum.HTML.equals(this.currentMediaType)
1204 && (previousMediaType == null || MediaTypeEnum.HTML.equals(previousMediaType)))
1205 {
1206 writeHTMLData();
1207 }
1208 else if (!MediaTypeEnum.HTML.equals(this.currentMediaType))
1209 {
1210 if (log.isDebugEnabled())
1211 {
1212 log.debug("[" + getUid() + "] doEndTag - exporting");
1213 }
1214
1215 returnValue = doExport();
1216 }
1217
1218
1219
1220
1221 if (log.isDebugEnabled())
1222 {
1223 log.debug("[" + getUid() + "] doEndTag - end");
1224 }
1225
1226 cleanUp();
1227 return returnValue;
1228 }
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238 private String getConfiguredDecoratorName()
1239 {
1240 String
1241 tableDecoratorName = (this.decoratorName == null) ?
1242 this.properties.getMediaTypeDecoratorName(this.currentMediaType) :
1243 this.decoratorName;
1244 tableDecoratorName = (tableDecoratorName == null) ?
1245 this.properties.getExportDecoratorName(this.currentMediaType) :
1246 tableDecoratorName;
1247 return tableDecoratorName;
1248 }
1249
1250
1251
1252
1253 private void cleanUp()
1254 {
1255
1256 this.currentMediaType = null;
1257 this.baseHref = null;
1258 this.caption = null;
1259 this.captionTag = null;
1260 this.currentRow = null;
1261 this.doAfterBodyExecuted = false;
1262 this.footer = null;
1263 this.listHelper = null;
1264 this.pageNumber = 0;
1265 this.paramEncoder = null;
1266 this.properties = null;
1267 this.rowNumber = 1;
1268 this.tableIterator = null;
1269 this.tableModel = null;
1270 this.list = null;
1271 }
1272
1273
1274
1275
1276
1277
1278 private void describeEmptyTable()
1279 {
1280 this.tableIterator = IteratorUtils.getIterator(this.list);
1281
1282 if (this.tableIterator.hasNext())
1283 {
1284 Object iteratedObject = this.tableIterator.next();
1285 Map objectProperties = new HashMap();
1286
1287
1288 if (iteratedObject instanceof String)
1289 {
1290 return;
1291 }
1292
1293 if (iteratedObject instanceof Map)
1294 {
1295 objectProperties = (Map) iteratedObject;
1296 }
1297 else
1298 {
1299 try
1300 {
1301 objectProperties = BeanUtils.describe(iteratedObject);
1302 }
1303 catch (Exception e)
1304 {
1305 log.warn("Unable to automatically add columns: " + e.getMessage(), e);
1306 }
1307 }
1308
1309
1310 Iterator propertiesIterator = objectProperties.keySet().iterator();
1311
1312 while (propertiesIterator.hasNext())
1313 {
1314
1315 String propertyName = (String) propertiesIterator.next();
1316
1317
1318 if (!"class".equals(propertyName))
1319 {
1320
1321 HeaderCell headerCell = new HeaderCell();
1322 headerCell.setBeanPropertyName(propertyName);
1323
1324
1325 headerCell.setTitle(this.properties.geResourceProvider().getResource(
1326 null,
1327 propertyName,
1328 this,
1329 this.pageContext));
1330
1331 this.tableModel.addColumnHeader(headerCell);
1332 }
1333 }
1334 }
1335 }
1336
1337
1338
1339
1340
1341
1342 protected int doExport() throws JspException
1343 {
1344
1345 boolean exportFullList = this.properties.getExportFullList();
1346
1347 if (log.isDebugEnabled())
1348 {
1349 log.debug("[" + getUid() + "] currentMediaType=" + this.currentMediaType);
1350 }
1351
1352 boolean exportHeader = this.properties.getExportHeader(this.currentMediaType);
1353 boolean exportDecorated = this.properties.getExportDecorated();
1354
1355 ExportView exportView = ExportViewFactory.getInstance().getView(
1356 this.currentMediaType,
1357 this.tableModel,
1358 exportFullList,
1359 exportHeader,
1360 exportDecorated);
1361
1362 try
1363 {
1364 writeExport(exportView);
1365 }
1366 catch (IOException e)
1367 {
1368 throw new WrappedRuntimeException(getClass(), e);
1369 }
1370
1371 return SKIP_PAGE;
1372 }
1373
1374
1375
1376
1377
1378
1379
1380
1381 protected void writeExport(ExportView exportView) throws IOException, JspException
1382 {
1383 String filename = properties.getExportFileName(this.currentMediaType);
1384
1385 HttpServletResponse response = (HttpServletResponse) this.pageContext.getResponse();
1386 HttpServletRequest request = (HttpServletRequest) this.pageContext.getRequest();
1387
1388 Map bean = (Map) request.getAttribute(FILTER_CONTENT_OVERRIDE_BODY);
1389 boolean usingFilter = bean != null;
1390
1391 String mimeType = exportView.getMimeType();
1392
1393 String characterEncoding = response.getCharacterEncoding();
1394
1395 if (usingFilter)
1396 {
1397 if (!bean.containsKey(TableTagParameters.BEAN_BUFFER))
1398 {
1399
1400 log.debug("Exportfilter enabled in unbuffered mode, setting headers");
1401 response.addHeader(TableTagParameters.PARAMETER_EXPORTING, TagConstants.EMPTY_STRING);
1402 }
1403 else
1404 {
1405
1406 bean.put(TableTagParameters.BEAN_CONTENTTYPE, mimeType);
1407 bean.put(TableTagParameters.BEAN_FILENAME, filename);
1408
1409 if (exportView instanceof TextExportView)
1410 {
1411 StringWriter writer = new StringWriter();
1412 ((TextExportView) exportView).doExport(writer);
1413 bean.put(TableTagParameters.BEAN_BODY, writer.toString());
1414 }
1415 else if (exportView instanceof BinaryExportView)
1416 {
1417 ByteArrayOutputStream stream = new ByteArrayOutputStream();
1418 ((BinaryExportView) exportView).doExport(stream);
1419 bean.put(TableTagParameters.BEAN_BODY, stream.toByteArray());
1420
1421 }
1422 else
1423 {
1424 throw new JspTagException("Export view "
1425 + exportView.getClass().getName()
1426 + " must implement TextExportView or BinaryExportView");
1427 }
1428
1429 return;
1430 }
1431 }
1432 else
1433 {
1434 log.debug("Exportfilter NOT enabled");
1435
1436 if (response.isCommitted())
1437 {
1438 throw new ExportException(getClass());
1439 }
1440
1441 try
1442 {
1443 response.reset();
1444 pageContext.getOut().clearBuffer();
1445 }
1446 catch (Exception e)
1447 {
1448 throw new ExportException(getClass());
1449 }
1450 }
1451
1452 if (!usingFilter && characterEncoding != null && mimeType.indexOf("charset") == -1)
1453 {
1454 mimeType += "; charset=" + characterEncoding;
1455 }
1456
1457 response.setContentType(mimeType);
1458
1459 if (StringUtils.isNotEmpty(filename))
1460 {
1461 response.setHeader("Content-Disposition",
1462 "attachment; filename=\"" + filename + "\"");
1463 }
1464
1465 if (exportView instanceof TextExportView)
1466 {
1467 Writer writer;
1468 if (usingFilter)
1469 {
1470 writer = response.getWriter();
1471 }
1472 else
1473 {
1474 writer = pageContext.getOut();
1475 }
1476
1477 ((TextExportView) exportView).doExport(writer);
1478 }
1479 else if (exportView instanceof BinaryExportView)
1480 {
1481
1482
1483
1484 ((BinaryExportView) exportView).doExport(response.getOutputStream());
1485 }
1486 else
1487 {
1488 throw new JspTagException("Export view "
1489 + exportView.getClass().getName()
1490 + " must implement TextExportView or BinaryExportView");
1491 }
1492
1493 log.debug("Export completed");
1494
1495 }
1496
1497
1498
1499
1500
1501
1502 protected void setupViewableData()
1503 {
1504
1505
1506
1507
1508
1509 if (this.paginatedList == null || this.tableModel.isLocalSort())
1510 {
1511 if (this.tableModel.isSortFullTable())
1512 {
1513
1514 this.tableModel.sortFullList();
1515 }
1516 }
1517
1518 Object originalData = this.tableModel.getRowListFull();
1519
1520
1521
1522 List fullList = CollectionUtil.getListFromObject(originalData, this.offset, this.length);
1523
1524 int pageOffset = this.offset;
1525
1526
1527 if (this.paginatedList == null && this.pagesize > 0)
1528 {
1529 this.listHelper = new SmartListHelper(fullList, (this.partialList) ? ((Integer) size).intValue() : fullList
1530 .size(), this.pagesize, this.properties, this.partialList);
1531 this.listHelper.setCurrentPage(this.pageNumber);
1532 pageOffset = this.listHelper.getFirstIndexForCurrentPage();
1533 fullList = this.listHelper.getListForCurrentPage();
1534 }
1535 else if (this.paginatedList != null)
1536 {
1537 this.listHelper = new PaginatedListSmartListHelper(this.paginatedList, this.properties);
1538 }
1539 this.tableModel.setRowListPage(fullList);
1540 this.tableModel.setPageOffset(pageOffset);
1541 }
1542
1543
1544
1545
1546
1547 private void writeHTMLData() throws JspException
1548 {
1549 JspWriter out = this.pageContext.getOut();
1550
1551 String css = this.properties.getCssTable();
1552 if (StringUtils.isNotBlank(css))
1553 {
1554 this.addClass(css);
1555 }
1556
1557 new HtmlTableWriter(
1558 this.tableModel,
1559 this.properties,
1560 this.baseHref,
1561 this.export,
1562 out,
1563 getCaptionTag(),
1564 this.paginatedList,
1565 this.listHelper,
1566 this.pagesize,
1567 getAttributeMap(),
1568 this.uid).writeTable(this.tableModel, this.getUid());
1569
1570 if (this.varTotals != null)
1571 {
1572 pageContext.setAttribute(this.varTotals, getTotals());
1573 }
1574 }
1575
1576
1577
1578
1579
1580 public Map getTotals()
1581 {
1582 Map totalsMap = new HashMap();
1583 if (this.varTotals != null)
1584 {
1585 List headers = this.tableModel.getHeaderCellList();
1586 for (Iterator iterator = headers.iterator(); iterator.hasNext();)
1587 {
1588 HeaderCell headerCell = (HeaderCell) iterator.next();
1589 if (headerCell.isTotaled())
1590 {
1591 totalsMap.put("column" + (headerCell.getColumnNumber() + 1), new Double(headerCell.getTotal()));
1592 }
1593 }
1594 }
1595 return totalsMap;
1596 }
1597
1598
1599
1600
1601
1602
1603
1604 public TableModel getTableModel()
1605 {
1606 return this.tableModel;
1607 }
1608
1609
1610
1611
1612
1613
1614 public void setProperty(String propertyName, String propertyValue)
1615 {
1616 this.properties.setProperty(propertyName, propertyValue);
1617 }
1618
1619
1620
1621
1622 public void release()
1623 {
1624 if (log.isDebugEnabled())
1625 {
1626 log.debug("[" + getUid() + "] release() called");
1627 }
1628
1629 super.release();
1630
1631
1632 this.decoratorName = null;
1633 this.defaultSortedColumn = -1;
1634 this.defaultSortOrder = null;
1635 this.export = false;
1636 this.length = 0;
1637 this.listAttribute = null;
1638 this.localSort = true;
1639 this.name = null;
1640 this.offset = 0;
1641 this.pagesize = 0;
1642 this.partialList = false;
1643 this.requestUri = null;
1644 this.dontAppendContext = false;
1645 this.sortFullTable = null;
1646 this.excludedParams = null;
1647 this.filteredRows = null;
1648 this.uid = null;
1649 this.paginatedList = null;
1650 }
1651
1652
1653
1654
1655
1656 protected String getName()
1657 {
1658 return this.name;
1659 }
1660
1661
1662
1663
1664
1665
1666 private String encodeParameter(String parameterName)
1667 {
1668
1669 if (this.paramEncoder == null)
1670 {
1671
1672 this.paramEncoder = new ParamEncoder(getUid());
1673 }
1674
1675 return this.paramEncoder.encodeParameterName(parameterName);
1676 }
1677
1678 }