1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package javax.faces.component;
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
30 import javax.faces.application.FacesMessage;
31 import javax.faces.context.FacesContext;
32 import javax.faces.el.ValueBinding;
33 import javax.faces.event.AbortProcessingException;
34 import javax.faces.event.FacesEvent;
35 import javax.faces.event.FacesListener;
36 import javax.faces.event.PhaseId;
37 import javax.faces.model.ArrayDataModel;
38 import javax.faces.model.DataModel;
39 import javax.faces.model.ListDataModel;
40 import javax.faces.model.ResultDataModel;
41 import javax.faces.model.ResultSetDataModel;
42 import javax.faces.model.ScalarDataModel;
43 import javax.servlet.jsp.jstl.sql.Result;
44
45
46
47
48
49
50
51
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134 public class UIData extends UIComponentBase implements NamingContainer
135 {
136 public static final String COMPONENT_TYPE = "javax.faces.Data";
137 public static final String COMPONENT_FAMILY = "javax.faces.Data";
138 private static final String DEFAULT_RENDERER_TYPE = "javax.faces.Table";
139 private static final int DEFAULT_FIRST = 0;
140 private static final int DEFAULT_ROWS = 0;
141
142 private static final int STATE_SIZE = 5;
143 private static final int SUPER_STATE_INDEX = 0;
144 private static final int FIRST_STATE_INDEX = 1;
145 private static final int ROWS_STATE_INDEX = 2;
146 private static final int VALUE_STATE_INDEX = 3;
147 private static final int VAR_STATE_INDEX = 4;
148
149 private static final String FOOTER_FACET_NAME = "footer";
150 private static final String HEADER_FACET_NAME = "header";
151 private static final Class OBJECT_ARRAY_CLASS = (new Object[0]).getClass();
152 private static final int PROCESS_DECODES = 1;
153 private static final int PROCESS_VALIDATORS = 2;
154 private static final int PROCESS_UPDATES = 3;
155
156 private Integer _first = null;
157 private Integer _rows = null;
158 private Object _value = null;
159
160 private int _rowIndex = -1;
161 private String _var = null;
162
163
164
165
166 private Map _rowStates = new HashMap();
167
168
169
170
171
172
173
174
175 private Map _dataModelMap = new HashMap();
176
177
178 private boolean _isValidChilds = true;
179
180 private Object _initialDescendantComponentState = null;
181
182 public void setFooter(UIComponent footer)
183 {
184 getFacets().put(FOOTER_FACET_NAME, footer);
185 }
186
187
188
189
190 public UIComponent getFooter()
191 {
192 return (UIComponent) getFacets().get(FOOTER_FACET_NAME);
193 }
194
195 public void setHeader(UIComponent header)
196 {
197 getFacets().put(HEADER_FACET_NAME, header);
198 }
199
200
201
202
203 public UIComponent getHeader()
204 {
205 return (UIComponent) getFacets().get(HEADER_FACET_NAME);
206 }
207
208 public boolean isRowAvailable()
209 {
210 return getDataModel().isRowAvailable();
211 }
212
213 public int getRowCount()
214 {
215 return getDataModel().getRowCount();
216 }
217
218 public Object getRowData()
219 {
220 return getDataModel().getRowData();
221 }
222
223 public int getRowIndex()
224 {
225 return _rowIndex;
226 }
227
228
229
230
231
232
233
234
235 public void setRowIndex(int rowIndex)
236 {
237 if (rowIndex < -1)
238 {
239 throw new IllegalArgumentException("rowIndex is less than -1");
240 }
241
242 if (_rowIndex == rowIndex)
243 {
244 return;
245 }
246
247 FacesContext facesContext = getFacesContext();
248
249 if (_rowIndex == -1)
250 {
251 if (_initialDescendantComponentState == null)
252 {
253
254
255
256
257 _initialDescendantComponentState = saveDescendantComponentStates(
258 getChildren().iterator(), false);
259 }
260 }
261 else
262 {
263
264
265
266
267 _rowStates.put(getClientId(facesContext),
268 saveDescendantComponentStates(getChildren().iterator(),
269 false));
270 }
271
272 _rowIndex = rowIndex;
273
274 DataModel dataModel = getDataModel();
275 dataModel.setRowIndex(rowIndex);
276
277 String var = getVar();
278 if (rowIndex == -1)
279 {
280 if (var != null)
281 {
282 facesContext.getExternalContext().getRequestMap().remove(var);
283 }
284 }
285 else
286 {
287 if (var != null)
288 {
289 if (isRowAvailable())
290 {
291 Object rowData = dataModel.getRowData();
292 facesContext.getExternalContext().getRequestMap().put(var,
293 rowData);
294 }
295 else
296 {
297 facesContext.getExternalContext().getRequestMap().remove(
298 var);
299 }
300 }
301 }
302
303 if (_rowIndex == -1)
304 {
305
306 restoreDescendantComponentStates(getChildren().iterator(),
307 _initialDescendantComponentState, false);
308 }
309 else
310 {
311 Object rowState = _rowStates.get(getClientId(facesContext));
312 if (rowState == null)
313 {
314
315
316
317 restoreDescendantComponentStates(getChildren().iterator(),
318 _initialDescendantComponentState, false);
319 }
320 else
321 {
322
323
324
325
326 restoreDescendantComponentStates(getChildren().iterator(),
327 rowState, false);
328 }
329 }
330 }
331
332
333
334
335
336
337
338
339 private void restoreDescendantComponentStates(Iterator childIterator,
340 Object state, boolean restoreChildFacets)
341 {
342 Iterator descendantStateIterator = null;
343 while (childIterator.hasNext())
344 {
345 if (descendantStateIterator == null && state != null)
346 {
347 descendantStateIterator = ((Collection) state).iterator();
348 }
349 UIComponent component = (UIComponent) childIterator.next();
350
351
352 component.setId(component.getId());
353 if(!component.isTransient())
354 {
355 Object childState = null;
356 Object descendantState = null;
357 if (descendantStateIterator != null
358 && descendantStateIterator.hasNext())
359 {
360 Object[] object = (Object[]) descendantStateIterator.next();
361 childState = object[0];
362 descendantState = object[1];
363 }
364 if (component instanceof EditableValueHolder)
365 {
366 ((EditableValueHolderState) childState)
367 .restoreState((EditableValueHolder) component);
368 }
369 Iterator childsIterator;
370 if (restoreChildFacets)
371 {
372 childsIterator = component.getFacetsAndChildren();
373 }
374 else
375 {
376 childsIterator = component.getChildren().iterator();
377 }
378 restoreDescendantComponentStates(childsIterator, descendantState,
379 true);
380 }
381 }
382 }
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401 private Object saveDescendantComponentStates(Iterator childIterator,
402 boolean saveChildFacets)
403 {
404 Collection childStates = null;
405 while (childIterator.hasNext())
406 {
407 if (childStates == null)
408 {
409 childStates = new ArrayList();
410 }
411 UIComponent child = (UIComponent) childIterator.next();
412 if(!child.isTransient())
413 {
414
415
416
417
418
419 Iterator childsIterator;
420 if (saveChildFacets)
421 {
422 childsIterator = child.getFacetsAndChildren();
423 }
424 else
425 {
426 childsIterator = child.getChildren().iterator();
427 }
428 Object descendantState = saveDescendantComponentStates(
429 childsIterator, true);
430 Object state = null;
431 if (child instanceof EditableValueHolder)
432 {
433 state = new EditableValueHolderState(
434 (EditableValueHolder) child);
435 }
436 childStates.add(new Object[] { state, descendantState });
437 }
438 }
439 return childStates;
440 }
441
442
443
444
445 public void setRows(int rows)
446 {
447 _rows = new Integer(rows);
448 if (rows < 0)
449 throw new IllegalArgumentException("rows: " + rows);
450 }
451
452
453
454
455
456
457
458 public void setVar(String var)
459 {
460 _var = var;
461 }
462
463
464
465
466
467
468
469
470 public String getVar()
471 {
472 return _var;
473 }
474
475 public void setValueBinding(String name, ValueBinding binding)
476 {
477 if (name == null)
478 {
479 throw new NullPointerException("name");
480 }
481 else if (name.equals("value"))
482 {
483 _dataModelMap.clear();
484 }
485 else if (name.equals("var") || name.equals("rowIndex"))
486 {
487 throw new IllegalArgumentException(
488 "You can never set the 'rowIndex' or the 'var' attribute as a value-binding. Set the property directly instead. Name " + name);
489 }
490 super.setValueBinding(name, binding);
491 }
492
493 public String getClientId(FacesContext context)
494 {
495 String clientId = super.getClientId(context);
496 int rowIndex = getRowIndex();
497 if (rowIndex == -1)
498 {
499 return clientId;
500 }
501 return clientId + NamingContainer.SEPARATOR_CHAR + rowIndex;
502 }
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523 public void queueEvent(FacesEvent event)
524 {
525 super.queueEvent(new FacesEventWrapper(event, getRowIndex(), this));
526 }
527
528
529
530
531
532
533
534 public void broadcast(FacesEvent event) throws AbortProcessingException
535 {
536 if (event instanceof FacesEventWrapper)
537 {
538 FacesEvent originalEvent = ((FacesEventWrapper) event)
539 .getWrappedFacesEvent();
540 int eventRowIndex = ((FacesEventWrapper) event).getRowIndex();
541 int currentRowIndex = getRowIndex();
542 setRowIndex(eventRowIndex);
543 try
544 {
545 originalEvent.getComponent().broadcast(originalEvent);
546 }
547 finally
548 {
549 setRowIndex(currentRowIndex);
550 }
551 }
552 else
553 {
554 super.broadcast(event);
555 }
556 }
557
558
559
560
561
562
563 public void encodeBegin(FacesContext context) throws IOException
564 {
565 _initialDescendantComponentState = null;
566 if (_isValidChilds && !hasErrorMessages(context))
567 {
568
569
570
571 _dataModelMap.clear();
572
573
574
575
576
577 _rowStates.clear();
578 }
579 super.encodeBegin(context);
580 }
581
582 private boolean hasErrorMessages(FacesContext context)
583 {
584 for(Iterator iter = context.getMessages(); iter.hasNext();)
585 {
586 FacesMessage message = (FacesMessage) iter.next();
587 if(FacesMessage.SEVERITY_ERROR.compareTo(message.getSeverity()) <= 0)
588 {
589 return true;
590 }
591 }
592 return false;
593 }
594
595
596
597
598 public void encodeEnd(FacesContext context) throws IOException
599 {
600 try
601 {
602 setCachedFacesContext(context);
603 setRowIndex(-1);
604 }
605 finally
606 {
607 setCachedFacesContext(null);
608 }
609 super.encodeEnd(context);
610 }
611
612 public void processDecodes(FacesContext context)
613 {
614 if (context == null)
615 throw new NullPointerException("context");
616 try
617 {
618 setCachedFacesContext(context);
619 if (!isRendered())
620 return;
621 setRowIndex(-1);
622 processFacets(context, PROCESS_DECODES);
623 processColumnFacets(context, PROCESS_DECODES);
624 processColumnChildren(context, PROCESS_DECODES);
625 setRowIndex(-1);
626 try
627 {
628 decode(context);
629 }
630 catch (RuntimeException e)
631 {
632 context.renderResponse();
633 throw e;
634 }
635 }
636 finally
637 {
638 setCachedFacesContext(null);
639 }
640 }
641
642 public void processValidators(FacesContext context)
643 {
644 if (context == null)
645 throw new NullPointerException("context");
646 try
647 {
648 setCachedFacesContext(context);
649 if (!isRendered())
650 return;
651 setRowIndex(-1);
652 processFacets(context, PROCESS_VALIDATORS);
653 processColumnFacets(context, PROCESS_VALIDATORS);
654 processColumnChildren(context, PROCESS_VALIDATORS);
655 setRowIndex(-1);
656
657
658 if (context.getRenderResponse())
659 {
660 _isValidChilds = false;
661 }
662 }
663 finally
664 {
665 setCachedFacesContext(null);
666 }
667 }
668
669 public void processUpdates(FacesContext context)
670 {
671 if (context == null)
672 throw new NullPointerException("context");
673 try
674 {
675 setCachedFacesContext(context);
676 if (!isRendered())
677 return;
678 setRowIndex(-1);
679 processFacets(context, PROCESS_UPDATES);
680 processColumnFacets(context, PROCESS_UPDATES);
681 processColumnChildren(context, PROCESS_UPDATES);
682 setRowIndex(-1);
683
684 if (context.getRenderResponse())
685 {
686 _isValidChilds = false;
687 }
688 }
689 finally
690 {
691 setCachedFacesContext(null);
692 }
693 }
694
695 private void processFacets(FacesContext context, int processAction)
696 {
697 for (Iterator it = getFacets().values().iterator(); it.hasNext();)
698 {
699 UIComponent facet = (UIComponent) it.next();
700 process(context, facet, processAction);
701 }
702 }
703
704
705
706
707
708
709
710
711
712 private void processColumnFacets(FacesContext context, int processAction)
713 {
714 for (Iterator childIter = getChildren().iterator(); childIter.hasNext();)
715 {
716 UIComponent child = (UIComponent) childIter.next();
717 if (child instanceof UIColumn)
718 {
719 if (!child.isRendered())
720 {
721
722 continue;
723 }
724 for (Iterator facetsIter = child.getFacets().values()
725 .iterator(); facetsIter.hasNext();)
726 {
727 UIComponent facet = (UIComponent) facetsIter.next();
728 process(context, facet, processAction);
729 }
730 }
731 }
732 }
733
734
735
736
737
738
739
740
741
742 private void processColumnChildren(FacesContext context, int processAction)
743 {
744 int first = getFirst();
745 int rows = getRows();
746 int last;
747 if (rows == 0)
748 {
749 last = getRowCount();
750 }
751 else
752 {
753 last = first + rows;
754 }
755 for (int rowIndex = first; last==-1 || rowIndex < last; rowIndex++)
756 {
757 setRowIndex(rowIndex);
758
759
760 if (!isRowAvailable())
761 break;
762
763 for (Iterator it = getChildren().iterator(); it.hasNext();)
764 {
765 UIComponent child = (UIComponent) it.next();
766 if (child instanceof UIColumn)
767 {
768 if (!child.isRendered())
769 {
770
771 continue;
772 }
773 for (Iterator columnChildIter = child.getChildren()
774 .iterator(); columnChildIter.hasNext();)
775 {
776 UIComponent columnChild = (UIComponent) columnChildIter
777 .next();
778 process(context, columnChild, processAction);
779 }
780 }
781 }
782 }
783 }
784
785 private void process(FacesContext context, UIComponent component,
786 int processAction)
787 {
788 switch (processAction)
789 {
790 case PROCESS_DECODES:
791 component.processDecodes(context);
792 break;
793 case PROCESS_VALIDATORS:
794 component.processValidators(context);
795 break;
796 case PROCESS_UPDATES:
797 component.processUpdates(context);
798 break;
799 }
800 }
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817 private DataModel getDataModel()
818 {
819 DataModel dataModel = null;
820 String clientID = "";
821
822 UIComponent parent = getParent();
823 if (parent != null) {
824 clientID = parent.getClientId(getFacesContext());
825 }
826 dataModel = (DataModel) _dataModelMap.get(clientID);
827 if (dataModel == null)
828 {
829 dataModel = createDataModel();
830 _dataModelMap.put(clientID, dataModel);
831 }
832 return dataModel;
833 }
834
835
836
837
838
839
840
841
842
843
844
845
846
847 private DataModel createDataModel()
848 {
849 Object value = getValue();
850 if (value == null)
851 {
852 return EMPTY_DATA_MODEL;
853 }
854 else if (value instanceof DataModel)
855 {
856 return (DataModel) value;
857 }
858 else if (value instanceof List)
859 {
860 return new ListDataModel((List) value);
861 }
862 else if (OBJECT_ARRAY_CLASS.isAssignableFrom(value.getClass()))
863 {
864 return new ArrayDataModel((Object[]) value);
865 }
866 else if (value instanceof ResultSet)
867 {
868 return new ResultSetDataModel((ResultSet) value);
869 }
870 else if (value instanceof Result)
871 {
872 return new ResultDataModel((Result) value);
873 }
874 else
875 {
876 return new ScalarDataModel(value);
877 }
878 }
879
880 private static class FacesEventWrapper extends FacesEvent
881 {
882 private static final long serialVersionUID = 6648047974065628773L;
883 private FacesEvent _wrappedFacesEvent;
884 private int _rowIndex;
885
886 public FacesEventWrapper(FacesEvent facesEvent, int rowIndex,
887 UIData redirectComponent)
888 {
889 super(redirectComponent);
890 _wrappedFacesEvent = facesEvent;
891 _rowIndex = rowIndex;
892 }
893
894 public PhaseId getPhaseId()
895 {
896 return _wrappedFacesEvent.getPhaseId();
897 }
898
899 public void setPhaseId(PhaseId phaseId)
900 {
901 _wrappedFacesEvent.setPhaseId(phaseId);
902 }
903
904 public void queue()
905 {
906 _wrappedFacesEvent.queue();
907 }
908
909 public String toString()
910 {
911 return _wrappedFacesEvent.toString();
912 }
913
914 public boolean isAppropriateListener(FacesListener faceslistener)
915 {
916 return _wrappedFacesEvent.isAppropriateListener(faceslistener);
917 }
918
919 public void processListener(FacesListener faceslistener)
920 {
921 _wrappedFacesEvent.processListener(faceslistener);
922 }
923
924 public FacesEvent getWrappedFacesEvent()
925 {
926 return _wrappedFacesEvent;
927 }
928
929 public int getRowIndex()
930 {
931 return _rowIndex;
932 }
933 }
934
935 private static final DataModel EMPTY_DATA_MODEL = new DataModel()
936 {
937 public boolean isRowAvailable()
938 {
939 return false;
940 }
941
942 public int getRowCount()
943 {
944 return 0;
945 }
946
947 public Object getRowData()
948 {
949 throw new IllegalArgumentException();
950 }
951
952 public int getRowIndex()
953 {
954 return -1;
955 }
956
957 public void setRowIndex(int i)
958 {
959 if (i < -1)
960 throw new IllegalArgumentException();
961 }
962
963 public Object getWrappedData()
964 {
965 return null;
966 }
967
968 public void setWrappedData(Object obj)
969 {
970 if (obj == null)
971 return;
972 throw new UnsupportedOperationException(this.getClass().getName()
973 + " UnsupportedOperationException");
974 }
975 };
976
977 public void setValue(Object value)
978 {
979 _value = value;
980 _dataModelMap.clear();
981 _rowStates.clear();
982 _isValidChilds = true;
983 }
984
985 public Object saveState(FacesContext context)
986 {
987 Object[] values = new Object[STATE_SIZE];
988 values[SUPER_STATE_INDEX] = super.saveState(context);
989 values[FIRST_STATE_INDEX] = _first;
990 values[ROWS_STATE_INDEX] = _rows;
991 values[VALUE_STATE_INDEX] = _value;
992 values[VAR_STATE_INDEX] = _var;
993 return values;
994 }
995
996 public void restoreState(FacesContext context, Object state)
997 {
998 Object[] values = (Object[]) state;
999 super.restoreState(context, values[0]);
1000 _first = (Integer) values[FIRST_STATE_INDEX];
1001 _rows = (Integer) values[ROWS_STATE_INDEX];
1002 _value = values[VALUE_STATE_INDEX];
1003 _var = (String) values[VAR_STATE_INDEX];
1004 }
1005
1006 private class EditableValueHolderState
1007 {
1008 private final Object _value;
1009 private final boolean _localValueSet;
1010 private final boolean _valid;
1011 private final Object _submittedValue;
1012
1013 public EditableValueHolderState(EditableValueHolder evh)
1014 {
1015 _value = evh.getLocalValue();
1016 _localValueSet = evh.isLocalValueSet();
1017 _valid = evh.isValid();
1018 _submittedValue = evh.getSubmittedValue();
1019 }
1020
1021 public void restoreState(EditableValueHolder evh)
1022 {
1023 evh.setValue(_value);
1024 evh.setLocalValueSet(_localValueSet);
1025 evh.setValid(_valid);
1026 evh.setSubmittedValue(_submittedValue);
1027 }
1028 }
1029
1030 public UIData()
1031 {
1032 setRendererType(DEFAULT_RENDERER_TYPE);
1033 }
1034
1035 public String getFamily()
1036 {
1037 return COMPONENT_FAMILY;
1038 }
1039
1040 public void setFirst(int first)
1041 {
1042 if (first < 0)
1043 {
1044 throw new IllegalArgumentException("Illegal value for first row: " + first);
1045 }
1046 _first = new Integer(first);
1047 }
1048
1049
1050
1051
1052
1053
1054 public int getFirst()
1055 {
1056 if (_first != null)
1057 {
1058 return _first.intValue();
1059 }
1060 ValueBinding vb = getValueBinding("first");
1061 Number v = vb != null ? (Number) vb.getValue(getFacesContext()) : null;
1062 return v != null ? v.intValue() : DEFAULT_FIRST;
1063 }
1064
1065
1066
1067
1068
1069
1070 public int getRows()
1071 {
1072 if (_rows != null)
1073 {
1074 return _rows.intValue();
1075 }
1076 ValueBinding vb = getValueBinding("rows");
1077 Number v = vb != null ? (Number) vb.getValue(getFacesContext()) : null;
1078 return v != null ? v.intValue() : DEFAULT_ROWS;
1079 }
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090 public Object getValue()
1091 {
1092 if (_value != null)
1093 return _value;
1094 ValueBinding vb = getValueBinding("value");
1095 return vb != null ? vb.getValue(getFacesContext()) : null;
1096 }
1097 }