Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/myfaces/renderkit/RendererUtils.java


1   /*
2    * Copyright 2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.myfaces.renderkit;
17  
18  import java.io.IOException;
19  import java.io.Serializable;
20  import java.lang.reflect.Array;
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.Collections;
24  import java.util.Date;
25  import java.util.HashSet;
26  import java.util.Iterator;
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.EditableValueHolder;
33  import javax.faces.component.NamingContainer;
34  import javax.faces.component.UIComponent;
35  import javax.faces.component.UIComponentBase;
36  import javax.faces.component.UIForm;
37  import javax.faces.component.UIOutput;
38  import javax.faces.component.UISelectItem;
39  import javax.faces.component.UISelectItems;
40  import javax.faces.component.UISelectMany;
41  import javax.faces.component.UISelectOne;
42  import javax.faces.component.UIViewRoot;
43  import javax.faces.component.ValueHolder;
44  import javax.faces.component.html.HtmlInputText;
45  import javax.faces.context.FacesContext;
46  import javax.faces.convert.Converter;
47  import javax.faces.convert.ConverterException;
48  import javax.faces.el.PropertyNotFoundException;
49  import javax.faces.el.ValueBinding;
50  import javax.faces.model.SelectItem;
51  
52  import org.apache.commons.logging.Log;
53  import org.apache.commons.logging.LogFactory;
54  import org.apache.myfaces.util.HashMapUtils;
55  import org.apache.myfaces.util.SelectItemsIterator;
56  
57  /**
58   * @author Manfred Geiler (latest modification by $Author: mbr $)
59   * @version $Revision: 290413 $ $Date: 2005-09-20 06:26:13 -0400 (Tue, 20 Sep 2005) $
60   */
61  public class RendererUtils
62  {
63      private static final Log log = LogFactory.getLog(RendererUtils.class);
64  
65      public static final String SELECT_ITEM_LIST_ATTR = RendererUtils.class.getName() + ".LIST";
66      public static final String EMPTY_STRING = new String();
67      public static final Object NOTHING = new Serializable() {};
68  
69      public static String getPathToComponent(UIComponent component)
70      {
71          StringBuffer buf = new StringBuffer();
72  
73          if(component == null)
74          {
75              buf.append("{Component-Path : ");
76              buf.append("[null]}");
77              return buf.toString();
78          }
79  
80          getPathToComponent(component,buf);
81  
82          buf.insert(0,"{Component-Path : ");
83          buf.append("}");
84  
85          return buf.toString();
86      }
87  
88      private static void getPathToComponent(UIComponent component, StringBuffer buf)
89      {
90          if(component == null)
91              return;
92  
93          StringBuffer intBuf = new StringBuffer();
94  
95          intBuf.append("[Class: ");
96          intBuf.append(component.getClass().getName());
97          if(component instanceof UIViewRoot)
98          {
99              intBuf.append(",ViewId: ");
100             intBuf.append(((UIViewRoot) component).getViewId());
101         }
102         else
103         {
104             intBuf.append(",Id: ");
105             intBuf.append(component.getId());
106         }
107         intBuf.append("]");
108 
109         buf.insert(0,intBuf);
110 
111         if(component!=null)
112         {
113             getPathToComponent(component.getParent(),buf);
114         }
115     }
116 
117     public static String getConcatenatedId(FacesContext context, UIComponent container,
118                                            String clientId)
119     {
120         UIComponent child = container.findComponent(clientId);
121 
122         if(child == null)
123                 return clientId;
124 
125         return getConcatenatedId(context, child);
126     }
127 
128     public static String getConcatenatedId(FacesContext context, UIComponent component)
129     {
130         if (context == null) throw new NullPointerException("context");
131 
132         StringBuffer idBuf = new StringBuffer();
133 
134         idBuf.append(component.getId());
135 
136         UIComponent parent = null;
137 
138         while((parent = component.getParent())!=null)
139         {
140             if(parent instanceof NamingContainer)
141             {
142                 idBuf.insert(0,NamingContainer.SEPARATOR_CHAR);
143                 idBuf.insert(0,parent.getId());
144             }
145         }
146 
147         return idBuf.toString();
148     }
149 
150     public static Boolean getBooleanValue(UIComponent component)
151     {
152         Object value = getObjectValue(component);
153         if (value==null || value instanceof Boolean)
154         {
155             return (Boolean) value;
156         }
157         else
158         {
159             throw new IllegalArgumentException("Expected submitted value of type Boolean for Component : "+
160                     getPathToComponent(component));
161         }
162     }
163 
164     public static Date getDateValue(UIComponent component)
165     {
166         Object value = getObjectValue(component);
167         if (value==null || value instanceof Date)
168         {
169             return (Date) value;
170         }
171         else
172         {
173             throw new IllegalArgumentException("Expected submitted value of type Date for component : "
174                 +getPathToComponent(component));
175         }
176     }
177 
178     public static Object getObjectValue(UIComponent component)
179     {
180         if (!(component instanceof ValueHolder))
181         {
182             throw new IllegalArgumentException("Component : "+
183                     getPathToComponent(component)+"is not a ValueHolder");
184         }
185 
186         if (component instanceof EditableValueHolder)
187         {
188             Object value = ((EditableValueHolder)component).getSubmittedValue();
189             if(value != null && !NOTHING.equals(value))
190             {
191                 return value;
192             }
193         }
194 
195         return ((ValueHolder)component).getValue();
196     }
197 
198     public static String getStringValue(FacesContext facesContext,
199                                         UIComponent component)
200     {
201         try
202         {
203             if (!(component instanceof ValueHolder))
204             {
205                 throw new IllegalArgumentException("Component : "+getPathToComponent(component)+"is not a ValueHolder");
206             }
207 
208             if (component instanceof EditableValueHolder)
209             {
210                 Object submittedValue = ((EditableValueHolder)component).getSubmittedValue();
211                 if (submittedValue != null)
212                 {
213                     if (submittedValue instanceof String)
214                     {
215                         return (String)submittedValue;
216                     }
217                     else
218                     {
219                         throw new IllegalArgumentException("Expected submitted value of type String for component : "
220                             +getPathToComponent(component));
221                     }
222                 }
223             }
224 
225             Object value = ((ValueHolder)component).getValue();
226 
227             Converter converter = ((ValueHolder)component).getConverter();
228             if (converter == null  && value != null)
229             {
230                 if (value instanceof String)
231                 {
232                     return (String) value;
233                 }
234 
235                 try
236                 {
237                     converter = facesContext.getApplication().createConverter(value.getClass());
238                 }
239                 catch (FacesException e)
240                 {
241                     log.error("No converter for class " + value.getClass().getName() + " found (component id=" + component.getId() + ").");
242                     // converter stays null
243                 }
244             }
245 
246             if (converter == null)
247             {
248                 if (value == null)
249                 {
250                     return "";
251                 }
252                 else
253                 {
254                     return value.toString();
255                 }
256             }
257             else
258             {
259                 return converter.getAsString(facesContext, component, value);
260             }
261         }
262         catch(PropertyNotFoundException ex)
263         {
264             log.error("Property not found - called by component : "+getPathToComponent(component));
265 
266             throw ex;
267         }
268     }
269 
270     /**
271      * See JSF Spec. 8.5 Table 8-1
272      * @param value
273      * @return boolean
274      */
275     public static boolean isDefaultAttributeValue(Object value)
276     {
277         if (value == null)
278         {
279             return true;
280         }
281         else if (value instanceof Boolean)
282         {
283             return ((Boolean)value).booleanValue() == false;
284         }
285         else if (value instanceof Number)
286         {
287             if (value instanceof Integer)
288             {
289                 return ((Number)value).intValue() == Integer.MIN_VALUE;
290             }
291             else if (value instanceof Double)
292             {
293                 return ((Number)value).doubleValue() == Double.MIN_VALUE;
294             }
295             else if (value instanceof Long)
296             {
297                 return ((Number)value).longValue() == Long.MIN_VALUE;
298             }
299             else if (value instanceof Byte)
300             {
301                 return ((Number)value).byteValue() == Byte.MIN_VALUE;
302             }
303             else if (value instanceof Float)
304             {
305                 return ((Number)value).floatValue() == Float.MIN_VALUE;
306             }
307             else if (value instanceof Short)
308             {
309                 return ((Number)value).shortValue() == Short.MIN_VALUE;
310             }
311         }
312         return false;
313     }
314 
315     /**
316      * Find the proper Converter for the given UIOutput component.
317      * @return the Converter or null if no Converter specified or needed
318      * @throws FacesException if the Converter could not be created
319      */
320     public static Converter findUIOutputConverter(FacesContext facesContext,
321                                                   UIOutput component)
322             throws FacesException
323     {
324         return _SharedRendererUtils.findUIOutputConverter(facesContext, component);
325     }
326 
327 
328     /**
329      * Find proper Converter for the entries in the associated List or Array of
330      * the given UISelectMany as specified in API Doc of UISelectMany.
331      * @return the Converter or null if no Converter specified or needed
332      * @throws FacesException if the Converter could not be created
333      */
334     public static Converter findUISelectManyConverter(FacesContext facesContext,
335                                                       UISelectMany component)
336     {
337         Converter converter = component.getConverter();
338         if (converter != null) return converter;
339 
340         //Try to find out by value binding
341         ValueBinding vb = component.getValueBinding("value");
342         if (vb == null) return null;
343 
344         Class valueType = vb.getType(facesContext);
345         if (valueType == null) return null;
346 
347         if (List.class.isAssignableFrom(valueType))
348         {
349             //According to API Doc of UISelectMany the assumed entry type for a List is String
350             //--> so basically no converter needed
351 
352             // However, if the List contains something other than Strings, we can attempt
353             // to find a suitable converter. In JDK 1.4, we can try to find out what the List
354             // contains by looking at the SelectItem value of the first item. With generics in
355             // JDK 1.5, it would be much easier to determine the type.
356 
357             List selectItems = RendererUtils.internalGetSelectItemList(component);
358 
359             if (selectItems != null && selectItems.size() > 0)
360             {
361                 SelectItem selectItem = (SelectItem) selectItems.get(0);
362                 Class listComponentType = selectItem.getValue().getClass();
363 
364                 if (!(String.class.equals(listComponentType)))
365                 {
366                     try
367                     {
368                         return facesContext.getApplication().createConverter(listComponentType);
369                     }
370                     catch (FacesException e)
371                     {
372                         log.error("No Converter for type " + listComponentType.getName() + " found", e);
373                         return null;
374                     }
375                 }
376             }
377 
378             return null;
379         }
380 
381         if (!valueType.isArray())
382         {
383             throw new IllegalArgumentException("ValueBinding for UISelectMany : "+getPathToComponent(component)+" must be of type List or Array");
384         }
385 
386         Class arrayComponentType = valueType.getComponentType();
387         if (String.class.equals(arrayComponentType)) return null;    //No converter needed for String type
388         if (Object.class.equals(arrayComponentType)) return null;    //There is no converter for Object class
389 
390         try
391         {
392             return facesContext.getApplication().createConverter(arrayComponentType);
393         }
394         catch (FacesException e)
395         {
396             log.error("No Converter for type " + arrayComponentType.getName() + " found", e);
397             return null;
398         }
399     }
400 
401 
402     public static void checkParamValidity(FacesContext facesContext, UIComponent uiComponent, Class compClass)
403     {
404         if(facesContext == null)
405             throw new NullPointerException("facesContext may not be null");
406         if(uiComponent == null)
407             throw new NullPointerException("uiComponent may not be null");
408 
409         //if (compClass != null && !(compClass.isAssignableFrom(uiComponent.getClass())))
410         // why isAssignableFrom with additional getClass method call if isInstance does the same?
411         if (compClass != null && !(compClass.isInstance(uiComponent)))
412         {
413             throw new IllegalArgumentException("uiComponent : "+getPathToComponent(uiComponent)+
414                     " is not instance of "+compClass.getName()+" as it should be");
415         }
416     }
417 
418 
419     public static void renderChildren(FacesContext facesContext, UIComponent component)
420             throws IOException
421     {
422         if (component.getChildCount() > 0)
423         {
424             for (Iterator it = component.getChildren().iterator(); it.hasNext(); )
425             {
426                 UIComponent child = (UIComponent)it.next();
427                 renderChild(facesContext, child);
428             }
429         }
430     }
431 
432 
433     public static void renderChild(FacesContext facesContext, UIComponent child)
434             throws IOException
435     {
436         if (!child.isRendered())
437         {
438             return;
439         }
440 
441         child.encodeBegin(facesContext);
442         if (child.getRendersChildren())
443         {
444             child.encodeChildren(facesContext);
445         }
446         else
447         {
448             renderChildren(facesContext, child);
449         }
450         child.encodeEnd(facesContext);
451     }
452 
453 
454 
455     /**
456      * @param uiSelectOne
457      * @return List of SelectItem Objects
458      */
459     public static List getSelectItemList(UISelectOne uiSelectOne)
460     {
461         return internalGetSelectItemList(uiSelectOne);
462     }
463 
464     /**
465      * @param uiSelectMany
466      * @return List of SelectItem Objects
467      */
468     public static List getSelectItemList(UISelectMany uiSelectMany)
469     {
470         return internalGetSelectItemList(uiSelectMany);
471     }
472 
473     private static List internalGetSelectItemList(UIComponent uiComponent)
474     {
475         /* TODO: Shall we cache the list in a component attribute?
476         ArrayList list = (ArrayList)uiComponent.getAttributes().get(SELECT_ITEM_LIST_ATTR);
477         if (list != null)
478         {
479             return list;
480         }
481          */
482         
483         List list = new ArrayList();
484         
485         for (Iterator iter = new SelectItemsIterator(uiComponent); iter.hasNext();)
486         {
487             list.add(iter.next());            
488         }        
489         return list;
490     }
491 
492 
493     /**
494      * Convenient utility method that returns the currently submitted values of
495      * a UISelectMany component as a Set, of which the contains method can then be
496      * easily used to determine if a select item is currently selected.
497      * Calling the contains method of this Set with the renderable (String converted) item value
498      * as argument returns true if this item is selected.
499      * @param uiSelectMany
500      * @return Set containing all currently selected values
501      */
502     public static Set getSubmittedValuesAsSet(FacesContext context, UIComponent component, Converter converter, UISelectMany uiSelectMany)
503     {
504         Object submittedValues = uiSelectMany.getSubmittedValue();
505         if (submittedValues == null)
506         {
507             return null;
508         }
509 
510         return internalSubmittedOrSelectedValuesAsSet(context, component, converter, uiSelectMany, submittedValues);
511     }
512 
513 
514     /**
515      * Convenient utility method that returns the currently selected values of
516      * a UISelectMany component as a Set, of which the contains method can then be
517      * easily used to determine if a value is currently selected.
518      * Calling the contains method of this Set with the item value
519      * as argument returns true if this item is selected.
520      * @param uiSelectMany
521      * @return Set containing all currently selected values
522      */
523     public static Set getSelectedValuesAsSet(FacesContext context, UIComponent component, Converter converter, UISelectMany uiSelectMany)
524     {
525         Object selectedValues = uiSelectMany.getValue();
526 
527         return internalSubmittedOrSelectedValuesAsSet(context, component, converter, uiSelectMany, selectedValues);
528     }
529 
530 
531     /**
532      * Convenient utility method that returns the currently given value as String,
533      * using the given converter.
534      * Especially usefull for dealing with primitive types.
535      */
536     public static String getConvertedStringValue(FacesContext context,
537             UIComponent component, Converter converter, Object value) {
538         if (converter == null) {
539             if (value == null) {
540                 return "";
541             } else if (value instanceof String) {
542                 return (String) value;
543             } else {
544                 throw new IllegalArgumentException(
545                         "Value is no String and component "
546                                 + component.getClientId(context)
547                                 + " does not have a Converter");
548             }
549         }
550 
551         return converter.getAsString(context, component, value);
552     }
553 
554 
555     /**
556      * Convenient utility method that returns the currently given SelectItem value
557      * as String, using the given converter.
558      * Especially usefull for dealing with primitive types.
559      */
560     public static String getConvertedStringValue(FacesContext context,
561             UIComponent component, Converter converter, SelectItem selectItem) {
562         return getConvertedStringValue(context, component, converter, selectItem.getValue());
563     }
564 
565 
566     private static Set internalSubmittedOrSelectedValuesAsSet(FacesContext context,
567             UIComponent component, Converter converter, UISelectMany uiSelectMany,
568             Object values)
569     {
570         if (values == null || EMPTY_STRING.equals(values))
571         {
572             return Collections.EMPTY_SET;
573         }
574         else if (values instanceof Object[])
575         {
576             //Object array
577             Object[] ar = (Object[])values;
578             if (ar.length == 0)
579             {
580                 return Collections.EMPTY_SET;
581             }
582 
583             HashSet set = new HashSet(HashMapUtils.calcCapacity(ar.length));
584             for (int i = 0; i < ar.length; i++)
585             {
586                 set.add( getConvertedStringValue(context, component, converter, ar[i]) );
587             }
588             return set;
589         }
590         else if (values.getClass().isArray())
591         {
592             //primitive array
593             int len = Array.getLength(values);
594             HashSet set = new HashSet(HashMapUtils.calcCapacity(len));
595             for (int i = 0; i < len; i++)
596             {
597                 set.add( getConvertedStringValue(context, component, converter, Array.get(values,i)) );
598             }
599             return set;
600         }
601         else if (values instanceof List)
602         {
603             List lst = (List)values;
604             if (lst.size() == 0)
605             {
606                 return Collections.EMPTY_SET;
607             }
608             else
609             {
610                 HashSet set = new HashSet(HashMapUtils.calcCapacity(lst.size()));
611                 for(Iterator i =lst.iterator(); i.hasNext(); )
612                     set.add( getConvertedStringValue(context, component, converter, i.next()) );
613 
614                 return set;
615             }
616         }
617         else
618         {
619             throw new IllegalArgumentException("Value of UISelectMany component with path : " + getPathToComponent(uiSelectMany) + " is not of type Array or List");
620         }
621     }
622 
623 
624 
625     public static Object getConvertedUIOutputValue(FacesContext facesContext,
626                                                    UIOutput output,
627                                                    Object submittedValue)
628         throws ConverterException
629     {
630         if (submittedValue!=null && !(submittedValue instanceof String))
631         {
632             if(RendererUtils.NOTHING.equals(submittedValue))
633             {
634                 return null;
635             }
636             throw new IllegalArgumentException("Submitted value of type String for component : "+
637                     getPathToComponent(output)+"expected");
638         }
639 
640         Converter converter;
641         try
642         {
643             converter = findUIOutputConverter(facesContext, output);
644         }
645         catch (FacesException e)
646         {
647             throw new ConverterException(e);
648         }
649 
650         if (converter == null)
651         {
652             //No conversion needed
653             return submittedValue;
654         }
655         else
656         {
657             //Conversion
658             return converter.getAsObject(facesContext, output, (String)submittedValue);
659         }
660     }
661 
662 
663     public static Object getConvertedUISelectManyValue(FacesContext facesContext,
664                                                        UISelectMany selectMany,
665                                                        Object submittedValue)
666             throws ConverterException
667     {
668         if (submittedValue == null)
669         {
670             return null;
671         }
672         else
673         {
674             if (!(submittedValue instanceof String[]))
675             {
676                 throw new ConverterException("Submitted value of type String[] for component : "
677                                              + getPathToComponent(selectMany) + "expected");
678             }
679         }
680         return _SharedRendererUtils.getConvertedUISelectManyValue(facesContext,
681                                                                   selectMany,
682                                                                   (String[])submittedValue);
683     }
684 
685 
686     public static boolean getBooleanAttribute(UIComponent component,
687                                               String attrName,
688                                               boolean defaultValue)
689     {
690         Boolean b = (Boolean)component.getAttributes().get(attrName);
691         return b != null ? b.booleanValue() : defaultValue;
692     }
693 
694     public static int getIntegerAttribute(UIComponent component,
695                                           String attrName,
696                                           int defaultValue)
697     {
698         Integer i = (Integer)component.getAttributes().get(attrName);
699         return i != null ? i.intValue() : defaultValue;
700     }
701 
702     public static UIForm findParentForm(UIComponentBase comp)
703     {
704         UIComponent parent = comp.getParent();
705         while (parent != null)
706         {
707             if (parent instanceof UIForm)
708             {
709                 return (UIForm)parent;
710             }
711             parent = parent.getParent();
712         }
713         return null;
714     }
715 
716     public static void copyHtmlInputTextAttributes(HtmlInputText src, HtmlInputText dest)
717     {
718         dest.setId(src.getId());
719         dest.setImmediate(src.isImmediate());
720         dest.setTransient(src.isTransient());
721         dest.setAccesskey(src.getAccesskey());
722         dest.setAlt(src.getAlt());
723         dest.setConverter(src.getConverter());
724         dest.setDir(src.getDir());
725         dest.setDisabled(src.isDisabled());
726         dest.setLang(src.getLang());
727         dest.setLocalValueSet(src.isLocalValueSet());
728         dest.setMaxlength(src.getMaxlength());
729         dest.setOnblur(src.getOnblur());
730         dest.setOnchange(src.getOnchange());
731         dest.setOnclick(src.getOnclick());
732         dest.setOndblclick(src.getOndblclick());
733         dest.setOnfocus(src.getOnfocus());
734         dest.setOnkeydown(src.getOnkeydown());
735         dest.setOnkeypress(src.getOnkeypress());
736         dest.setOnkeyup(src.getOnkeyup());
737         dest.setOnmousedown(src.getOnmousedown());
738         dest.setOnmousemove(src.getOnmousemove());
739         dest.setOnmouseout(src.getOnmouseout());
740         dest.setOnmouseover(src.getOnmouseover());
741         dest.setOnmouseup(src.getOnmouseup());
742         dest.setOnselect(src.getOnselect());
743         dest.setReadonly(src.isReadonly());
744         dest.setRendered(src.isRendered());
745         dest.setRequired(src.isRequired());
746         dest.setSize(src.getSize());
747         dest.setStyle(src.getStyle());
748         dest.setStyleClass(src.getStyleClass());
749         dest.setTabindex(src.getTabindex());
750         dest.setTitle(src.getTitle());
751         dest.setValidator(src.getValidator());
752     }
753 }