1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.component.html.ext;
20
21 import java.io.IOException;
22 import java.sql.ResultSet;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29
30 import javax.el.ValueExpression;
31 import javax.faces.application.FacesMessage;
32 import javax.faces.component.EditableValueHolder;
33 import javax.faces.component.UIComponent;
34 import javax.faces.component.UIComponentBase;
35 import javax.faces.component.UINamingContainer;
36 import javax.faces.context.FacesContext;
37 import javax.faces.el.ValueBinding;
38 import javax.faces.model.ArrayDataModel;
39 import javax.faces.model.DataModel;
40 import javax.faces.model.ListDataModel;
41 import javax.faces.model.ResultDataModel;
42 import javax.faces.model.ResultSetDataModel;
43 import javax.faces.model.ScalarDataModel;
44 import javax.servlet.jsp.jstl.sql.Result;
45
46 import org.apache.commons.lang.StringUtils;
47 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
48 import org.apache.myfaces.component.html.util.HtmlComponentUtils;
49 import org.apache.myfaces.custom.ExtendedComponentBase;
50
51
52
53
54
55
56
57
58
59
60
61 public abstract class HtmlDataTableHack extends
62 javax.faces.component.html.HtmlDataTable implements
63 ExtendedComponentBase
64
65 {
66 @SuppressWarnings("unchecked")
67 private Map<String, DataModel> _dataModelMap = new HashMap<String, DataModel>();
68
69
70 private boolean _isValidChilds = true;
71
72
73 private Map<String, Object> _rowStates = new HashMap<String, Object>();
74
75
76 private Map<String, Map<String, Object> > _rowDeltaStates = new HashMap<String, Map<String, Object> >();
77
78
79 private Object _initialDescendantComponentState = null;
80
81 private Object _initialDescendantFullComponentState = null;
82
83
84
85
86
87 @SuppressWarnings("unchecked")
88 private static final Class OBJECT_ARRAY_CLASS = (new Object[0]).getClass();
89
90 private static final boolean DEFAULT_PRESERVEROWSTATES = false;
91
92 private static final String UNIQUE_ROW_ID_PREFIX = "r_id_";
93
94 private int _rowIndex = -1;
95
96 public boolean isRowAvailable()
97 {
98 return getDataModel().isRowAvailable();
99 }
100
101 public int getRowCount()
102 {
103 return getDataModel().getRowCount();
104 }
105
106 public Object getRowData()
107 {
108 return getDataModel().getRowData();
109 }
110
111 public int getRowIndex()
112 {
113 return _rowIndex;
114 }
115
116
117
118
119 public String getClientId(FacesContext context)
120 {
121
122 String clientId = HtmlComponentUtils.getClientId(this, getRenderer(context), context);
123 if (clientId == null)
124 {
125 clientId = super.getClientId(context);
126
127 int rowIndex = getRowIndex();
128 if (rowIndex != -1)
129 {
130 char separator = UINamingContainer.getSeparatorChar(context);
131 int index = clientId.lastIndexOf(separator);
132 if(index != -1)
133 {
134 String rowIndexString = clientId.substring(index + 1);
135 if (rowIndexString.length() > 0 &&
136 StringUtils.isNumeric(rowIndexString) &&
137 rowIndex == Integer.valueOf(rowIndexString).intValue())
138 {
139 clientId = clientId.substring(0,index - 1);
140 }
141 }
142 }
143 }
144 return clientId;
145 }
146
147 @Override
148 public String getContainerClientId(FacesContext context)
149 {
150
151 String clientId = HtmlComponentUtils.getClientId(this, getRenderer(context), context);
152 if (clientId == null)
153 {
154 clientId = super.getClientId(context);
155 }
156 int rowIndex = getRowIndex();
157 if (rowIndex == -1)
158 {
159 return clientId;
160 }
161
162 char separator = UINamingContainer.getSeparatorChar(context);
163 int index = clientId.lastIndexOf(separator);
164 if(index != -1)
165 {
166 String rowIndexString = clientId.substring(index + 1);
167
168 if(rowIndexString.length() > 0 &&
169 StringUtils.isNumeric(rowIndexString) &&
170 Integer.valueOf(rowIndexString) == rowIndex)
171 {
172
173 return clientId.substring(0,index+1)+getDerivedSubClientId();
174 }
175 }
176
177 return clientId + separator + getDerivedSubClientId();
178 }
179
180
181
182
183 public void processUpdates(FacesContext context)
184 {
185 super.processUpdates(context);
186
187 if (context.getRenderResponse())
188 {
189 _isValidChilds = false;
190 }
191 }
192
193
194
195
196
197
198
199
200 protected void checkUpdateModelError(FacesContext context)
201 {
202 if (context.getRenderResponse())
203 {
204 _isValidChilds = false;
205 }
206 }
207
208
209
210
211 public void processValidators(FacesContext context)
212 {
213 super.processValidators(context);
214
215 if (context.getRenderResponse())
216 {
217 _isValidChilds = false;
218 }
219 }
220
221
222
223
224 public void encodeBegin(FacesContext context) throws IOException
225 {
226 _initialDescendantComponentState = null;
227 if (_isValidChilds && !hasErrorMessages(context))
228 {
229
230 _dataModelMap.clear();
231 if (!isPreserveRowStates())
232 {
233 _rowStates.clear();
234 }
235 }
236 super.encodeBegin(context);
237 }
238
239 public void setPreserveRowStates(boolean preserveRowStates)
240 {
241 getStateHelper().put(PropertyKeys.preserveRowStates, preserveRowStates);
242 }
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259 public boolean isPreserveRowStates()
260 {
261 Object value = getStateHelper().eval(PropertyKeys.preserveRowStates,DEFAULT_PRESERVEROWSTATES);
262 if (value != null)
263 {
264 return (Boolean) value;
265 }
266 return DEFAULT_PRESERVEROWSTATES;
267 }
268
269
270
271
272
273
274
275
276
277
278
279
280
281 @JSFProperty(literalOnly=true, faceletsOnly=true, defaultValue="false")
282 public boolean isRowStatePreserved()
283 {
284 Boolean b = (Boolean) getStateHelper().get(PropertyKeys.rowStatePreserved);
285 return b == null ? false : b.booleanValue();
286 }
287
288 public void setRowStatePreserved(boolean preserveComponentState)
289 {
290 getStateHelper().put(PropertyKeys.rowStatePreserved, preserveComponentState);
291 }
292
293 protected boolean hasErrorMessages(FacesContext context)
294 {
295 for(Iterator<FacesMessage> iter = context.getMessages(); iter.hasNext();)
296 {
297 FacesMessage message = (FacesMessage) iter.next();
298 if(FacesMessage.SEVERITY_ERROR.compareTo(message.getSeverity()) <= 0)
299 {
300 return true;
301 }
302 }
303 return false;
304 }
305
306
307
308
309 public void encodeEnd(FacesContext context) throws IOException
310 {
311 setRowIndex(-1);
312 super.encodeEnd(context);
313 }
314
315 @SuppressWarnings("unchecked")
316 public void setRowIndex(int rowIndex)
317 {
318 if ( (isPreserveRowComponentState() || isRowStatePreserved()) && _initialDescendantFullComponentState != null)
319 {
320 setRowIndexPreserveComponentState(rowIndex);
321 }
322 else
323 {
324 setRowIndexWithoutPreserveComponentState(rowIndex);
325 }
326 }
327
328 private void setRowIndexWithoutPreserveComponentState(int rowIndex)
329 {
330 if (rowIndex < -1)
331 {
332 throw new IllegalArgumentException("rowIndex is less than -1");
333 }
334
335 if (_rowIndex == rowIndex)
336 {
337 return;
338 }
339
340 FacesContext facesContext = getFacesContext();
341
342 if (_rowIndex == -1)
343 {
344 if (_initialDescendantComponentState == null)
345 {
346 _initialDescendantComponentState = saveDescendantComponentStates();
347 }
348 }
349 else
350 {
351 _rowStates.put(getContainerClientId(facesContext),
352 saveDescendantComponentStates());
353 }
354
355 _rowIndex = rowIndex;
356
357 DataModel dataModel = getDataModel();
358 dataModel.setRowIndex(rowIndex);
359
360 String var = getVar();
361 if (rowIndex == -1)
362 {
363 if (var != null)
364 {
365 facesContext.getExternalContext().getRequestMap().remove(var);
366 }
367 }
368 else
369 {
370 if (var != null)
371 {
372 if (isRowAvailable())
373 {
374 Object rowData = dataModel.getRowData();
375 facesContext.getExternalContext().getRequestMap().put(var,
376 rowData);
377 }
378 else
379 {
380 facesContext.getExternalContext().getRequestMap().remove(
381 var);
382 }
383 }
384 }
385
386 if (_rowIndex == -1)
387 {
388 restoreDescendantComponentStates(_initialDescendantComponentState);
389 }
390 else
391 {
392 Object rowState = _rowStates.get(getContainerClientId(facesContext));
393 if (rowState == null)
394 {
395 restoreDescendantComponentStates(_initialDescendantComponentState);
396 }
397 else
398 {
399 restoreDescendantComponentStates(rowState);
400 }
401 }
402 }
403
404 private void setRowIndexPreserveComponentState(int rowIndex)
405 {
406 if (rowIndex < -1)
407 {
408 throw new IllegalArgumentException("rowIndex is less than -1");
409 }
410
411 if (_rowIndex == rowIndex)
412 {
413 return;
414 }
415
416 FacesContext facesContext = getFacesContext();
417
418 if (_initialDescendantFullComponentState != null)
419 {
420
421 Map<String, Object> sm = saveFullDescendantComponentStates(facesContext);
422 if (sm != null && !sm.isEmpty())
423 {
424 _rowDeltaStates.put(getContainerClientId(facesContext), sm);
425 }
426 }
427
428 _rowIndex = rowIndex;
429
430 DataModel dataModel = getDataModel();
431 dataModel.setRowIndex(rowIndex);
432
433 String var = getVar();
434 if (rowIndex == -1)
435 {
436 if (var != null)
437 {
438 facesContext.getExternalContext().getRequestMap().remove(var);
439 }
440 }
441 else
442 {
443 if (var != null)
444 {
445 if (isRowAvailable())
446 {
447 Object rowData = dataModel.getRowData();
448 facesContext.getExternalContext().getRequestMap().put(var,
449 rowData);
450 }
451 else
452 {
453 facesContext.getExternalContext().getRequestMap().remove(
454 var);
455 }
456 }
457 }
458
459 if (_initialDescendantFullComponentState != null)
460 {
461 Map<String, Object> rowState = _rowDeltaStates.get(getContainerClientId(facesContext));
462 if (rowState == null)
463 {
464
465 restoreFullDescendantComponentStates(facesContext, _initialDescendantFullComponentState);
466 }
467 else
468 {
469
470 restoreFullDescendantComponentDeltaStates(facesContext, rowState, _initialDescendantFullComponentState);
471 }
472 }
473 }
474
475 @SuppressWarnings("unchecked")
476 protected void restoreDescendantComponentStates(Object state)
477 {
478 restoreDescendantComponentStates(getChildren().iterator(), state, false);
479 }
480
481 @SuppressWarnings("unchecked")
482 protected void restoreDescendantComponentStates(Iterator<UIComponent> childIterator,
483 Object state, boolean restoreChildFacets)
484 {
485 Iterator descendantStateIterator = null;
486 while (childIterator.hasNext())
487 {
488 if (descendantStateIterator == null && state != null)
489 {
490 descendantStateIterator = ((Collection) state).iterator();
491 }
492 UIComponent component = (UIComponent) childIterator.next();
493
494 component.setId(component.getId());
495 if(!component.isTransient())
496 {
497 Object childState = null;
498 Object descendantState = null;
499 if (descendantStateIterator != null
500 && descendantStateIterator.hasNext())
501 {
502 Object[] object = (Object[]) descendantStateIterator.next();
503 childState = object[0];
504 descendantState = object[1];
505 }
506 if (childState != null && component instanceof EditableValueHolder)
507 {
508 ((EditableValueHolderState) childState)
509 .restoreState((EditableValueHolder) component);
510 }
511 Iterator<UIComponent> childsIterator;
512 if (restoreChildFacets)
513 {
514 childsIterator = component.getFacetsAndChildren();
515 }
516 else
517 {
518 childsIterator = component.getChildren().iterator();
519 }
520 restoreDescendantComponentStates(childsIterator, descendantState,
521 true);
522 }
523 }
524 }
525
526 @SuppressWarnings("unchecked")
527 protected Object saveDescendantComponentStates()
528 {
529 return saveDescendantComponentStates(getChildren().iterator(), false);
530 }
531
532 @SuppressWarnings("unchecked")
533 protected Object saveDescendantComponentStates(Iterator<UIComponent> childIterator,
534 boolean saveChildFacets)
535 {
536 Collection childStates = null;
537 while (childIterator.hasNext())
538 {
539 if (childStates == null)
540 {
541 childStates = new ArrayList();
542 }
543 UIComponent child = (UIComponent) childIterator.next();
544 if(!child.isTransient())
545 {
546 Iterator<UIComponent> childsIterator;
547 if (saveChildFacets)
548 {
549 childsIterator = child.getFacetsAndChildren();
550 }
551 else
552 {
553 childsIterator = child.getChildren().iterator();
554 }
555 Object descendantState = saveDescendantComponentStates(
556 childsIterator, true);
557 Object state = null;
558 if (child instanceof EditableValueHolder)
559 {
560 state = new EditableValueHolderState(
561 (EditableValueHolder) child);
562 }
563 childStates.add(new Object[] { state, descendantState });
564 }
565 }
566 return childStates;
567 }
568
569
570
571
572 @Override
573 public void markInitialState()
574 {
575 if (isPreserveRowComponentState() || isRowStatePreserved())
576 {
577 if (getFacesContext().getAttributes().containsKey("javax.faces.view.ViewDeclarationLanguage.IS_BUILDING_INITIAL_STATE"))
578 {
579 _initialDescendantFullComponentState = saveDescendantInitialComponentStates(getFacesContext());
580 }
581 }
582 super.markInitialState();
583 }
584
585 protected void restoreFullDescendantComponentStates(FacesContext facesContext, Object initialState)
586 {
587 restoreFullDescendantComponentStates(facesContext, getChildren().iterator(), initialState, false);
588 }
589
590 protected void restoreFullDescendantComponentStates(FacesContext facesContext,
591 Iterator<UIComponent> childIterator, Object initialState,
592 boolean restoreChildFacets)
593 {
594 Iterator<? extends Object[]> descendantStateIterator = null;
595 while (childIterator.hasNext())
596 {
597 if (descendantStateIterator == null && initialState != null)
598 {
599 descendantStateIterator = ((Collection<? extends Object[]>) initialState)
600 .iterator();
601 }
602 UIComponent component = childIterator.next();
603
604
605 component.setId(component.getId());
606 if (!component.isTransient())
607 {
608 Object childState = null;
609 Object descendantState = null;
610 String childId = null;
611 if (descendantStateIterator != null
612 && descendantStateIterator.hasNext())
613 {
614 do
615 {
616 Object[] object = descendantStateIterator.next();
617 childState = object[0];
618 descendantState = object[1];
619 childId = (String) object[2];
620 }
621 while(descendantStateIterator.hasNext() && !component.getId().equals(childId));
622
623 if (!component.getId().equals(childId))
624 {
625
626 throw new IllegalStateException("Cannot restore row correctly.");
627 }
628 }
629
630 component.clearInitialState();
631 component.restoreState(facesContext, childState);
632 component.markInitialState();
633
634 Iterator<UIComponent> childsIterator;
635 if (restoreChildFacets)
636 {
637 childsIterator = component.getFacetsAndChildren();
638 }
639 else
640 {
641 childsIterator = component.getChildren().iterator();
642 }
643 restoreFullDescendantComponentStates(facesContext, childsIterator,
644 descendantState, true);
645 }
646 }
647 }
648
649 protected Collection<Object[]> saveDescendantInitialComponentStates(FacesContext facesContext)
650 {
651 return saveDescendantInitialComponentStates(facesContext, getChildren().iterator(), false);
652 }
653
654 protected Collection<Object[]> saveDescendantInitialComponentStates(FacesContext facesContext,
655 Iterator<UIComponent> childIterator, boolean saveChildFacets)
656 {
657 Collection<Object[]> childStates = null;
658 while (childIterator.hasNext())
659 {
660 if (childStates == null)
661 {
662 childStates = new ArrayList<Object[]>();
663 }
664
665 UIComponent child = childIterator.next();
666 if (!child.isTransient())
667 {
668
669
670
671
672
673 Iterator<UIComponent> childsIterator;
674 if (saveChildFacets)
675 {
676 childsIterator = child.getFacetsAndChildren();
677 }
678 else
679 {
680 childsIterator = child.getChildren().iterator();
681 }
682 Object descendantState = saveDescendantInitialComponentStates(
683 facesContext, childsIterator, true);
684 Object state = null;
685 if (child.initialStateMarked())
686 {
687 child.clearInitialState();
688 state = child.saveState(facesContext);
689 child.markInitialState();
690 }
691 else
692 {
693 state = child.saveState(facesContext);
694 }
695
696 childStates.add(new Object[] { state, descendantState, child.getId()});
697 }
698 }
699 return childStates;
700 }
701
702 protected Map<String,Object> saveFullDescendantComponentStates(FacesContext facesContext)
703 {
704 return saveFullDescendantComponentStates(facesContext, null, getChildren().iterator(), false, getContainerClientId(facesContext));
705 }
706
707 protected Map<String,Object> saveFullDescendantComponentStates(FacesContext facesContext, Map<String,Object> stateMap,
708 Iterator<UIComponent> childIterator, boolean saveChildFacets, String containerClientId)
709 {
710 while (childIterator.hasNext())
711 {
712 UIComponent child = childIterator.next();
713 if (!child.isTransient())
714 {
715
716
717
718
719
720 Iterator<UIComponent> childsIterator;
721 if (saveChildFacets)
722 {
723 childsIterator = child.getFacetsAndChildren();
724 }
725 else
726 {
727 childsIterator = child.getChildren().iterator();
728 }
729 stateMap = saveFullDescendantComponentStates(facesContext, stateMap,
730 childsIterator, true, containerClientId);
731 Object state = child.saveState(facesContext);
732 if (state != null)
733 {
734 if (stateMap == null)
735 {
736 stateMap = new HashMap<String,Object>();
737 }
738 stateMap.put(child.getClientId(facesContext).substring(containerClientId.length()+1), state);
739 }
740 }
741 }
742 return stateMap;
743 }
744
745 protected void restoreFullDescendantComponentDeltaStates(FacesContext facesContext,
746 Map<String, Object> rowState, Object initialState)
747 {
748 restoreFullDescendantComponentDeltaStates(facesContext, getChildren().iterator(), rowState, initialState, false, getContainerClientId(facesContext));
749 }
750
751 protected void restoreFullDescendantComponentDeltaStates(FacesContext facesContext,
752 Iterator<UIComponent> childIterator, Map<String, Object> state, Object initialState,
753 boolean restoreChildFacets, String containerClientId)
754 {
755 Iterator<? extends Object[]> descendantFullStateIterator = null;
756 while (childIterator.hasNext())
757 {
758 if (descendantFullStateIterator == null && initialState != null)
759 {
760 descendantFullStateIterator = ((Collection<? extends Object[]>) initialState).iterator();
761 }
762 UIComponent component = childIterator.next();
763
764
765 component.setId(component.getId());
766 if (!component.isTransient())
767 {
768 Object childInitialState = null;
769 Object descendantInitialState = null;
770 Object childState = null;
771 String childId = null;
772 childState = (state == null) ? null : state.get(component.getClientId(facesContext).substring(containerClientId.length()+1));
773 if (descendantFullStateIterator != null
774 && descendantFullStateIterator.hasNext())
775 {
776 do
777 {
778 Object[] object = descendantFullStateIterator.next();
779 childInitialState = object[0];
780 descendantInitialState = object[1];
781 childId = (String) object[2];
782 }while(descendantFullStateIterator.hasNext() && !component.getId().equals(childId));
783
784 if (!component.getId().equals(childId))
785 {
786
787 throw new IllegalStateException("Cannot restore row correctly.");
788 }
789 }
790
791 component.clearInitialState();
792 if (childInitialState != null)
793 {
794 component.restoreState(facesContext, childInitialState);
795 component.markInitialState();
796 component.restoreState(facesContext, childState);
797 }
798 else
799 {
800 component.restoreState(facesContext, childState);
801 component.markInitialState();
802 }
803
804 Iterator<UIComponent> childsIterator;
805 if (restoreChildFacets)
806 {
807 childsIterator = component.getFacetsAndChildren();
808 }
809 else
810 {
811 childsIterator = component.getChildren().iterator();
812 }
813 restoreFullDescendantComponentDeltaStates(facesContext, childsIterator,
814 state, descendantInitialState , true, containerClientId);
815 }
816 }
817 }
818
819 @Override
820 public void restoreState(FacesContext context, Object state)
821 {
822 if (state == null)
823 {
824 return;
825 }
826
827 Object values[] = (Object[]) state;
828 super.restoreState(context, values[0]);
829 Object restoredRowStates = UIComponentBase.restoreAttachedState(context, values[1]);
830 if (restoredRowStates == null)
831 {
832 if (!_rowDeltaStates.isEmpty())
833 {
834 _rowDeltaStates.clear();
835 }
836 }
837 else
838 {
839 _rowDeltaStates = (Map<String, Map<String, Object> >) restoredRowStates;
840 }
841 }
842
843 @Override
844 public Object saveState(FacesContext context)
845 {
846 if (initialStateMarked())
847 {
848 Object parentSaved = super.saveState(context);
849 if (parentSaved == null &&_rowDeltaStates.isEmpty())
850 {
851 return null;
852 }
853 else
854 {
855 Object values[] = new Object[2];
856 values[0] = parentSaved;
857 values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
858 return values;
859 }
860 }
861 else
862 {
863 Object values[] = new Object[2];
864 values[0] = super.saveState(context);
865 values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
866 return values;
867 }
868 }
869
870 public void setValueBinding(String name, ValueBinding binding)
871 {
872 if (name == null)
873 {
874 throw new NullPointerException("name");
875 }
876 else if (name.equals("value"))
877 {
878 _dataModelMap.clear();
879 }
880 else if (name.equals("var") || name.equals("rowIndex"))
881 {
882 throw new IllegalArgumentException(
883 "You can never set the 'rowIndex' or the 'var' attribute as a value-binding. Set the property directly instead. Name " + name);
884 }
885 super.setValueBinding(name, binding);
886 }
887
888 public void setValueExpression(String name, ValueExpression binding)
889 {
890 if (name == null)
891 {
892 throw new NullPointerException("name");
893 }
894 else if (name.equals("value"))
895 {
896 _dataModelMap.clear();
897 }
898 else if (name.equals("var") || name.equals("rowIndex"))
899 {
900 throw new IllegalArgumentException(
901 "You can never set the 'rowIndex' or the 'var' attribute as a value-binding. Set the property directly instead. Name " + name);
902 }
903 super.setValueExpression(name, binding);
904 }
905
906
907
908
909 public void setValue(Object value)
910 {
911 super.setValue(value);
912 _dataModelMap.clear();
913 _rowStates.clear();
914 _rowDeltaStates.clear();
915 _isValidChilds = true;
916 }
917
918 @SuppressWarnings("unchecked")
919 protected DataModel getDataModel()
920 {
921 DataModel dataModel = null;
922 String clientID = "";
923
924 UIComponent parent = getParent();
925 if (parent != null)
926 {
927 clientID = parent.getContainerClientId(getFacesContext());
928 }
929 dataModel = (DataModel) _dataModelMap.get(clientID);
930 if (dataModel == null)
931 {
932 dataModel = createDataModel();
933 _dataModelMap.put(clientID, dataModel);
934 }
935
936 return dataModel;
937 }
938
939 @SuppressWarnings("unchecked")
940 protected void setDataModel(DataModel datamodel)
941 {
942 UIComponent parent = getParent();
943 String clientID = "";
944 if(parent != null)
945 {
946 clientID = parent.getContainerClientId(getFacesContext());
947 }
948 _dataModelMap.put(clientID, datamodel);
949 }
950
951
952
953
954 @SuppressWarnings("unchecked")
955 protected DataModel createDataModel()
956 {
957 Object value = getValue();
958 if (value == null)
959 {
960 return EMPTY_DATA_MODEL;
961 }
962 else if (value instanceof DataModel)
963 {
964 return (DataModel) value;
965 }
966 else if (value instanceof List)
967 {
968 return new ListDataModel((List) value);
969 }
970
971 else if (value instanceof Collection)
972 {
973 return new ListDataModel(new ArrayList((Collection) value));
974 }
975 else if (OBJECT_ARRAY_CLASS.isAssignableFrom(value.getClass()))
976 {
977 return new ArrayDataModel((Object[]) value);
978 }
979 else if (value instanceof ResultSet)
980 {
981 return new ResultSetDataModel((ResultSet) value);
982 }
983 else if (value instanceof Result)
984 {
985 return new ResultDataModel((Result) value);
986 }
987 else
988 {
989 return new ScalarDataModel(value);
990 }
991 }
992
993 @SuppressWarnings("unchecked")
994 private static final DataModel EMPTY_DATA_MODEL = new _SerializableDataModel()
995 {
996 public boolean isRowAvailable()
997 {
998 return false;
999 }
1000
1001 public int getRowCount()
1002 {
1003 return 0;
1004 }
1005
1006 public Object getRowData()
1007 {
1008 throw new IllegalArgumentException();
1009 }
1010
1011 public int getRowIndex()
1012 {
1013 return -1;
1014 }
1015
1016 public void setRowIndex(int i)
1017 {
1018 if (i < -1)
1019 throw new IndexOutOfBoundsException("Index < 0 : " + i);
1020 }
1021
1022 public Object getWrappedData()
1023 {
1024 return null;
1025 }
1026
1027 public void setWrappedData(Object obj)
1028 {
1029 if (obj == null)
1030 return;
1031 throw new UnsupportedOperationException(this.getClass().getName()
1032 + " UnsupportedOperationException");
1033 }
1034 };
1035
1036 private class EditableValueHolderState
1037 {
1038 private final Object _value;
1039 private final boolean _localValueSet;
1040 private final boolean _valid;
1041 private final Object _submittedValue;
1042
1043 public EditableValueHolderState(EditableValueHolder evh)
1044 {
1045 _value = evh.getLocalValue();
1046 _localValueSet = evh.isLocalValueSet();
1047 _valid = evh.isValid();
1048 _submittedValue = evh.getSubmittedValue();
1049 }
1050
1051 public void restoreState(EditableValueHolder evh)
1052 {
1053 evh.setValue(_value);
1054 evh.setLocalValueSet(_localValueSet);
1055 evh.setValid(_valid);
1056 evh.setSubmittedValue(_submittedValue);
1057 }
1058 }
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071 public boolean isForceId()
1072 {
1073 Object value = getStateHelper().get(PropertyKeys.forceId);
1074 if (value != null)
1075 {
1076 return (Boolean) value;
1077 }
1078 return false;
1079 }
1080
1081 public void setForceId(boolean forceId)
1082 {
1083 getStateHelper().put(PropertyKeys.forceId, forceId );
1084 }
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100 public boolean isForceIdIndex()
1101 {
1102 Object value = getStateHelper().get(PropertyKeys.forceIdIndex);
1103 if (value != null)
1104 {
1105 return (Boolean) value;
1106 }
1107 return true;
1108 }
1109
1110 public void setForceIdIndex(boolean forceIdIndex)
1111 {
1112 getStateHelper().put(PropertyKeys.forceIdIndex, forceIdIndex );
1113 }
1114
1115
1116
1117
1118 public void clearRowStates()
1119 {
1120 if (isPreserveRowComponentState() || isRowStatePreserved())
1121 {
1122 _rowDeltaStates.clear();
1123 }
1124 else
1125 {
1126 _rowStates.clear();
1127 }
1128 }
1129
1130
1131
1132
1133
1134 public void deleteRowStateForRow(int deletedIndex)
1135 {
1136
1137 int savedRowIndex = getRowIndex();
1138
1139 FacesContext facesContext = getFacesContext();
1140 setRowIndex(deletedIndex);
1141 String currentRowStateKey = getContainerClientId(facesContext);
1142
1143 Object rowKey = getRowKey();
1144 if (rowKey != null)
1145 {
1146 setRowIndex(deletedIndex);
1147 if (isPreserveRowComponentState() || isRowStatePreserved())
1148 {
1149 _rowDeltaStates.remove(currentRowStateKey);
1150 }
1151 else
1152 {
1153 _rowStates.remove(currentRowStateKey);
1154 }
1155 setRowIndex(savedRowIndex);
1156 }
1157 else
1158 {
1159
1160 int rowCount = getRowCount();
1161 if (isPreserveRowComponentState() || isRowStatePreserved())
1162 {
1163 for (int index = deletedIndex + 1; index < rowCount; ++index)
1164 {
1165 setRowIndex(index);
1166 String nextRowStateKey = getContainerClientId(facesContext);
1167
1168 Map<String, Object> nextRowState = _rowDeltaStates.get(nextRowStateKey);
1169 if (nextRowState == null)
1170 {
1171 _rowDeltaStates.remove(currentRowStateKey);
1172 }
1173 else
1174 {
1175 _rowDeltaStates.put(currentRowStateKey, nextRowState);
1176 }
1177 currentRowStateKey = nextRowStateKey;
1178 }
1179
1180
1181 setRowIndex(savedRowIndex);
1182
1183
1184 _rowDeltaStates.remove(currentRowStateKey);
1185 }
1186 else
1187 {
1188 for (int index = deletedIndex + 1; index < rowCount; ++index)
1189 {
1190 setRowIndex(index);
1191 String nextRowStateKey = getContainerClientId(facesContext);
1192
1193 Object nextRowState = _rowStates.get(nextRowStateKey);
1194 if (nextRowState == null)
1195 {
1196 _rowStates.remove(currentRowStateKey);
1197 }
1198 else
1199 {
1200 _rowStates.put(currentRowStateKey, nextRowState);
1201 }
1202 currentRowStateKey = nextRowStateKey;
1203 }
1204
1205
1206 setRowIndex(savedRowIndex);
1207
1208
1209 _rowStates.remove(currentRowStateKey);
1210 }
1211 }
1212 }
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227 @JSFProperty(faceletsOnly=true, literalOnly=true)
1228 public boolean isPreserveRowComponentState()
1229 {
1230 Boolean b = (Boolean) getStateHelper().get(PropertyKeys.preserveRowComponentState);
1231 return b == null ? false : b.booleanValue();
1232 }
1233
1234 public void setPreserveRowComponentState(boolean preserveComponentState)
1235 {
1236 getStateHelper().put(PropertyKeys.preserveRowComponentState, preserveComponentState);
1237 }
1238
1239
1240
1241
1242
1243
1244
1245
1246 @JSFProperty
1247 public Object getRowKey()
1248 {
1249 return getStateHelper().eval(PropertyKeys.rowKey);
1250 }
1251
1252 public void setRowKey(Object rowKey)
1253 {
1254 getStateHelper().put(PropertyKeys.rowKey, rowKey);
1255 }
1256
1257
1258
1259
1260
1261
1262
1263
1264 @JSFProperty(defaultValue="r_id_")
1265 public String getDerivedRowKeyPrefix()
1266 {
1267 return (String) getStateHelper().eval(PropertyKeys.derivedRowKeyPrefix, UNIQUE_ROW_ID_PREFIX);
1268 }
1269
1270 public void setDerivedRowKeyPrefix(String derivedRowKeyPrefix)
1271 {
1272 getStateHelper().put(PropertyKeys.derivedRowKeyPrefix, derivedRowKeyPrefix);
1273 }
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291 protected String getDerivedSubClientId()
1292 {
1293 Object key = getRowKey();
1294 if (key == null)
1295 {
1296 return _SubIdConverter.encode(Integer.toString(getRowIndex()));
1297 }
1298 else
1299 {
1300 return getDerivedRowKeyPrefix() + _SubIdConverter.encode(key.toString());
1301 }
1302 }
1303
1304 protected enum PropertyKeys
1305 {
1306 preserveRowStates
1307 , forceId
1308 , forceIdIndex
1309 , preserveRowComponentState
1310 , rowKey
1311 , derivedRowKeyPrefix
1312 , rowStatePreserved
1313 }
1314 }