1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.trinidad.component;
20
21 import java.io.IOException;
22 import java.io.ObjectInputStream;
23 import java.io.Serializable;
24
25 import java.util.AbstractMap;
26 import java.util.Collections;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30
31 import javax.faces.FacesException;
32 import javax.faces.component.ContextCallback;
33 import javax.faces.component.NamingContainer;
34 import javax.faces.component.UIComponent;
35 import javax.faces.component.visit.VisitCallback;
36 import javax.faces.component.visit.VisitContext;
37 import javax.faces.component.visit.VisitContextWrapper;
38 import javax.faces.component.visit.VisitResult;
39 import javax.faces.context.FacesContext;
40 import javax.faces.event.AbortProcessingException;
41 import javax.faces.event.ComponentSystemEvent;
42 import javax.faces.event.FacesEvent;
43 import javax.faces.event.PhaseId;
44 import javax.faces.render.Renderer;
45
46 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
47 import org.apache.myfaces.trinidad.bean.FacesBean;
48 import org.apache.myfaces.trinidad.bean.PropertyKey;
49 import org.apache.myfaces.trinidad.context.ComponentContextChange;
50 import org.apache.myfaces.trinidad.context.ComponentContextManager;
51 import org.apache.myfaces.trinidad.context.RequestContext;
52 import org.apache.myfaces.trinidad.event.SelectionEvent;
53 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
54 import org.apache.myfaces.trinidad.model.CollectionModel;
55 import org.apache.myfaces.trinidad.model.LocalRowKeyIndex;
56 import org.apache.myfaces.trinidad.model.SortCriterion;
57 import org.apache.myfaces.trinidad.render.ClientRowKeyManager;
58 import org.apache.myfaces.trinidad.render.ClientRowKeyManagerFactory;
59 import org.apache.myfaces.trinidad.util.ComponentUtils;
60
61
62
63
64
65
66
67
68 @JSFComponent
69 public abstract class UIXCollection extends UIXComponentBase
70 implements NamingContainer
71 {
72 static public final FacesBean.Type TYPE = new FacesBean.Type(
73 UIXComponentBase.TYPE);
74 static public final PropertyKey VAR_KEY =
75 TYPE.registerKey("var", String.class, PropertyKey.CAP_NOT_BOUND);
76
77 protected UIXCollection(String rendererType)
78 {
79 super(rendererType);
80 }
81
82 protected UIXCollection()
83 {
84 this(null);
85 }
86
87
88
89
90
91
92 final public String getVar()
93 {
94 return ComponentUtils.resolveString(getProperty(VAR_KEY));
95 }
96
97
98
99
100
101
102 final public void setVar(String var)
103 {
104 setProperty(VAR_KEY, (var));
105 InternalState iState = _getInternalState(false);
106 if (iState != null)
107 {
108 iState._var = var;
109 }
110 }
111
112
113
114
115
116
117
118 @Override
119 public void queueEvent(FacesEvent event)
120 {
121 if (event.getSource() == this)
122 {
123
124
125 if (!(event instanceof SelectionEvent))
126 {
127 InternalState iState = _getInternalState(true);
128 iState._hasEvent = true;
129 }
130 }
131
132
133
134
135 Object currencyKey = getRowKey();
136 event = new TableRowEvent(this, event, currencyKey);
137
138
139
140 super.queueEvent(new CollectionContextEvent(this, event));
141 }
142
143
144
145
146
147
148
149 @Override
150 public void broadcast(FacesEvent event)
151 throws AbortProcessingException
152 {
153
154
155 if (event instanceof CollectionContextEvent)
156 {
157 _setupContextChange();
158 try
159 {
160 this.broadcast(((CollectionContextEvent)event).getEvent());
161 }
162 finally
163 {
164 _tearDownContextChange();
165 }
166 }
167 else
168 {
169
170
171 if (event instanceof TableRowEvent)
172 {
173 TableRowEvent rowEvent = (TableRowEvent) event;
174 Object old = getRowKey();
175 setRowKey(rowEvent.getCurrencyKey());
176 FacesEvent wrapped = rowEvent.getEvent();
177 wrapped.getComponent().broadcast(wrapped);
178 setRowKey(old);
179 }
180 else
181 {
182 super.broadcast(event);
183 }
184 }
185 }
186
187
188
189
190
191
192 @Override
193 public final void processDecodes(FacesContext context)
194 {
195 if (context == null)
196 throw new NullPointerException();
197
198 _setupContextChange();
199 try
200 {
201 _init();
202
203 InternalState iState = _getInternalState(true);
204 iState._isFirstRender = false;
205
206 if (!isRendered())
207 return;
208
209 __flushCachedModel();
210
211
212 iState._hasEvent = false;
213
214
215
216
217
218
219
220
221 decode(context);
222
223
224 decodeChildren(context);
225 }
226 finally
227 {
228 _tearDownContextChange();
229 }
230 }
231
232 @Override
233 protected void decodeChildrenImpl(FacesContext context)
234 {
235 processFacetsAndChildren(context, PhaseId.APPLY_REQUEST_VALUES);
236 }
237
238 @Override
239 protected void validateChildrenImpl(FacesContext context)
240 {
241 processFacetsAndChildren(context, PhaseId.PROCESS_VALIDATIONS);
242 }
243
244 @Override
245 protected void updateChildrenImpl(FacesContext context)
246 {
247 processFacetsAndChildren(context, PhaseId.UPDATE_MODEL_VALUES);
248 }
249
250
251
252
253
254
255 public void resetStampState()
256 {
257 InternalState iState = _getInternalState(true);
258
259 Object initKey = _getCurrencyKeyForInitialStampState();
260
261
262
263 if (iState._stampState != null)
264 iState._stampState.clear(initKey);
265 }
266
267 @Override
268 public Object processSaveState(FacesContext context)
269 {
270 _setupContextChange();
271 try
272 {
273 _stateSavingCurrencyKey = _resetCurrencyKeyForStateSaving(context);
274
275 Object savedState = super.processSaveState(context);
276
277 _restoreCurrencyKeyForStateSaving(_stateSavingCurrencyKey);
278 _resetInternalState();
279
280 return savedState;
281 }
282 finally
283 {
284 _tearDownContextChange();
285 }
286 }
287
288 @Override
289 public Object saveState(FacesContext context)
290 {
291
292
293 Object superState = super.saveState(context);
294 final Object stampState, clientKeyMgr;
295
296
297
298
299 InternalState iState = _getInternalState(false);
300 if (iState != null)
301 {
302 stampState = iState._stampState;
303 clientKeyMgr = iState._clientKeyMgr;
304 }
305 else
306 {
307 stampState = null;
308 clientKeyMgr = null;
309 }
310
311 if ((superState != null) || (stampState != null) || (clientKeyMgr != null))
312 return new Object[]{superState, stampState, clientKeyMgr};
313 return null;
314 }
315
316
317 @SuppressWarnings("unchecked")
318 @Override
319 public void restoreState(FacesContext context, Object state)
320 {
321 final Object superState, stampState, clientKeyMgr;
322 Object[] array = (Object[]) state;
323 if (array != null)
324 {
325 superState = array[0];
326 stampState = array[1];
327 clientKeyMgr = array[2];
328 }
329 else
330 {
331 superState = null;
332 stampState = null;
333 clientKeyMgr = null;
334 }
335 super.restoreState(context, superState);
336
337 if ((stampState != null) || (clientKeyMgr != null))
338 {
339 InternalState iState = _getInternalState(true);
340 iState._stampState = (StampState) stampState;
341 iState._clientKeyMgr = (ClientRowKeyManager) clientKeyMgr;
342 }
343 else
344 {
345
346
347 InternalState iState = _getInternalState(false);
348 if (iState != null)
349 {
350 iState._stampState = null;
351 iState._clientKeyMgr = null;
352 }
353 }
354 }
355
356
357
358
359
360
361
362 public final boolean isRowAvailable()
363 {
364 return getCollectionModel().isRowAvailable();
365 }
366
367
368
369
370
371
372 public final boolean isRowAvailable(Object rowKey)
373 {
374 return getCollectionModel().isRowAvailable(rowKey);
375 }
376
377
378
379
380
381
382 public final Object getRowData(Object rowKey)
383 {
384 return getCollectionModel().getRowData(rowKey);
385 }
386
387
388
389
390
391
392 public final boolean areRowsAvailable(int rowCount)
393 {
394 return getCollectionModel().areRowsAvailable(rowCount);
395 }
396
397
398
399
400
401
402
403
404 public final boolean areRowsAvailable(int startIndex, int rowCount)
405 {
406 return getCollectionModel().areRowsAvailable(startIndex, rowCount);
407 }
408
409
410
411
412
413
414
415
416 public final boolean areRowsAvailable(Object startRowKey, int rowCount)
417 {
418 return getCollectionModel().areRowsAvailable(startRowKey, rowCount);
419 }
420
421
422
423
424
425
426
427
428 public final int getRowCount()
429 {
430 return getCollectionModel().getRowCount();
431 }
432
433
434
435
436
437
438 public final int getRowIndex()
439 {
440 return getCollectionModel().getRowIndex();
441 }
442
443
444
445
446
447
448 public final Object getRowKey()
449 {
450 InternalState iState = _getInternalState(true);
451 if (iState._currentRowKey == _NULL)
452 {
453
454
455
456
457
458 iState._currentRowKey = getCollectionModel().getRowKey();
459 }
460
461 return iState._currentRowKey;
462 }
463
464
465
466
467
468
469 public final Object getRowData()
470 {
471 CollectionModel model = getCollectionModel();
472
473
474 return model.isRowAvailable() ? model.getRowData() : null;
475 }
476
477
478
479
480
481
482
483 public boolean isRowAvailable(int rowIndex)
484 {
485 return getCollectionModel().isRowAvailable(rowIndex);
486 }
487
488
489
490
491
492
493
494 public Object getRowData(int rowIndex)
495 {
496 return getCollectionModel().getRowData(rowIndex);
497 }
498
499
500
501
502
503 public abstract String getVarStatus();
504
505
506
507
508
509
510
511
512
513 public void setRowKey(Object rowKey)
514 {
515 _verifyComponentInContext();
516
517 preRowDataChange();
518 getCollectionModel().setRowKey(rowKey);
519 postRowDataChange();
520 if (_LOG.isFine() && (rowKey != null) && (!isRowAvailable()))
521 _LOG.fine("no row available for rowKey:"+rowKey);
522 }
523
524
525
526
527
528
529
530
531
532 public void setRowIndex(int rowIndex)
533 {
534 _verifyComponentInContext();
535
536 preRowDataChange();
537 getCollectionModel().setRowIndex(rowIndex);
538 postRowDataChange();
539 if (_LOG.isFine() && (rowIndex != -1) && (!isRowAvailable()))
540 _LOG.fine("no row available for rowIndex:"+rowIndex);
541 }
542
543
544
545
546
547
548 public final boolean isSortable(String property)
549 {
550 return getCollectionModel().isSortable(property);
551 }
552
553
554
555
556
557
558
559 public void setSortCriteria(List<SortCriterion> criteria)
560 {
561 getCollectionModel().setSortCriteria(criteria);
562 }
563
564
565
566
567
568
569
570
571 public final List<SortCriterion> getSortCriteria()
572 {
573 return getCollectionModel().getSortCriteria();
574 }
575
576
577
578
579
580
581
582
583
584 @Deprecated
585 protected void clearCurrencyStringCache()
586 {
587 _getInternalState(true)._clearTokenCache = true;
588 }
589
590
591
592
593 @Override
594 public final void encodeBegin(FacesContext context) throws IOException
595 {
596 _setupContextChange();
597 boolean teardown = true;
598 try
599 {
600 _init();
601
602 InternalState istate = _getInternalState(true);
603
604
605
606
607 if (istate._clearTokenCache)
608 {
609 istate._clearTokenCache = false;
610 ClientRowKeyManager keyMgr = getClientRowKeyManager();
611 if (keyMgr instanceof DefaultClientKeyManager)
612 ((DefaultClientKeyManager) keyMgr).clear();
613 }
614 __flushCachedModel();
615
616 Object assertKey = null;
617 assert ((assertKey = getRowKey()) != null) || true;
618 __encodeBegin(context);
619
620 assert _assertKeyPreserved(assertKey) : "CurrencyKey not preserved";
621
622 teardown = false;
623 }
624 finally
625 {
626 if (teardown)
627 {
628
629 _tearDownContextChange();
630 }
631 }
632 }
633
634 @Override
635 public void encodeEnd(FacesContext context) throws IOException
636 {
637 try
638 {
639 Object assertKey = null;
640 assert ((assertKey = getRowKey()) != null) || true;
641 super.encodeEnd(context);
642
643 assert _assertKeyPreserved(assertKey) : "CurrencyKey not preserved";
644 }
645 finally
646 {
647 _tearDownContextChange();
648 }
649 }
650
651 @Override
652 protected void setupVisitingContext(FacesContext context)
653 {
654 super.setupVisitingContext(context);
655 _setupContextChange();
656
657 if (Boolean.TRUE.equals(context.getAttributes().get("javax.faces.IS_SAVING_STATE")))
658 {
659 _stateSavingCurrencyKey = _resetCurrencyKeyForStateSaving(context);
660 }
661 }
662
663 @Override
664 protected void tearDownVisitingContext(FacesContext context)
665 {
666 if (Boolean.TRUE.equals(context.getAttributes().get("javax.faces.IS_SAVING_STATE")))
667 {
668 _restoreCurrencyKeyForStateSaving(_stateSavingCurrencyKey);
669 _resetInternalState();
670 }
671
672 _tearDownContextChange();
673 super.tearDownVisitingContext(context);
674 }
675
676 private boolean _assertKeyPreserved(Object oldKey)
677 {
678 Object newKey = getRowKey();
679 return (oldKey != null) ? oldKey.equals(newKey) : (newKey == null);
680 }
681
682 void __encodeBegin(FacesContext context) throws IOException
683 {
684 super.encodeBegin(context);
685 }
686
687
688
689
690
691 boolean __isFirstRender()
692 {
693 InternalState iState = _getInternalState(true);
694 return iState._isFirstRender;
695 }
696
697
698
699
700
701 @Deprecated
702 public String getCurrencyString()
703 {
704 return getClientRowKey();
705 }
706
707
708
709
710
711 @Deprecated
712 public void setCurrencyString(String currency)
713 {
714 setClientRowKey(currency);
715 }
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731 public String getClientRowKey()
732 {
733
734
735
736
737
738 Object currencyObject = _getCurrencyKey();
739 if (currencyObject == null)
740 return null;
741
742 Object initKey = _getCurrencyKeyForInitialStampState();
743 if (_equals(currencyObject, initKey))
744 return null;
745
746 FacesContext fc = FacesContext.getCurrentInstance();
747 String key = getClientRowKeyManager().getClientRowKey(fc, this, currencyObject);
748 return key;
749 }
750
751
752
753
754
755
756
757
758 private Object _getCurrencyKey()
759 {
760
761
762
763
764 InternalState iState = _getInternalState(false);
765 if (iState == null)
766 return null;
767
768 return (iState._model != null)
769 ? getRowKey()
770 : _getCurrencyKeyForInitialStampState();
771 }
772
773
774
775
776
777
778 public void setClientRowKey(String clientRowKey)
779 {
780 if (clientRowKey == null)
781 {
782 setRowKey(_getCurrencyKeyForInitialStampState());
783 return;
784 }
785
786 FacesContext fc = FacesContext.getCurrentInstance();
787 Object rowkey = getClientRowKeyManager().getRowKey(fc, this, clientRowKey);
788
789 if (rowkey == null)
790 {
791 _LOG.severe("CANNOT_FIND_ROWKEY",clientRowKey);
792 }
793 else
794 setRowKey(rowkey);
795 }
796
797 public void processRestoreState(
798 FacesContext context,
799 Object state)
800 {
801 _setupContextChange();
802 try
803 {
804 super.processRestoreState(context, state);
805 }
806 finally
807 {
808 _tearDownContextChange();
809 }
810 }
811
812 public void processUpdates(FacesContext context)
813 {
814 _setupContextChange();
815 try
816 {
817 super.processUpdates(context);
818 }
819 finally
820 {
821 _tearDownContextChange();
822 }
823 }
824
825 public void processValidators(FacesContext context)
826 {
827 _setupContextChange();
828 try
829 {
830 super.processValidators(context);
831 }
832 finally
833 {
834 _tearDownContextChange();
835 }
836 }
837
838 public void processEvent(ComponentSystemEvent event)
839 throws AbortProcessingException
840 {
841 _setupContextChange();
842 try
843 {
844 super.processEvent(event);
845 }
846 finally
847 {
848 _tearDownContextChange();
849 }
850 }
851
852
853
854
855
856
857
858
859
860
861 @Override
862 public final String getContainerClientId(FacesContext context)
863 {
864 String id = getClientId(context);
865 String key = getClientRowKey();
866 if (key != null)
867 {
868 StringBuilder bld = __getSharedStringBuilder();
869 bld.append(id).append(NamingContainer.SEPARATOR_CHAR).append(key);
870 id = bld.toString();
871 }
872
873 return id;
874 }
875
876
877
878
879
880
881
882 protected final void preRowDataChange()
883 {
884 _saveStampState();
885 InternalState iState = _getInternalState(true);
886
887 iState._currentRowKey = _NULL;
888 }
889
890
891
892
893
894
895
896
897 protected final void postRowDataChange()
898 {
899 Object rowData = getRowData();
900 if (_LOG.isFinest() && (rowData == null))
901 {
902 _LOG.finest("rowData is null at rowIndex:"+getRowIndex()+
903 " and currencyKey:"+getRowKey());
904 }
905
906 InternalState iState = _getInternalState(true);
907 if (rowData == null)
908 {
909
910
911 if (iState._prevVarValue != _NULL)
912 {
913 _setELVar(iState._var, iState._prevVarValue);
914 iState._prevVarValue = _NULL;
915 }
916 if (iState._prevVarStatus != _NULL)
917 {
918 _setELVar(iState._varStatus, iState._prevVarStatus);
919 iState._prevVarStatus = _NULL;
920 }
921 }
922 else
923 {
924 if (iState._var != null)
925 {
926 Object oldData = _setELVar(iState._var, rowData);
927 if (iState._prevVarValue == _NULL)
928 iState._prevVarValue = oldData;
929 }
930
931
932
933
934 if ((iState._varStatus != null) && (iState._prevVarStatus == _NULL))
935 {
936 Map<String, Object> varStatusMap = createVarStatusMap();
937 iState._prevVarStatus = _setELVar(iState._varStatus, varStatusMap);
938 }
939 }
940
941 _restoreStampState();
942
943
944
945
946 List<UIComponent> stamps = getStamps();
947
948 for (UIComponent stamp : stamps)
949 UIXComponent.clearCachedClientIds(stamp);
950 }
951
952
953
954
955
956
957 @SuppressWarnings("unchecked")
958 protected List<UIComponent> getStamps()
959 {
960 return getChildren();
961 }
962
963
964
965
966
967
968
969
970
971
972 private Object _getCurrencyKeyForInitialStampState()
973 {
974 InternalState iState = _getInternalState(false);
975 if (iState == null)
976 return null;
977
978 Object rowKey = iState._initialStampStateKey;
979 return (rowKey == _NULL) ? null : rowKey;
980 }
981
982
983
984
985
986
987
988
989
990 @SuppressWarnings("unchecked")
991 protected Object saveStampState(FacesContext context, UIComponent stamp)
992 {
993 if (stamp.isTransient())
994 return Transient.TRUE;
995
996 boolean needsTearDownContext = false;
997
998 if(stamp instanceof FlattenedComponent && stamp instanceof UIXComponent)
999 {
1000 ((UIXComponent)stamp).setupVisitingContext(context);
1001 needsTearDownContext = true;
1002 }
1003
1004 Object[] state = null;
1005
1006 try
1007 {
1008
1009
1010
1011
1012
1013
1014
1015
1016 Object stampState = StampState.saveStampState(context, stamp);
1017
1018
1019
1020
1021 assert(!(stampState instanceof Object[]));
1022
1023 int facetCount = stamp.getFacetCount();
1024
1025 if (facetCount > 0)
1026 {
1027 boolean facetStateIsEmpty = true;
1028 Object[] facetState = null;
1029
1030 Map<String, UIComponent> facetMap = stamp.getFacets();
1031
1032 int i = 0;
1033 for(Map.Entry<String, UIComponent> entry : facetMap.entrySet())
1034 {
1035 Object singleFacetState = saveStampState(context, entry.getValue());
1036 if ((singleFacetState == null) ||
1037 (singleFacetState == Transient.TRUE))
1038 continue;
1039
1040
1041
1042 if (facetStateIsEmpty)
1043 {
1044 facetStateIsEmpty = false;
1045 facetState = new Object[facetCount * 2];
1046 }
1047
1048 int base = i * 2;
1049 assert(facetState != null);
1050 facetState[base] = entry.getKey();
1051 facetState[base + 1] = singleFacetState;
1052 i++;
1053 }
1054
1055
1056
1057 if (!facetStateIsEmpty)
1058 {
1059
1060 if(i < facetCount)
1061 {
1062 Object[] trimmed = new Object[i*2];
1063 System.arraycopy(facetState, 0, trimmed, 0, i*2);
1064 facetState = trimmed;
1065 }
1066 state = new Object[3];
1067 state[2] = facetState;
1068 }
1069 }
1070
1071
1072
1073 Object childState = StampState.saveChildStampState(context,
1074 stamp,
1075 this);
1076 if (childState != null)
1077 {
1078
1079
1080 if (state == null)
1081 state = new Object[2];
1082 state[1] = childState;
1083 }
1084
1085
1086
1087 if (state == null)
1088 return stampState;
1089
1090
1091 state[0] = stampState;
1092 }
1093 finally
1094 {
1095 if(needsTearDownContext)
1096 ((UIXComponent)stamp).tearDownVisitingContext(context);
1097 }
1098 return state;
1099 }
1100
1101
1102
1103
1104
1105
1106
1107 @SuppressWarnings("unchecked")
1108 protected void restoreStampState(FacesContext context, UIComponent stamp,
1109 Object stampState)
1110 {
1111
1112 if ((stampState == Transient.TRUE) || (stampState == null))
1113 {
1114 return;
1115 }
1116
1117
1118
1119 if (!(stampState instanceof Object[]))
1120 {
1121 StampState.restoreStampState(context, stamp, stampState);
1122
1123 return;
1124 }
1125
1126 Object[] state = (Object[]) stampState;
1127 int stateSize = state.length;
1128
1129 assert(stateSize >= 1);
1130
1131 StampState.restoreStampState(context, stamp, state[0]);
1132
1133
1134
1135 if (stateSize >= 3)
1136 {
1137 Object[] facetStateArray = (Object[]) state[2];
1138
1139
1140 assert(facetStateArray != null);
1141
1142 for(int i=0; i<facetStateArray.length; i+=2)
1143 {
1144 String facetName = (String) facetStateArray[i];
1145 Object facetState = facetStateArray[i + 1];
1146 if (facetState != Transient.TRUE)
1147 restoreStampState(context, stamp.getFacet(facetName), facetState);
1148 }
1149 }
1150
1151
1152 if (stateSize >= 2)
1153 {
1154 StampState.restoreChildStampState(context,
1155 stamp,
1156 this,
1157 state[1]);
1158 }
1159 }
1160
1161
1162
1163
1164
1165
1166
1167
1168 protected final void processComponent(
1169 FacesContext context,
1170 UIComponent component,
1171 PhaseId phaseId)
1172 {
1173 if (component != null)
1174 {
1175 if (phaseId == PhaseId.APPLY_REQUEST_VALUES)
1176 component.processDecodes(context);
1177 else if (phaseId == PhaseId.PROCESS_VALIDATIONS)
1178 component.processValidators(context);
1179 else if (phaseId == PhaseId.UPDATE_MODEL_VALUES)
1180 component.processUpdates(context);
1181 else
1182 throw new IllegalArgumentException(_LOG.getMessage(
1183 "BAD_PHASEID",phaseId));
1184 }
1185 }
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195 protected abstract void processFacetsAndChildren(
1196 FacesContext context,
1197 PhaseId phaseId);
1198
1199
1200
1201
1202 protected final CollectionModel getCollectionModel()
1203 {
1204 return getCollectionModel(true);
1205 }
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216 public final ClientRowKeyManager getClientRowKeyManager()
1217 {
1218
1219
1220
1221 InternalState iState = _getInternalState(true);
1222 if (iState._clientKeyMgr == null)
1223 {
1224 FacesContext fc = FacesContext.getCurrentInstance();
1225 Renderer r = getRenderer(fc);
1226 iState._clientKeyMgr = (r instanceof ClientRowKeyManagerFactory)
1227 ? ((ClientRowKeyManagerFactory) r).createClientRowKeyManager(fc, this)
1228 : new DefaultClientKeyManager();
1229 }
1230 return iState._clientKeyMgr;
1231 }
1232
1233 public boolean invokeOnComponent(FacesContext context,
1234 String clientId,
1235 ContextCallback callback)
1236 throws FacesException
1237 {
1238 boolean invokedComponent;
1239 setupVisitingContext(context);
1240
1241 try
1242 {
1243 String thisClientId = getClientId(context);
1244 if (clientId.equals(thisClientId))
1245 {
1246 if (!_getAndMarkFirstInvokeForRequest(context, clientId))
1247 {
1248
1249
1250 _init();
1251
1252 __flushCachedModel();
1253 }
1254
1255 pushComponentToEL(context, null);
1256
1257 try
1258 {
1259 callback.invokeContextCallback(context, this);
1260 }
1261 finally
1262 {
1263 popComponentFromEL(context);
1264 }
1265
1266 invokedComponent = true;
1267 }
1268 else
1269 {
1270
1271
1272 int thisClientIdLength = thisClientId.length();
1273 if (clientId.startsWith(thisClientId) &&
1274 (clientId.charAt(thisClientIdLength) == NamingContainer.SEPARATOR_CHAR))
1275 {
1276 if (!_getAndMarkFirstInvokeForRequest(context, thisClientId))
1277 {
1278
1279
1280 _init();
1281
1282 __flushCachedModel();
1283 }
1284
1285 String postId = clientId.substring(thisClientIdLength + 1);
1286 int sepIndex = postId.indexOf(NamingContainer.SEPARATOR_CHAR);
1287
1288
1289 if (sepIndex < 0)
1290 return invokeOnChildrenComponents(context, clientId, callback);
1291 else
1292 {
1293 String currencyString = postId.substring(0, sepIndex);
1294 Object rowKey = getClientRowKeyManager().getRowKey(context, this, currencyString);
1295
1296
1297
1298 if (rowKey != null)
1299 {
1300 Object oldRowKey = getRowKey();
1301 try
1302 {
1303 setRowKey(rowKey);
1304 invokedComponent = invokeOnChildrenComponents(context, clientId, callback);
1305 }
1306 finally
1307 {
1308
1309 setRowKey(oldRowKey);
1310 }
1311 }
1312 else
1313 {
1314 invokedComponent = invokeOnChildrenComponents(context, clientId, callback);
1315 }
1316 }
1317 }
1318 else
1319 {
1320
1321 invokedComponent = false;
1322 }
1323 }
1324 }
1325 finally
1326 {
1327 tearDownVisitingContext(context);
1328 }
1329
1330 return invokedComponent;
1331 }
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347 @Override
1348 protected boolean visitChildren(
1349 VisitContext visitContext,
1350 VisitCallback callback)
1351 {
1352 return defaultVisitChildren(visitContext, callback);
1353 }
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363 protected boolean visitChildrenWithoutIterating(
1364 VisitContext visitContext,
1365 VisitCallback callback)
1366 {
1367 return visitAllChildren(visitContext, callback);
1368 }
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378 protected final boolean defaultVisitChildren(
1379 VisitContext visitContext,
1380 VisitCallback callback)
1381 {
1382 if (ComponentUtils.isSkipIterationVisit(visitContext))
1383 {
1384 return visitChildrenWithoutIterating(visitContext, callback);
1385 }
1386 else
1387 {
1388 boolean doneVisiting;
1389
1390
1391
1392 int oldRowIndex = getRowIndex();
1393 setRowIndex(-1);
1394
1395 try
1396 {
1397
1398 doneVisiting = visitUnstampedFacets(visitContext, callback);
1399
1400 if (!doneVisiting)
1401 {
1402 doneVisiting = _visitStampedColumnFacets(visitContext, callback);
1403
1404
1405 if (!doneVisiting)
1406 {
1407 doneVisiting = visitData(visitContext, callback);
1408 }
1409 }
1410 }
1411 finally
1412 {
1413
1414 setRowIndex(oldRowIndex);
1415 }
1416
1417 return doneVisiting;
1418 }
1419 }
1420
1421
1422
1423
1424
1425
1426
1427 protected boolean visitUnstampedFacets(
1428 VisitContext visitContext,
1429 VisitCallback callback)
1430 {
1431
1432 if (getFacetCount() > 0)
1433 {
1434 for (UIComponent facet : getFacets().values())
1435 {
1436 if (UIXComponent.visitTree(visitContext, facet, callback))
1437 {
1438 return true;
1439 }
1440 }
1441 }
1442
1443 return false;
1444 }
1445
1446
1447
1448
1449
1450
1451 private static class ColumnFacetsOnlyVisitContext extends VisitContextWrapper
1452 {
1453 public ColumnFacetsOnlyVisitContext(VisitContext wrappedContext)
1454 {
1455 _wrapped = wrappedContext;
1456 }
1457
1458 @Override
1459 public VisitContext getWrapped()
1460 {
1461 return _wrapped;
1462 }
1463
1464 @Override
1465 public VisitResult invokeVisitCallback(UIComponent component, VisitCallback callback)
1466 {
1467 if (component instanceof UIXColumn)
1468 {
1469 if (component.getFacetCount() > 0)
1470 {
1471
1472 for (UIComponent facetChild : component.getFacets().values())
1473 {
1474 if (UIXComponent.visitTree(getWrapped(), facetChild, callback))
1475 return VisitResult.COMPLETE;
1476 }
1477
1478
1479 for (UIComponent child : component.getChildren())
1480 {
1481 if (UIXComponent.visitTree(this, child, callback))
1482 return VisitResult.COMPLETE;
1483 }
1484 }
1485 }
1486
1487
1488
1489 return VisitResult.REJECT;
1490 }
1491
1492 private final VisitContext _wrapped;
1493 }
1494
1495
1496
1497
1498
1499 protected static final class NoColumnFacetsVisitContext extends VisitContextWrapper
1500 {
1501 NoColumnFacetsVisitContext(VisitContext wrapped)
1502 {
1503 _wrapped = wrapped;
1504 }
1505
1506 @Override
1507 public VisitContext getWrapped()
1508 {
1509 return _wrapped;
1510 }
1511
1512 @Override
1513 public VisitResult invokeVisitCallback(UIComponent component, VisitCallback callback)
1514 {
1515 if (component instanceof UIXColumn)
1516 {
1517 if (component.getChildCount() > 0)
1518 {
1519
1520 for (UIComponent child : component.getChildren())
1521 {
1522 if (UIXComponent.visitTree(this, child, callback))
1523 return VisitResult.COMPLETE;
1524 }
1525 }
1526
1527 return VisitResult.REJECT;
1528 }
1529 else
1530 {
1531
1532
1533
1534
1535
1536 VisitContext wrappedContext = getWrapped();
1537 VisitResult visitResult = wrappedContext.invokeVisitCallback(component, callback);
1538
1539 if (visitResult == VisitResult.ACCEPT)
1540 {
1541
1542 return (UIXComponent.visitChildren(wrappedContext, component, callback)) ?
1543 VisitResult.COMPLETE : VisitResult.REJECT;
1544 }
1545 else
1546 {
1547 return visitResult;
1548 }
1549 }
1550 }
1551
1552 private final VisitContext _wrapped;
1553 }
1554
1555
1556
1557
1558 private boolean _visitStampedColumnFacets(
1559 VisitContext visitContext,
1560 VisitCallback callback)
1561 {
1562
1563 List<UIComponent> stamps = getStamps();
1564
1565 if (!stamps.isEmpty())
1566 {
1567 VisitContext columnVisitingContext = new ColumnFacetsOnlyVisitContext(visitContext);
1568
1569 for (UIComponent stamp : stamps)
1570 {
1571 if (UIXComponent.visitTree(columnVisitingContext, stamp, callback))
1572 {
1573 return true;
1574 }
1575 }
1576 }
1577
1578 return false;
1579 }
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592 protected abstract boolean visitData(
1593 VisitContext visitContext,
1594 VisitCallback callback);
1595
1596
1597
1598
1599
1600
1601 protected final CollectionModel getCollectionModel(
1602 boolean createIfNull)
1603 {
1604 InternalState iState = _getInternalState(true);
1605 if (iState._model == null && createIfNull)
1606 {
1607
1608
1609
1610
1611
1612
1613 _init();
1614
1615 iState._value = getValue();
1616 iState._model = createCollectionModel(null, iState._value);
1617 postCreateCollectionModel(iState._model);
1618 assert iState._model != null;
1619 }
1620
1621 if ((iState._initialStampStateKey == _NULL) &&
1622 (iState._model != null))
1623 {
1624
1625
1626
1627
1628
1629 iState._initialStampStateKey = iState._model.getRowKey();
1630 }
1631 return iState._model;
1632 }
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644 protected abstract CollectionModel createCollectionModel(
1645 CollectionModel current,
1646 Object value);
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657 protected void postCreateCollectionModel(CollectionModel model)
1658 {
1659
1660 }
1661
1662
1663
1664
1665
1666 protected abstract Object getValue();
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679 protected Map<String, Object> createVarStatusMap()
1680 {
1681 return new AbstractMap<String, Object>()
1682 {
1683 @Override
1684 public Object get(Object key)
1685 {
1686
1687
1688 if ("model".equals(key))
1689 return getCollectionModel();
1690 if ("rowKey".equals(key))
1691 return getRowKey();
1692 if ("index".equals(key))
1693 return Integer.valueOf(getRowIndex());
1694 if("hierarchicalIndex".equals(key))
1695 {
1696 int rowIndex = getRowIndex();
1697 return rowIndex>=0 ? new Integer[]{rowIndex}: new Integer[]{};
1698 }
1699 if("hierarchicalLabel".equals(key))
1700 {
1701 int rowIndex = getRowIndex();
1702 return rowIndex>=0 ? Integer.toString(rowIndex+1): "";
1703 }
1704 if ("current".equals(key))
1705 return getRowData();
1706 return null;
1707 }
1708
1709 @Override
1710 public Set<Map.Entry<String, Object>> entrySet()
1711 {
1712 return Collections.emptySet();
1713 }
1714 };
1715 }
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727 public boolean isRowLocallyAvailable(int rowIndex)
1728 {
1729 return getCollectionModel().isRowLocallyAvailable(rowIndex);
1730 }
1731
1732
1733
1734
1735
1736
1737 public boolean isRowLocallyAvailable(Object rowKey)
1738 {
1739 return getCollectionModel().isRowLocallyAvailable(rowKey);
1740 }
1741
1742
1743
1744
1745
1746
1747 public boolean areRowsLocallyAvailable(int rowCount)
1748 {
1749 return getCollectionModel().areRowsLocallyAvailable(rowCount);
1750 }
1751
1752
1753
1754
1755
1756
1757
1758 public boolean areRowsLocallyAvailable(int startIndex, int rowCount)
1759 {
1760 return getCollectionModel().areRowsLocallyAvailable(startIndex, rowCount);
1761 }
1762
1763
1764
1765
1766
1767
1768
1769 public boolean areRowsLocallyAvailable(Object startRowKey, int rowCount)
1770 {
1771 return getCollectionModel().areRowsLocallyAvailable(startRowKey, rowCount);
1772 }
1773
1774
1775
1776
1777
1778
1779 public int getEstimatedRowCount()
1780 {
1781 return getCollectionModel().getEstimatedRowCount();
1782 }
1783
1784
1785
1786
1787
1788
1789 public LocalRowKeyIndex.Confidence getEstimatedRowCountConfidence()
1790 {
1791 return getCollectionModel().getEstimatedRowCountConfidence();
1792 }
1793
1794
1795
1796
1797 public void clearLocalCache()
1798 {
1799 getCollectionModel().clearLocalCache();
1800 }
1801
1802
1803
1804
1805
1806
1807 public void clearCachedRows(int startingIndex, int rowsToClear)
1808 {
1809 getCollectionModel().clearCachedRows(startingIndex, rowsToClear);
1810 }
1811
1812
1813
1814
1815
1816
1817 public void clearCachedRows(Object startingRowKey, int rowsToClear)
1818 {
1819 getCollectionModel().clearCachedRows(startingRowKey, rowsToClear);
1820 }
1821
1822
1823
1824
1825
1826 public void clearCachedRow(int index)
1827 {
1828 getCollectionModel().clearCachedRow(index);
1829 }
1830
1831
1832
1833
1834
1835 public void clearCachedRow(Object rowKey)
1836 {
1837 getCollectionModel().clearCachedRow(rowKey);
1838 }
1839
1840
1841
1842
1843
1844
1845 public LocalRowKeyIndex.LocalCachingStrategy getCachingStrategy()
1846 {
1847 return getCollectionModel().getCachingStrategy();
1848 }
1849
1850
1851
1852
1853
1854
1855
1856 void __init()
1857 {
1858 InternalState iState = _getInternalState(true);
1859 iState._var = getVar();
1860 if (_LOG.isFine() && (iState._var == null))
1861 {
1862 _LOG.fine("'var' attribute is null.");
1863 }
1864 iState._varStatus = getVarStatus();
1865 if (_LOG.isFinest() && (iState._varStatus == null))
1866 {
1867 _LOG.finest("'varStatus' attribute is null.");
1868 }
1869 }
1870
1871
1872
1873
1874
1875
1876
1877
1878 void __processFlattenedChildrenBegin()
1879 {
1880
1881
1882 _init();
1883 __flushCachedModel();
1884 }
1885
1886 private void _init()
1887 {
1888 InternalState iState = _getInternalState(true);
1889 if (!iState._isInitialized)
1890 {
1891 assert iState._model == null;
1892 iState._isInitialized = true;
1893 __init();
1894 }
1895 }
1896
1897 void __flushCachedModel()
1898 {
1899 InternalState iState = _getInternalState(true);
1900 Object value = getValue();
1901 if (iState._value != value)
1902 {
1903 iState._value = value;
1904 iState._model = createCollectionModel(iState._model, value);
1905 postCreateCollectionModel(iState._model);
1906 }
1907 }
1908
1909
1910
1911
1912 static private boolean _getAndMarkFirstInvokeForRequest(
1913 FacesContext context, String clientId)
1914 {
1915
1916
1917 Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
1918 String key = _INVOKE_KEY + clientId;
1919
1920 if (requestMap.containsKey(key))
1921 return true;
1922
1923
1924 requestMap.put(key, Boolean.TRUE);
1925 return false;
1926 }
1927
1928
1929
1930
1931
1932 Object __getMyStampState()
1933 {
1934 return _state;
1935 }
1936
1937
1938
1939
1940
1941
1942 void __setMyStampState(Object stampState)
1943 {
1944 InternalState iState = (InternalState) stampState;
1945 _state = iState;
1946 }
1947
1948
1949
1950
1951
1952
1953
1954 void __resetMyStampState()
1955 {
1956 _state = null;
1957 }
1958
1959
1960
1961
1962
1963
1964 boolean __hasEvent()
1965 {
1966 InternalState iState = _getInternalState(true);
1967 return iState._hasEvent;
1968 }
1969
1970
1971
1972
1973
1974
1975
1976 private void _saveStampState()
1977 {
1978
1979
1980
1981 StampState stampState = _getStampState();
1982 FacesContext context = getFacesContext();
1983 Object currencyObj = getRowKey();
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995 int position = 0;
1996 for (UIComponent stamp : getStamps())
1997 {
1998 Object state = saveStampState(context, stamp);
1999
2000
2001
2002
2003 String stampId = String.valueOf(position++);
2004 stampState.put(currencyObj, stampId, state);
2005 if (_LOG.isFinest())
2006 _LOG.finest("saving stamp state for currencyObject:"+currencyObj+
2007 " and stampId:"+stampId);
2008 }
2009 }
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019 private void _restoreStampState()
2020 {
2021 StampState stampState = _getStampState();
2022 FacesContext context = getFacesContext();
2023 Object currencyObj = getRowKey();
2024 int position = 0;
2025 for(UIComponent stamp : getStamps())
2026 {
2027
2028
2029
2030
2031 String stampId = String.valueOf(position++);
2032 Object state = stampState.get(currencyObj, stampId);
2033 if (state == null)
2034 {
2035 Object iniStateObj = _getCurrencyKeyForInitialStampState();
2036 state = stampState.get(iniStateObj, stampId);
2037
2038
2039
2040
2041
2042
2043 }
2044 restoreStampState(context, stamp, state);
2045 }
2046 }
2047
2048 private InternalState _getInternalState(boolean create)
2049 {
2050 if ((_state == null) && create)
2051 {
2052 _state = new InternalState();
2053 }
2054 return _state;
2055 }
2056
2057 private StampState _getStampState()
2058 {
2059 InternalState iState = _getInternalState(true);
2060 if (iState._stampState == null)
2061 iState._stampState = new StampState();
2062
2063 return iState._stampState;
2064 }
2065
2066
2067
2068
2069
2070
2071
2072 private Object _setELVar(String varName, Object newData)
2073 {
2074 if (varName == null)
2075 return null;
2076
2077
2078
2079
2080 return TableUtils.setupELVariable(getFacesContext(), varName, newData);
2081 }
2082
2083 private static boolean _equals(Object a, Object b)
2084 {
2085 if (b == null)
2086 return (a == null);
2087
2088 return b.equals(a);
2089 }
2090
2091 private void _setupContextChange()
2092 {
2093 if (_inSuspendOrResume)
2094 {
2095
2096
2097 return;
2098 }
2099
2100 ComponentContextManager compCtxMgr =
2101 RequestContext.getCurrentInstance().getComponentContextManager();
2102
2103 compCtxMgr.pushChange(new CollectionComponentChange(this));
2104 }
2105
2106 private void _tearDownContextChange()
2107 {
2108 if (_inSuspendOrResume)
2109 {
2110
2111
2112 return;
2113 }
2114
2115 try
2116 {
2117 ComponentContextManager compCtxMgr =
2118 RequestContext.getCurrentInstance().getComponentContextManager();
2119 ComponentContextChange change = compCtxMgr.peekChange();
2120
2121 if (change instanceof CollectionComponentChange &&
2122 ((CollectionComponentChange)change)._component == this)
2123 {
2124
2125 compCtxMgr.popChange();
2126 }
2127 else
2128 {
2129 _LOG.severe("COLLECTION_CHANGE_TEARDOWN", new Object[] { getId(), change });
2130 }
2131 }
2132 catch (RuntimeException re)
2133 {
2134 _LOG.severe(re);
2135 }
2136 }
2137
2138 private void _verifyComponentInContext()
2139 {
2140 if (_inSuspendOrResume)
2141 {
2142 return;
2143 }
2144
2145 ComponentContextManager compCtxMgr =
2146 RequestContext.getCurrentInstance().getComponentContextManager();
2147 ComponentContextChange change = compCtxMgr.peekChange();
2148
2149 if (!(change instanceof CollectionComponentChange) ||
2150 ((CollectionComponentChange)change)._component != this)
2151 {
2152 _LOG.warning("COLLECTION_NOT_IN_CONTEXT", getId());
2153 if (_LOG.isFine())
2154 {
2155 Thread.currentThread().dumpStack();
2156 }
2157 }
2158 }
2159
2160
2161
2162
2163
2164
2165
2166
2167 private Object _resetCurrencyKeyForStateSaving(FacesContext context)
2168 {
2169
2170
2171
2172
2173
2174 Object currencyKey = _getCurrencyKey();
2175
2176
2177
2178 if (currencyKey != null)
2179 {
2180 if (_LOG.isWarning())
2181 {
2182 String scopedId = ComponentUtils.getScopedIdForComponent(this, context.getViewRoot());
2183 String viewId = context.getViewRoot() == null? null: context.getViewRoot().getViewId();
2184 _LOG.warning("ROWKEY_NOT_RESET", new Object[]
2185 { scopedId, viewId });
2186 }
2187 }
2188
2189 Object initKey = _getCurrencyKeyForInitialStampState();
2190 if (currencyKey != initKey)
2191 {
2192 setRowKey(initKey);
2193 }
2194
2195 return currencyKey;
2196 }
2197
2198
2199
2200
2201
2202
2203 private void _restoreCurrencyKeyForStateSaving(Object key)
2204 {
2205 Object currencyKey = key;
2206 Object initKey = _getCurrencyKeyForInitialStampState();
2207
2208 if (currencyKey != initKey)
2209 {
2210 setRowKey(currencyKey);
2211 }
2212 }
2213
2214
2215
2216
2217 private void _resetInternalState()
2218 {
2219 InternalState iState = _getInternalState(false);
2220 if (iState != null)
2221 {
2222 iState._value = null;
2223 iState._model= null;
2224 }
2225 }
2226
2227 private static final class DefaultClientKeyManager extends ClientRowKeyManager
2228 {
2229 public void clear()
2230 {
2231 _currencyCache.clear();
2232 }
2233
2234
2235
2236
2237 @Override
2238 public Object getRowKey(FacesContext context, UIComponent component, String clientRowKey)
2239 {
2240 ValueMap<Object,String> currencyCache = _currencyCache;
2241 Object rowkey = currencyCache.getKey(clientRowKey);
2242 return rowkey;
2243 }
2244
2245
2246
2247
2248 @Override
2249 public String getClientRowKey(FacesContext context, UIComponent component, Object rowKey)
2250 {
2251 assert rowKey != null;
2252
2253 ValueMap<Object,String> currencyCache = _currencyCache;
2254 String key = currencyCache.get(rowKey);
2255
2256 if (key == null)
2257 {
2258
2259 key = _createToken(currencyCache);
2260
2261 if (_LOG.isFiner())
2262 _LOG.finer("Storing token:"+key+
2263 " for rowKey:"+rowKey);
2264
2265 currencyCache.put(rowKey, key);
2266 }
2267 return key;
2268 }
2269
2270
2271
2272
2273 @Override
2274 public boolean replaceRowKey(FacesContext context, UIComponent component, Object oldRowKey, Object newRowKey)
2275 {
2276 assert oldRowKey != null && newRowKey != null;
2277
2278 ValueMap<Object,String> currencyCache = _currencyCache;
2279 String key = currencyCache.remove(oldRowKey);
2280
2281 if (key != null)
2282 {
2283 currencyCache.put(newRowKey, key);
2284 }
2285 return key != null;
2286 }
2287
2288
2289
2290 private static String _createToken(ValueMap<Object,String> currencyCache)
2291 {
2292 String key = String.valueOf(currencyCache.size());
2293 return key;
2294 }
2295
2296 private ValueMap<Object,String> _currencyCache = new ValueMap<Object,String>();
2297 private static final long serialVersionUID = 1L;
2298 }
2299
2300
2301
2302
2303
2304
2305 private static final class InternalState implements Serializable
2306 {
2307 private transient boolean _hasEvent = false;
2308 private transient Object _prevVarValue = _NULL;
2309 private transient Object _prevVarStatus = _NULL;
2310 private transient String _var = null;
2311 private transient String _varStatus = null;
2312 private transient Object _value = null;
2313 private transient CollectionModel _model = null;
2314 private transient Object _currentRowKey = _NULL;
2315 private transient boolean _clearTokenCache = false;
2316
2317
2318 private transient boolean _isFirstRender = true;
2319 private transient boolean _isInitialized = false;
2320
2321 private transient Object _initialStampStateKey = _NULL;
2322
2323 private ClientRowKeyManager _clientKeyMgr = null;
2324 private StampState _stampState = null;
2325
2326 private void readObject(ObjectInputStream in)
2327 throws IOException, ClassNotFoundException
2328 {
2329 in.defaultReadObject();
2330
2331 _prevVarValue = _NULL;
2332 _prevVarStatus = _NULL;
2333 _currentRowKey = _NULL;
2334 _initialStampStateKey = _NULL;
2335
2336
2337 _isFirstRender = false;
2338 }
2339
2340 private static final long serialVersionUID = 1L;
2341 }
2342
2343
2344
2345
2346
2347
2348 private static class CollectionComponentChange
2349 extends ComponentContextChange
2350 {
2351 private CollectionComponentChange(
2352 UIXCollection component)
2353 {
2354 _component = component;
2355 }
2356
2357 public void suspend(
2358 FacesContext facesContext)
2359 {
2360 _component._inSuspendOrResume = true;
2361
2362 try
2363 {
2364 InternalState iState = _component._getInternalState(false);
2365 if (iState == null || iState._model == null || iState._currentRowKey == _NULL)
2366 {
2367
2368
2369
2370
2371
2372
2373
2374
2375 _rowKey = null;
2376 }
2377 else
2378 {
2379 _rowKey = _component.getRowKey();
2380
2381
2382
2383
2384 if (_rowKey != null)
2385 {
2386 _component.setRowKey(null);
2387 }
2388 }
2389 }
2390 finally
2391 {
2392 _component._inSuspendOrResume = false;
2393 }
2394 }
2395
2396 public void resume(
2397 FacesContext facesContext)
2398 {
2399 _component._inSuspendOrResume = true;
2400 try
2401 {
2402
2403 if (_rowKey != null)
2404 {
2405 _component.setRowKey(_rowKey);
2406 }
2407 }
2408 finally
2409 {
2410 _component._inSuspendOrResume = false;
2411 }
2412 }
2413
2414 @Override
2415 public String toString()
2416 {
2417 String className = _component.getClass().getName();
2418 String componentId = _component.getId();
2419 return new StringBuilder(58 + className.length() + componentId.length())
2420 .append("UIXCollection.CollectionComponentChange[Component class: ")
2421 .append(className)
2422 .append(", component ID: ")
2423 .append(componentId)
2424 .append("]")
2425 .toString();
2426 }
2427
2428 private final UIXCollection _component;
2429 private CollectionModel _collectionModel;
2430 private Object _rowKey;
2431 }
2432
2433 private static class CollectionContextEvent
2434 extends WrapperEvent
2435 {
2436 public CollectionContextEvent(
2437 UIComponent source,
2438 FacesEvent event)
2439 {
2440 super(source, event);
2441 }
2442
2443 @SuppressWarnings("compatibility:-7639429485707197863")
2444 private static final long serialVersionUID = 1L;
2445 }
2446
2447
2448
2449
2450
2451 private InternalState _state = null;
2452 private boolean _inSuspendOrResume = false;
2453
2454
2455
2456
2457 private static final Object _NULL = new Object();
2458 private static final String _INVOKE_KEY =
2459 UIXCollection.class.getName() + ".INVOKE";
2460
2461 private transient Object _stateSavingCurrencyKey = null;
2462
2463 private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(UIXCollection.class);
2464
2465
2466
2467
2468
2469
2470
2471 enum Transient { TRUE };
2472 }