1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.component.html.ext;
20
21 import java.io.IOException;
22 import java.sql.ResultSet;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.StringTokenizer;
30
31 import javax.faces.application.Application;
32 import javax.faces.component.EditableValueHolder;
33 import javax.faces.component.NamingContainer;
34 import javax.faces.component.UIColumn;
35 import javax.faces.component.UIComponent;
36 import javax.faces.context.FacesContext;
37 import javax.faces.el.ValueBinding;
38 import javax.faces.model.DataModel;
39
40 import org.apache.commons.logging.Log;
41 import org.apache.commons.logging.LogFactory;
42 import org.apache.myfaces.component.NewspaperTable;
43 import org.apache.myfaces.component.UserRoleAware;
44 import org.apache.myfaces.component.UserRoleUtils;
45 import org.apache.myfaces.custom.column.HtmlSimpleColumn;
46 import org.apache.myfaces.custom.crosstable.UIColumns;
47 import org.apache.myfaces.custom.sortheader.HtmlCommandSortHeader;
48 import org.apache.myfaces.renderkit.html.ext.HtmlTableRenderer;
49 import org.apache.myfaces.renderkit.html.util.TableContext;
50 import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
51 import org.apache.myfaces.shared_tomahawk.util.ClassUtils;
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 public abstract class AbstractHtmlDataTable extends HtmlDataTableHack implements UserRoleAware, NewspaperTable
80 {
81 private static final Log log = LogFactory.getLog(AbstractHtmlDataTable.class);
82
83 private static final int PROCESS_DECODES = 1;
84 private static final int PROCESS_VALIDATORS = 2;
85 private static final int PROCESS_UPDATES = 3;
86
87 private static final boolean DEFAULT_SORTASCENDING = true;
88 private static final boolean DEFAULT_SORTABLE = false;
89 private static final boolean DEFAULT_EMBEDDED = false;
90 private static final boolean DEFAULT_DETAILSTAMP_EXPANDED = false;
91 private static final Class OBJECT_ARRAY_CLASS = (new Object[0]).getClass();
92
93 private static final Integer DEFAULT_NEWSPAPER_COLUMNS = new Integer(1);
94 private static final String DEFAULT_NEWSPAPER_ORIENTATION = "vertical";
95 private static final String DEFAULT_DETAILSTAMP_LOCATION = "after";
96
97
98
99
100 public static final String NEWSPAPER_COLUMNS_PROPERTY = "newspaperColumns";
101 public static final String SPACER_FACET_NAME = "spacer";
102 public static final String NEWSPAPER_ORIENTATION_PROPERTY = "newspaperOrientation";
103
104 public static final String DETAIL_STAMP_FACET_NAME = "detailStamp";
105
106 private _SerializableDataModel _preservedDataModel;
107
108 private String _forceIdIndexFormula = null;
109 private String _sortColumn = null;
110 private Boolean _sortAscending = null;
111 private String _sortProperty = null;
112 private String _rowStyleClass = null;
113 private String _rowStyle = null;
114 private String _varDetailToggler = null;
115
116 private int _sortColumnIndex = -1;
117
118 private boolean _isValidChildren = true;
119
120 private Map _expandedNodes = new HashMap();
121
122
123
124 private TableContext _tableContext = null;
125
126 public TableContext getTableContext()
127 {
128 if (_tableContext == null)
129 {
130 _tableContext = new TableContext();
131 }
132 return _tableContext;
133 }
134
135 public void setDetailStamp(UIComponent facet)
136 {
137 getFacets().put(DETAIL_STAMP_FACET_NAME, facet);
138 }
139
140
141
142
143
144
145
146
147
148 public UIComponent getDetailStamp()
149 {
150 return (UIComponent) getFacets().get(DETAIL_STAMP_FACET_NAME);
151 }
152
153 public String getClientId(FacesContext context)
154 {
155 String standardClientId = super.getClientId(context);
156 int rowIndex = getRowIndex();
157 if (rowIndex == -1)
158 {
159 return standardClientId;
160 }
161
162 String forcedIdIndex = getForceIdIndexFormula();
163 if (forcedIdIndex == null || forcedIdIndex.length() == 0)
164 return standardClientId;
165
166
167
168
169 int indexLast_ = standardClientId.lastIndexOf(NamingContainer.SEPARATOR_CHAR);
170 if (indexLast_ == -1)
171 {
172 log.info("Could not parse super.getClientId. forcedIdIndex will contain the rowIndex.");
173 return standardClientId + NamingContainer.SEPARATOR_CHAR + forcedIdIndex;
174 }
175
176
177 String parsedForcedClientId = standardClientId.substring(0, indexLast_ + 1) + forcedIdIndex;
178 return parsedForcedClientId;
179 }
180
181 public UIComponent findComponent(String expr)
182 {
183 if (expr.length() > 0 && Character.isDigit(expr.charAt(0)))
184 {
185 int separatorIndex = expr.indexOf(NamingContainer.SEPARATOR_CHAR);
186
187 String rowIndexStr = expr;
188 String remainingPart = null;
189
190 if (separatorIndex != -1)
191 {
192 rowIndexStr = expr.substring(0, separatorIndex);
193 remainingPart = expr.substring(separatorIndex + 1);
194 }
195
196 int rowIndex = Integer.valueOf(rowIndexStr).intValue();
197
198 if (remainingPart == null)
199 {
200 log.error("Wrong syntax of expression : " + expr +
201 " rowIndex was provided, but no component name.");
202 return null;
203 }
204
205 UIComponent comp = super.findComponent(remainingPart);
206
207 if (comp == null)
208 return null;
209
210
211 UIComponentPerspective perspective = new UIComponentPerspective(this, comp, rowIndex);
212 return perspective;
213 }
214 else
215 {
216 return super.findComponent(expr);
217 }
218 }
219
220 public void setRowIndex(int rowIndex)
221 {
222
223
224 if (rowIndex < -1)
225 {
226 throw new IllegalArgumentException("rowIndex is less than -1");
227 }
228
229
230
231
232
233
234
235
236
237
238 String rowIndexVar = getRowIndexVar();
239 String rowCountVar = getRowCountVar();
240 String previousRowDataVar = getPreviousRowDataVar();
241 if (rowIndexVar != null || rowCountVar != null || previousRowDataVar != null)
242 {
243 Map requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
244
245 if (previousRowDataVar != null && rowIndex >= 0)
246 {
247 if (isRowAvailable())
248 {
249
250 requestMap.put(previousRowDataVar, getRowData());
251 }
252 else
253 {
254
255 requestMap.put(previousRowDataVar, null);
256 }
257 }
258
259 super.setRowIndex(rowIndex);
260
261 if (rowIndex >= 0)
262 {
263
264 if (rowIndexVar != null)
265 {
266 requestMap.put(rowIndexVar, new Integer(rowIndex));
267 }
268
269 if (rowCountVar != null)
270 {
271 requestMap.put(rowCountVar, new Integer(getRowCount()));
272 }
273 }
274 else
275 {
276
277 if (rowIndexVar != null)
278 {
279 requestMap.remove(rowIndexVar);
280 }
281
282 if (rowCountVar != null)
283 {
284 requestMap.remove(rowCountVar);
285 }
286
287 if (previousRowDataVar != null)
288 {
289 requestMap.remove(previousRowDataVar);
290 }
291 }
292 }
293 else
294 {
295
296 super.setRowIndex(rowIndex);
297 }
298
299
300
301
302
303
304
305
306
307
308 if (_varDetailToggler != null)
309 {
310 Map requestMap = getFacesContext().getExternalContext().getRequestMap();
311 requestMap.put(_varDetailToggler, this);
312 }
313 }
314
315 protected Object saveDescendantComponentStates()
316 {
317 if (!getFacets().isEmpty())
318 {
319 UIComponent detailStampFacet = getFacet(DETAIL_STAMP_FACET_NAME);
320 if (detailStampFacet != null)
321 {
322 return saveDescendantComponentStates(new _DetailStampFacetAndChildrenIterator(detailStampFacet, getChildren()), false);
323 }
324 }
325 return super.saveDescendantComponentStates();
326 }
327
328 protected void restoreDescendantComponentStates(Object state)
329 {
330 if (!getFacets().isEmpty())
331 {
332 UIComponent detailStampFacet = getFacet(DETAIL_STAMP_FACET_NAME);
333 if (detailStampFacet != null)
334 {
335 restoreDescendantComponentStates(new _DetailStampFacetAndChildrenIterator(detailStampFacet, getChildren()), state, false);
336 return;
337 }
338 }
339 super.restoreDescendantComponentStates(state);
340 }
341
342 public void processDecodes(FacesContext context)
343 {
344 if (!isRendered())
345 {
346 return;
347 }
348
349
350
351
352
353
354
355 setRowIndex(-1);
356 processFacets(context, PROCESS_DECODES);
357 processColumnFacets(context, PROCESS_DECODES);
358 processColumnChildren(context, PROCESS_DECODES);
359 setRowIndex(-1);
360 try
361 {
362 decode(context);
363 }
364 catch (RuntimeException e)
365 {
366 context.renderResponse();
367 throw e;
368 }
369
370 setRowIndex(-1);
371 processColumns(context, PROCESS_DECODES);
372 setRowIndex(-1);
373 processDetails(context, PROCESS_DECODES);
374 setRowIndex(-1);
375 }
376
377 private void processFacets(FacesContext context, int processAction)
378 {
379 for (Iterator it = getFacets().entrySet().iterator(); it.hasNext(); )
380 {
381 Map.Entry entry = (Map.Entry) it.next();
382 if (!DETAIL_STAMP_FACET_NAME.equals((String)entry.getKey()))
383 {
384 process(context, (UIComponent) entry.getValue(), processAction);
385 }
386 }
387 }
388
389
390
391
392
393
394
395
396
397
398 private void processColumnFacets(FacesContext context, int processAction)
399 {
400 for (Iterator childIter = getChildren().iterator(); childIter.hasNext();)
401 {
402 UIComponent child = (UIComponent) childIter.next();
403 if (child instanceof UIColumn)
404 {
405 if (!child.isRendered())
406 {
407
408 continue;
409 }
410 for (Iterator facetsIter = child.getFacets().values()
411 .iterator(); facetsIter.hasNext();)
412 {
413 UIComponent facet = (UIComponent) facetsIter.next();
414 process(context, facet, processAction);
415 }
416 }
417 }
418 }
419
420
421
422
423
424
425
426
427
428
429 private void processColumnChildren(FacesContext context, int processAction)
430 {
431 int first = getFirst();
432 int rows = getRows();
433 int last;
434 if (rows == 0)
435 {
436 last = getRowCount();
437 }
438 else
439 {
440 last = first + rows;
441 }
442 for (int rowIndex = first; last==-1 || rowIndex < last; rowIndex++)
443 {
444 setRowIndex(rowIndex);
445
446
447 if (!isRowAvailable())
448 break;
449
450 for (Iterator it = getChildren().iterator(); it.hasNext();)
451 {
452 UIComponent child = (UIComponent) it.next();
453 if (child instanceof UIColumn)
454 {
455 if (!child.isRendered())
456 {
457
458 continue;
459 }
460 for (Iterator columnChildIter = child.getChildren()
461 .iterator(); columnChildIter.hasNext();)
462 {
463 UIComponent columnChild = (UIComponent) columnChildIter
464 .next();
465 process(context, columnChild, processAction);
466 }
467 }
468 }
469 }
470 }
471
472
473
474
475
476 private void processDetails(FacesContext context, int processAction)
477 {
478 UIComponent facet = getFacet(HtmlTableRenderer.DETAIL_STAMP_FACET_NAME);
479
480 if (facet != null)
481 {
482 int first = getFirst();
483 int rows = getRows();
484 int last;
485 if (rows == 0)
486 {
487 last = getRowCount();
488 }
489 else
490 {
491 last = first + rows;
492 }
493 for (int rowIndex = first; last == -1 || rowIndex < last; rowIndex++)
494 {
495 setRowIndex(rowIndex);
496
497
498 if (!isRowAvailable())
499 {
500 break;
501 }
502
503 if (!isCurrentDetailExpanded())
504 {
505 continue;
506 }
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526 if (PROCESS_DECODES == processAction)
527 {
528 resetAllSubmittedValues(facet);
529 }
530
531 process(context, facet, processAction);
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546 }
547 }
548 }
549
550 private void resetAllSubmittedValues(UIComponent component)
551 {
552 if (component instanceof EditableValueHolder)
553 {
554 ((EditableValueHolder) component).setSubmittedValue(null);
555 }
556
557 for (Iterator it = component.getFacetsAndChildren(); it.hasNext();)
558 {
559 resetAllSubmittedValues((UIComponent) it.next());
560 }
561 }
562
563
564
565
566
567 private void processColumns(FacesContext context, int processAction)
568 {
569 for (Iterator it = getChildren().iterator(); it.hasNext();)
570 {
571 UIComponent child = (UIComponent) it.next();
572 if (child instanceof UIColumns)
573 {
574 process(context, child, processAction);
575 }
576 }
577 }
578
579 private void process(FacesContext context, UIComponent component, int processAction)
580 {
581 switch (processAction)
582 {
583 case PROCESS_DECODES:
584 component.processDecodes(context);
585 break;
586 case PROCESS_VALIDATORS:
587 component.processValidators(context);
588 break;
589 case PROCESS_UPDATES:
590 component.processUpdates(context);
591 break;
592 }
593 }
594
595 public void processValidators(FacesContext context)
596 {
597 if (!isRendered())
598 {
599 return;
600 }
601
602
603
604
605
606
607 setRowIndex(-1);
608 processFacets(context, PROCESS_VALIDATORS);
609 processColumnFacets(context, PROCESS_VALIDATORS);
610 processColumnChildren(context, PROCESS_VALIDATORS);
611 setRowIndex(-1);
612
613 processColumns(context, PROCESS_VALIDATORS);
614 setRowIndex(-1);
615 processDetails(context, PROCESS_VALIDATORS);
616 setRowIndex(-1);
617
618 if (context.getRenderResponse())
619 {
620 _isValidChildren = false;
621 }
622 }
623
624 public void processUpdates(FacesContext context)
625 {
626 if (!isRendered())
627 {
628 return;
629 }
630
631
632
633
634
635
636
637
638 setRowIndex(-1);
639 processFacets(context, PROCESS_UPDATES);
640 processColumnFacets(context, PROCESS_UPDATES);
641 processColumnChildren(context, PROCESS_UPDATES);
642 setRowIndex(-1);
643
644 processColumns(context, PROCESS_UPDATES);
645 setRowIndex(-1);
646 processDetails(context, PROCESS_UPDATES);
647 setRowIndex(-1);
648
649 if (isPreserveDataModel())
650 {
651 updateModelFromPreservedDataModel(context);
652 }
653
654 if (context.getRenderResponse())
655 {
656 _isValidChildren = false;
657 }
658 }
659
660 private void updateModelFromPreservedDataModel(FacesContext context)
661 {
662 ValueBinding vb = getValueBinding("value");
663 if (vb != null && !vb.isReadOnly(context))
664 {
665 _SerializableDataModel dm = (_SerializableDataModel) getDataModel();
666 Class type = (getValueType() == null) ?
667 vb.getType(context) :
668 ClassUtils.simpleClassForName(getValueType());
669 Class dmType = dm.getClass();
670 if (DataModel.class.isAssignableFrom(type))
671 {
672 vb.setValue(context, dm);
673 }
674 else if (List.class.isAssignableFrom(type) || _SerializableListDataModel.class.isAssignableFrom(dmType))
675 {
676 vb.setValue(context, dm.getWrappedData());
677 }
678 else if (OBJECT_ARRAY_CLASS.isAssignableFrom(type))
679 {
680 List lst = (List) dm.getWrappedData();
681 vb.setValue(context, lst.toArray(new Object[lst.size()]));
682 }
683 else if (ResultSet.class.isAssignableFrom(type))
684 {
685 throw new UnsupportedOperationException(this.getClass().getName()
686 + " UnsupportedOperationException");
687 }
688 else
689 {
690
691 List lst = (List) dm.getWrappedData();
692 if (lst!= null && lst.size() > 0)
693 {
694 vb.setValue(context, lst.get(0));
695 }
696 else
697 {
698 vb.setValue(context, null);
699 }
700 }
701 }
702 _preservedDataModel = null;
703 }
704
705 public void encodeBegin(FacesContext context) throws IOException
706 {
707 if (!isRendered())
708 return;
709
710 if (_isValidChildren && !hasErrorMessages(context))
711 {
712 _preservedDataModel = null;
713 }
714
715 for (Iterator iter = getChildren().iterator(); iter.hasNext();)
716 {
717 UIComponent component = (UIComponent) iter.next();
718 if (component instanceof UIColumns)
719 {
720
721
722 ((UIColumns) component).encodeTableBegin(context);
723 }
724 }
725
726
727
728 for (Iterator iter = getChildren().iterator(); iter.hasNext();)
729 {
730 UIComponent component = (UIComponent) iter.next();
731 if (component instanceof UIColumn)
732 {
733 UIColumn aColumn = (UIColumn) component;
734 UIComponent headerFacet = aColumn.getHeader();
735
736 boolean replaceHeaderFacets = isSortable();
737
738 String columnName = null;
739 String propertyName = null;
740 boolean defaultSorted = false;
741
742 if (aColumn instanceof HtmlSimpleColumn)
743 {
744 HtmlSimpleColumn asColumn = (HtmlSimpleColumn) aColumn;
745 propertyName = asColumn.getSortPropertyName();
746 defaultSorted = asColumn.isDefaultSorted();
747
748 if (asColumn.isSortable())
749 replaceHeaderFacets = true;
750 }
751
752
753 if (replaceHeaderFacets && isSortHeaderNeeded(aColumn, headerFacet))
754 {
755 propertyName = propertyName != null ? propertyName : getSortPropertyFromEL(aColumn);
756 if (propertyName == null)
757 log.warn("Couldn't determine sort property for column [" + aColumn.getId() + "].");
758
759 if (headerFacet != null)
760 {
761 HtmlCommandSortHeader sortHeader = createSortHeaderComponent(context, aColumn, headerFacet, propertyName);
762 columnName = sortHeader.getColumnName();
763
764 aColumn.setHeader(sortHeader);
765 sortHeader.setParent(aColumn);
766 }
767 }
768 else if (headerFacet instanceof HtmlCommandSortHeader)
769 {
770
771 HtmlCommandSortHeader sortHeader = (HtmlCommandSortHeader) headerFacet;
772 columnName = sortHeader.getColumnName();
773 propertyName = sortHeader.getPropertyName();
774
775
776 if (propertyName == null)
777 {
778 propertyName = getSortPropertyFromEL(aColumn);
779 sortHeader.setPropertyName(propertyName);
780 }
781
782 if (propertyName == null)
783 log.warn("Couldn't determine sort property for column [" + aColumn.getId() + "].");
784 }
785
786
787 if (defaultSorted && getSortColumn() == null)
788 {
789 setSortColumn(columnName);
790 setSortProperty(propertyName);
791 }
792 }
793 }
794
795
796
797 super.encodeBegin(context);
798 }
799
800
801
802
803 protected boolean isSortHeaderNeeded(UIColumn parentColumn, UIComponent headerFacet)
804 {
805 return !(headerFacet instanceof HtmlCommandSortHeader);
806 }
807
808
809
810
811 protected HtmlCommandSortHeader createSortHeaderComponent(FacesContext context, UIColumn parentColumn, UIComponent initialHeaderFacet, String propertyName)
812 {
813 Application application = context.getApplication();
814
815 HtmlCommandSortHeader sortHeader = (HtmlCommandSortHeader) application.createComponent(HtmlCommandSortHeader.COMPONENT_TYPE);
816 String id = context.getViewRoot().createUniqueId();
817 sortHeader.setId(id);
818 sortHeader.setColumnName(id);
819 sortHeader.setPropertyName(propertyName);
820 sortHeader.setArrow(true);
821 sortHeader.setImmediate(true);
822 sortHeader.getChildren().add(initialHeaderFacet);
823 initialHeaderFacet.setParent(sortHeader);
824
825 return sortHeader;
826 }
827
828
829
830
831 protected String getSortPropertyFromEL(UIComponent component)
832 {
833 if (getVar() == null)
834 {
835 log.warn("There is no 'var' specified on the dataTable, sort properties cannot be determined automaticaly.");
836 return null;
837 }
838
839 for (Iterator iter = component.getChildren().iterator(); iter.hasNext();)
840 {
841 UIComponent aChild = (UIComponent) iter.next();
842 if (aChild.isRendered())
843 {
844 ValueBinding vb = aChild.getValueBinding("value");
845 if (vb != null)
846 {
847 String expressionString = vb.getExpressionString();
848
849 int varIndex = expressionString.indexOf(getVar() + ".");
850 if (varIndex != -1)
851 {
852 int varEndIndex = varIndex + getVar().length();
853 String tempProp = expressionString.substring(varEndIndex + 1, expressionString.length());
854
855 StringTokenizer tokenizer = new StringTokenizer(tempProp, " +[]{}-/*|?:&<>!=()%");
856 if (tokenizer.hasMoreTokens())
857 return tokenizer.nextToken();
858 }
859 }
860 else
861 {
862 String sortProperty = getSortPropertyFromEL(aChild);
863 if (sortProperty != null)
864 return sortProperty;
865 }
866 }
867 }
868
869 return null;
870 }
871
872
873
874
875 protected int columnNameToIndex(String columnName)
876 {
877 int index = 0;
878 for (Iterator iter = getChildren().iterator(); iter.hasNext();)
879 {
880 UIComponent aChild = (UIComponent) iter.next();
881 if (aChild instanceof UIColumn)
882 {
883 UIComponent headerFacet = ((UIColumn) aChild).getHeader();
884 if (headerFacet != null && headerFacet instanceof HtmlCommandSortHeader)
885 {
886 HtmlCommandSortHeader sortHeader = (HtmlCommandSortHeader) headerFacet;
887 if (columnName != null && columnName.equals(sortHeader.getColumnName()))
888 return index;
889 }
890 }
891
892 index += 1;
893 }
894
895 return -1;
896 }
897
898
899
900
901 public void encodeEnd(FacesContext context) throws IOException
902 {
903 super.encodeEnd(context);
904 for (Iterator iter = getChildren().iterator(); iter.hasNext();)
905 {
906 UIComponent component = (UIComponent) iter.next();
907 if (component instanceof UIColumns)
908 {
909 ((UIColumns) component).encodeTableEnd(context);
910 }
911 }
912 }
913
914
915
916
917
918
919 public int getFirst()
920 {
921 if (_preservedDataModel != null)
922 {
923
924 return _preservedDataModel.getFirst();
925 }
926 else
927 {
928 return super.getFirst();
929 }
930 }
931
932 public void setFirst(int first)
933 {
934 if (_preservedDataModel != null)
935 {
936
937 _preservedDataModel.setFirst(first);
938 }
939 super.setFirst(first);
940 }
941
942
943
944
945
946
947 public int getRows()
948 {
949 if (_preservedDataModel != null)
950 {
951
952 return _preservedDataModel.getRows();
953 }
954 else
955 {
956 return super.getRows();
957 }
958 }
959
960 public void setRows(int rows)
961 {
962 if (_preservedDataModel != null)
963 {
964
965 _preservedDataModel.setRows(rows);
966 }
967 super.setRows(rows);
968 }
969
970 public Object saveState(FacesContext context)
971 {
972 boolean preserveSort = isPreserveSort();
973
974 Object[] values = new Object[15];
975 values[0] = super.saveState(context);
976 values[1] = _preserveDataModel;
977
978 if (isPreserveDataModel())
979 {
980 _preservedDataModel = getSerializableDataModel();
981 values[2] = saveAttachedState(context, _preservedDataModel);
982 }
983 else
984 {
985 values[2] = null;
986 }
987 values[3] = _preserveSort;
988 values[4] = _forceIdIndexFormula;
989 values[5] = _sortColumn;
990 values[6] = _sortAscending;
991 values[7] = _sortProperty;
992
993 values[8] = _rowStyleClass;
994 values[9] = _rowStyle;
995
996 values[10] = preserveSort ? getSortColumn() : null;
997 values[11] = preserveSort ? Boolean.valueOf(isSortAscending()) : null;
998
999 values[12] = _varDetailToggler;
1000 values[13] = _expandedNodes;
1001 values[14] = new Integer(_sortColumnIndex);
1002
1003 return values;
1004 }
1005
1006
1007
1008
1009 protected DataModel getDataModel()
1010 {
1011 if (_preservedDataModel != null)
1012 {
1013 setDataModel(_preservedDataModel);
1014 _preservedDataModel = null;
1015 }
1016
1017 return super.getDataModel();
1018 }
1019
1020
1021
1022
1023 protected DataModel createDataModel()
1024 {
1025 DataModel dataModel = super.createDataModel();
1026
1027 boolean isSortable = isSortable();
1028
1029 if (!(dataModel instanceof SortableModel))
1030 {
1031
1032
1033
1034 for (Iterator iter = getChildren().iterator(); iter.hasNext();)
1035 {
1036 UIComponent component = (UIComponent) iter.next();
1037 if (component instanceof HtmlSimpleColumn)
1038 {
1039 HtmlSimpleColumn aColumn = (HtmlSimpleColumn) component;
1040 if (isSortable())
1041 aColumn.setSortable(true);
1042
1043 if (aColumn.isSortable())
1044 isSortable = true;
1045
1046 if (aColumn.isDefaultSorted() && getSortColumn() == null)
1047 setSortProperty(aColumn.getSortPropertyName());
1048 }
1049 }
1050
1051 if (isSortable)
1052 dataModel = new SortableModel(dataModel);
1053 }
1054
1055 if (isSortable && getSortProperty() != null)
1056 {
1057 SortCriterion criterion = new SortCriterion(getSortProperty(), isSortAscending());
1058 List criteria = new ArrayList();
1059 criteria.add(criterion);
1060
1061 ((SortableModel) dataModel).setSortCriteria(criteria);
1062 }
1063
1064 return dataModel;
1065 }
1066
1067 public void restoreState(FacesContext context, Object state)
1068 {
1069 Object[] values = (Object[]) state;
1070 super.restoreState(context, values[0]);
1071 _preserveDataModel = (Boolean) values[1];
1072 if (isPreserveDataModel())
1073 {
1074 _preservedDataModel = (_SerializableDataModel) restoreAttachedState(context, values[2]);
1075 }
1076 else
1077 {
1078 _preservedDataModel = null;
1079 }
1080 _preserveSort = (Boolean) values[3];
1081 _forceIdIndexFormula = (String) values[4];
1082 _sortColumn = (String) values[5];
1083 _sortAscending = (Boolean) values[6];
1084 _sortProperty = (String) values[7];
1085
1086 _rowStyleClass = (String) values[8];
1087 _rowStyle = (String) values[9];
1088
1089 if (isPreserveSort())
1090 {
1091 String sortColumn = (String) values[10];
1092 Boolean sortAscending = (Boolean) values[11];
1093 if (sortColumn != null && sortAscending != null)
1094 {
1095 ValueBinding vb = getValueBinding("sortColumn");
1096 if (vb != null && !vb.isReadOnly(context))
1097 {
1098 vb.setValue(context, sortColumn);
1099 }
1100
1101 vb = getValueBinding("sortAscending");
1102 if (vb != null && !vb.isReadOnly(context))
1103 {
1104 vb.setValue(context, sortAscending);
1105 }
1106 }
1107 }
1108
1109 _varDetailToggler = (String) values[12];
1110 _expandedNodes = (Map) values[13];
1111 _sortColumnIndex = values[14] != null ? ((Integer) values[14]).intValue() : -1;
1112 }
1113
1114 public _SerializableDataModel getSerializableDataModel()
1115 {
1116 DataModel dm = getDataModel();
1117 if (dm instanceof _SerializableDataModel)
1118 {
1119 return (_SerializableDataModel) dm;
1120 }
1121 return createSerializableDataModel();
1122 }
1123
1124
1125
1126
1127 private _SerializableDataModel createSerializableDataModel()
1128 {
1129 Object value = getValue();
1130 if (value == null)
1131 {
1132 return null;
1133 }
1134 else if (value instanceof DataModel)
1135 {
1136 return new _SerializableDataModel(getFirst(), getRows(), (DataModel) value);
1137 }
1138 else if (value instanceof List)
1139 {
1140 return new _SerializableListDataModel(getFirst(), getRows(), (List) value);
1141 }
1142
1143 else if (value instanceof Collection)
1144 {
1145 return new _SerializableListDataModel(getFirst(), getRows(), new ArrayList((Collection) value));
1146 }
1147 else if (OBJECT_ARRAY_CLASS.isAssignableFrom(value.getClass()))
1148 {
1149 return new _SerializableArrayDataModel(getFirst(), getRows(), (Object[]) value);
1150 }
1151 else if (value instanceof ResultSet)
1152 {
1153 return new _SerializableResultSetDataModel(getFirst(), getRows(), (ResultSet) value);
1154 }
1155 else if (value instanceof javax.servlet.jsp.jstl.sql.Result)
1156 {
1157 return new _SerializableResultDataModel(getFirst(), getRows(),
1158 (javax.servlet.jsp.jstl.sql.Result) value);
1159 }
1160 else
1161 {
1162 return new _SerializableScalarDataModel(getFirst(), getRows(), value);
1163 }
1164 }
1165
1166 public boolean isRendered()
1167 {
1168 if (!UserRoleUtils.isVisibleOnUserRole(this))
1169 return false;
1170 return super.isRendered();
1171 }
1172
1173 public void setForceIdIndexFormula(String forceIdIndexFormula)
1174 {
1175 _forceIdIndexFormula = forceIdIndexFormula;
1176 ValueBinding vb = getValueBinding("forceIdIndexFormula");
1177 if (vb != null)
1178 {
1179 vb.setValue(getFacesContext(), _forceIdIndexFormula);
1180 _forceIdIndexFormula = null;
1181 }
1182 }
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193 public String getForceIdIndexFormula()
1194 {
1195 if (_forceIdIndexFormula != null)
1196 return _forceIdIndexFormula;
1197 ValueBinding vb = getValueBinding("forceIdIndexFormula");
1198 if (vb == null)
1199 return null;
1200 Object eval = vb.getValue(getFacesContext());
1201 return eval == null ? null : eval.toString();
1202 }
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217 public void setSortColumn(String sortColumn)
1218 {
1219 _sortColumn = sortColumn;
1220
1221
1222 ValueBinding vb = getValueBinding("sortColumn");
1223 if (vb != null)
1224 {
1225 vb.setValue(getFacesContext(), _sortColumn);
1226 _sortColumn = null;
1227 }
1228
1229 setSortColumnIndex(columnNameToIndex(sortColumn));
1230 }
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243 public String getSortColumn()
1244 {
1245 if (_sortColumn != null) return _sortColumn;
1246 ValueBinding vb = getValueBinding("sortColumn");
1247 return vb != null ? (String) vb.getValue(getFacesContext()) : null;
1248 }
1249
1250 public void setSortAscending(boolean sortAscending)
1251 {
1252 _sortAscending = Boolean.valueOf(sortAscending);
1253
1254
1255 ValueBinding vb = getValueBinding("sortAscending");
1256 if (vb != null)
1257 {
1258 vb.setValue(getFacesContext(), _sortAscending);
1259 _sortAscending = null;
1260 }
1261 }
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275 public boolean isSortAscending()
1276 {
1277 if (_sortAscending != null)
1278 return _sortAscending.booleanValue();
1279 ValueBinding vb = getValueBinding("sortAscending");
1280 Boolean v = vb != null ? (Boolean) vb.getValue(getFacesContext()) : null;
1281 return v != null ? v.booleanValue() : DEFAULT_SORTASCENDING;
1282 }
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295 public void setSortProperty(String sortProperty)
1296 {
1297 _sortProperty = sortProperty;
1298 }
1299
1300
1301
1302
1303
1304
1305 public String getSortProperty()
1306 {
1307 return _sortProperty;
1308 }
1309
1310
1311
1312
1313
1314
1315
1316 public abstract boolean isSortable();
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331 public abstract boolean isEmbedded();
1332
1333
1334
1335
1336
1337
1338
1339 public abstract boolean isDetailStampExpandedDefault();
1340
1341
1342
1343
1344
1345
1346
1347
1348 public abstract String getDetailStampLocation();
1349
1350
1351
1352
1353
1354
1355 public abstract String getRowOnMouseOver();
1356
1357
1358
1359
1360
1361
1362 public abstract String getRowOnMouseOut();
1363
1364
1365
1366
1367
1368
1369 public abstract String getRowOnClick();
1370
1371
1372
1373
1374
1375
1376 public abstract String getRowOnDblClick();
1377
1378
1379
1380
1381
1382
1383 public abstract String getRowOnKeyDown();
1384
1385
1386
1387
1388
1389
1390 public abstract String getRowOnKeyPress();
1391
1392
1393
1394
1395
1396
1397 public abstract String getRowOnKeyUp();
1398
1399
1400
1401
1402
1403
1404 public String getRowStyleClass()
1405 {
1406 if (_rowStyleClass != null)
1407 return _rowStyleClass;
1408
1409
1410 ValueBinding vb = getValueBinding("org.apache.myfaces.dataTable.ROW_STYLECLASS");
1411 if (vb != null)
1412 log.warn("org.apache.myfaces.dataTable.ROW_STYLECLASS is deprecated. Please use rowStyleClass instead.");
1413 else
1414 vb = getValueBinding(JSFAttr.ROW_STYLECLASS_ATTR);
1415 if(vb == null)
1416 return null;
1417 String bindingValue = (String) vb.getValue(getFacesContext());
1418 if(bindingValue == "")
1419 return null;
1420 return bindingValue;
1421 }
1422
1423 public void setRowStyleClass(String rowStyleClass)
1424 {
1425 _rowStyleClass = rowStyleClass;
1426 }
1427
1428
1429
1430
1431
1432
1433 public String getRowStyle()
1434 {
1435 if (_rowStyle != null)
1436 return _rowStyle;
1437
1438
1439 ValueBinding vb = getValueBinding("org.apache.myfaces.dataTable.ROW_STYLE");
1440 if (vb != null)
1441 log.warn("org.apache.myfaces.dataTable.ROW_STYLE is deprecated. Please use rowStyle instead.");
1442 else
1443 vb = getValueBinding(JSFAttr.ROW_STYLE_ATTR);
1444 if(vb == null)
1445 return null;
1446 String bindingValue = (String) vb.getValue(getFacesContext());
1447 if(bindingValue == "")
1448 return null;
1449 return bindingValue;
1450 }
1451
1452 public void setRowStyle(String rowStyle)
1453 {
1454 _rowStyle = rowStyle;
1455 }
1456
1457
1458
1459
1460
1461
1462 public abstract String getRowOnMouseDown();
1463
1464
1465
1466
1467
1468
1469 public abstract String getRowOnMouseMove();
1470
1471
1472
1473
1474
1475
1476 public abstract String getRowOnMouseUp();
1477
1478
1479
1480
1481
1482 protected boolean isValidChildren()
1483 {
1484 return _isValidChildren;
1485 }
1486
1487 protected void setIsValidChildren(boolean isValidChildren)
1488 {
1489 _isValidChildren = isValidChildren;
1490 }
1491
1492 protected _SerializableDataModel getPreservedDataModel()
1493 {
1494 return _preservedDataModel;
1495 }
1496
1497 protected void setPreservedDataModel(_SerializableDataModel preservedDataModel)
1498 {
1499 _preservedDataModel = preservedDataModel;
1500 }
1501
1502
1503 public boolean isCurrentDetailExpanded()
1504 {
1505 Boolean expanded = (Boolean) _expandedNodes.get(getClientId(getFacesContext()));
1506 if (expanded != null)
1507 {
1508 return expanded.booleanValue();
1509 }
1510
1511 return isDetailStampExpandedDefault();
1512 }
1513
1514 public void setVarDetailToggler(String varDetailToggler)
1515 {
1516 _varDetailToggler = varDetailToggler;
1517 }
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527 public String getVarDetailToggler()
1528 {
1529 if (_varDetailToggler != null)
1530 return _varDetailToggler;
1531 ValueBinding vb = getValueBinding("varDetailToggler");
1532 return vb != null ? (String) vb.getValue(getFacesContext()) : null;
1533 }
1534
1535
1536
1537
1538
1539
1540 public abstract String getRowGroupStyle();
1541
1542
1543
1544
1545
1546
1547 public abstract String getRowGroupStyleClass();
1548
1549
1550
1551
1552
1553
1554 public abstract String getBodyStyle();
1555
1556
1557
1558
1559
1560
1561 public abstract String getBodyStyleClass();
1562
1563 public AbstractHtmlDataTable()
1564 {
1565 setRendererType(DEFAULT_RENDERER_TYPE);
1566 }
1567
1568
1569
1570
1571
1572 public void toggleDetail()
1573 {
1574 String derivedRowKey = getClientId(getFacesContext());
1575
1576
1577 boolean expanded = isDetailExpanded();
1578 if (expanded)
1579 {
1580
1581
1582 if (isDetailStampExpandedDefault())
1583 {
1584
1585 _expandedNodes.put(derivedRowKey, Boolean.FALSE);
1586 }
1587 else
1588 {
1589
1590 _expandedNodes.remove(derivedRowKey);
1591 }
1592 }
1593 else
1594 {
1595
1596
1597 if (isDetailStampExpandedDefault())
1598 {
1599
1600 _expandedNodes.remove(derivedRowKey);
1601 }
1602 else
1603 {
1604
1605 _expandedNodes.put(derivedRowKey, Boolean.TRUE);
1606 }
1607 }
1608 }
1609
1610
1611
1612
1613
1614
1615 public boolean isDetailExpanded()
1616 {
1617 Boolean expanded = (Boolean) _expandedNodes.get(getClientId(getFacesContext()));
1618 if (expanded == null)
1619 {
1620 return isDetailStampExpandedDefault();
1621 }
1622
1623 return expanded.booleanValue();
1624 }
1625
1626 public int getSortColumnIndex()
1627 {
1628 if (_sortColumnIndex == -1)
1629 _sortColumnIndex = columnNameToIndex(getSortColumn());
1630
1631 return _sortColumnIndex;
1632 }
1633
1634 public void setSortColumnIndex(int sortColumnIndex)
1635 {
1636 _sortColumnIndex = sortColumnIndex;
1637 }
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647 public abstract int getNewspaperColumns();
1648
1649
1650
1651
1652
1653
1654
1655
1656 public abstract String getNewspaperOrientation();
1657
1658
1659
1660
1661
1662
1663
1664 public UIComponent getSpacer()
1665 {
1666 return (UIComponent) getFacets().get(SPACER_FACET_NAME);
1667 }
1668
1669 public void setSpacer(UIComponent spacer)
1670 {
1671 getFacets().put(SPACER_FACET_NAME, spacer);
1672 }
1673
1674
1675
1676
1677 public void expandAllDetails()
1678 {
1679 int rowCount = getRowCount();
1680
1681 _expandedNodes.clear();
1682
1683 if (getRowKey() != null)
1684 {
1685 int oldRow = getRowIndex();
1686 try
1687 {
1688 for (int row = 0; row < rowCount; row++)
1689 {
1690 setRowIndex(row);
1691 _expandedNodes.put(getClientId(getFacesContext()), Boolean.TRUE);
1692 }
1693 }
1694 finally
1695 {
1696 setRowIndex(oldRow);
1697 }
1698 }
1699 else
1700 {
1701 for (int row = 0; row < rowCount; row++)
1702 {
1703 _expandedNodes.put(new Integer(row).toString(), Boolean.TRUE);
1704 }
1705 }
1706 }
1707
1708
1709
1710
1711 public void collapseAllDetails()
1712 {
1713 _expandedNodes.clear();
1714 }
1715
1716
1717
1718
1719 public boolean isExpandedEmpty()
1720 {
1721 boolean expandedEmpty = true;
1722 if (_expandedNodes != null)
1723 {
1724 expandedEmpty = _expandedNodes.isEmpty();
1725 }
1726 return expandedEmpty;
1727 }
1728
1729
1730
1731
1732
1733
1734 public void setExpandedEmpty(boolean expandedEmpty)
1735 {
1736 if (expandedEmpty)
1737 {
1738 if (_expandedNodes != null)
1739 {
1740 _expandedNodes.clear();
1741 }
1742 }
1743 }
1744
1745
1746
1747 public static final String COMPONENT_TYPE = "org.apache.myfaces.HtmlDataTable";
1748 public static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.Table";
1749
1750 private static final boolean DEFAULT_PRESERVEDATAMODEL = false;
1751 private static final boolean DEFAULT_PRESERVESORT = true;
1752 private static final boolean DEFAULT_RENDEREDIFEMPTY = true;
1753
1754 private Boolean _preserveDataModel = null;
1755 private Boolean _preserveSort = null;
1756
1757 public void setPreserveDataModel(boolean preserveDataModel)
1758 {
1759 _preserveDataModel = Boolean.valueOf(preserveDataModel);
1760 }
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776 public boolean isPreserveDataModel()
1777 {
1778 if (_preserveDataModel != null)
1779 return _preserveDataModel.booleanValue();
1780 ValueBinding vb = getValueBinding("preserveDataModel");
1781 Boolean v = vb != null ? (Boolean) vb.getValue(getFacesContext()) : null;
1782 return v != null ? v.booleanValue() : DEFAULT_PRESERVEDATAMODEL;
1783 }
1784
1785 public void setPreserveSort(boolean preserveSort)
1786 {
1787 _preserveSort = Boolean.valueOf(preserveSort);
1788 }
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798 public boolean isPreserveSort()
1799 {
1800 if (_preserveSort != null)
1801 return _preserveSort.booleanValue();
1802 ValueBinding vb = getValueBinding("preserveSort");
1803 Boolean v = vb != null ? (Boolean) vb.getValue(getFacesContext()) : null;
1804 return v != null ? v.booleanValue() : DEFAULT_PRESERVESORT;
1805 }
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822 public abstract boolean isRenderedIfEmpty();
1823
1824
1825
1826
1827
1828
1829
1830 public abstract String getRowIndexVar();
1831
1832
1833
1834
1835
1836
1837
1838 public abstract String getRowCountVar();
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849 public abstract String getPreviousRowDataVar();
1850
1851
1852
1853
1854
1855
1856
1857
1858 public abstract String getSortedColumnVar();
1859
1860
1861
1862
1863
1864
1865
1866 public abstract String getAlign();
1867
1868
1869
1870
1871
1872
1873 public abstract String getRowId();
1874
1875
1876
1877
1878
1879
1880 public abstract String getDatafld();
1881
1882
1883
1884
1885
1886
1887 public abstract String getDatasrc();
1888
1889
1890
1891
1892
1893
1894 public abstract String getDataformatas();
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904 public abstract String getValueType();
1905
1906 }