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 javax.faces.component;
17
18 import javax.faces.FacesException;
19 import javax.faces.context.FacesContext;
20 import javax.faces.convert.Converter;
21 import javax.faces.convert.ConverterException;
22 import javax.faces.el.ValueBinding;
23 import java.lang.reflect.Array;
24 import java.util.ArrayList;
25 import java.util.List;
26
27 /**
28 * The util methods in this class are shared between the javax.faces.component package and
29 * the org.apache.myfaces.renderkit package.
30 * Please note: Any changes here must also apply to the class in the other package!
31 *
32 * @author Manfred Geiler (latest modification by $Author: baranda $)
33 * @version $Revision: 291887 $ $Date: 2005-09-27 06:09:38 -0400 (Tue, 27 Sep 2005) $
34 */
35 class _SharedRendererUtils
36 {
37 static Converter findUIOutputConverter(FacesContext facesContext, UIOutput component)
38 {
39 // Attention!
40 // This code is duplicated in myfaces implementation renderkit package.
41 // If you change something here please do the same in the other class!
42
43 Converter converter = component.getConverter();
44 if (converter != null) return converter;
45
46 //Try to find out by value binding
47 ValueBinding vb = component.getValueBinding("value");
48 if (vb == null) return null;
49
50 Class valueType = vb.getType(facesContext);
51 if (valueType == null) return null;
52
53 if (String.class.equals(valueType)) return null; //No converter needed for String type
54 if (Object.class.equals(valueType)) return null; //There is no converter for Object class
55
56 try
57 {
58 return facesContext.getApplication().createConverter(valueType);
59 }
60 catch (FacesException e)
61 {
62 log(facesContext, "No Converter for type " + valueType.getName() + " found", e);
63 return null;
64 }
65 }
66
67 static Object getConvertedUISelectManyValue(FacesContext facesContext,
68 UISelectMany component,
69 String[] submittedValue)
70 throws ConverterException
71 {
72 // Attention!
73 // This code is duplicated in myfaces implementation renderkit package.
74 // If you change something here please do the same in the other class!
75
76 if (submittedValue == null) throw new NullPointerException("submittedValue");
77
78 ValueBinding vb = component.getValueBinding("value");
79 Class valueType = null;
80 Class arrayComponentType = null;
81 if (vb != null)
82 {
83 valueType = vb.getType(facesContext);
84 if (valueType != null && valueType.isArray())
85 {
86 arrayComponentType = valueType.getComponentType();
87 }
88 }
89
90 Converter converter = component.getConverter();
91 if (converter == null)
92 {
93 if (valueType == null)
94 {
95 // No converter, and no idea of expected type
96 // --> return the submitted String array
97 return submittedValue;
98 }
99
100 if (List.class.isAssignableFrom(valueType))
101 {
102 // expected type is a List
103 // --> according to javadoc of UISelectMany we assume that the element type
104 // is java.lang.String, and copy the String array to a new List
105 int len = submittedValue.length;
106 List lst = new ArrayList(len);
107 for (int i = 0; i < len; i++)
108 {
109 lst.add(submittedValue[i]);
110 }
111 return lst;
112 }
113
114 if (arrayComponentType == null)
115 {
116 throw new IllegalArgumentException("ValueBinding for UISelectMany must be of type List or Array");
117 }
118
119 if (String.class.equals(arrayComponentType)) return submittedValue; //No conversion needed for String type
120 if (Object.class.equals(arrayComponentType)) return submittedValue; //No conversion for Object class
121
122 try
123 {
124 converter = facesContext.getApplication().createConverter(arrayComponentType);
125 }
126 catch (FacesException e)
127 {
128 log(facesContext, "No Converter for type " + arrayComponentType.getName() + " found", e);
129 return submittedValue;
130 }
131 }
132
133 // Now, we have a converter...
134 if (valueType == null)
135 {
136 // ...but have no idea of expected type
137 // --> so let's convert it to an Object array
138 int len = submittedValue.length;
139 Object [] convertedValues = (Object []) Array.newInstance(arrayComponentType, len);
140 for (int i = 0; i < len; i++)
141 {
142 convertedValues[i]
143 = converter.getAsObject(facesContext, component, submittedValue[i]);
144 }
145 return convertedValues;
146 }
147
148 if (List.class.isAssignableFrom(valueType))
149 {
150 // Curious case: According to specs we should assume, that the element type
151 // of this List is java.lang.String. But there is a Converter set for this
152 // component. Because the user must know what he is doing, we will convert the values.
153 int len = submittedValue.length;
154 List lst = new ArrayList(len);
155 for (int i = 0; i < len; i++)
156 {
157 lst.add(converter.getAsObject(facesContext, component, submittedValue[i]));
158 }
159 return lst;
160 }
161
162 if (arrayComponentType == null)
163 {
164 throw new IllegalArgumentException("ValueBinding for UISelectMany must be of type List or Array");
165 }
166
167 if (arrayComponentType.isPrimitive())
168 {
169 //primitive array
170 int len = submittedValue.length;
171 Object convertedValues = Array.newInstance(arrayComponentType, len);
172 for (int i = 0; i < len; i++)
173 {
174 Array.set(convertedValues, i,
175 converter.getAsObject(facesContext, component, submittedValue[i]));
176 }
177 return convertedValues;
178 }
179 else
180 {
181 //Object array
182 int len = submittedValue.length;
183 ArrayList convertedValues = new ArrayList(len);
184 for (int i = 0; i < len; i++)
185 {
186 convertedValues.add(i, converter.getAsObject(facesContext, component, submittedValue[i]));
187 }
188 return convertedValues.toArray((Object[]) Array.newInstance(arrayComponentType, len));
189 }
190 }
191
192
193
194 /**
195 * This method is different in the two versions of _SharedRendererUtils.
196 */
197 private static void log(FacesContext context, String msg, Exception e)
198 {
199 context.getExternalContext().log(msg, e);
200 }
201 }