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.el.ValueExpression;
32 import javax.faces.FacesException;
33 import javax.faces.application.Application;
34 import javax.faces.component.ContextCallback;
35 import javax.faces.component.EditableValueHolder;
36 import javax.faces.component.UIColumn;
37 import javax.faces.component.UIComponent;
38 import javax.faces.component.UINamingContainer;
39 import javax.faces.component.UIPanel;
40 import javax.faces.component.visit.VisitCallback;
41 import javax.faces.component.visit.VisitContext;
42 import javax.faces.component.visit.VisitResult;
43 import javax.faces.context.FacesContext;
44 import javax.faces.model.DataModel;
45
46 import org.apache.commons.logging.Log;
47 import org.apache.commons.logging.LogFactory;
48 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
49 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFacet;
50 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
51 import org.apache.myfaces.component.NewspaperTable;
52 import org.apache.myfaces.component.UserRoleAware;
53 import org.apache.myfaces.component.UserRoleUtils;
54 import org.apache.myfaces.custom.column.HtmlSimpleColumn;
55 import org.apache.myfaces.custom.crosstable.UIColumns;
56 import org.apache.myfaces.custom.sortheader.HtmlCommandSortHeader;
57 import org.apache.myfaces.renderkit.html.ext.HtmlTableRenderer;
58 import org.apache.myfaces.renderkit.html.util.TableContext;
59 import org.apache.myfaces.shared_tomahawk.util.ClassUtils;
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83 @JSFComponent(
84 name = "t:dataTable",
85 clazz = "org.apache.myfaces.component.html.ext.HtmlDataTable",
86 tagClass = "org.apache.myfaces.generated.taglib.html.ext.HtmlDataTableTag",
87 tagHandler = "org.apache.myfaces.component.html.ext.HtmlDataTableTagHandler")
88 public abstract class AbstractHtmlDataTable extends HtmlDataTableHack implements UserRoleAware, NewspaperTable
89 {
90 private static final Log log = LogFactory.getLog(AbstractHtmlDataTable.class);
91
92 private static final int PROCESS_DECODES = 1;
93 private static final int PROCESS_VALIDATORS = 2;
94 private static final int PROCESS_UPDATES = 3;
95
96 private static final boolean DEFAULT_SORTASCENDING = true;
97 private static final boolean DEFAULT_SORTABLE = false;
98 private static final boolean DEFAULT_EMBEDDED = false;
99 private static final boolean DEFAULT_DETAILSTAMP_EXPANDED = false;
100 private static final Class OBJECT_ARRAY_CLASS = (new Object[0]).getClass();
101
102 private static final Integer DEFAULT_NEWSPAPER_COLUMNS = new Integer(1);
103 private static final String DEFAULT_NEWSPAPER_ORIENTATION = "vertical";
104 private static final String DEFAULT_DETAILSTAMP_LOCATION = "after";
105
106 private static final String SKIP_ITERATION_HINT = "javax.faces.visit.SKIP_ITERATION";
107
108
109
110 public static final String NEWSPAPER_COLUMNS_PROPERTY = "newspaperColumns";
111 public static final String SPACER_FACET_NAME = "spacer";
112 public static final String NEWSPAPER_ORIENTATION_PROPERTY = "newspaperOrientation";
113
114 public static final String DETAIL_STAMP_FACET_NAME = "detailStamp";
115
116 public static final String DETAIL_STAMP_ROW_FACET_NAME = "detailStampRow";
117
118 public static final String TABLE_ROW_FACET_NAME = "row";
119
120 private _SerializableDataModel _preservedDataModel;
121
122 private boolean _isValidChildren = true;
123
124 private Map<String, Boolean> _expandedNodes = new HashMap<String, Boolean>();
125
126
127
128 private TableContext _tableContext = null;
129
130 public TableContext getTableContext()
131 {
132 if (_tableContext == null)
133 {
134 _tableContext = new TableContext();
135 }
136 return _tableContext;
137 }
138
139 public void setDetailStamp(UIComponent facet)
140 {
141 getFacets().put(DETAIL_STAMP_FACET_NAME, facet);
142 }
143
144
145
146
147
148
149
150
151
152 public UIComponent getDetailStamp()
153 {
154 return (UIComponent) getFacets().get(DETAIL_STAMP_FACET_NAME);
155 }
156
157 @Override
158 public String getContainerClientId(FacesContext context)
159 {
160 String standardClientId = super.getContainerClientId(context);
161 int rowIndex = getRowIndex();
162 if (rowIndex == -1)
163 {
164 return standardClientId;
165 }
166
167 String forcedIdIndex = getForceIdIndexFormula();
168 if (forcedIdIndex == null || forcedIdIndex.length() == 0)
169 return standardClientId;
170
171
172
173 final String indexLessClientId = getClientId(context);
174
175
176 String parsedForcedClientId = indexLessClientId + forcedIdIndex;
177 return parsedForcedClientId;
178 }
179
180 public UIComponent findComponent(String expr)
181 {
182 if (expr.length() > 0 && Character.isDigit(expr.charAt(0)))
183 {
184 char separator = UINamingContainer.getSeparatorChar(getFacesContext());
185 int separatorIndex = expr.indexOf(separator);
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 @Override
221 public boolean invokeOnComponent(FacesContext context, String clientId,
222 ContextCallback callback) throws FacesException
223 {
224 if (context == null || clientId == null || callback == null)
225 {
226 throw new NullPointerException();
227 }
228
229 final String baseClientId = getClientId(context);
230
231
232 boolean returnValue = baseClientId.equals(clientId);
233
234 pushComponentToEL(context, this);
235 try
236 {
237 if (returnValue)
238 {
239 try
240 {
241 callback.invokeContextCallback(context, this);
242 return true;
243 }
244 catch (Exception e)
245 {
246 throw new FacesException(e);
247 }
248 }
249
250
251 for (Iterator<UIComponent> it = this.getFacets().values().iterator(); !returnValue && it.hasNext();)
252 {
253 returnValue = it.next().invokeOnComponent(context, clientId, callback);
254 }
255
256 if (returnValue)
257 {
258 return returnValue;
259 }
260
261
262 if (clientId.startsWith(baseClientId))
263 {
264
265
266 char separator = UINamingContainer.getSeparatorChar(context);
267
268 ValueExpression rowKeyVE = getValueExpression("rowKey");
269 boolean rowKeyFound = false;
270
271 if (rowKeyVE != null)
272 {
273 int oldRow = this.getRowIndex();
274 try
275 {
276
277 int rowsToProcess = getRows();
278
279 if (rowsToProcess == 0)
280 {
281 rowsToProcess = getRowCount();
282 }
283 int rowIndex = getFirst();
284 for (int rowsProcessed = 0; rowsProcessed < rowsToProcess; rowsProcessed++, rowIndex++)
285 {
286 setRowIndex(rowIndex);
287 if (!isRowAvailable())
288 {
289 break;
290 }
291
292 if (clientId.startsWith(getContainerClientId(context)))
293 {
294 rowKeyFound = true;
295 break;
296 }
297 }
298
299 if (rowKeyFound)
300 {
301 returnValue = invokeOnComponentTraverseRow(context, clientId, callback);
302 }
303 }
304 finally
305 {
306 this.setRowIndex(oldRow);
307 }
308 }
309 if (rowKeyVE == null && clientId.matches(baseClientId + separator+"[0-9]+"+separator+".*"))
310 {
311 String subId = clientId.substring(baseClientId.length() + 1);
312 String clientRow = subId.substring(0, subId.indexOf(separator));
313
314
315 int oldRow = this.getRowIndex();
316
317
318 try
319 {
320
321
322 this.setRowIndex(Integer.parseInt(clientRow));
323
324
325 if (!isRowAvailable())
326 {
327 return false;
328 }
329
330 returnValue = invokeOnComponentTraverseRow(context, clientId, callback);
331 }
332 finally
333 {
334
335
336 this.setRowIndex(oldRow);
337 }
338 }
339 else if (!rowKeyFound)
340 {
341
342
343
344
345
346 for (Iterator<UIComponent> itChildren = this.getChildren().iterator();
347 !returnValue && itChildren.hasNext();)
348 {
349 UIComponent child = itChildren.next();
350
351
352
353
354 if (child instanceof UIColumn && clientId.equals(child.getClientId(context)))
355 {
356 try {
357 callback.invokeContextCallback(context, child);
358 } catch (Exception e) {
359 throw new FacesException(e);
360 }
361 returnValue = true;
362 }
363
364 for (Iterator<UIComponent> itChildFacets = child.getFacets().values().iterator();
365 !returnValue && itChildFacets.hasNext();)
366 {
367
368 returnValue = itChildFacets.next().invokeOnComponent(context, clientId, callback);
369 }
370 }
371 }
372 }
373 }
374 finally
375 {
376
377 popComponentFromEL(context);
378 }
379
380 return returnValue;
381 }
382
383 private boolean invokeOnComponentTraverseRow(FacesContext context, String clientId,
384 ContextCallback callback)
385 {
386 boolean returnValue = false;
387 for (Iterator<UIComponent> it1 = getChildren().iterator();
388 !returnValue && it1.hasNext();)
389 {
390
391 returnValue = it1.next().invokeOnComponent(context, clientId, callback);
392 }
393
394 if (!returnValue)
395 {
396 UIComponent detailStampRowFacet = getFacet(DETAIL_STAMP_ROW_FACET_NAME);
397 if (detailStampRowFacet != null)
398 {
399 returnValue = detailStampRowFacet.invokeOnComponent(context, clientId, callback);
400 }
401 UIComponent detailStampFacet = getFacet(DETAIL_STAMP_FACET_NAME);
402 if (detailStampFacet != null)
403 {
404 returnValue = detailStampFacet.invokeOnComponent(context, clientId, callback);
405 }
406 UIComponent tableRowFacet = getFacet(TABLE_ROW_FACET_NAME);
407 if (tableRowFacet != null)
408 {
409 returnValue = tableRowFacet.invokeOnComponent(context, clientId, callback);
410 }
411 }
412 return returnValue;
413 }
414
415 public boolean visitTree(VisitContext context, VisitCallback callback)
416 {
417 if (!isVisitable(context))
418 {
419 return false;
420 }
421
422
423 int oldRowIndex = getRowIndex();
424
425 setRowIndex(-1);
426
427 pushComponentToEL(context.getFacesContext(), this);
428 try
429 {
430 VisitResult visitResult = context.invokeVisitCallback(this,
431 callback);
432 switch (visitResult)
433 {
434
435 case COMPLETE:
436 return true;
437
438 case REJECT:
439 return false;
440
441
442 default:
443
444 Collection<String> subtreeIdsToVisit = context
445 .getSubtreeIdsToVisit(this);
446 boolean doVisitChildren = subtreeIdsToVisit != null
447 && !subtreeIdsToVisit.isEmpty();
448 if (doVisitChildren)
449 {
450
451 for (UIComponent facet : getFacets().values())
452 {
453 if (facet.visitTree(context, callback))
454 {
455 return true;
456 }
457 }
458 Boolean skipIterationHint = (Boolean) context.getFacesContext().getAttributes().get(SKIP_ITERATION_HINT);
459 if (skipIterationHint != null && skipIterationHint.booleanValue())
460 {
461
462 if (getChildCount() > 0) {
463 for (UIComponent child : getChildren()) {
464 if (child.visitTree(context, callback)) {
465 return true;
466 }
467 }
468 }
469 }
470 else
471 {
472
473
474
475 for (UIComponent child : getChildren())
476 {
477 if (child instanceof UIColumn)
478 {
479 VisitResult columnResult = context.invokeVisitCallback(child, callback);
480 if (columnResult == VisitResult.COMPLETE)
481 {
482 return true;
483 }
484 for (UIComponent facet : child.getFacets().values())
485 {
486 if (facet.visitTree(context, callback))
487 {
488 return true;
489 }
490 }
491 }
492 }
493 boolean visitDetailStamp = (getFacet(DETAIL_STAMP_FACET_NAME) != null);
494 boolean visitDetailStampRow = (getFacet(DETAIL_STAMP_ROW_FACET_NAME) != null);
495 boolean visitTableRow = (getFacet(TABLE_ROW_FACET_NAME) != null);
496
497
498 int rowsToProcess = getRows();
499
500 if (rowsToProcess == 0)
501 {
502 rowsToProcess = getRowCount();
503 }
504 int rowIndex = getFirst();
505 for (int rowsProcessed = 0; rowsProcessed < rowsToProcess; rowsProcessed++, rowIndex++)
506 {
507 setRowIndex(rowIndex);
508 if (!isRowAvailable())
509 {
510 return false;
511 }
512
513 for (UIComponent child : getChildren())
514 {
515 if (child instanceof UIColumn)
516 {
517 for (UIComponent grandchild : child
518 .getChildren())
519 {
520 if (grandchild.visitTree(context, callback))
521 {
522 return true;
523 }
524 }
525 }
526 }
527 if (visitDetailStampRow)
528 {
529 UIComponent detailStampRowFacet = getFacet(DETAIL_STAMP_ROW_FACET_NAME);
530 if (detailStampRowFacet.visitTree(context, callback))
531 {
532 return true;
533 }
534 }
535 if (visitDetailStamp)
536 {
537 UIComponent detailStampFacet = getFacet(DETAIL_STAMP_FACET_NAME);
538 if (detailStampFacet.visitTree(context, callback))
539 {
540 return true;
541 }
542 }
543 if (visitTableRow)
544 {
545 UIComponent tableRowFacet = getFacet(TABLE_ROW_FACET_NAME);
546 if (tableRowFacet.visitTree(context, callback))
547 {
548 return true;
549 }
550 }
551 }
552 }
553 }
554 }
555 }
556 finally
557 {
558
559 popComponentFromEL(context.getFacesContext());
560 setRowIndex(oldRowIndex);
561 }
562
563
564 return false;
565 }
566
567 public void setRowIndex(int rowIndex)
568 {
569
570
571 if (rowIndex < -1)
572 {
573 throw new IllegalArgumentException("rowIndex is less than -1");
574 }
575
576
577
578
579
580
581
582
583
584
585 String rowIndexVar = getRowIndexVar();
586 String rowCountVar = getRowCountVar();
587 String previousRowDataVar = getPreviousRowDataVar();
588 if (rowIndexVar != null || rowCountVar != null || previousRowDataVar != null)
589 {
590 Map requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
591
592 if (previousRowDataVar != null && rowIndex >= 0)
593 {
594 if (isRowAvailable())
595 {
596
597 requestMap.put(previousRowDataVar, getRowData());
598 }
599 else
600 {
601
602 requestMap.put(previousRowDataVar, null);
603 }
604 }
605
606 super.setRowIndex(rowIndex);
607
608 if (rowIndex >= 0)
609 {
610
611 if (rowIndexVar != null)
612 {
613 requestMap.put(rowIndexVar, new Integer(rowIndex));
614 }
615
616 if (rowCountVar != null)
617 {
618 requestMap.put(rowCountVar, new Integer(getRowCount()));
619 }
620 }
621 else
622 {
623
624 if (rowIndexVar != null)
625 {
626 requestMap.remove(rowIndexVar);
627 }
628
629 if (rowCountVar != null)
630 {
631 requestMap.remove(rowCountVar);
632 }
633
634 if (previousRowDataVar != null)
635 {
636 requestMap.remove(previousRowDataVar);
637 }
638 }
639 }
640 else
641 {
642
643 super.setRowIndex(rowIndex);
644 }
645
646
647
648
649
650
651
652
653
654 UIComponent detailStampRowFacet = getFacet(DETAIL_STAMP_ROW_FACET_NAME);
655 if (detailStampRowFacet != null)
656 {
657 detailStampRowFacet.setId(detailStampRowFacet.getId());
658 }
659 UIComponent tableRowFacet = getFacet(TABLE_ROW_FACET_NAME);
660 if (tableRowFacet != null){
661 tableRowFacet.setId(tableRowFacet.getId());
662 }
663
664 if (getStateHelper().get(PropertyKeys.varDetailToggler) != null)
665 {
666 Map requestMap = getFacesContext().getExternalContext().getRequestMap();
667 requestMap.put(getStateHelper().get(PropertyKeys.varDetailToggler), this);
668 }
669 }
670
671 @Override
672 protected Object saveDescendantComponentStates()
673 {
674 if (getFacetCount() > 0)
675 {
676 UIComponent detailStampFacet = getFacet(DETAIL_STAMP_FACET_NAME);
677 if (detailStampFacet != null)
678 {
679 return saveDescendantComponentStates(new _DetailStampFacetAndChildrenIterator(detailStampFacet, getChildren()), false);
680 }
681 }
682 return super.saveDescendantComponentStates();
683 }
684
685 @Override
686 protected void restoreDescendantComponentStates(Object state)
687 {
688 if (getFacetCount() > 0)
689 {
690 UIComponent detailStampFacet = getFacet(DETAIL_STAMP_FACET_NAME);
691 if (detailStampFacet != null)
692 {
693 restoreDescendantComponentStates(new _DetailStampFacetAndChildrenIterator(detailStampFacet, getChildren()), state, false);
694 return;
695 }
696 }
697 super.restoreDescendantComponentStates(state);
698 }
699
700 @Override
701 protected void restoreFullDescendantComponentDeltaStates(FacesContext facesContext,
702 Map<String, Object> rowState, Object initialState)
703 {
704 if (getFacetCount() > 0)
705 {
706 UIComponent detailStampFacet = getFacet(DETAIL_STAMP_FACET_NAME);
707 if (detailStampFacet != null)
708 {
709 restoreFullDescendantComponentDeltaStates(facesContext, new _DetailStampFacetAndChildrenIterator(detailStampFacet, getChildren()), rowState, initialState, false, getContainerClientId(facesContext));
710 return;
711 }
712 }
713 super.restoreFullDescendantComponentDeltaStates(facesContext, rowState, initialState);
714 }
715
716 @Override
717 protected void restoreFullDescendantComponentStates(FacesContext facesContext,
718 Object initialState)
719 {
720 if (getFacetCount() > 0)
721 {
722 UIComponent detailStampFacet = getFacet(DETAIL_STAMP_FACET_NAME);
723 if (detailStampFacet != null)
724 {
725 restoreFullDescendantComponentStates(facesContext, new _DetailStampFacetAndChildrenIterator(detailStampFacet, getChildren()), initialState, false);
726 return;
727 }
728 }
729 super.restoreFullDescendantComponentStates(facesContext, initialState);
730 }
731
732 @Override
733 protected Collection<Object[]> saveDescendantInitialComponentStates(
734 FacesContext facesContext)
735 {
736 if (getFacetCount() > 0)
737 {
738 UIComponent detailStampFacet = getFacet(DETAIL_STAMP_FACET_NAME);
739 if (detailStampFacet != null)
740 {
741 return saveDescendantInitialComponentStates(facesContext, new _DetailStampFacetAndChildrenIterator(detailStampFacet, getChildren()), false);
742 }
743 }
744 return super.saveDescendantInitialComponentStates(facesContext);
745 }
746
747 @Override
748 protected Map<String,Object> saveFullDescendantComponentStates(FacesContext facesContext)
749 {
750 if (getFacetCount() > 0)
751 {
752 UIComponent detailStampFacet = getFacet(DETAIL_STAMP_FACET_NAME);
753 if (detailStampFacet != null)
754 {
755 return saveFullDescendantComponentStates(facesContext, null, new _DetailStampFacetAndChildrenIterator(detailStampFacet, getChildren()), false, getContainerClientId(facesContext));
756 }
757 }
758 return super.saveFullDescendantComponentStates(facesContext);
759 }
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834 public void processDecodes(FacesContext context)
835 {
836 if (!isRendered())
837 {
838 return;
839 }
840
841
842
843
844
845
846
847 setRowIndex(-1);
848 processFacets(context, PROCESS_DECODES);
849 processColumnFacets(context, PROCESS_DECODES);
850 processColumnChildren(context, PROCESS_DECODES);
851 setRowIndex(-1);
852 try
853 {
854 decode(context);
855 }
856 catch (RuntimeException e)
857 {
858 context.renderResponse();
859 throw e;
860 }
861
862 setRowIndex(-1);
863 processColumns(context, PROCESS_DECODES);
864 setRowIndex(-1);
865 processDetails(context, PROCESS_DECODES);
866 setRowIndex(-1);
867 }
868
869 private void processFacets(FacesContext context, int processAction)
870 {
871 for (Map.Entry<String, UIComponent> entry : getFacets().entrySet())
872 {
873 if (!DETAIL_STAMP_FACET_NAME.equals(entry.getKey()))
874 {
875 process(context, entry.getValue(), processAction);
876 }
877 }
878 }
879
880
881
882
883
884
885
886
887
888
889 private void processColumnFacets(FacesContext context, int processAction)
890 {
891 for (UIComponent child : getChildren())
892 {
893 if (child instanceof UIColumn)
894 {
895 if (!child.isRendered())
896 {
897
898 continue;
899 }
900
901 for (UIComponent facet : child.getFacets().values())
902 {
903 process(context, facet, processAction);
904 }
905 }
906 }
907 }
908
909
910
911
912
913
914
915
916
917
918 private void processColumnChildren(FacesContext context, int processAction)
919 {
920 int first = getFirst();
921 int rows = getRows();
922 int last;
923 if (rows == 0)
924 {
925 last = getRowCount();
926 }
927 else
928 {
929 last = first + rows;
930 }
931 for (int rowIndex = first; last == -1 || rowIndex < last; rowIndex++)
932 {
933 setRowIndex(rowIndex);
934
935
936 if (!isRowAvailable())
937 {
938 break;
939 }
940
941 for (UIComponent child : getChildren())
942 {
943 if (child instanceof UIColumn)
944 {
945 if (!child.isRendered())
946 {
947
948 continue;
949 }
950 for (UIComponent columnChild : child.getChildren())
951 {
952 process(context, columnChild, processAction);
953 }
954 }
955 }
956 }
957 }
958
959
960
961
962
963 private void processDetails(FacesContext context, int processAction)
964 {
965 UIComponent facet = getFacet(HtmlTableRenderer.DETAIL_STAMP_FACET_NAME);
966
967 if (facet != null)
968 {
969 int first = getFirst();
970 int rows = getRows();
971 int last;
972 if (rows == 0)
973 {
974 last = getRowCount();
975 }
976 else
977 {
978 last = first + rows;
979 }
980 for (int rowIndex = first; last == -1 || rowIndex < last; rowIndex++)
981 {
982 setRowIndex(rowIndex);
983
984
985 if (!isRowAvailable())
986 {
987 break;
988 }
989
990 if (!isCurrentDetailExpanded())
991 {
992 continue;
993 }
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013 if (PROCESS_DECODES == processAction)
1014 {
1015 resetAllSubmittedValues(facet);
1016 }
1017
1018 process(context, facet, processAction);
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033 }
1034 }
1035 }
1036
1037 private void resetAllSubmittedValues(UIComponent component)
1038 {
1039 if (component instanceof EditableValueHolder)
1040 {
1041 ((EditableValueHolder) component).setSubmittedValue(null);
1042 }
1043
1044 for (Iterator it = component.getFacetsAndChildren(); it.hasNext();)
1045 {
1046 resetAllSubmittedValues((UIComponent) it.next());
1047 }
1048 }
1049
1050
1051
1052
1053
1054 private void processColumns(FacesContext context, int processAction)
1055 {
1056 for (Iterator it = getChildren().iterator(); it.hasNext();)
1057 {
1058 UIComponent child = (UIComponent) it.next();
1059 if (child instanceof UIColumns)
1060 {
1061 process(context, child, processAction);
1062 }
1063 }
1064 }
1065
1066 private void process(FacesContext context, UIComponent component, int processAction)
1067 {
1068 switch (processAction)
1069 {
1070 case PROCESS_DECODES:
1071 component.processDecodes(context);
1072 break;
1073 case PROCESS_VALIDATORS:
1074 component.processValidators(context);
1075 break;
1076 case PROCESS_UPDATES:
1077 component.processUpdates(context);
1078 break;
1079 }
1080 }
1081
1082 public void processValidators(FacesContext context)
1083 {
1084 if (!isRendered())
1085 {
1086 return;
1087 }
1088
1089
1090
1091
1092
1093
1094 setRowIndex(-1);
1095 processFacets(context, PROCESS_VALIDATORS);
1096 processColumnFacets(context, PROCESS_VALIDATORS);
1097 processColumnChildren(context, PROCESS_VALIDATORS);
1098 setRowIndex(-1);
1099
1100 processColumns(context, PROCESS_VALIDATORS);
1101 setRowIndex(-1);
1102 processDetails(context, PROCESS_VALIDATORS);
1103 setRowIndex(-1);
1104
1105 if (context.getRenderResponse())
1106 {
1107 _isValidChildren = false;
1108 }
1109 }
1110
1111 public void processUpdates(FacesContext context)
1112 {
1113 if (!isRendered())
1114 {
1115 return;
1116 }
1117
1118
1119
1120
1121
1122
1123
1124
1125 setRowIndex(-1);
1126 processFacets(context, PROCESS_UPDATES);
1127 processColumnFacets(context, PROCESS_UPDATES);
1128 processColumnChildren(context, PROCESS_UPDATES);
1129 setRowIndex(-1);
1130
1131 processColumns(context, PROCESS_UPDATES);
1132 setRowIndex(-1);
1133 processDetails(context, PROCESS_UPDATES);
1134 setRowIndex(-1);
1135
1136 if (isPreserveDataModel())
1137 {
1138 updateModelFromPreservedDataModel(context);
1139 }
1140
1141 if (context.getRenderResponse())
1142 {
1143 _isValidChildren = false;
1144 }
1145 }
1146
1147 private void updateModelFromPreservedDataModel(FacesContext context)
1148 {
1149 ValueExpression vb = getValueExpression("value");
1150 if (vb != null && !vb.isReadOnly(context.getELContext()))
1151 {
1152 DataModel qdm = getDataModel();
1153 if (qdm instanceof _SerializableDataModel)
1154 {
1155 _SerializableDataModel dm = (_SerializableDataModel) qdm;
1156 Class type = (getValueType() == null) ?
1157 vb.getType(context.getELContext()) :
1158 ClassUtils.simpleClassForName(getValueType());
1159 Class dmType = dm.getClass();
1160 if (DataModel.class.isAssignableFrom(type))
1161 {
1162 vb.setValue(context.getELContext(), dm);
1163 }
1164 else if (List.class.isAssignableFrom(type) || _SerializableListDataModel.class.isAssignableFrom(dmType))
1165 {
1166 vb.setValue(context.getELContext(), dm.getWrappedData());
1167 }
1168 else if (OBJECT_ARRAY_CLASS.isAssignableFrom(type))
1169 {
1170 List lst = (List) dm.getWrappedData();
1171 vb.setValue(context.getELContext(), lst.toArray(new Object[lst.size()]));
1172 }
1173 else if (ResultSet.class.isAssignableFrom(type))
1174 {
1175 throw new UnsupportedOperationException(this.getClass().getName()
1176 + " UnsupportedOperationException");
1177 }
1178 else
1179 {
1180
1181 List lst = (List) dm.getWrappedData();
1182 if (lst!= null && lst.size() > 0)
1183 {
1184 vb.setValue(context.getELContext(), lst.get(0));
1185 }
1186 else
1187 {
1188 vb.setValue(context.getELContext(), null);
1189 }
1190 }
1191 }
1192 }
1193 _preservedDataModel = null;
1194 }
1195
1196 public void markInitialState()
1197 {
1198 if (isPreserveRowComponentState() || isRowStatePreserved())
1199 {
1200 if (getFacesContext().getAttributes().containsKey("javax.faces.view.ViewDeclarationLanguage.IS_BUILDING_INITIAL_STATE"))
1201 {
1202
1203 replaceColumnsWithCommandSortHeadersIfNeeded(getFacesContext());
1204 }
1205 }
1206 super.markInitialState();
1207 }
1208
1209 public void encodeBegin(FacesContext context) throws IOException
1210 {
1211 if (!isRendered())
1212 return;
1213
1214 if (_isValidChildren && !hasErrorMessages(context))
1215 {
1216 _preservedDataModel = null;
1217 }
1218
1219 for (Iterator iter = getChildren().iterator(); iter.hasNext();)
1220 {
1221 UIComponent component = (UIComponent) iter.next();
1222 if (component instanceof UIColumns)
1223 {
1224
1225
1226 ((UIColumns) component).encodeTableBegin(context);
1227 }
1228 }
1229
1230 replaceColumnsWithCommandSortHeadersIfNeeded(context);
1231
1232
1233
1234 super.encodeBegin(context);
1235 }
1236
1237 private void replaceColumnsWithCommandSortHeadersIfNeeded(FacesContext context)
1238 {
1239
1240
1241 for (Iterator iter = getChildren().iterator(); iter.hasNext();)
1242 {
1243 UIComponent component = (UIComponent) iter.next();
1244 if (component instanceof UIColumn)
1245 {
1246 UIColumn aColumn = (UIColumn) component;
1247 UIComponent headerFacet = aColumn.getHeader();
1248
1249 boolean replaceHeaderFacets = isSortable();
1250
1251 String columnName = null;
1252 String propertyName = null;
1253 boolean defaultSorted = false;
1254
1255 if (aColumn instanceof HtmlSimpleColumn)
1256 {
1257 HtmlSimpleColumn asColumn = (HtmlSimpleColumn) aColumn;
1258 propertyName = asColumn.getSortPropertyName();
1259 defaultSorted = asColumn.isDefaultSorted();
1260
1261 if (asColumn.isSortable())
1262 replaceHeaderFacets = true;
1263 }
1264
1265
1266 if (replaceHeaderFacets && isSortHeaderNeeded(aColumn, headerFacet))
1267 {
1268 propertyName = propertyName != null ? propertyName : getSortPropertyFromEL(aColumn);
1269 if (propertyName == null)
1270 log.warn("Couldn't determine sort property for column [" + aColumn.getId() + "].");
1271
1272 if (headerFacet instanceof UIPanel)
1273 {
1274
1275
1276
1277
1278 HtmlCommandSortHeader sortHeader = null;
1279 for (UIComponent childHeaderFacet : headerFacet.getChildren())
1280 {
1281 if (childHeaderFacet instanceof HtmlCommandSortHeader)
1282 {
1283 sortHeader = (HtmlCommandSortHeader) childHeaderFacet;
1284 break;
1285 }
1286 }
1287 if (sortHeader != null)
1288 {
1289 aColumn.getFacets().remove("header");
1290 aColumn.setHeader(sortHeader);
1291 headerFacet = sortHeader;
1292
1293
1294 columnName = sortHeader.getColumnName();
1295 propertyName = sortHeader.getPropertyName();
1296
1297
1298 if (propertyName == null)
1299 {
1300 propertyName = getSortPropertyFromEL(aColumn);
1301 sortHeader.setPropertyName(propertyName);
1302 }
1303
1304 if (propertyName == null)
1305 log.warn("Couldn't determine sort property for column [" + aColumn.getId() + "].");
1306 }
1307 }
1308 if (headerFacet != null && isSortHeaderNeeded(aColumn, headerFacet))
1309 {
1310
1311
1312 aColumn.getFacets().remove("header");
1313
1314 HtmlCommandSortHeader sortHeader = createSortHeaderComponent(context, aColumn, headerFacet, propertyName);
1315 columnName = sortHeader.getColumnName();
1316
1317 aColumn.setHeader(sortHeader);
1318
1319
1320 }
1321 }
1322 else if (headerFacet instanceof HtmlCommandSortHeader)
1323 {
1324
1325 HtmlCommandSortHeader sortHeader = (HtmlCommandSortHeader) headerFacet;
1326 columnName = sortHeader.getColumnName();
1327 propertyName = sortHeader.getPropertyName();
1328
1329
1330 if (propertyName == null)
1331 {
1332 propertyName = getSortPropertyFromEL(aColumn);
1333 sortHeader.setPropertyName(propertyName);
1334 }
1335
1336 if (propertyName == null)
1337 log.warn("Couldn't determine sort property for column [" + aColumn.getId() + "].");
1338 }
1339
1340
1341
1342
1343 String sortColumn = getSortColumn();
1344 if (defaultSorted && (sortColumn == null ? true : sortColumn.length() == 0))
1345 {
1346 setSortColumn(columnName);
1347 setSortProperty(propertyName);
1348 }
1349 }
1350 }
1351 }
1352
1353
1354
1355
1356 protected boolean isSortHeaderNeeded(UIColumn parentColumn, UIComponent headerFacet)
1357 {
1358 return !(headerFacet instanceof HtmlCommandSortHeader);
1359 }
1360
1361
1362
1363
1364 protected HtmlCommandSortHeader createSortHeaderComponent(FacesContext context, UIColumn parentColumn, UIComponent initialHeaderFacet, String propertyName)
1365 {
1366 Application application = context.getApplication();
1367
1368 HtmlCommandSortHeader sortHeader = (HtmlCommandSortHeader) application.createComponent(HtmlCommandSortHeader.COMPONENT_TYPE);
1369 String id = context.getViewRoot().createUniqueId();
1370 sortHeader.setId(id);
1371 sortHeader.setColumnName(id);
1372 sortHeader.setPropertyName(propertyName);
1373 sortHeader.setArrow(true);
1374 sortHeader.setImmediate(true);
1375 sortHeader.getChildren().add(initialHeaderFacet);
1376 initialHeaderFacet.setParent(sortHeader);
1377
1378 return sortHeader;
1379 }
1380
1381
1382
1383
1384 protected String getSortPropertyFromEL(UIComponent component)
1385 {
1386 if (getVar() == null)
1387 {
1388 log.warn("There is no 'var' specified on the dataTable, sort properties cannot be determined automaticaly.");
1389 return null;
1390 }
1391
1392 for (Iterator<UIComponent> iter = component.getChildren().iterator(); iter.hasNext();)
1393 {
1394 UIComponent aChild = (UIComponent) iter.next();
1395 if (aChild.isRendered())
1396 {
1397 ValueExpression vb = aChild.getValueExpression("value");
1398 if (vb != null)
1399 {
1400 String expressionString = vb.getExpressionString();
1401
1402 int varIndex = expressionString.indexOf(getVar() + ".");
1403 if (varIndex != -1)
1404 {
1405 int varEndIndex = varIndex + getVar().length();
1406 String tempProp = expressionString.substring(varEndIndex + 1, expressionString.length());
1407
1408 StringTokenizer tokenizer = new StringTokenizer(tempProp, " +[]{}-/*|?:&<>!=()%");
1409 if (tokenizer.hasMoreTokens())
1410 return tokenizer.nextToken();
1411 }
1412 }
1413 else
1414 {
1415 String sortProperty = getSortPropertyFromEL(aChild);
1416 if (sortProperty != null)
1417 return sortProperty;
1418 }
1419 }
1420 }
1421
1422 return null;
1423 }
1424
1425
1426
1427
1428 protected int columnNameToIndex(String columnName)
1429 {
1430 int index = 0;
1431 for (Iterator<UIComponent> iter = getChildren().iterator(); iter.hasNext();)
1432 {
1433 UIComponent aChild = (UIComponent) iter.next();
1434 if (aChild instanceof UIColumn)
1435 {
1436 UIComponent headerFacet = ((UIColumn) aChild).getHeader();
1437 if (headerFacet != null && headerFacet instanceof HtmlCommandSortHeader)
1438 {
1439 HtmlCommandSortHeader sortHeader = (HtmlCommandSortHeader) headerFacet;
1440 if (columnName != null && columnName.length()>0 && columnName.equals(sortHeader.getColumnName()))
1441 return index;
1442 }
1443 }
1444
1445 index += 1;
1446 }
1447
1448 return -1;
1449 }
1450
1451
1452
1453
1454 public void encodeEnd(FacesContext context) throws IOException
1455 {
1456 super.encodeEnd(context);
1457 for (Iterator<UIComponent> iter = getChildren().iterator(); iter.hasNext();)
1458 {
1459 UIComponent component = (UIComponent) iter.next();
1460 if (component instanceof UIColumns)
1461 {
1462 ((UIColumns) component).encodeTableEnd(context);
1463 }
1464 }
1465 }
1466
1467
1468
1469
1470
1471 @JSFProperty
1472 public int getFirst()
1473 {
1474 if (_preservedDataModel != null)
1475 {
1476
1477 return _preservedDataModel.getFirst();
1478 }
1479 else
1480 {
1481 return super.getFirst();
1482 }
1483 }
1484
1485 public void setFirst(int first)
1486 {
1487 if (_preservedDataModel != null)
1488 {
1489
1490 _preservedDataModel.setFirst(first);
1491 }
1492 super.setFirst(first);
1493 }
1494
1495
1496
1497
1498
1499 @JSFProperty
1500 public int getRows()
1501 {
1502 if (_preservedDataModel != null)
1503 {
1504
1505 return _preservedDataModel.getRows();
1506 }
1507 else
1508 {
1509 return super.getRows();
1510 }
1511 }
1512
1513 public void setRows(int rows)
1514 {
1515 if (_preservedDataModel != null)
1516 {
1517
1518 _preservedDataModel.setRows(rows);
1519 }
1520 super.setRows(rows);
1521 }
1522
1523 public Object saveState(FacesContext context)
1524 {
1525 boolean preserveSort = isPreserveSort();
1526
1527 if (initialStateMarked())
1528 {
1529 Object parentSaved = super.saveState(context);
1530 boolean preserveDataModel = isPreserveDataModel();
1531
1532 if (parentSaved == null && !preserveSort
1533 && !preserveDataModel && isExpandedEmpty())
1534 {
1535
1536 return null;
1537 }
1538
1539 Object[] values = new Object[5];
1540 values[0] = parentSaved;
1541
1542 if (isPreserveDataModel())
1543 {
1544 _preservedDataModel = getSerializableDataModel();
1545 values[1] = saveAttachedState(context, _preservedDataModel);
1546 }
1547 else
1548 {
1549 values[1] = null;
1550 }
1551
1552 values[2] = preserveSort ? getSortColumn() : null;
1553 values[3] = preserveSort ? Boolean.valueOf(isSortAscending()) : null;
1554 values[4] = _expandedNodes;
1555 return values;
1556 }
1557 else
1558 {
1559 Object[] values = new Object[5];
1560 values[0] = super.saveState(context);
1561
1562 if (isPreserveDataModel())
1563 {
1564 _preservedDataModel = getSerializableDataModel();
1565 values[1] = saveAttachedState(context, _preservedDataModel);
1566 }
1567 else
1568 {
1569 values[1] = null;
1570 }
1571
1572 values[2] = preserveSort ? getSortColumn() : null;
1573 values[3] = preserveSort ? Boolean.valueOf(isSortAscending()) : null;
1574 values[4] = _expandedNodes;
1575
1576 return values;
1577 }
1578 }
1579
1580
1581
1582
1583 protected DataModel getDataModel()
1584 {
1585 if (_preservedDataModel != null)
1586 {
1587 setDataModel(_preservedDataModel);
1588 _preservedDataModel = null;
1589 }
1590
1591 return super.getDataModel();
1592 }
1593
1594
1595
1596
1597 protected DataModel createDataModel()
1598 {
1599 DataModel dataModel = super.createDataModel();
1600
1601 boolean isSortable = isSortable();
1602
1603 if (!(dataModel instanceof SortableModel))
1604 {
1605
1606
1607
1608 for (Iterator iter = getChildren().iterator(); iter.hasNext();)
1609 {
1610 UIComponent component = (UIComponent) iter.next();
1611 if (component instanceof HtmlSimpleColumn)
1612 {
1613 HtmlSimpleColumn aColumn = (HtmlSimpleColumn) component;
1614 if (isSortable())
1615 aColumn.setSortable(true);
1616
1617 if (aColumn.isSortable())
1618 isSortable = true;
1619
1620 String sortColumn = getSortColumn();
1621
1622 if (aColumn.isDefaultSorted() && (sortColumn == null ? true : sortColumn.length() == 0))
1623 setSortProperty(aColumn.getSortPropertyName());
1624 }
1625 }
1626
1627 if (isSortable)
1628 dataModel = new SortableModel(dataModel);
1629 }
1630
1631 if (isSortable && getSortProperty() != null)
1632 {
1633 SortCriterion criterion = new SortCriterion(getSortProperty(), isSortAscending());
1634 List criteria = new ArrayList();
1635 criteria.add(criterion);
1636
1637 ((SortableModel) dataModel).setSortCriteria(criteria);
1638 }
1639
1640 return dataModel;
1641 }
1642
1643 public void restoreState(FacesContext context, Object state)
1644 {
1645 if (state == null)
1646 {
1647 return;
1648 }
1649
1650 Object[] values = (Object[]) state;
1651 super.restoreState(context, values[0]);
1652 if (isPreserveDataModel())
1653 {
1654 _preservedDataModel = (_SerializableDataModel) restoreAttachedState(context, values[1]);
1655 }
1656 else
1657 {
1658 _preservedDataModel = null;
1659 }
1660
1661 if (isPreserveSort())
1662 {
1663 String sortColumn = (String) values[2];
1664 Boolean sortAscending = (Boolean) values[3];
1665 if (sortColumn != null && sortAscending != null)
1666 {
1667 ValueExpression vb = getValueExpression("sortColumn");
1668 if (vb != null && !vb.isReadOnly(context.getELContext()))
1669 {
1670 vb.setValue(context.getELContext(), sortColumn);
1671 }
1672
1673 vb = getValueExpression("sortAscending");
1674 if (vb != null && !vb.isReadOnly(context.getELContext()))
1675 {
1676 vb.setValue(context.getELContext(), sortAscending);
1677 }
1678 }
1679 }
1680
1681 _expandedNodes = (Map) values[4];
1682 }
1683
1684 public _SerializableDataModel getSerializableDataModel()
1685 {
1686 DataModel dm = getDataModel();
1687 if (dm instanceof _SerializableDataModel)
1688 {
1689 return (_SerializableDataModel) dm;
1690 }
1691 return createSerializableDataModel();
1692 }
1693
1694
1695
1696
1697 private _SerializableDataModel createSerializableDataModel()
1698 {
1699 Object value = getValue();
1700 if (value == null)
1701 {
1702 return null;
1703 }
1704 else if (value instanceof DataModel)
1705 {
1706 return new _SerializableDataModel(getFirst(), getRows(), (DataModel) value);
1707 }
1708 else if (value instanceof List)
1709 {
1710 return new _SerializableListDataModel(getFirst(), getRows(), (List) value);
1711 }
1712
1713 else if (value instanceof Collection)
1714 {
1715 return new _SerializableListDataModel(getFirst(), getRows(), new ArrayList((Collection) value));
1716 }
1717 else if (OBJECT_ARRAY_CLASS.isAssignableFrom(value.getClass()))
1718 {
1719 return new _SerializableArrayDataModel(getFirst(), getRows(), (Object[]) value);
1720 }
1721 else if (value instanceof ResultSet)
1722 {
1723 return new _SerializableResultSetDataModel(getFirst(), getRows(), (ResultSet) value);
1724 }
1725 else if (value instanceof javax.servlet.jsp.jstl.sql.Result)
1726 {
1727 return new _SerializableResultDataModel(getFirst(), getRows(),
1728 (javax.servlet.jsp.jstl.sql.Result) value);
1729 }
1730 else
1731 {
1732 return new _SerializableScalarDataModel(getFirst(), getRows(), value);
1733 }
1734 }
1735
1736 public boolean isRendered()
1737 {
1738 if (!UserRoleUtils.isVisibleOnUserRole(this))
1739 return false;
1740 return super.isRendered();
1741 }
1742
1743 public void setForceIdIndexFormula(String forceIdIndexFormula)
1744 {
1745 getStateHelper().put(PropertyKeys.forceIdIndexFormula, forceIdIndexFormula);
1746 ValueExpression vb = getValueExpression("forceIdIndexFormula");
1747 if (vb != null)
1748 {
1749 vb.setValue(getFacesContext().getELContext(), forceIdIndexFormula);
1750 getStateHelper().put(PropertyKeys.forceIdIndexFormula, null);
1751 }
1752 }
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762 @JSFProperty
1763 public String getForceIdIndexFormula()
1764 {
1765 return (String) getStateHelper().eval(PropertyKeys.forceIdIndexFormula);
1766 }
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781 public void setSortColumn(String sortColumn)
1782 {
1783 getStateHelper().put(PropertyKeys.sortColumn, sortColumn);
1784
1785
1786 ValueExpression vb = getValueExpression("sortColumn");
1787 if (vb != null)
1788 {
1789 vb.setValue(getFacesContext().getELContext(), sortColumn);
1790 getStateHelper().put(PropertyKeys.sortColumn, null);
1791 }
1792
1793 setSortColumnIndex(columnNameToIndex(sortColumn));
1794 }
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806 @JSFProperty
1807 public String getSortColumn()
1808 {
1809 return (String) getStateHelper().eval(PropertyKeys.sortColumn);
1810 }
1811
1812 public void setSortAscending(boolean sortAscending)
1813 {
1814 getStateHelper().put(PropertyKeys.sortAscending, sortAscending);
1815
1816
1817
1818 ValueExpression vb = getValueExpression("sortAscending");
1819 if (vb != null)
1820 {
1821 vb.setValue(getFacesContext().getELContext(), sortAscending);
1822 getStateHelper().put(PropertyKeys.sortAscending, null);
1823 }
1824 }
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836 @JSFProperty(defaultValue="true")
1837 public boolean isSortAscending()
1838 {
1839 return (Boolean) getStateHelper().eval(PropertyKeys.sortAscending, DEFAULT_SORTASCENDING);
1840 }
1841
1842 public abstract void setSortProperty(String sortProperty);
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855 @JSFProperty(literalOnly=true,tagExcluded=true)
1856 public abstract String getSortProperty();
1857
1858
1859
1860
1861
1862 @JSFProperty(defaultValue="false")
1863 public abstract boolean isSortable();
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876 @JSFProperty(defaultValue="false")
1877 public abstract boolean isEmbedded();
1878
1879
1880
1881
1882
1883 @JSFProperty(defaultValue="false")
1884 public abstract boolean isDetailStampExpandedDefault();
1885
1886
1887
1888
1889
1890
1891 @JSFProperty(defaultValue="after")
1892 public abstract String getDetailStampLocation();
1893
1894
1895
1896
1897
1898 @JSFProperty(clientEvent="rowMouseOver")
1899 public abstract String getRowOnMouseOver();
1900
1901
1902
1903
1904
1905 @JSFProperty(clientEvent="rowMouseOut")
1906 public abstract String getRowOnMouseOut();
1907
1908
1909
1910
1911
1912 @JSFProperty(clientEvent="rowClick")
1913 public abstract String getRowOnClick();
1914
1915
1916
1917
1918
1919 @JSFProperty(clientEvent="rowDblClick")
1920 public abstract String getRowOnDblClick();
1921
1922
1923
1924
1925
1926 @JSFProperty(clientEvent="rowKeyDown")
1927 public abstract String getRowOnKeyDown();
1928
1929
1930
1931
1932
1933 @JSFProperty(clientEvent="rowKeyPress")
1934 public abstract String getRowOnKeyPress();
1935
1936
1937
1938
1939
1940 @JSFProperty(clientEvent="rowKeyUp")
1941 public abstract String getRowOnKeyUp();
1942
1943
1944
1945
1946
1947 @JSFProperty
1948 public abstract String getRowStyleClass();
1949
1950
1951
1952
1953
1954 @JSFProperty
1955 public abstract String getRowStyle();
1956
1957
1958
1959
1960
1961 @JSFProperty(clientEvent="rowMouseDown")
1962 public abstract String getRowOnMouseDown();
1963
1964
1965
1966
1967
1968 @JSFProperty(clientEvent="rowMouseMove")
1969 public abstract String getRowOnMouseMove();
1970
1971
1972
1973
1974
1975 @JSFProperty(clientEvent="rowMouseUp")
1976 public abstract String getRowOnMouseUp();
1977
1978
1979
1980 @JSFProperty(tagExcluded=true)
1981 protected boolean isValidChildren()
1982 {
1983 return _isValidChildren;
1984 }
1985
1986 protected void setIsValidChildren(boolean isValidChildren)
1987 {
1988 _isValidChildren = isValidChildren;
1989 }
1990
1991 protected _SerializableDataModel getPreservedDataModel()
1992 {
1993 return _preservedDataModel;
1994 }
1995
1996 protected void setPreservedDataModel(_SerializableDataModel preservedDataModel)
1997 {
1998 _preservedDataModel = preservedDataModel;
1999 }
2000
2001
2002 public boolean isCurrentDetailExpanded()
2003 {
2004 Boolean expanded = (Boolean) _expandedNodes.get(getContainerClientId(getFacesContext()));
2005 if (expanded != null)
2006 {
2007 return expanded.booleanValue();
2008 }
2009
2010 return isDetailStampExpandedDefault();
2011 }
2012
2013 public void setVarDetailToggler(String varDetailToggler)
2014 {
2015 getStateHelper().put(PropertyKeys.varDetailToggler, varDetailToggler );
2016 }
2017
2018
2019
2020
2021
2022
2023
2024
2025 @JSFProperty
2026 public String getVarDetailToggler()
2027 {
2028 return (String) getStateHelper().eval(PropertyKeys.varDetailToggler);
2029 }
2030
2031
2032
2033
2034
2035 @JSFProperty
2036 public abstract String getRowGroupStyle();
2037
2038
2039
2040
2041
2042 @JSFProperty
2043 public abstract String getRowGroupStyleClass();
2044
2045
2046
2047
2048
2049 @JSFProperty
2050 public abstract String getBodyStyle();
2051
2052
2053
2054
2055
2056 @JSFProperty
2057 public abstract String getBodyStyleClass();
2058
2059 public AbstractHtmlDataTable()
2060 {
2061 setRendererType(DEFAULT_RENDERER_TYPE);
2062 }
2063
2064
2065
2066
2067
2068 public void toggleDetail()
2069 {
2070 String derivedRowKey = getContainerClientId(getFacesContext());
2071
2072
2073 boolean expanded = isDetailExpanded();
2074 if (expanded)
2075 {
2076
2077
2078 if (isDetailStampExpandedDefault())
2079 {
2080
2081 _expandedNodes.put(derivedRowKey, Boolean.FALSE);
2082 }
2083 else
2084 {
2085
2086 _expandedNodes.remove(derivedRowKey);
2087 }
2088 }
2089 else
2090 {
2091
2092
2093 if (isDetailStampExpandedDefault())
2094 {
2095
2096 _expandedNodes.remove(derivedRowKey);
2097 }
2098 else
2099 {
2100
2101 _expandedNodes.put(derivedRowKey, Boolean.TRUE);
2102 }
2103 }
2104 }
2105
2106
2107
2108
2109
2110
2111 public boolean isDetailExpanded()
2112 {
2113 Boolean expanded = (Boolean) _expandedNodes.get(getContainerClientId(getFacesContext()));
2114 if (expanded == null)
2115 {
2116 return isDetailStampExpandedDefault();
2117 }
2118
2119 return expanded.booleanValue();
2120 }
2121
2122 public int getSortColumnIndex()
2123 {
2124 Integer sortColumnIndex = (Integer) getStateHelper().get(PropertyKeys.sortColumnIndex);
2125 if (sortColumnIndex == null)
2126 {
2127
2128 sortColumnIndex = -1;
2129 }
2130 if (sortColumnIndex == -1)
2131 sortColumnIndex = columnNameToIndex(getSortColumn());
2132
2133 return sortColumnIndex;
2134 }
2135
2136 public void setSortColumnIndex(int sortColumnIndex)
2137 {
2138 getStateHelper().put(PropertyKeys.sortColumnIndex, sortColumnIndex );
2139 }
2140
2141
2142
2143
2144
2145
2146
2147 @JSFProperty(defaultValue="1")
2148 public abstract int getNewspaperColumns();
2149
2150
2151
2152
2153
2154
2155 @JSFProperty(defaultValue = "vertical")
2156 public abstract String getNewspaperOrientation();
2157
2158
2159
2160
2161
2162 @JSFFacet
2163 public UIComponent getSpacer()
2164 {
2165 return (UIComponent) getFacets().get(SPACER_FACET_NAME);
2166 }
2167
2168 public void setSpacer(UIComponent spacer)
2169 {
2170 getFacets().put(SPACER_FACET_NAME, spacer);
2171 }
2172
2173
2174
2175
2176 public void expandAllDetails()
2177 {
2178 int rowCount = getRowCount();
2179
2180 _expandedNodes.clear();
2181
2182 if (getRowKey() != null)
2183 {
2184 int oldRow = getRowIndex();
2185 try
2186 {
2187 for (int row = 0; row < rowCount; row++)
2188 {
2189 setRowIndex(row);
2190 _expandedNodes.put(getContainerClientId(getFacesContext()), Boolean.TRUE);
2191 }
2192 }
2193 finally
2194 {
2195 setRowIndex(oldRow);
2196 }
2197 }
2198 else
2199 {
2200 for (int row = 0; row < rowCount; row++)
2201 {
2202 _expandedNodes.put(new Integer(row).toString(), Boolean.TRUE);
2203 }
2204 }
2205 }
2206
2207
2208
2209
2210 public void collapseAllDetails()
2211 {
2212 _expandedNodes.clear();
2213 }
2214
2215
2216
2217
2218 public boolean isExpandedEmpty()
2219 {
2220 boolean expandedEmpty = true;
2221 if (_expandedNodes != null)
2222 {
2223 expandedEmpty = _expandedNodes.isEmpty();
2224 }
2225 return expandedEmpty;
2226 }
2227
2228
2229
2230
2231
2232
2233 public void setExpandedEmpty(boolean expandedEmpty)
2234 {
2235 if (expandedEmpty)
2236 {
2237 if (_expandedNodes != null)
2238 {
2239 _expandedNodes.clear();
2240 }
2241 }
2242 }
2243
2244
2245
2246 public static final String COMPONENT_TYPE = "org.apache.myfaces.HtmlDataTable";
2247 public static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.Table";
2248
2249 private static final boolean DEFAULT_PRESERVEDATAMODEL = false;
2250 private static final boolean DEFAULT_PRESERVESORT = true;
2251 private static final boolean DEFAULT_RENDEREDIFEMPTY = true;
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267 @JSFProperty
2268 public abstract boolean isPreserveDataModel();
2269
2270
2271
2272
2273
2274
2275
2276 @JSFProperty(defaultValue = "true")
2277 public abstract boolean isPreserveSort();
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292 @JSFProperty(defaultValue = "true")
2293 public abstract boolean isRenderedIfEmpty();
2294
2295
2296
2297
2298
2299
2300 @JSFProperty
2301 public abstract String getRowIndexVar();
2302
2303
2304
2305
2306
2307
2308 @JSFProperty
2309 public abstract String getRowCountVar();
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319 @JSFProperty
2320 public abstract String getPreviousRowDataVar();
2321
2322
2323
2324
2325
2326
2327
2328 @JSFProperty
2329 public abstract String getSortedColumnVar();
2330
2331
2332
2333
2334
2335
2336 @JSFProperty
2337 public abstract String getAlign();
2338
2339
2340
2341
2342
2343 @JSFProperty
2344 public abstract String getRowId();
2345
2346
2347
2348
2349
2350 @JSFProperty
2351 public abstract String getDatafld();
2352
2353
2354
2355
2356
2357 @JSFProperty
2358 public abstract String getDatasrc();
2359
2360
2361
2362
2363
2364 @JSFProperty
2365 public abstract String getDataformatas();
2366
2367
2368
2369
2370
2371
2372
2373
2374 @JSFProperty
2375 public abstract String getValueType();
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387 @JSFProperty(defaultValue="false")
2388 public abstract boolean isAjaxRowRender();
2389
2390 protected enum PropertyKeys
2391 {
2392 preservedDataModel
2393 , forceIdIndexFormula
2394 , sortColumn
2395 , sortAscending
2396 , varDetailToggler
2397 , expandedNodes
2398 , sortColumnIndex
2399 }
2400 }