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.Collections;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Map;
30
31 import javax.el.ValueExpression;
32 import javax.faces.FacesException;
33 import javax.faces.application.FacesMessage;
34 import javax.faces.component.visit.VisitCallback;
35 import javax.faces.component.visit.VisitContext;
36 import javax.faces.component.visit.VisitResult;
37 import javax.faces.context.ExternalContext;
38 import javax.faces.context.FacesContext;
39 import javax.faces.event.AbortProcessingException;
40 import javax.faces.event.FacesEvent;
41 import javax.faces.event.FacesListener;
42 import javax.faces.event.PhaseId;
43 import javax.faces.event.PostValidateEvent;
44 import javax.faces.event.PreValidateEvent;
45 import javax.faces.model.ArrayDataModel;
46 import javax.faces.model.DataModel;
47 import javax.faces.model.ListDataModel;
48 import javax.faces.model.ResultDataModel;
49 import javax.faces.model.ResultSetDataModel;
50 import javax.faces.model.ScalarDataModel;
51 import javax.servlet.jsp.jstl.sql.Result;
52
53 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
54 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFacet;
55 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
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 @JSFComponent(defaultRendererType = "javax.faces.Table")
120 public class UIData extends UIComponentBase implements NamingContainer, UniqueIdVendor
121 {
122 public static final String COMPONENT_FAMILY = "javax.faces.Data";
123 public static final String COMPONENT_TYPE = "javax.faces.Data";
124
125 private static final String FOOTER_FACET_NAME = "footer";
126 private static final String HEADER_FACET_NAME = "header";
127 private static final Class<Object[]> OBJECT_ARRAY_CLASS = Object[].class;
128 private static final int PROCESS_DECODES = 1;
129 private static final int PROCESS_VALIDATORS = 2;
130 private static final int PROCESS_UPDATES = 3;
131 private static final String SKIP_ITERATION_HINT = "javax.faces.visit.SKIP_ITERATION";
132
133 private static final Object[] LEAF_NO_STATE = new Object[]{null,null};
134
135 private int _rowIndex = -1;
136
137
138
139
140 private Map<String, Collection<Object[]>> _rowStates = new HashMap<String, Collection<Object[]>>();
141
142
143
144
145
146
147 private Map<String, DataModel> _dataModelMap = new HashMap<String, DataModel>();
148
149
150 private boolean _isValidChilds = true;
151
152 private Object _initialDescendantComponentState = null;
153
154
155
156
157
158
159
160 private static class FacesEventWrapper extends FacesEvent
161 {
162 private static final long serialVersionUID = 6648047974065628773L;
163 private FacesEvent _wrappedFacesEvent;
164 private int _rowIndex;
165
166 public FacesEventWrapper(FacesEvent facesEvent, int rowIndex, UIData redirectComponent)
167 {
168 super(redirectComponent);
169 _wrappedFacesEvent = facesEvent;
170 _rowIndex = rowIndex;
171 }
172
173 @Override
174 public PhaseId getPhaseId()
175 {
176 return _wrappedFacesEvent.getPhaseId();
177 }
178
179 @Override
180 public void setPhaseId(PhaseId phaseId)
181 {
182 _wrappedFacesEvent.setPhaseId(phaseId);
183 }
184
185 @Override
186 public void queue()
187 {
188 _wrappedFacesEvent.queue();
189 }
190
191 @Override
192 public String toString()
193 {
194 return _wrappedFacesEvent.toString();
195 }
196
197 @Override
198 public boolean isAppropriateListener(FacesListener faceslistener)
199 {
200 return _wrappedFacesEvent.isAppropriateListener(faceslistener);
201 }
202
203 @Override
204 public void processListener(FacesListener faceslistener)
205 {
206 _wrappedFacesEvent.processListener(faceslistener);
207 }
208
209 public FacesEvent getWrappedFacesEvent()
210 {
211 return _wrappedFacesEvent;
212 }
213
214 public int getRowIndex()
215 {
216 return _rowIndex;
217 }
218 }
219
220 private static final DataModel EMPTY_DATA_MODEL = new DataModel()
221 {
222 @Override
223 public boolean isRowAvailable()
224 {
225 return false;
226 }
227
228 @Override
229 public int getRowCount()
230 {
231 return 0;
232 }
233
234 @Override
235 public Object getRowData()
236 {
237 throw new IllegalArgumentException();
238 }
239
240 @Override
241 public int getRowIndex()
242 {
243 return -1;
244 }
245
246 @Override
247 public void setRowIndex(int i)
248 {
249 if (i < -1)
250 {
251 throw new IllegalArgumentException();
252 }
253 }
254
255 @Override
256 public Object getWrappedData()
257 {
258 return null;
259 }
260
261 @Override
262 public void setWrappedData(Object obj)
263 {
264 if (obj == null)
265 {
266 return;
267 }
268 throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
269 }
270 };
271
272 private class EditableValueHolderState
273 {
274 private final Object _value;
275 private final boolean _localValueSet;
276 private final boolean _valid;
277 private final Object _submittedValue;
278
279 public EditableValueHolderState(EditableValueHolder evh)
280 {
281 _value = evh.getLocalValue();
282 _localValueSet = evh.isLocalValueSet();
283 _valid = evh.isValid();
284 _submittedValue = evh.getSubmittedValue();
285 }
286
287 public void restoreState(EditableValueHolder evh)
288 {
289 evh.setValue(_value);
290 evh.setLocalValueSet(_localValueSet);
291 evh.setValid(_valid);
292 evh.setSubmittedValue(_submittedValue);
293 }
294 }
295
296
297
298
299 public UIData()
300 {
301 setRendererType("javax.faces.Table");
302 }
303
304 @Override
305 public boolean invokeOnComponent(FacesContext context, String clientId, ContextCallback callback)
306 throws FacesException
307 {
308 if (context == null || clientId == null || callback == null)
309 {
310 throw new NullPointerException();
311 }
312
313 final String baseClientId = getClientId(context);
314
315
316 boolean returnValue = baseClientId.equals(clientId);
317
318 boolean isCachedFacesContext = isCachedFacesContext();
319 if (!isCachedFacesContext)
320 {
321 setCachedFacesContext(context);
322 }
323
324 pushComponentToEL(context, this);
325 try
326 {
327 if (returnValue)
328 {
329 try
330 {
331 callback.invokeContextCallback(context, this);
332 return true;
333 }
334 catch (Exception e)
335 {
336 throw new FacesException(e);
337 }
338 }
339
340
341 if (this.getFacetCount() > 0)
342 {
343 for (Iterator<UIComponent> it = this.getFacets().values().iterator(); !returnValue && it.hasNext();)
344 {
345 returnValue = it.next().invokeOnComponent(context, clientId, callback);
346 }
347 }
348
349 if (returnValue)
350 {
351 return returnValue;
352 }
353
354
355 if (clientId.startsWith(baseClientId))
356 {
357
358
359 char separator = UINamingContainer.getSeparatorChar(context);
360 String subId = clientId.substring(baseClientId.length() + 1);
361
362
363 if (clientId.charAt(baseClientId.length()) == separator &&
364 subId.matches("[0-9]+"+separator+".*"))
365 {
366 String clientRow = subId.substring(0, subId.indexOf(separator));
367
368
369 int oldRow = this.getRowIndex();
370
371
372 try
373 {
374
375
376 this.setRowIndex(Integer.parseInt(clientRow));
377
378
379 if (!isRowAvailable())
380 {
381 return false;
382 }
383
384 for (Iterator<UIComponent> it1 = getChildren().iterator();
385 !returnValue && it1.hasNext();)
386 {
387
388 returnValue = it1.next().invokeOnComponent(context, clientId, callback);
389 }
390 }
391 finally
392 {
393
394
395 this.setRowIndex(oldRow);
396 }
397 }
398 else
399 {
400
401
402
403
404
405 for (Iterator<UIComponent> itChildren = this.getChildren().iterator();
406 !returnValue && itChildren.hasNext();)
407 {
408 UIComponent child = itChildren.next();
409 if (child instanceof UIColumn && clientId.equals(child.getClientId(context)))
410 {
411 try
412 {
413 callback.invokeContextCallback(context, child);
414 }
415 catch (Exception e)
416 {
417 throw new FacesException(e);
418 }
419 returnValue = true;
420 }
421
422 if (child.getFacetCount() > 0)
423 {
424 for (Iterator<UIComponent> itChildFacets =
425 child.getFacets().values().iterator();
426 !returnValue && itChildFacets.hasNext();)
427 {
428
429 returnValue = itChildFacets.next().invokeOnComponent(
430 context, clientId, callback);
431 }
432 }
433 }
434 }
435 }
436 }
437 finally
438 {
439
440 popComponentFromEL(context);
441 if (!isCachedFacesContext)
442 {
443 setCachedFacesContext(null);
444 }
445 }
446
447 return returnValue;
448 }
449
450 public void setFooter(UIComponent footer)
451 {
452 getFacets().put(FOOTER_FACET_NAME, footer);
453 }
454
455 @JSFFacet
456 public UIComponent getFooter()
457 {
458 return getFacets().get(FOOTER_FACET_NAME);
459 }
460
461 public void setHeader(UIComponent header)
462 {
463 getFacets().put(HEADER_FACET_NAME, header);
464 }
465
466 @JSFFacet
467 public UIComponent getHeader()
468 {
469 return getFacets().get(HEADER_FACET_NAME);
470 }
471
472 public boolean isRowAvailable()
473 {
474 return getDataModel().isRowAvailable();
475 }
476
477 public int getRowCount()
478 {
479 return getDataModel().getRowCount();
480 }
481
482 public Object getRowData()
483 {
484 return getDataModel().getRowData();
485 }
486
487 public int getRowIndex()
488 {
489 return _rowIndex;
490 }
491
492
493
494
495
496
497
498
499
500 public void setRowIndex(int rowIndex)
501 {
502 if (rowIndex < -1)
503 {
504 throw new IllegalArgumentException("rowIndex is less than -1");
505 }
506
507 if (_rowIndex == rowIndex)
508 {
509 return;
510 }
511
512 FacesContext facesContext = getFacesContext();
513
514 if (_rowIndex == -1)
515 {
516 if (_initialDescendantComponentState == null)
517 {
518
519
520
521
522 _initialDescendantComponentState = saveDescendantComponentStates(this, false, false);
523 }
524 }
525 else
526 {
527
528
529
530 if (_initialDescendantComponentState != null)
531 {
532
533
534
535
536 Collection<Object[]> savedRowState = saveDescendantComponentStates(this, false, false);
537 if (savedRowState != null)
538 {
539 _rowStates.put(getContainerClientId(facesContext), savedRowState);
540 }
541 }
542 }
543
544 _rowIndex = rowIndex;
545
546 DataModel dataModel = getDataModel();
547 dataModel.setRowIndex(rowIndex);
548
549 String var = (String) getStateHelper().get(PropertyKeys.var);
550 if (rowIndex == -1)
551 {
552 if (var != null)
553 {
554 facesContext.getExternalContext().getRequestMap().remove(var);
555 }
556 }
557 else
558 {
559 if (var != null)
560 {
561 if (isRowAvailable())
562 {
563 Object rowData = dataModel.getRowData();
564 facesContext.getExternalContext().getRequestMap().put(var, rowData);
565 }
566 else
567 {
568 facesContext.getExternalContext().getRequestMap().remove(var);
569 }
570 }
571 }
572
573 if (_rowIndex == -1)
574 {
575
576
577 if (_initialDescendantComponentState != null)
578 {
579 restoreDescendantComponentStates(this, false, _initialDescendantComponentState, false);
580 }
581 else
582 {
583 restoreDescendantComponentWithoutRestoreState(this, false, false);
584 }
585 }
586 else
587 {
588 Object rowState = _rowStates.get(getContainerClientId(facesContext));
589 if (rowState == null)
590 {
591
592
593
594
595 if (_initialDescendantComponentState != null)
596 {
597 restoreDescendantComponentStates(this, false, _initialDescendantComponentState, false);
598 }
599 else
600 {
601 restoreDescendantComponentWithoutRestoreState(this, false, false);
602 }
603 }
604 else
605 {
606
607
608
609
610 restoreDescendantComponentStates(this, false, rowState, false);
611 }
612 }
613 }
614
615
616
617
618
619
620
621
622 @SuppressWarnings("unchecked")
623 private void restoreDescendantComponentStates(UIComponent parent, boolean iterateFacets, Object state,
624 boolean restoreChildFacets)
625 {
626 int descendantStateIndex = -1;
627 List<? extends Object[]> stateCollection = null;
628
629 if (iterateFacets && parent.getFacetCount() > 0)
630 {
631 Iterator<UIComponent> childIterator = parent.getFacets().values().iterator();
632
633 while (childIterator.hasNext())
634 {
635 UIComponent component = childIterator.next();
636
637
638 component.setId(component.getId());
639 if (!component.isTransient())
640 {
641 if (descendantStateIndex == -1)
642 {
643 stateCollection = ((List<? extends Object[]>) state);
644 descendantStateIndex = stateCollection.isEmpty() ? -1 : 0;
645 }
646
647 if (descendantStateIndex != -1 && descendantStateIndex < stateCollection.size())
648 {
649 Object[] object = stateCollection.get(descendantStateIndex);
650 if (object[0] != null && component instanceof EditableValueHolder)
651 {
652 ((EditableValueHolderState) object[0]).restoreState((EditableValueHolder) component);
653 }
654
655
656 if (object[1] != null)
657 {
658 restoreDescendantComponentStates(component, restoreChildFacets, object[1], true);
659 }
660 else
661 {
662 restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
663 }
664 }
665 else
666 {
667 restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
668 }
669 descendantStateIndex++;
670 }
671 }
672 }
673
674 if (parent.getChildCount() > 0)
675 {
676 for (int i = 0; i < parent.getChildCount(); i++)
677 {
678 UIComponent component = parent.getChildren().get(i);
679
680
681 component.setId(component.getId());
682 if (!component.isTransient())
683 {
684 if (descendantStateIndex == -1)
685 {
686 stateCollection = ((List<? extends Object[]>) state);
687 descendantStateIndex = stateCollection.isEmpty() ? -1 : 0;
688 }
689
690 if (descendantStateIndex != -1 && descendantStateIndex < stateCollection.size())
691 {
692 Object[] object = stateCollection.get(descendantStateIndex);
693 if (object[0] != null && component instanceof EditableValueHolder)
694 {
695 ((EditableValueHolderState) object[0]).restoreState((EditableValueHolder) component);
696 }
697
698
699 if (object[1] != null)
700 {
701 restoreDescendantComponentStates(component, restoreChildFacets, object[1], true);
702 }
703 else
704 {
705 restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
706 }
707 }
708 else
709 {
710 restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
711 }
712 descendantStateIndex++;
713 }
714 }
715 }
716 }
717
718
719
720
721
722
723
724
725
726
727 private void restoreDescendantComponentWithoutRestoreState(UIComponent parent, boolean iterateFacets,
728 boolean restoreChildFacets)
729 {
730 if (iterateFacets && parent.getFacetCount() > 0)
731 {
732 Iterator<UIComponent> childIterator = parent.getFacets().values().iterator();
733
734 while (childIterator.hasNext())
735 {
736 UIComponent component = childIterator.next();
737
738
739 component.setId(component.getId());
740 if (!component.isTransient())
741 {
742 restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
743 }
744 }
745 }
746
747 if (parent.getChildCount() > 0)
748 {
749 for (int i = 0; i < parent.getChildCount(); i++)
750 {
751 UIComponent component = parent.getChildren().get(i);
752
753
754 component.setId(component.getId());
755 if (!component.isTransient())
756 {
757 restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
758 }
759 }
760 }
761 }
762
763
764
765
766
767
768
769
770
771
772
773
774
775 private Collection<Object[]> saveDescendantComponentStates(UIComponent parent, boolean iterateFacets,
776 boolean saveChildFacets)
777 {
778 Collection<Object[]> childStates = null;
779
780 int childEmptyIndex = 0;
781 int totalChildCount = 0;
782
783 if (iterateFacets && parent.getFacetCount() > 0)
784 {
785 Iterator<UIComponent> childIterator = parent.getFacets().values().iterator();
786
787 while (childIterator.hasNext())
788 {
789 UIComponent child = childIterator.next();
790 if (!child.isTransient())
791 {
792
793
794
795
796
797 if (child instanceof EditableValueHolder)
798 {
799 if (childStates == null)
800 {
801 childStates = new ArrayList<Object[]>(
802 parent.getFacetCount()
803 + parent.getChildCount()
804 - totalChildCount
805 + childEmptyIndex);
806 for (int ci = 0; ci < childEmptyIndex; ci++)
807 {
808 childStates.add(LEAF_NO_STATE);
809 }
810 }
811
812 childStates.add(child.getChildCount() > 0 ?
813 new Object[]{new EditableValueHolderState((EditableValueHolder) child),
814 saveDescendantComponentStates(child, saveChildFacets, true)} :
815 new Object[]{new EditableValueHolderState((EditableValueHolder) child),
816 null});
817 }
818 else if (child.getChildCount() > 0 || (saveChildFacets && child.getFacetCount() > 0))
819 {
820 Object descendantSavedState = saveDescendantComponentStates(child, saveChildFacets, true);
821
822 if (descendantSavedState == null)
823 {
824 if (childStates == null)
825 {
826 childEmptyIndex++;
827 }
828 else
829 {
830 childStates.add(LEAF_NO_STATE);
831 }
832 }
833 else
834 {
835 if (childStates == null)
836 {
837 childStates = new ArrayList<Object[]>(
838 parent.getFacetCount()
839 + parent.getChildCount()
840 - totalChildCount
841 + childEmptyIndex);
842 for (int ci = 0; ci < childEmptyIndex; ci++)
843 {
844 childStates.add(LEAF_NO_STATE);
845 }
846 }
847 childStates.add(new Object[]{null, descendantSavedState});
848 }
849 }
850 else
851 {
852 if (childStates == null)
853 {
854 childEmptyIndex++;
855 }
856 else
857 {
858 childStates.add(LEAF_NO_STATE);
859 }
860 }
861 }
862 totalChildCount++;
863 }
864 }
865
866 if (parent.getChildCount() > 0)
867 {
868 for (int i = 0; i < parent.getChildCount(); i++)
869 {
870 UIComponent child = parent.getChildren().get(i);
871 if (!child.isTransient())
872 {
873
874
875
876
877
878 if (child instanceof EditableValueHolder)
879 {
880 if (childStates == null)
881 {
882 childStates = new ArrayList<Object[]>(
883 parent.getFacetCount()
884 + parent.getChildCount()
885 - totalChildCount
886 + childEmptyIndex);
887 for (int ci = 0; ci < childEmptyIndex; ci++)
888 {
889 childStates.add(LEAF_NO_STATE);
890 }
891 }
892
893 childStates.add(child.getChildCount() > 0 ?
894 new Object[]{new EditableValueHolderState((EditableValueHolder) child),
895 saveDescendantComponentStates(child, saveChildFacets, true)} :
896 new Object[]{new EditableValueHolderState((EditableValueHolder) child),
897 null});
898 }
899 else if (child.getChildCount() > 0 || (saveChildFacets && child.getFacetCount() > 0))
900 {
901 Object descendantSavedState = saveDescendantComponentStates(child, saveChildFacets, true);
902
903 if (descendantSavedState == null)
904 {
905 if (childStates == null)
906 {
907 childEmptyIndex++;
908 }
909 else
910 {
911 childStates.add(LEAF_NO_STATE);
912 }
913 }
914 else
915 {
916 if (childStates == null)
917 {
918 childStates = new ArrayList<Object[]>(
919 parent.getFacetCount()
920 + parent.getChildCount()
921 - totalChildCount
922 + childEmptyIndex);
923 for (int ci = 0; ci < childEmptyIndex; ci++)
924 {
925 childStates.add(LEAF_NO_STATE);
926 }
927 }
928 childStates.add(new Object[]{null, descendantSavedState});
929 }
930 }
931 else
932 {
933 if (childStates == null)
934 {
935 childEmptyIndex++;
936 }
937 else
938 {
939 childStates.add(LEAF_NO_STATE);
940 }
941 }
942 }
943 totalChildCount++;
944 }
945 }
946
947 return childStates;
948 }
949
950 @Override
951 public void setValueExpression(String name, ValueExpression binding)
952 {
953 if (name == null)
954 {
955 throw new NullPointerException("name");
956 }
957 else if (name.equals("value"))
958 {
959 _dataModelMap.clear();
960 }
961 else if (name.equals("rowIndex"))
962 {
963 throw new IllegalArgumentException("name " + name);
964 }
965 super.setValueExpression(name, binding);
966 }
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983 @Override
984 public String getContainerClientId(FacesContext context)
985 {
986
987 String clientId = super.getContainerClientId(context);
988
989 int rowIndex = getRowIndex();
990 if (rowIndex == -1)
991 {
992 return clientId;
993 }
994
995 StringBuilder bld = __getSharedStringBuilder(context);
996 return bld.append(clientId).append(UINamingContainer.getSeparatorChar(context)).append(rowIndex).toString();
997 }
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012 @Override
1013 public void queueEvent(FacesEvent event)
1014 {
1015 super.queueEvent(new FacesEventWrapper(event, getRowIndex(), this));
1016 }
1017
1018
1019
1020
1021
1022
1023
1024 @Override
1025 public void broadcast(FacesEvent event) throws AbortProcessingException
1026 {
1027 if (event instanceof FacesEventWrapper)
1028 {
1029 FacesEvent originalEvent = ((FacesEventWrapper) event).getWrappedFacesEvent();
1030 int eventRowIndex = ((FacesEventWrapper) event).getRowIndex();
1031 final int currentRowIndex = getRowIndex();
1032 UIComponent source = originalEvent.getComponent();
1033 UIComponent compositeParent = UIComponent.getCompositeComponentParent(source);
1034
1035 setRowIndex(eventRowIndex);
1036 if (compositeParent != null)
1037 {
1038 pushComponentToEL(getFacesContext(), compositeParent);
1039 }
1040 pushComponentToEL(getFacesContext(), source);
1041 try
1042 {
1043 source.broadcast(originalEvent);
1044 }
1045 finally
1046 {
1047 source.popComponentFromEL(getFacesContext());
1048 if (compositeParent != null)
1049 {
1050 compositeParent.popComponentFromEL(getFacesContext());
1051 }
1052 setRowIndex(currentRowIndex);
1053 }
1054 }
1055 else
1056 {
1057 super.broadcast(event);
1058 }
1059 }
1060
1061
1062
1063
1064
1065
1066
1067 public String createUniqueId(FacesContext context, String seed)
1068 {
1069 StringBuilder bld = __getSharedStringBuilder(context);
1070
1071
1072
1073 if(seed==null)
1074 {
1075 Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
1076 uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
1077 getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
1078 return bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append(uniqueIdCounter).toString();
1079 }
1080
1081
1082 else
1083 {
1084 return bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append(seed).toString();
1085 }
1086 }
1087
1088
1089
1090
1091
1092 @Override
1093 public void encodeBegin(FacesContext context) throws IOException
1094 {
1095 _initialDescendantComponentState = null;
1096 if (_isValidChilds && !hasErrorMessages(context))
1097 {
1098
1099
1100
1101 _dataModelMap.clear();
1102
1103
1104
1105
1106
1107 _rowStates.clear();
1108 }
1109 super.encodeBegin(context);
1110 }
1111
1112 private boolean hasErrorMessages(FacesContext context)
1113 {
1114
1115
1116 List<FacesMessage> messageList = context.getMessageList();
1117 for (int i = 0, size = messageList.size(); i < size; i++)
1118 {
1119 FacesMessage message = messageList.get(i);
1120 if (FacesMessage.SEVERITY_ERROR.compareTo(message.getSeverity()) <= 0)
1121 {
1122 return true;
1123 }
1124 }
1125 return false;
1126 }
1127
1128
1129
1130
1131 @Override
1132 public void encodeEnd(FacesContext context) throws IOException
1133 {
1134 try
1135 {
1136 setCachedFacesContext(context);
1137 setRowIndex(-1);
1138 }
1139 finally
1140 {
1141 setCachedFacesContext(null);
1142 }
1143 super.encodeEnd(context);
1144 }
1145
1146 @Override
1147 public void processDecodes(FacesContext context)
1148 {
1149 if (context == null)
1150 {
1151 throw new NullPointerException("context");
1152 }
1153 try
1154 {
1155 setCachedFacesContext(context);
1156 pushComponentToEL(context, this);
1157 if (!isRendered())
1158 {
1159 return;
1160 }
1161 setRowIndex(-1);
1162 processFacets(context, PROCESS_DECODES);
1163 processColumnFacets(context, PROCESS_DECODES);
1164 processColumnChildren(context, PROCESS_DECODES);
1165 setRowIndex(-1);
1166 try
1167 {
1168 decode(context);
1169 }
1170 catch (RuntimeException e)
1171 {
1172 context.renderResponse();
1173 throw e;
1174 }
1175 }
1176 finally
1177 {
1178 popComponentFromEL(context);
1179 setCachedFacesContext(null);
1180 }
1181 }
1182
1183 @Override
1184 public void processValidators(FacesContext context)
1185 {
1186 if (context == null)
1187 {
1188 throw new NullPointerException("context");
1189 }
1190
1191 try
1192 {
1193 setCachedFacesContext(context);
1194 pushComponentToEL(context, this);
1195 if (!isRendered())
1196 {
1197 return;
1198 }
1199
1200
1201 context.getApplication().publishEvent(context, PreValidateEvent.class, getClass(), this);
1202
1203 try
1204 {
1205 setRowIndex(-1);
1206 processFacets(context, PROCESS_VALIDATORS);
1207 processColumnFacets(context, PROCESS_VALIDATORS);
1208 processColumnChildren(context, PROCESS_VALIDATORS);
1209 setRowIndex(-1);
1210 }
1211 finally
1212 {
1213 context.getApplication().publishEvent(context, PostValidateEvent.class, getClass(), this);
1214 }
1215
1216
1217 if (context.getRenderResponse())
1218 {
1219 _isValidChilds = false;
1220 }
1221 }
1222 finally
1223 {
1224 popComponentFromEL(context);
1225 setCachedFacesContext(null);
1226 }
1227 }
1228
1229 @Override
1230 public void processUpdates(FacesContext context)
1231 {
1232 if (context == null)
1233 {
1234 throw new NullPointerException("context");
1235 }
1236 try
1237 {
1238 setCachedFacesContext(context);
1239 pushComponentToEL(context, this);
1240 if (!isRendered())
1241 {
1242 return;
1243 }
1244 setRowIndex(-1);
1245 processFacets(context, PROCESS_UPDATES);
1246 processColumnFacets(context, PROCESS_UPDATES);
1247 processColumnChildren(context, PROCESS_UPDATES);
1248 setRowIndex(-1);
1249
1250 if (context.getRenderResponse())
1251 {
1252 _isValidChilds = false;
1253 }
1254 }
1255 finally
1256 {
1257 popComponentFromEL(context);
1258 setCachedFacesContext(null);
1259 }
1260 }
1261
1262 private void processFacets(FacesContext context, int processAction)
1263 {
1264 if (this.getFacetCount() > 0)
1265 {
1266 for (UIComponent facet : getFacets().values())
1267 {
1268 process(context, facet, processAction);
1269 }
1270 }
1271 }
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282 private void processColumnFacets(FacesContext context, int processAction)
1283 {
1284 for (int i = 0, childCount = getChildCount(); i < childCount; i++)
1285 {
1286 UIComponent child = getChildren().get(i);
1287 if (child instanceof UIColumn)
1288 {
1289 if (! _ComponentUtils.isRendered(context, child))
1290 {
1291
1292 continue;
1293 }
1294
1295 if (child.getFacetCount() > 0)
1296 {
1297 for (UIComponent facet : child.getFacets().values())
1298 {
1299 process(context, facet, processAction);
1300 }
1301 }
1302 }
1303 }
1304 }
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315 private void processColumnChildren(FacesContext context, int processAction)
1316 {
1317 int first = getFirst();
1318 int rows = getRows();
1319 int last;
1320 if (rows == 0)
1321 {
1322 last = getRowCount();
1323 }
1324 else
1325 {
1326 last = first + rows;
1327 }
1328 for (int rowIndex = first; last == -1 || rowIndex < last; rowIndex++)
1329 {
1330 setRowIndex(rowIndex);
1331
1332
1333 if (!isRowAvailable())
1334 {
1335 break;
1336 }
1337
1338 for (int i = 0, childCount = getChildCount(); i < childCount; i++)
1339 {
1340 UIComponent child = getChildren().get(i);
1341 if (child instanceof UIColumn)
1342 {
1343 if (! _ComponentUtils.isRendered(context, child))
1344 {
1345
1346 continue;
1347 }
1348 for (int j = 0, columnChildCount = child.getChildCount(); j < columnChildCount; j++)
1349 {
1350 UIComponent columnChild = child.getChildren().get(j);
1351 process(context, columnChild, processAction);
1352 }
1353 }
1354 }
1355 }
1356 }
1357
1358 private void process(FacesContext context, UIComponent component, int processAction)
1359 {
1360 switch (processAction)
1361 {
1362 case PROCESS_DECODES:
1363 component.processDecodes(context);
1364 break;
1365 case PROCESS_VALIDATORS:
1366 component.processValidators(context);
1367 break;
1368 case PROCESS_UPDATES:
1369 component.processUpdates(context);
1370 break;
1371 }
1372 }
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385 protected DataModel getDataModel()
1386 {
1387 DataModel dataModel;
1388 String clientID = "";
1389
1390 UIComponent parent = getParent();
1391 if (parent != null)
1392 {
1393 clientID = parent.getContainerClientId(getFacesContext());
1394 }
1395 dataModel = _dataModelMap.get(clientID);
1396 if (dataModel == null)
1397 {
1398 dataModel = createDataModel();
1399 _dataModelMap.put(clientID, dataModel);
1400 }
1401 return dataModel;
1402 }
1403
1404 protected void setDataModel(DataModel dataModel)
1405 {
1406 throw new UnsupportedOperationException("this method is here only to maintain binary compatibility w/ the RI");
1407 }
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419 private DataModel createDataModel()
1420 {
1421 Object value = getValue();
1422
1423 if (value == null)
1424 {
1425 return EMPTY_DATA_MODEL;
1426 }
1427 else if (value instanceof DataModel)
1428 {
1429 return (DataModel) value;
1430 }
1431 else if (value instanceof List)
1432 {
1433 return new ListDataModel((List<?>) value);
1434 }
1435 else if (OBJECT_ARRAY_CLASS.isAssignableFrom(value.getClass()))
1436 {
1437 return new ArrayDataModel((Object[]) value);
1438 }
1439 else if (value instanceof ResultSet)
1440 {
1441 return new ResultSetDataModel((ResultSet) value);
1442 }
1443 else if (value instanceof Result)
1444 {
1445 return new ResultDataModel((Result) value);
1446 }
1447 else
1448 {
1449 return new ScalarDataModel(value);
1450 }
1451 }
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470 @JSFProperty
1471 public Object getValue()
1472 {
1473 return getStateHelper().eval(PropertyKeys.value);
1474 }
1475
1476 public void setValue(Object value)
1477 {
1478 getStateHelper().put(PropertyKeys.value, value );
1479 _dataModelMap.clear();
1480 _rowStates.clear();
1481 _isValidChilds = true;
1482 }
1483
1484
1485
1486
1487 @JSFProperty
1488 public int getFirst()
1489 {
1490 return (Integer) getStateHelper().eval(PropertyKeys.first,0);
1491 }
1492
1493 public void setFirst(int first)
1494 {
1495 if (first < 0)
1496 {
1497 throw new IllegalArgumentException("Illegal value for first row: " + first);
1498 }
1499 getStateHelper().put(PropertyKeys.first, first );
1500 }
1501
1502
1503
1504
1505
1506
1507
1508 @JSFProperty
1509 public int getRows()
1510 {
1511 return (Integer) getStateHelper().eval(PropertyKeys.rows,0);
1512 }
1513
1514
1515
1516
1517 public void setRows(int rows)
1518 {
1519 if (rows < 0)
1520 {
1521 throw new IllegalArgumentException("rows: " + rows);
1522 }
1523 getStateHelper().put(PropertyKeys.rows, rows );
1524 }
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536 @JSFProperty(literalOnly = true)
1537 public String getVar()
1538 {
1539 return (String) getStateHelper().get(PropertyKeys.var);
1540 }
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554 @Override
1555 public boolean visitTree(VisitContext context, VisitCallback callback)
1556 {
1557 if (!isVisitable(context))
1558 {
1559 return false;
1560 }
1561
1562 boolean isCachedFacesContext = isCachedFacesContext();
1563 if (!isCachedFacesContext)
1564 {
1565 setCachedFacesContext(context.getFacesContext());
1566 }
1567
1568 int oldRowIndex = getRowIndex();
1569
1570 setRowIndex(-1);
1571
1572 pushComponentToEL(context.getFacesContext(), this);
1573 try
1574 {
1575 VisitResult visitResult = context.invokeVisitCallback(this,
1576 callback);
1577 switch (visitResult)
1578 {
1579
1580 case COMPLETE:
1581 return true;
1582
1583 case REJECT:
1584 return false;
1585
1586
1587 default:
1588
1589 Collection<String> subtreeIdsToVisit = context
1590 .getSubtreeIdsToVisit(this);
1591 boolean doVisitChildren = subtreeIdsToVisit != null
1592 && !subtreeIdsToVisit.isEmpty();
1593 if (doVisitChildren)
1594 {
1595
1596 if (getFacetCount() > 0)
1597 {
1598 for (UIComponent facet : getFacets().values())
1599 {
1600 if (facet.visitTree(context, callback))
1601 {
1602 return true;
1603 }
1604 }
1605 }
1606 Boolean skipIterationHint = (Boolean) context.getFacesContext().getAttributes().get(SKIP_ITERATION_HINT);
1607 if (skipIterationHint != null && skipIterationHint.booleanValue())
1608 {
1609
1610 for (int i = 0, childCount = getChildCount(); i < childCount; i++ )
1611 {
1612 UIComponent child = getChildren().get(i);
1613 if (child.visitTree(context, callback))
1614 {
1615 return true;
1616 }
1617 }
1618 }
1619 else
1620 {
1621
1622
1623
1624 for (int i = 0, childCount = getChildCount(); i < childCount; i++)
1625 {
1626 UIComponent child = getChildren().get(i);
1627 if (child instanceof UIColumn)
1628 {
1629 VisitResult columnResult = context.invokeVisitCallback(child, callback);
1630 if (columnResult == VisitResult.COMPLETE)
1631 {
1632 return true;
1633 }
1634 if (child.getFacetCount() > 0)
1635 {
1636 for (UIComponent facet : child.getFacets().values())
1637 {
1638 if (facet.visitTree(context, callback))
1639 {
1640 return true;
1641 }
1642 }
1643 }
1644 }
1645 }
1646
1647 int rowsToProcess = getRows();
1648
1649 if (rowsToProcess == 0)
1650 {
1651 rowsToProcess = getRowCount();
1652 }
1653 int rowIndex = getFirst();
1654 for (int rowsProcessed = 0; rowsProcessed < rowsToProcess; rowsProcessed++, rowIndex++)
1655 {
1656 setRowIndex(rowIndex);
1657 if (!isRowAvailable())
1658 {
1659 return false;
1660 }
1661
1662 for (int i = 0, childCount = getChildCount(); i < childCount; i++)
1663 {
1664 UIComponent child = getChildren().get(i);
1665 if (child instanceof UIColumn)
1666 {
1667 for (int j = 0, grandChildCount = child.getChildCount(); j < grandChildCount; j++)
1668 {
1669 UIComponent grandchild = child.getChildren().get(j);
1670 if (grandchild.visitTree(context, callback))
1671 {
1672 return true;
1673 }
1674 }
1675 }
1676 }
1677 }
1678 }
1679 }
1680 }
1681 }
1682 finally
1683 {
1684
1685 popComponentFromEL(context.getFacesContext());
1686 setRowIndex(oldRowIndex);
1687 if (!isCachedFacesContext)
1688 {
1689 setCachedFacesContext(null);
1690 }
1691 }
1692
1693
1694 return false;
1695 }
1696
1697 public void setVar(String var)
1698 {
1699 getStateHelper().put(PropertyKeys.var, var );
1700 }
1701
1702 enum PropertyKeys
1703 {
1704 value
1705 , first
1706 , rows
1707 , var
1708 , uniqueIdCounter
1709 }
1710
1711 @Override
1712 public String getFamily()
1713 {
1714 return COMPONENT_FAMILY;
1715 }
1716 }