View Javadoc

1   /*
2    * $Id: CollectionTools.java,v 1.8 2009/03/04 10:08:54 oeuillot Exp $
3    */
4   package org.rcfaces.core.internal.tools;
5   
6   import java.lang.reflect.Array;
7   import java.lang.reflect.Method;
8   import java.util.ArrayList;
9   import java.util.Arrays;
10  import java.util.Collection;
11  import java.util.Collections;
12  import java.util.HashMap;
13  import java.util.HashSet;
14  import java.util.Iterator;
15  import java.util.List;
16  import java.util.Map;
17  import java.util.Set;
18  
19  import javax.faces.FacesException;
20  import javax.faces.component.UIComponent;
21  import javax.faces.context.FacesContext;
22  import javax.faces.model.DataModel;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.rcfaces.core.internal.RcfacesContext;
27  import org.rcfaces.core.internal.capability.IGridComponent;
28  import org.rcfaces.core.internal.util.StringList;
29  import org.rcfaces.core.lang.IAdaptable;
30  import org.rcfaces.core.lang.OrderedSet;
31  import org.rcfaces.core.model.ICommitableObject;
32  import org.rcfaces.core.model.IIndexesModel;
33  import org.rcfaces.core.model.IRangeDataModel;
34  
35  /**
36   * 
37   * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
38   * @version $Revision: 1.8 $ $Date: 2009/03/04 10:08:54 $
39   */
40  public class CollectionTools {
41      private static final String REVISION = "$Revision: 1.8 $";
42  
43      private static final Log LOG = LogFactory.getLog(CollectionTools.class);
44  
45      protected static final Object[] EMPTY_VALUES = new Object[0];
46  
47      private static final Object[] EMPTY_STRING_ARRAY = new String[0];
48  
49      private static final boolean SORT_INDICES = true;
50  
51      private static final Map IMPLEMENTATION_TYPES = new HashMap(64);
52      static {
53          IMPLEMENTATION_TYPES.put(Collection.class, ArrayList.class);
54          IMPLEMENTATION_TYPES.put(List.class, ArrayList.class);
55          IMPLEMENTATION_TYPES.put(Set.class, HashSet.class);
56          IMPLEMENTATION_TYPES.put(Map.class, HashMap.class);
57  
58          IMPLEMENTATION_TYPES.put(IIndexesModel.class, ArrayIndexesModel.class);
59      }
60  
61      private static final IValuesAccessor NULL_VALUES_ACCESSOR = new AbstractValuesAccessor() {
62          private static final String REVISION = "$Revision: 1.8 $";
63  
64          public int getCount(Object value) {
65              return 0;
66          }
67  
68          public Object getFirst(Object value, Object refValues) {
69              return null;
70          }
71  
72          public Object[] listValues(Object value, Object refValues) {
73              return EMPTY_VALUES;
74          }
75      };
76  
77      private static final IValuesAccessor ARRAY_VALUES_ACCESSOR = new AbstractValuesAccessor() {
78          private static final String REVISION = "$Revision: 1.8 $";
79  
80          public int getCount(Object array) {
81              return Array.getLength(array);
82          }
83  
84          public Object getFirst(Object array, Object refValues) {
85              if (getCount(array) < 1) {
86                  return null;
87              }
88  
89              return Array.get(array, 0);
90          }
91  
92          public Object[] listValues(Object array, Object refValues) {
93              return (Object[]) array;
94          }
95      };
96  
97      private static final IValuesAccessor STRING_VALUES_ACCESSOR = new AbstractValuesAccessor() {
98          private static final String REVISION = "$Revision: 1.8 $";
99  
100         public int getCount(Object array) {
101             return StringList.countTokens((String) array);
102         }
103 
104         public Object getFirst(Object array, Object refValues) {
105             return StringList.getFirstToken((String) array);
106         }
107 
108         public Object[] listValues(Object array, Object refValues) {
109             return convertToObjectArray(array);
110         }
111 
112     };
113 
114     private static final IValuesAccessor COLLECTION_VALUES_ACCESSOR = new AbstractValuesAccessor() {
115         private static final String REVISION = "$Revision: 1.8 $";
116 
117         public int getCount(Object collection) {
118             return ((Collection) collection).size();
119         }
120 
121         public Object getFirst(Object collection, Object refValues) {
122             Collection cl = (Collection) collection;
123 
124             if (cl.isEmpty()) {
125                 return null;
126             }
127 
128             if (cl instanceof List) {
129                 return ((List) cl).get(0);
130             }
131 
132             return cl.iterator().next();
133         }
134 
135         public Object[] listValues(Object collection, Object refValues) {
136             return ((Collection) collection).toArray();
137         }
138     };
139 
140     private static final IValuesAccessor MAP_VALUES_ACCESSOR = new AbstractValuesAccessor() {
141         private static final String REVISION = "$Revision: 1.8 $";
142 
143         public int getCount(Object map) {
144             return ((Map) map).size();
145         }
146 
147         public Object getFirst(Object map, Object refValues) {
148             return ((Map) map).keySet().iterator().next();
149         }
150 
151         public Object[] listValues(Object map, Object refValues) {
152             return ((Map) map).keySet().toArray();
153         }
154     };
155 
156     private static final IValuesAccessor INDEXES_MODEL_VALUES_ACCESSOR = new AbstractValuesAccessor() {
157         private static final String REVISION = "$Revision: 1.8 $";
158 
159         public int getCount(Object indexesModel) {
160             return ((IIndexesModel) indexesModel).countIndexes();
161         }
162 
163         public Object getFirst(Object indexesModel, Object refValues) {
164             return ((IIndexesModel) indexesModel)
165                     .getFirstSelectedObject(refValues);
166         }
167 
168         public Object[] listValues(Object indexesModel, Object refValues) {
169             return ((IIndexesModel) indexesModel).listSelectedObjects(null,
170                     refValues);
171         }
172     };
173 
174     protected static IValuesAccessor getValuesAccessor(Object values,
175             Class providerClass, IValuesAccessor providerValuesAccessor,
176             boolean useValue) {
177 
178         if (values == null) {
179             if (useValue == false) {
180                 return null;
181             }
182             return NULL_VALUES_ACCESSOR;
183         }
184 
185         if (values.getClass().isArray()) {
186             if (useValue == false) {
187                 return null;
188             }
189             return ARRAY_VALUES_ACCESSOR;
190         }
191 
192         if (values instanceof String) {
193             if (useValue == false) {
194                 return null;
195             }
196             return STRING_VALUES_ACCESSOR;
197         }
198 
199         if (values instanceof Collection) {
200             if (useValue == false) {
201                 return null;
202             }
203             return COLLECTION_VALUES_ACCESSOR;
204         }
205 
206         if (values instanceof Map) {
207             if (useValue == false) {
208                 return null;
209             }
210             return MAP_VALUES_ACCESSOR;
211         }
212 
213         if (values instanceof IIndexesModel) {
214             if (useValue == false) {
215                 return null;
216             }
217             return INDEXES_MODEL_VALUES_ACCESSOR;
218         }
219 
220         if (providerClass == null) {
221             return null;
222         }
223 
224         if (values.getClass().isAssignableFrom(providerClass)) {
225             return providerValuesAccessor;
226         }
227 
228         if (values instanceof IAdaptable) {
229             Object provider = ((IAdaptable) values).getAdapter(providerClass,
230                     null);
231 
232             if (provider != null) {
233                 return new ProviderValuesAccessor(providerValuesAccessor,
234                         provider);
235             }
236         }
237 
238         Object provider = RcfacesContext.getCurrentInstance()
239                 .getAdapterManager().getAdapter(values, providerClass, null);
240 
241         if (provider != null) {
242             return new ProviderValuesAccessor(providerValuesAccessor, provider);
243         }
244 
245         return null;
246     }
247 
248     public static Object getEmptyValues() {
249         return EMPTY_VALUES;
250     }
251 
252     protected static Object[] convertToObjectArray(Object values) {
253         if (values == null) {
254             return null;
255         }
256 
257         if (values instanceof String) {
258             Set set = valuesToSet(values, true);
259             if (set.isEmpty()) {
260                 return EMPTY_STRING_ARRAY;
261             }
262 
263             return set.toArray(new String[set.size()]);
264         }
265 
266         if (values instanceof Object[]) {
267             return (Object[]) values;
268         }
269 
270         if (values instanceof Collection) {
271             return ((Collection) values).toArray();
272         }
273 
274         if (values instanceof Map) {
275             return ((Map) values).keySet().toArray();
276         }
277 
278         throw new FacesException("Can not convert object '" + values
279                 + "' to object array.");
280     }
281 
282     private static Object createNewValues(UIComponent component,
283             IValuesAccessor valuesAccessor) {
284         Class type = valuesAccessor.getComponentValuesType(null, component);
285         if (type == null) {
286 
287             if ((component instanceof IComponentValueTypeCapability) == false) {
288                 throw new FacesException(
289                         "Can not identify IComponentValueType for component id='"
290                                 + component.getId() + " renderType='"
291                                 + component.getRendererType() + "'");
292             }
293 
294             IComponentValueType componentValueType = ((IComponentValueTypeCapability) component)
295                     .getComponentValueType();
296 
297             Object values = componentValueType.createNewValue(component);
298 
299             valuesAccessor.setComponentValues(component, values);
300 
301             return values;
302         }
303 
304         if (type.isArray()) {
305             Object values = Array.newInstance(type.getComponentType(), 0);
306 
307             valuesAccessor.setComponentValues(component, values);
308 
309             return values;
310         }
311 
312         Class implementationType = (Class) IMPLEMENTATION_TYPES.get(type);
313         if (implementationType != null) {
314             type = implementationType;
315         }
316 
317         Object values;
318         try {
319             values = type.newInstance();
320 
321         } catch (Throwable th) {
322             throw new FacesException("Can not instanciate values for type '"
323                     + type + "'", th);
324         }
325 
326         valuesAccessor.setComponentValues(component, values);
327 
328         return values;
329     }
330 
331     public static void select(UIComponent component,
332             IValuesAccessor valuesAccessor, int indices[]) {
333         Object values = valuesAccessor.getComponentValues(component);
334 
335         if (values == null) {
336             values = createNewValues(component, valuesAccessor);
337         }
338 
339         if (values instanceof IIndexesModel) {
340             IIndexesModel indexesModel = cloneIndexModel(component,
341                     valuesAccessor, (IIndexesModel) values);
342 
343             for (int i = 0; i < indices.length; i++) {
344                 indexesModel.addIndex(indices[i]);
345             }
346 
347             return;
348         }
349 
350         List rowDatas = getRowDatas((IGridComponent) component, indices);
351         if (rowDatas.isEmpty()) {
352             return;
353         }
354 
355         select(component, valuesAccessor, values, rowDatas);
356     }
357 
358     public static void select(UIComponent component,
359             IValuesAccessor valuesAccessor, int start, int end) {
360 
361         Object values = valuesAccessor.getComponentValues(component);
362 
363         if (values == null) {
364             values = createNewValues(component, valuesAccessor);
365         }
366 
367         if (values instanceof IIndexesModel) {
368             IIndexesModel indexesModel = cloneIndexModel(component,
369                     valuesAccessor, (IIndexesModel) values);
370 
371             for (; start < end; start++) {
372                 indexesModel.addIndex(start);
373             }
374 
375             return;
376         }
377 
378         List rowDatas = getRowDatas((IGridComponent) component, start, end);
379         if (rowDatas.isEmpty()) {
380             return;
381         }
382 
383         select(component, valuesAccessor, values, rowDatas);
384     }
385 
386     public static void select(UIComponent component,
387             IValuesAccessor valuesAccessor, int index) {
388 
389         Object values = valuesAccessor.getComponentValues(component);
390 
391         if (values == null) {
392             values = createNewValues(component, valuesAccessor);
393         }
394 
395         if (values instanceof IIndexesModel) {
396             IIndexesModel indexesModel = cloneIndexModel(component,
397                     valuesAccessor, (IIndexesModel) values);
398 
399             indexesModel.addIndex(index);
400             return;
401         }
402 
403         Object rowData = getRowData((IGridComponent) component, index);
404         if (rowData == null) {
405             LOG.error("No rowData for index='" + index + "'.");
406             return;
407         }
408 
409         if (LOG.isDebugEnabled()) {
410             LOG.debug("Select index=" + index + " => " + rowData
411                     + "   selectedValues=" + values);
412         }
413 
414         select(component, valuesAccessor, values, Collections
415                 .singleton(rowData));
416     }
417 
418     public static void selectAll(UIComponent component,
419             IValuesAccessor valuesAccessor) {
420 
421         if ((component instanceof IGridComponent) == false) {
422             throw new UnsupportedOperationException(
423                     "Can not list all values of component '"
424                             + component.getId() + "'.");
425         }
426 
427         Object values = valuesAccessor.getComponentValues(component);
428 
429         if (values == null) {
430             values = createNewValues(component, valuesAccessor);
431         }
432 
433         if (values instanceof IIndexesModel) {
434             IIndexesModel indexesModel = cloneIndexModel(component,
435                     valuesAccessor, (IIndexesModel) values);
436 
437             int rowCount = getRowCount(component);
438             for (int i = 0; i < rowCount; i++) {
439                 indexesModel.addIndex(i);
440             }
441 
442             return;
443         }
444 
445         List rowDatas = getRowDatas((IGridComponent) component);
446         if (rowDatas.isEmpty()) {
447             return;
448         }
449 
450         select(component, valuesAccessor, values, rowDatas);
451     }
452 
453     public static void select(UIComponent component,
454             IValuesAccessor valuesAccessor, Object rowValue) {
455 
456         Object values = valuesAccessor.getComponentValues(component);
457 
458         if (values == null) {
459             values = createNewValues(component, valuesAccessor);
460         }
461 
462         if (values instanceof IIndexesModel) {
463             int index = searchIndexIntoDataModel((IGridComponent) component,
464                     rowValue);
465             if (index < 0) {
466                 return;
467             }
468 
469             select(component, valuesAccessor, index);
470 
471             return;
472         }
473 
474         select(component, valuesAccessor, values, Collections
475                 .singletonList(rowValue));
476     }
477 
478     private static Object select(UIComponent component,
479             IValuesAccessor valuesAccessor, Object values, Collection rowDatas) {
480 
481         if (values.getClass().isArray()) {
482 
483             int length = Array.getLength(values);
484 
485             List l = null;
486 
487             next_data: for (Iterator it = rowDatas.iterator(); it.hasNext();) {
488                 Object rowData = it.next();
489 
490                 for (int i = 0; i < length; i++) {
491                     if (Array.get(values, i).equals(rowData) == false) {
492                         continue;
493                     }
494 
495                     continue next_data;
496                 }
497 
498                 if (l == null) {
499                     l = new ArrayList();
500 
501                 } else if (l.contains(rowData)) {
502                     continue;
503                 }
504 
505                 l.add(rowData);
506             }
507 
508             if (l == null) {
509                 return values;
510             }
511 
512             Class type = values.getClass().getComponentType();
513 
514             Object newValues = Array.newInstance(type, length + l.size());
515 
516             System.arraycopy(values, 0, newValues, 0, length);
517 
518             for (Iterator it = l.iterator(); it.hasNext(); length++) {
519                 Array.set(newValues, length, it.next());
520             }
521 
522             valuesAccessor.setComponentValues(component, newValues);
523 
524             return newValues;
525         }
526 
527         if (values instanceof String) {
528             Set set = valuesToSet(values, false);
529 
530             set.addAll(rowDatas);
531 
532             String newValues = StringList.joinTokens(set);
533 
534             if (newValues.equals(values)) {
535                 return values;
536             }
537 
538             valuesAccessor.setComponentValues(component, newValues);
539 
540             return newValues;
541         }
542 
543         if (values instanceof Collection) {
544             Collection collection = cloneCollection(component, valuesAccessor,
545                     (Collection) values);
546 
547             if (collection instanceof Set) {
548                 collection.addAll(rowDatas);
549                 return collection;
550             }
551 
552             for (Iterator it = rowDatas.iterator(); it.hasNext();) {
553                 Object rowData = it.next();
554 
555                 if (collection.contains(rowData)) {
556                     continue;
557                 }
558 
559                 collection.add(rowData);
560             }
561 
562             return collection;
563         }
564 
565         throw new FacesException("Select index is not implemented for values="
566                 + values);
567     }
568 
569     private static Collection cloneCollection(UIComponent component,
570             IValuesAccessor valuesAccessor, Collection collection) {
571 
572         boolean copy = true;
573 
574         if (collection instanceof ICommitableObject) {
575             copy = ((ICommitableObject) collection).isCommited();
576         }
577 
578         if (copy == false) {
579             return collection;
580         }
581 
582         try {
583             Method method = collection.getClass().getMethod("clone",
584                     (Class[]) null);
585 
586             collection = (Collection) method
587                     .invoke(collection, (Object[]) null);
588 
589         } catch (Throwable th) {
590             LOG.info("Can not copy the collection ! ("
591                     + collection.getClass().getName() + ")", th);
592         }
593 
594         valuesAccessor.setComponentValues(component, collection);
595 
596         return collection;
597     }
598 
599     private static int getRowCount(UIComponent component) {
600 
601         IGridComponent gridComponent = (IGridComponent) component;
602 
603         int index = gridComponent.getRowCount();
604 
605         if (index >= 0) {
606             return index;
607         }
608 
609         try {
610             for (index = 0;; index++) {
611                 gridComponent.setRowIndex(index);
612 
613                 if (gridComponent.isRowAvailable()) {
614                     return index;
615                 }
616             }
617         } finally {
618             gridComponent.setRowIndex(-1);
619         }
620     }
621 
622     public static void deselectAll(UIComponent component,
623             IValuesAccessor valuesAccessor) {
624 
625         Object values = valuesAccessor.getComponentValues(component);
626         if (values == null) {
627             return;
628         }
629 
630         if (values instanceof IIndexesModel) {
631             IIndexesModel indexesModel = cloneIndexModel(component,
632                     valuesAccessor, (IIndexesModel) values);
633 
634             indexesModel.clearIndexes();
635             return;
636         }
637 
638         if (values instanceof Collection) {
639             Collection collection = cloneCollection(component, valuesAccessor,
640                     (Collection) values);
641 
642             collection.clear();
643             return;
644         }
645 
646         if (values instanceof String) {
647             if ("".equals(values)) {
648                 return;
649             }
650 
651             valuesAccessor.setComponentValues(component, "");
652 
653             return;
654         }
655 
656         if (values instanceof Object[]) {
657             if (Array.getLength(values) == 0) {
658                 return;
659             }
660 
661             Class type = values.getClass().getComponentType();
662 
663             values = Array.newInstance(type, 0);
664 
665             valuesAccessor.setComponentValues(component, values);
666             return;
667         }
668 
669         throw new FacesException("Deselect all is not implemented for values="
670                 + values);
671     }
672 
673     public static void deselect(UIComponent component,
674             IValuesAccessor valuesAccessor, Object rowValue) {
675 
676         Object values = valuesAccessor.getComponentValues(component);
677 
678         if (values == null) {
679             return;
680         }
681 
682         if (values instanceof IIndexesModel) {
683             int index = searchIndexIntoDataModel((IGridComponent) component,
684                     rowValue);
685 
686             if (index < 0) {
687                 return;
688             }
689 
690             IIndexesModel indexesModel = cloneIndexModel(component,
691                     valuesAccessor, (IIndexesModel) values);
692 
693             indexesModel.removeIndex(index);
694 
695             return;
696         }
697 
698         deselect(component, valuesAccessor, values, Collections
699                 .singletonList(rowValue));
700     }
701 
702     public static void deselect(UIComponent component,
703             IValuesAccessor valuesAccessor, int index) {
704 
705         Object values = valuesAccessor.getComponentValues(component);
706 
707         if (values == null) {
708             return;
709         }
710 
711         if (values instanceof IIndexesModel) {
712             IIndexesModel indexesModel = cloneIndexModel(component,
713                     valuesAccessor, (IIndexesModel) values);
714 
715             indexesModel.removeIndex(index);
716             return;
717         }
718 
719         Object rowData = getRowData((IGridComponent) component, index);
720 
721         if (rowData == null) {
722             LOG.error("No rowData for index='" + index + "'.");
723             return;
724         }
725 
726         if (LOG.isDebugEnabled()) {
727             LOG.debug("Deselect index=" + index + " => " + rowData
728                     + "   selectedValues=" + values);
729         }
730 
731         deselect(component, valuesAccessor, values, Collections
732                 .singleton(rowData));
733     }
734 
735     public static void deselect(UIComponent component,
736             IValuesAccessor valuesAccessor, int indices[]) {
737 
738         if (indices == null || indices.length < 1) {
739             return;
740         }
741 
742         Object values = valuesAccessor.getComponentValues(component);
743 
744         if (values == null) {
745             return;
746         }
747 
748         if (values instanceof IIndexesModel) {
749             IIndexesModel indexesModel = cloneIndexModel(component,
750                     valuesAccessor, (IIndexesModel) values);
751 
752             for (int i = 0; i < indices.length; i++) {
753                 indexesModel.removeIndex(indices[i]);
754             }
755 
756             return;
757         }
758 
759         List rowDatas = getRowDatas((IGridComponent) component, indices);
760         if (rowDatas.isEmpty()) {
761             return;
762         }
763 
764         deselect(component, valuesAccessor, values, rowDatas);
765     }
766 
767     public static void deselect(UIComponent component,
768             IValuesAccessor valuesAccessor, int start, int end) {
769 
770         Object values = valuesAccessor.getComponentValues(component);
771 
772         if (values == null) {
773             return;
774         }
775 
776         if (values instanceof IIndexesModel) {
777             IIndexesModel indexesModel = cloneIndexModel(component,
778                     valuesAccessor, (IIndexesModel) values);
779 
780             for (; start < end; start++) {
781                 indexesModel.removeIndex(start);
782             }
783 
784             return;
785         }
786 
787         List rowDatas = getRowDatas((IGridComponent) component, start, end);
788         if (rowDatas.isEmpty()) {
789             return;
790         }
791 
792         deselect(component, valuesAccessor, values, rowDatas);
793     }
794 
795     private static Object deselect(UIComponent component,
796             IValuesAccessor valuesAccessor, Object values, Collection rowDatas) {
797 
798         if (values.getClass().isArray()) {
799 
800             int length = Array.getLength(values);
801             if (length == 0) {
802                 return values;
803             }
804 
805             for (Iterator it = rowDatas.iterator(); it.hasNext();) {
806                 Object rowData = it.next();
807 
808                 for (int i = 0; i < length;) {
809                     if (Array.get(values, i).equals(rowData) == false) {
810                         i++;
811                         continue;
812                     }
813 
814                     length--;
815                     if (i >= length) {
816                         break;
817                     }
818 
819                     System.arraycopy(values, i + 1, values, i, length - i);
820                 }
821             }
822 
823             if (Array.getLength(values) == length) {
824                 // On a pas touché au tableau !
825                 return values;
826             }
827 
828             Class type = values.getClass().getComponentType();
829 
830             Object newValues = Array.newInstance(type, length);
831             if (length > 0) {
832                 System.arraycopy(values, 0, newValues, 0, length);
833             }
834 
835             valuesAccessor.setComponentValues(component, newValues);
836 
837             return newValues;
838         }
839 
840         if (values instanceof String) {
841             Set set = valuesToSet(values, false);
842 
843             set.removeAll(rowDatas);
844 
845             String newValues = StringList.joinTokens(set);
846 
847             if (newValues.equals(values)) {
848                 return values;
849             }
850 
851             valuesAccessor.setComponentValues(component, newValues);
852 
853             return newValues;
854         }
855 
856         if (values instanceof Collection) {
857             Collection collection = cloneCollection(component, valuesAccessor,
858                     (Collection) values);
859 
860             if (collection instanceof Set) {
861                 collection.removeAll(rowDatas);
862                 return collection;
863             }
864 
865             for (Iterator it = rowDatas.iterator(); it.hasNext();) {
866                 Object rowData = it.next();
867 
868                 collection.remove(rowData);
869             }
870 
871             return collection;
872         }
873 
874         throw new FacesException(
875                 "Deselect index is not implemented for selectedValues="
876                         + values);
877     }
878 
879     private static IIndexesModel cloneIndexModel(UIComponent component,
880             IValuesAccessor valuesAccessor, IIndexesModel indexesModel) {
881 
882         boolean copy = true;
883 
884         if (indexesModel instanceof ICommitableObject) {
885             copy = ((ICommitableObject) indexesModel).isCommited();
886         }
887 
888         if (copy == false) {
889             return indexesModel;
890         }
891 
892         indexesModel = indexesModel.copy();
893         valuesAccessor.setComponentValues(component, indexesModel);
894 
895         return indexesModel;
896     }
897 
898     private static List getRowDatas(IGridComponent gridComponent, int[] indices) {
899 
900         int rowCount = gridComponent.getRowCount();
901         if (rowCount > 0) {
902             DataModel dataModel = gridComponent.getDataModelValue();
903 
904             if (dataModel instanceof IRangeDataModel) {
905                 ((IRangeDataModel) dataModel).setRowRange(0, rowCount);
906             }
907         }
908 
909         if (SORT_INDICES) {
910             indices = (int[]) indices.clone();
911             Arrays.sort(indices);
912         }
913 
914         List rowDatas = null;
915         try {
916             for (int i = 0; i < indices.length; i++) {
917                 int index = indices[i];
918                 gridComponent.setRowIndex(index);
919                 if (gridComponent.isRowAvailable() == false) {
920                     LOG.error("Row not available for index='" + index + "'.");
921                     continue;
922                 }
923 
924                 Object rowData = gridComponent.getRowData();
925 
926                 if (rowData == null) {
927                     LOG.error("No rowData for index='" + index + "'.");
928                     continue;
929                 }
930 
931                 if (LOG.isDebugEnabled()) {
932                     LOG.debug("Get row at index=" + index + " => " + rowData);
933                 }
934 
935                 if (rowDatas == null) {
936                     rowDatas = new ArrayList(indices.length - i);
937                 }
938                 rowDatas.add(rowData);
939             }
940 
941         } finally {
942             gridComponent.setRowIndex(-1);
943         }
944 
945         if (rowDatas == null) {
946             return Collections.EMPTY_LIST;
947         }
948 
949         return rowDatas;
950     }
951 
952     private static Object getRowData(IGridComponent gridComponent, int index) {
953 
954         DataModel dataModel = gridComponent.getDataModelValue();
955 
956         if (dataModel instanceof IRangeDataModel) {
957             ((IRangeDataModel) dataModel).setRowRange(index, 1);
958         }
959 
960         Object rowData = null;
961         gridComponent.setRowIndex(index);
962         try {
963             if (gridComponent.isRowAvailable() == false) {
964                 LOG.error("Row not available for index='" + index + "'.");
965                 return null;
966             }
967 
968             rowData = gridComponent.getRowData();
969 
970             if (LOG.isDebugEnabled()) {
971                 LOG.debug("Get row at index=" + index + " => " + rowData);
972             }
973 
974         } finally {
975             gridComponent.setRowIndex(-1);
976         }
977 
978         if (rowData == null) {
979             LOG.error("RowData is null for index='" + index + "'.");
980         }
981 
982         return rowData;
983     }
984 
985     private static List getRowDatas(IGridComponent gridComponent) {
986 
987         int rowCount = gridComponent.getRowCount();
988         if (rowCount > 0) {
989             DataModel dataModel = gridComponent.getDataModelValue();
990 
991             if (dataModel instanceof IRangeDataModel) {
992                 ((IRangeDataModel) dataModel).setRowRange(0, rowCount);
993             }
994         }
995 
996         List rowDatas = null;
997         try {
998             for (int index = 0;; index++) {
999                 gridComponent.setRowIndex(index);
1000 
1001                 if (gridComponent.isRowAvailable() == false) {
1002                     LOG.debug("Row not available for index='" + index + "'.");
1003                     break;
1004                 }
1005 
1006                 Object rowData = gridComponent.getRowData();
1007 
1008                 if (rowData == null) {
1009                     LOG.debug("RowData is null for index='" + index + "'.");
1010                     continue;
1011                 }
1012 
1013                 if (rowDatas == null) {
1014                     int size = rowCount - index;
1015 
1016                     if (size < 8) {
1017                         size = 8;
1018                     }
1019 
1020                     rowDatas = new ArrayList(size);
1021                 }
1022 
1023                 if (LOG.isDebugEnabled()) {
1024                     LOG.debug("Get row at index=" + index + " => " + rowData);
1025                 }
1026 
1027                 rowDatas.add(rowData);
1028             }
1029 
1030         } finally {
1031             gridComponent.setRowIndex(-1);
1032         }
1033 
1034         if (rowDatas == null) {
1035             return Collections.EMPTY_LIST;
1036         }
1037 
1038         return rowDatas;
1039     }
1040 
1041     private static List getRowDatas(IGridComponent gridComponent, int start,
1042             int end) {
1043 
1044         DataModel dataModel = gridComponent.getDataModelValue();
1045 
1046         if (dataModel instanceof IRangeDataModel) {
1047             ((IRangeDataModel) dataModel).setRowRange(start, end - start + 1);
1048         }
1049 
1050         List rowDatas = null;
1051         try {
1052             for (int index = start; index <= end; index++) {
1053                 gridComponent.setRowIndex(index);
1054 
1055                 if (gridComponent.isRowAvailable() == false) {
1056                     LOG.error("Row not available for index='" + index + "'.");
1057                     break;
1058                 }
1059 
1060                 Object rowData = gridComponent.getRowData();
1061 
1062                 if (rowData == null) {
1063                     LOG.error("RowData is null for index='" + index + "'.");
1064                     break;
1065                 }
1066 
1067                 if (LOG.isDebugEnabled()) {
1068                     LOG.debug("Get index=" + index + " => " + rowData);
1069                 }
1070 
1071                 if (rowDatas == null) {
1072                     rowDatas = new ArrayList(end - index + 1);
1073                 }
1074 
1075                 rowDatas.add(rowData);
1076             }
1077 
1078         } finally {
1079             gridComponent.setRowIndex(-1);
1080         }
1081 
1082         if (rowDatas == null) {
1083             return Collections.EMPTY_LIST;
1084         }
1085 
1086         return rowDatas;
1087     }
1088 
1089     private static int searchIndexIntoDataModel(IGridComponent component,
1090             Object rowValue) {
1091         int rowCount = component.getRowCount();
1092         if (rowCount > 0) {
1093             DataModel dataModel = component.getDataModelValue();
1094 
1095             if (dataModel instanceof IRangeDataModel) {
1096                 ((IRangeDataModel) dataModel).setRowRange(0, rowCount);
1097             }
1098         }
1099 
1100         try {
1101             for (int index = 0;; index++) {
1102                 component.setRowIndex(index);
1103                 if (component.isRowAvailable() == false) {
1104                     break;
1105                 }
1106 
1107                 Object rowData = component.getRowData();
1108 
1109                 if (rowData == null) {
1110                     LOG.error("RowData is null for index='" + index + "'.");
1111                     break;
1112                 }
1113 
1114                 if (rowData.equals(rowValue) == false) {
1115                     continue;
1116                 }
1117 
1118                 if (LOG.isDebugEnabled()) {
1119                     LOG.debug("Find row " + rowData + " => index=" + index);
1120                 }
1121 
1122                 return index;
1123             }
1124 
1125         } finally {
1126             component.setRowIndex(-1);
1127         }
1128 
1129         return -1;
1130     }
1131 
1132     /**
1133      * 
1134      * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
1135      * @version $Revision: 1.8 $ $Date: 2009/03/04 10:08:54 $
1136      */
1137     private static class ProviderValuesAccessor implements IValuesAccessor {
1138 
1139         private final IValuesAccessor providerValuesAccessor;
1140 
1141         private final Object provider;
1142 
1143         public ProviderValuesAccessor(IValuesAccessor providerValuesAccessor,
1144                 Object provider) {
1145             this.providerValuesAccessor = providerValuesAccessor;
1146             this.provider = provider;
1147         }
1148 
1149         public int getCount(Object value) {
1150             return providerValuesAccessor.getCount(provider);
1151         }
1152 
1153         public Object getFirst(Object value, Object refValues) {
1154             return providerValuesAccessor.getFirst(provider, null);
1155         }
1156 
1157         public Object[] listValues(Object value, Object refValues) {
1158             return providerValuesAccessor.listValues(provider, null);
1159         }
1160 
1161         public Object getAdaptedValues(Object value) {
1162             return provider;
1163         }
1164 
1165         public Object getComponentValues(UIComponent component) {
1166             return providerValuesAccessor.getComponentValues(component);
1167         }
1168 
1169         public void setComponentValues(UIComponent component, Object values) {
1170             providerValuesAccessor.setComponentValues(component, values);
1171         }
1172 
1173         public Class getComponentValuesType(FacesContext facesContext,
1174                 UIComponent component) {
1175             return providerValuesAccessor.getComponentValuesType(null,
1176                     component);
1177         }
1178 
1179         public void setAdaptedValues(Object value, Object values) {
1180             providerValuesAccessor.setAdaptedValues(value, values);
1181         }
1182     }
1183 
1184     /**
1185      * 
1186      * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
1187      * @version $Revision: 1.8 $ $Date: 2009/03/04 10:08:54 $
1188      */
1189     protected interface IValuesAccessor {
1190         Object getFirst(Object value, Object refValues);
1191 
1192         int getCount(Object value);
1193 
1194         Object[] listValues(Object value, Object refValues);
1195 
1196         Object getAdaptedValues(Object values);
1197 
1198         void setAdaptedValues(Object value, Object values);
1199 
1200         Object getComponentValues(UIComponent component);
1201 
1202         void setComponentValues(UIComponent component, Object values);
1203 
1204         Class getComponentValuesType(FacesContext facesContext,
1205                 UIComponent component);
1206     }
1207 
1208     /**
1209      * 
1210      * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
1211      * @version $Revision: 1.8 $ $Date: 2009/03/04 10:08:54 $
1212      */
1213     private static abstract class AbstractValuesAccessor implements
1214             IValuesAccessor {
1215         private static final String REVISION = "$Revision: 1.8 $";
1216 
1217         public Object getComponentValues(UIComponent component) {
1218             throw new IllegalStateException("Not implemented !");
1219         }
1220 
1221         public void setComponentValues(UIComponent component, Object values) {
1222             throw new IllegalStateException("Not implemented !");
1223         }
1224 
1225         public Class getComponentValuesType(FacesContext facesContext,
1226                 UIComponent component) {
1227             throw new IllegalStateException("Not implemented !");
1228         }
1229 
1230         public Object getAdaptedValues(Object value) {
1231             return value;
1232         }
1233 
1234         public void setAdaptedValues(Object value, Object values) {
1235             throw new IllegalStateException("Not supported");
1236         }
1237     }
1238 
1239     public static Object adaptValues(Class target, Collection collection) {
1240         if (target == null || target.equals(Object.class)
1241                 || target.equals(Object[].class)) {
1242             return collection.toArray();
1243         }
1244 
1245         if (target.isArray()) {
1246             Object array = Array.newInstance(target.getComponentType(),
1247                     collection.size());
1248 
1249             if (array instanceof Object[]) {
1250                 return collection.toArray((Object[]) array);
1251             }
1252 
1253             Object src[] = collection.toArray();
1254 
1255             System.arraycopy(src, 0, array, 0, collection.size());
1256 
1257             return array;
1258         }
1259 
1260         if (Set.class.isAssignableFrom(target)) {
1261             if (collection instanceof Set) {
1262                 return collection;
1263             }
1264             return new HashSet(collection);
1265         }
1266 
1267         if (List.class.isAssignableFrom(target)) {
1268             if (collection instanceof List) {
1269                 return collection;
1270             }
1271             return new ArrayList(collection);
1272         }
1273 
1274         if (Collection.class.isAssignableFrom(target)) {
1275             return collection;
1276         }
1277 
1278         throw new FacesException("Invalid collection type '" + target + "'.");
1279     }
1280 
1281     public static Set __convertSelection(Object selection) {
1282         if (selection instanceof Object[]) {
1283             return new OrderedSet(Arrays.asList((Object[]) selection));
1284         }
1285 
1286         if (selection instanceof Collection) {
1287             return new OrderedSet((Collection) selection);
1288         }
1289 
1290         if (selection == null) {
1291             return new OrderedSet();
1292         }
1293 
1294         throw new FacesException(
1295                 "Bad type of value for attribute selectedValues/checkedValues !");
1296     }
1297 
1298     protected static void setValues(UIComponent component,
1299             IValuesAccessor valuesAccessor, Collection values) {
1300 
1301         Object newValues = createNewValues(component, valuesAccessor);
1302 
1303         select(component, valuesAccessor, newValues, values);
1304     }
1305 
1306     protected static Set valuesToSet(UIComponent component,
1307             IValuesAccessor valuesAccessor, boolean immutable) {
1308         Object value = valuesAccessor.getComponentValues(component);
1309 
1310         return valuesToSet(value, immutable);
1311     }
1312 
1313     public static Set valuesToSet(Object value, boolean immutable) {
1314         if (value == null) {
1315             if (immutable == false) {
1316                 return new OrderedSet();
1317             }
1318             return Collections.EMPTY_SET;
1319         }
1320 
1321         if (value.getClass().isArray()) {
1322             int length = Array.getLength(value);
1323 
1324             if (length < 1) {
1325                 if (immutable == false) {
1326                     return new OrderedSet();
1327                 }
1328                 return Collections.EMPTY_SET;
1329             }
1330 
1331             Set set = new OrderedSet();
1332 
1333             for (int i = 0; i < length; i++) {
1334                 set.add(Array.get(value, i));
1335             }
1336 
1337             if (LOG.isDebugEnabled() && immutable) {
1338                 return Collections.unmodifiableSet(set);
1339             }
1340 
1341             return set;
1342         }
1343 
1344         if (value instanceof String) {
1345             String ss[] = StringList.parseTokensList((String) value);
1346 
1347             if (ss.length == 0) {
1348                 if (immutable == false) {
1349                     return new OrderedSet();
1350                 }
1351                 return Collections.EMPTY_SET;
1352             }
1353 
1354             Set set = new OrderedSet(Arrays.asList(ss));
1355 
1356             if (LOG.isDebugEnabled() && immutable) {
1357                 return Collections.unmodifiableSet(set);
1358             }
1359 
1360             return set;
1361         }
1362 
1363         if (value instanceof Set) {
1364             if (immutable == false) {
1365                 return new OrderedSet((Set) value);
1366             }
1367 
1368             if (LOG.isDebugEnabled() && immutable) {
1369                 return Collections.unmodifiableSet((Set) value);
1370             }
1371 
1372             return (Set) value;
1373         }
1374 
1375         if (value instanceof Collection) {
1376             Collection col = (Collection) value;
1377             if (col.isEmpty() && immutable) {
1378                 return Collections.EMPTY_SET;
1379             }
1380 
1381             Set set = new OrderedSet((Collection) value);
1382 
1383             if (LOG.isDebugEnabled() && immutable) {
1384                 return Collections.unmodifiableSet(set);
1385             }
1386 
1387             return set;
1388         }
1389 
1390         if (immutable == false) {
1391             Set set = new OrderedSet();
1392             set.add(value);
1393 
1394             return set;
1395         }
1396 
1397         return Collections.singleton(value);
1398     }
1399 
1400     /**
1401      * 
1402      * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
1403      * @version $Revision: 1.8 $ $Date: 2009/03/04 10:08:54 $
1404      */
1405     public interface IComponentValueType {
1406         Object createNewValue(UIComponent component);
1407     }
1408 
1409     /**
1410      * INTERNAL Stuff
1411      * 
1412      * @author Olivier Oeuillot (latest modification by $Author: oeuillot $)
1413      * @version $Revision: 1.8 $ $Date: 2009/03/04 10:08:54 $
1414      */
1415     public interface IComponentValueTypeCapability {
1416         IComponentValueType getComponentValueType();
1417     }
1418 }