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