View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.shared_orchestra.renderkit;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  
24  import javax.faces.FacesException;
25  import javax.faces.component.UIOutput;
26  import javax.faces.component.UISelectMany;
27  import javax.faces.context.FacesContext;
28  import javax.faces.convert.Converter;
29  import javax.faces.convert.ConverterException;
30  import javax.faces.el.ValueBinding;
31  import java.lang.reflect.Array;
32  import java.util.ArrayList;
33  import java.util.List;
34  
35  /**
36   * The util methods in this class are shared between the javax.faces.component package and
37   * the org.apache.myfaces.renderkit package.
38   * Please note: Any changes here must also apply to the class in the other package!
39   *
40   * @author Manfred Geiler (latest modification by $Author: grantsmith $)
41   * @version $Revision: 472618 $ $Date: 2006-11-08 15:06:54 -0500 (Wed, 08 Nov 2006) $
42   */
43  class _SharedRendererUtils
44  {
45      static Converter findUIOutputConverter(FacesContext facesContext, UIOutput component)
46      {
47          // Attention!
48          // This code is duplicated in jsfapi component package.
49          // If you change something here please do the same in the other class!
50  
51          Converter converter = component.getConverter();
52          if (converter != null) return converter;
53  
54          //Try to find out by value binding
55          ValueBinding vb = component.getValueBinding("value");
56          if (vb == null) return null;
57  
58          Class valueType = vb.getType(facesContext);
59          if (valueType == null) return null;
60  
61          if (String.class.equals(valueType)) return null;    //No converter needed for String type
62          if (Object.class.equals(valueType)) return null;    //There is no converter for Object class
63  
64          try
65          {
66              return facesContext.getApplication().createConverter(valueType);
67          }
68          catch (FacesException e)
69          {
70              log(facesContext, "No Converter for type " + valueType.getName() + " found", e);
71              return null;
72          }
73      }
74  
75      static Object getConvertedUISelectManyValue(FacesContext facesContext,
76                                                  UISelectMany component,
77                                                  String[] submittedValue)
78              throws ConverterException
79      {
80          // Attention!
81          // This code is duplicated in jsfapi component package.
82          // If you change something here please do the same in the other class!
83  
84          if (submittedValue == null) throw new NullPointerException("submittedValue");
85  
86          ValueBinding vb = component.getValueBinding("value");
87          Class valueType = null;
88          Class arrayComponentType = null;
89          if (vb != null)
90          {
91              valueType = vb.getType(facesContext);
92              if (valueType != null && valueType.isArray())
93              {
94                  arrayComponentType = valueType.getComponentType();
95              }
96          }
97          
98          Converter converter = component.getConverter();
99          if (converter == null)
100         {
101             if (valueType == null)
102             {
103                 // No converter, and no idea of expected type
104                 // --> return the submitted String array
105                 return submittedValue;
106             }
107 
108             if (List.class.isAssignableFrom(valueType))
109             {
110                 // expected type is a List
111                 // --> according to javadoc of UISelectMany we assume that the element type
112                 //     is java.lang.String, and copy the String array to a new List
113                 int len = submittedValue.length;
114                 List lst = new ArrayList(len);
115                 for (int i = 0; i < len; i++)
116                 {
117                     lst.add(submittedValue[i]);
118                 }
119                 return lst;
120             }
121 
122             if (arrayComponentType == null)
123             {
124                 throw new IllegalArgumentException("ValueBinding for UISelectMany must be of type List or Array");
125             }
126 
127             if (String.class.equals(arrayComponentType)) return submittedValue; //No conversion needed for String type
128             if (Object.class.equals(arrayComponentType)) return submittedValue; //No conversion for Object class
129 
130             try
131             {
132                 converter = facesContext.getApplication().createConverter(arrayComponentType);
133             }
134             catch (FacesException e)
135             {
136                 log(facesContext, "No Converter for type " + arrayComponentType.getName() + " found", e);
137                 return submittedValue;
138             }
139             if(converter==null)
140             {
141                 log(facesContext, "No Converter for type " + arrayComponentType.getName() + " found.",null);
142                 return submittedValue;
143             }
144         }
145 
146         // Now, we have a converter...
147         // We determine the type of the component array after converting one of it's elements
148         if (vb != null)
149         {
150             valueType = vb.getType(facesContext);
151             if (valueType != null && valueType.isArray())
152             {
153                 if (submittedValue.length > 0) 
154                 {
155                     arrayComponentType = converter.getAsObject(facesContext, component, submittedValue[0]).getClass();
156                 }
157             }
158         }
159         
160         if (valueType == null)
161         {
162             // ...but have no idea of expected type
163             // --> so let's convert it to an Object array
164             int len = submittedValue.length;
165             Object [] convertedValues = (Object []) Array.newInstance(
166                     arrayComponentType==null?Object.class:arrayComponentType,len);
167             for (int i = 0; i < len; i++)
168             {
169                 convertedValues[i]
170                     = converter.getAsObject(facesContext, component, submittedValue[i]);
171             }
172             return convertedValues;
173         }
174 
175         if (List.class.isAssignableFrom(valueType))
176         {
177             // Curious case: According to specs we should assume, that the element type
178             // of this List is java.lang.String. But there is a Converter set for this
179             // component. Because the user must know what he is doing, we will convert the values.
180             int len = submittedValue.length;
181             List lst = new ArrayList(len);
182             for (int i = 0; i < len; i++)
183             {
184                 lst.add(converter.getAsObject(facesContext, component, submittedValue[i]));
185             }
186             return lst;
187         }
188 
189         if (arrayComponentType == null)
190         {
191             throw new IllegalArgumentException("ValueBinding for UISelectMany must be of type List or Array");
192         }
193 
194         if (arrayComponentType.isPrimitive())
195         {
196             //primitive array
197             int len = submittedValue.length;
198             Object convertedValues = Array.newInstance(arrayComponentType, len);
199             for (int i = 0; i < len; i++)
200             {
201                 Array.set(convertedValues, i,
202                           converter.getAsObject(facesContext, component, submittedValue[i]));
203             }
204             return convertedValues;
205         }
206         else
207         {
208             //Object array
209             int len = submittedValue.length;
210             ArrayList convertedValues = new ArrayList(len); 
211             for (int i = 0; i < len; i++)
212             {
213                 convertedValues.add(i, converter.getAsObject(facesContext, component, submittedValue[i])); 
214             }
215             return convertedValues.toArray((Object[]) Array.newInstance(arrayComponentType, len));
216         }
217     }
218 
219 
220 
221     private static final Log log = LogFactory.getLog(_SharedRendererUtils.class);
222 
223     /**
224      * This method is different in the two versions of _SharedRendererUtils.
225      */
226     private static void log(FacesContext context, String msg, Exception e)
227     {
228         if(e!=null)
229         {
230             log.error(msg, e);
231         }
232         else
233         {
234             log.error(msg);
235         }
236     }
237 }