annotate src/main/java/com/sun/faces/renderkit/html_basic/MenuRenderer.java @ 1:2e911857a759

(none)
author jurzua
date Wed, 29 Oct 2014 14:00:28 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
jurzua
parents:
diff changeset
1 /*
jurzua
parents:
diff changeset
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jurzua
parents:
diff changeset
3 *
jurzua
parents:
diff changeset
4 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
jurzua
parents:
diff changeset
5 *
jurzua
parents:
diff changeset
6 * The contents of this file are subject to the terms of either the GNU
jurzua
parents:
diff changeset
7 * General Public License Version 2 only ("GPL") or the Common Development
jurzua
parents:
diff changeset
8 * and Distribution License("CDDL") (collectively, the "License"). You
jurzua
parents:
diff changeset
9 * may not use this file except in compliance with the License. You can
jurzua
parents:
diff changeset
10 * obtain a copy of the License at
jurzua
parents:
diff changeset
11 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
jurzua
parents:
diff changeset
12 * or packager/legal/LICENSE.txt. See the License for the specific
jurzua
parents:
diff changeset
13 * language governing permissions and limitations under the License.
jurzua
parents:
diff changeset
14 *
jurzua
parents:
diff changeset
15 * When distributing the software, include this License Header Notice in each
jurzua
parents:
diff changeset
16 * file and include the License file at packager/legal/LICENSE.txt.
jurzua
parents:
diff changeset
17 *
jurzua
parents:
diff changeset
18 * GPL Classpath Exception:
jurzua
parents:
diff changeset
19 * Oracle designates this particular file as subject to the "Classpath"
jurzua
parents:
diff changeset
20 * exception as provided by Oracle in the GPL Version 2 section of the License
jurzua
parents:
diff changeset
21 * file that accompanied this code.
jurzua
parents:
diff changeset
22 *
jurzua
parents:
diff changeset
23 * Modifications:
jurzua
parents:
diff changeset
24 * If applicable, add the following below the License Header, with the fields
jurzua
parents:
diff changeset
25 * enclosed by brackets [] replaced by your own identifying information:
jurzua
parents:
diff changeset
26 * "Portions Copyright [year] [name of copyright owner]"
jurzua
parents:
diff changeset
27 *
jurzua
parents:
diff changeset
28 * Contributor(s):
jurzua
parents:
diff changeset
29 * If you wish your version of this file to be governed by only the CDDL or
jurzua
parents:
diff changeset
30 * only the GPL Version 2, indicate your decision by adding "[Contributor]
jurzua
parents:
diff changeset
31 * elects to include this software in this distribution under the [CDDL or GPL
jurzua
parents:
diff changeset
32 * Version 2] license." If you don't indicate a single choice of license, a
jurzua
parents:
diff changeset
33 * recipient has the option to distribute your version of this file under
jurzua
parents:
diff changeset
34 * either the CDDL, the GPL Version 2 or to extend the choice of license to
jurzua
parents:
diff changeset
35 * its licensees as provided above. However, if you add GPL Version 2 code
jurzua
parents:
diff changeset
36 * and therefore, elected the GPL Version 2 license, then the option applies
jurzua
parents:
diff changeset
37 * only if the new code is made subject to such option by the copyright
jurzua
parents:
diff changeset
38 * holder.
jurzua
parents:
diff changeset
39 */
jurzua
parents:
diff changeset
40
jurzua
parents:
diff changeset
41 /*
jurzua
parents:
diff changeset
42 * (C) Copyright International Business Machines Corp., 2001,2002
jurzua
parents:
diff changeset
43 * The source code for this program is not published or otherwise
jurzua
parents:
diff changeset
44 * divested of its trade secrets, irrespective of what has been
jurzua
parents:
diff changeset
45 * deposited with the U. S. Copyright Office.
jurzua
parents:
diff changeset
46 */
jurzua
parents:
diff changeset
47
jurzua
parents:
diff changeset
48 // MenuRenderer.java
jurzua
parents:
diff changeset
49
jurzua
parents:
diff changeset
50 package com.sun.faces.renderkit.html_basic;
jurzua
parents:
diff changeset
51
jurzua
parents:
diff changeset
52 import java.io.IOException;
jurzua
parents:
diff changeset
53 import java.lang.reflect.Array;
jurzua
parents:
diff changeset
54 import java.lang.reflect.Method;
jurzua
parents:
diff changeset
55 import java.lang.reflect.Modifier;
jurzua
parents:
diff changeset
56 import java.util.ArrayList;
jurzua
parents:
diff changeset
57 import java.util.Arrays;
jurzua
parents:
diff changeset
58 import java.util.Collection;
jurzua
parents:
diff changeset
59 import java.util.Iterator;
jurzua
parents:
diff changeset
60 import java.util.Map;
jurzua
parents:
diff changeset
61 import java.util.Set;
jurzua
parents:
diff changeset
62 import java.util.HashSet;
jurzua
parents:
diff changeset
63 import java.util.SortedSet;
jurzua
parents:
diff changeset
64 import java.util.TreeSet;
jurzua
parents:
diff changeset
65 import java.util.Queue;
jurzua
parents:
diff changeset
66 import java.util.LinkedList;
jurzua
parents:
diff changeset
67 import java.util.logging.Level;
jurzua
parents:
diff changeset
68
jurzua
parents:
diff changeset
69 import javax.el.ELException;
jurzua
parents:
diff changeset
70 import javax.el.ValueExpression;
jurzua
parents:
diff changeset
71 import javax.el.ExpressionFactory;
jurzua
parents:
diff changeset
72 import javax.faces.component.UIComponent;
jurzua
parents:
diff changeset
73 import javax.faces.component.UISelectMany;
jurzua
parents:
diff changeset
74 import javax.faces.component.UISelectOne;
jurzua
parents:
diff changeset
75 import javax.faces.component.ValueHolder;
jurzua
parents:
diff changeset
76 import javax.faces.context.FacesContext;
jurzua
parents:
diff changeset
77 import javax.faces.context.ResponseWriter;
jurzua
parents:
diff changeset
78 import javax.faces.convert.Converter;
jurzua
parents:
diff changeset
79 import javax.faces.convert.ConverterException;
jurzua
parents:
diff changeset
80 import javax.faces.model.SelectItem;
jurzua
parents:
diff changeset
81 import javax.faces.model.SelectItemGroup;
jurzua
parents:
diff changeset
82 import javax.faces.FacesException;
jurzua
parents:
diff changeset
83
jurzua
parents:
diff changeset
84 import org.apache.commons.lang.StringUtils;
jurzua
parents:
diff changeset
85
jurzua
parents:
diff changeset
86 import com.sun.faces.RIConstants;
jurzua
parents:
diff changeset
87 import com.sun.faces.io.FastStringWriter;
jurzua
parents:
diff changeset
88 import com.sun.faces.renderkit.Attribute;
jurzua
parents:
diff changeset
89 import com.sun.faces.renderkit.AttributeManager;
jurzua
parents:
diff changeset
90 import com.sun.faces.renderkit.RenderKitUtils;
jurzua
parents:
diff changeset
91 import com.sun.faces.util.MessageUtils;
jurzua
parents:
diff changeset
92 import com.sun.faces.util.Util;
jurzua
parents:
diff changeset
93 import com.sun.faces.util.RequestStateManager;
jurzua
parents:
diff changeset
94 import com.sun.faces.util.ReflectionUtils;
jurzua
parents:
diff changeset
95
jurzua
parents:
diff changeset
96 /**
jurzua
parents:
diff changeset
97 * <B>MenuRenderer</B> is a class that renders the current value of
jurzua
parents:
diff changeset
98 * <code>UISelectOne<code> or <code>UISelectMany<code> component as a list of
jurzua
parents:
diff changeset
99 * menu options.
jurzua
parents:
diff changeset
100 */
jurzua
parents:
diff changeset
101
jurzua
parents:
diff changeset
102 public class MenuRenderer extends HtmlBasicInputRenderer {
jurzua
parents:
diff changeset
103
jurzua
parents:
diff changeset
104
jurzua
parents:
diff changeset
105 private static final Attribute[] ATTRIBUTES =
jurzua
parents:
diff changeset
106 AttributeManager.getAttributes(AttributeManager.Key.SELECTMANYMENU);
jurzua
parents:
diff changeset
107
jurzua
parents:
diff changeset
108
jurzua
parents:
diff changeset
109 // ---------------------------------------------------------- Public Methods
jurzua
parents:
diff changeset
110
jurzua
parents:
diff changeset
111
jurzua
parents:
diff changeset
112 public Object convertSelectManyValue(FacesContext context,
jurzua
parents:
diff changeset
113 UISelectMany uiSelectMany,
jurzua
parents:
diff changeset
114 String[] newValues)
jurzua
parents:
diff changeset
115 throws ConverterException {
jurzua
parents:
diff changeset
116
jurzua
parents:
diff changeset
117 // if we have no local value, try to get the valueExpression.
jurzua
parents:
diff changeset
118 ValueExpression valueExpression =
jurzua
parents:
diff changeset
119 uiSelectMany.getValueExpression("value");
jurzua
parents:
diff changeset
120
jurzua
parents:
diff changeset
121 Object result = newValues; // default case, set local value
jurzua
parents:
diff changeset
122 boolean throwException = false;
jurzua
parents:
diff changeset
123
jurzua
parents:
diff changeset
124 // If we have a ValueExpression
jurzua
parents:
diff changeset
125 if (null != valueExpression) {
jurzua
parents:
diff changeset
126 Class modelType = valueExpression.getType(context.getELContext());
jurzua
parents:
diff changeset
127 // Does the valueExpression resolve properly to something with
jurzua
parents:
diff changeset
128 // a type?
jurzua
parents:
diff changeset
129 if (modelType != null) {
jurzua
parents:
diff changeset
130 result = convertSelectManyValuesForModel(context,
jurzua
parents:
diff changeset
131 uiSelectMany,
jurzua
parents:
diff changeset
132 modelType,
jurzua
parents:
diff changeset
133 newValues);
jurzua
parents:
diff changeset
134 }
jurzua
parents:
diff changeset
135 // If it could not be converted, as a fall back try the type of
jurzua
parents:
diff changeset
136 // the valueExpression's current value covering some edge cases such
jurzua
parents:
diff changeset
137 // as where the current value came from a Map.
jurzua
parents:
diff changeset
138 if(result == null) {
jurzua
parents:
diff changeset
139 Object value = valueExpression.getValue(context.getELContext());
jurzua
parents:
diff changeset
140 if(value != null) {
jurzua
parents:
diff changeset
141 result = convertSelectManyValuesForModel(context,
jurzua
parents:
diff changeset
142 uiSelectMany,
jurzua
parents:
diff changeset
143 value.getClass(),
jurzua
parents:
diff changeset
144 newValues);
jurzua
parents:
diff changeset
145 }
jurzua
parents:
diff changeset
146 }
jurzua
parents:
diff changeset
147 if(result == null) {
jurzua
parents:
diff changeset
148 throwException = true;
jurzua
parents:
diff changeset
149 }
jurzua
parents:
diff changeset
150 } else {
jurzua
parents:
diff changeset
151 // No ValueExpression, just use Object array.
jurzua
parents:
diff changeset
152 result = convertSelectManyValues(context, uiSelectMany,
jurzua
parents:
diff changeset
153 Object[].class,
jurzua
parents:
diff changeset
154 newValues);
jurzua
parents:
diff changeset
155 }
jurzua
parents:
diff changeset
156 if (throwException) {
jurzua
parents:
diff changeset
157 StringBuffer values = new StringBuffer();
jurzua
parents:
diff changeset
158 if (null != newValues) {
jurzua
parents:
diff changeset
159 for (int i = 0; i < newValues.length; i++) {
jurzua
parents:
diff changeset
160 if (i == 0) {
jurzua
parents:
diff changeset
161 values.append(newValues[i]);
jurzua
parents:
diff changeset
162 } else {
jurzua
parents:
diff changeset
163 values.append(' ').append(newValues[i]);
jurzua
parents:
diff changeset
164 }
jurzua
parents:
diff changeset
165 }
jurzua
parents:
diff changeset
166 }
jurzua
parents:
diff changeset
167 Object[] params = {
jurzua
parents:
diff changeset
168 values.toString(),
jurzua
parents:
diff changeset
169 valueExpression.getExpressionString()
jurzua
parents:
diff changeset
170 };
jurzua
parents:
diff changeset
171 throw new ConverterException
jurzua
parents:
diff changeset
172 (MessageUtils.getExceptionMessage(MessageUtils.CONVERSION_ERROR_MESSAGE_ID,
jurzua
parents:
diff changeset
173 params));
jurzua
parents:
diff changeset
174 }
jurzua
parents:
diff changeset
175
jurzua
parents:
diff changeset
176 // At this point, result is ready to be set as the value
jurzua
parents:
diff changeset
177 if (logger.isLoggable(Level.FINE)) {
jurzua
parents:
diff changeset
178 logger.fine("SelectMany Component " + uiSelectMany.getId() +
jurzua
parents:
diff changeset
179 " convertedValues " + result);
jurzua
parents:
diff changeset
180 }
jurzua
parents:
diff changeset
181 return result;
jurzua
parents:
diff changeset
182
jurzua
parents:
diff changeset
183 }
jurzua
parents:
diff changeset
184
jurzua
parents:
diff changeset
185
jurzua
parents:
diff changeset
186 public Object convertSelectOneValue(FacesContext context,
jurzua
parents:
diff changeset
187 UISelectOne uiSelectOne,
jurzua
parents:
diff changeset
188 String newValue)
jurzua
parents:
diff changeset
189 throws ConverterException {
jurzua
parents:
diff changeset
190
jurzua
parents:
diff changeset
191 if (RIConstants.NO_VALUE.equals(newValue)) {
jurzua
parents:
diff changeset
192 return null;
jurzua
parents:
diff changeset
193 }
jurzua
parents:
diff changeset
194 if (newValue == null) {
jurzua
parents:
diff changeset
195 if (logger.isLoggable(Level.FINE)) {
jurzua
parents:
diff changeset
196 logger.fine("No conversion necessary for SelectOne Component "
jurzua
parents:
diff changeset
197 + uiSelectOne.getId()
jurzua
parents:
diff changeset
198 + " since the new value is null ");
jurzua
parents:
diff changeset
199 }
jurzua
parents:
diff changeset
200 return null;
jurzua
parents:
diff changeset
201 }
jurzua
parents:
diff changeset
202
jurzua
parents:
diff changeset
203 Object convertedValue =
jurzua
parents:
diff changeset
204 super.getConvertedValue(context, uiSelectOne, newValue);
jurzua
parents:
diff changeset
205 if (logger.isLoggable(Level.FINE)) {
jurzua
parents:
diff changeset
206 logger.fine("SelectOne Component " + uiSelectOne.getId() +
jurzua
parents:
diff changeset
207 " convertedValue " + convertedValue);
jurzua
parents:
diff changeset
208 }
jurzua
parents:
diff changeset
209 return convertedValue;
jurzua
parents:
diff changeset
210
jurzua
parents:
diff changeset
211 }
jurzua
parents:
diff changeset
212
jurzua
parents:
diff changeset
213 @Override
jurzua
parents:
diff changeset
214 public void decode(FacesContext context, UIComponent component) {
jurzua
parents:
diff changeset
215
jurzua
parents:
diff changeset
216 rendererParamsNotNull(context, component);
jurzua
parents:
diff changeset
217
jurzua
parents:
diff changeset
218 if (!shouldDecode(component)) {
jurzua
parents:
diff changeset
219 return;
jurzua
parents:
diff changeset
220 }
jurzua
parents:
diff changeset
221
jurzua
parents:
diff changeset
222 String clientId = decodeBehaviors(context, component);
jurzua
parents:
diff changeset
223
jurzua
parents:
diff changeset
224 if (clientId == null) {
jurzua
parents:
diff changeset
225 clientId = component.getClientId(context);
jurzua
parents:
diff changeset
226 }
jurzua
parents:
diff changeset
227 assert(clientId != null);
jurzua
parents:
diff changeset
228 // currently we assume the model type to be of type string or
jurzua
parents:
diff changeset
229 // convertible to string and localized by the application.
jurzua
parents:
diff changeset
230 if (component instanceof UISelectMany) {
jurzua
parents:
diff changeset
231 Map<String, String[]> requestParameterValuesMap =
jurzua
parents:
diff changeset
232 context.getExternalContext().
jurzua
parents:
diff changeset
233 getRequestParameterValuesMap();
jurzua
parents:
diff changeset
234 if (requestParameterValuesMap.containsKey(clientId)) {
jurzua
parents:
diff changeset
235 String newValues[] = requestParameterValuesMap.
jurzua
parents:
diff changeset
236 get(clientId);
jurzua
parents:
diff changeset
237 setSubmittedValue(component, newValues);
jurzua
parents:
diff changeset
238 if (logger.isLoggable(Level.FINE)) {
jurzua
parents:
diff changeset
239 logger.fine("submitted values for UISelectMany component "
jurzua
parents:
diff changeset
240 +
jurzua
parents:
diff changeset
241 component.getId()
jurzua
parents:
diff changeset
242 + " after decoding "
jurzua
parents:
diff changeset
243 + Arrays.toString(newValues));
jurzua
parents:
diff changeset
244 }
jurzua
parents:
diff changeset
245 } else {
jurzua
parents:
diff changeset
246 // Use the empty array, not null, to distinguish
jurzua
parents:
diff changeset
247 // between an deselected UISelectMany and a disabled one
jurzua
parents:
diff changeset
248 setSubmittedValue(component, new String[0]);
jurzua
parents:
diff changeset
249 if (logger.isLoggable(Level.FINE)) {
jurzua
parents:
diff changeset
250 logger.fine("Set empty array for UISelectMany component " +
jurzua
parents:
diff changeset
251 component.getId() + " after decoding ");
jurzua
parents:
diff changeset
252 }
jurzua
parents:
diff changeset
253 }
jurzua
parents:
diff changeset
254 } else {
jurzua
parents:
diff changeset
255 // this is a UISelectOne
jurzua
parents:
diff changeset
256 Map<String, String> requestParameterMap =
jurzua
parents:
diff changeset
257 context.getExternalContext().
jurzua
parents:
diff changeset
258 getRequestParameterMap();
jurzua
parents:
diff changeset
259 if (requestParameterMap.containsKey(clientId)) {
jurzua
parents:
diff changeset
260 String newValue = requestParameterMap.get(clientId);
jurzua
parents:
diff changeset
261 setSubmittedValue(component, newValue);
jurzua
parents:
diff changeset
262 if (logger.isLoggable(Level.FINE)) {
jurzua
parents:
diff changeset
263 logger.fine("submitted value for UISelectOne component "
jurzua
parents:
diff changeset
264 +
jurzua
parents:
diff changeset
265 component.getId()
jurzua
parents:
diff changeset
266 + " after decoding "
jurzua
parents:
diff changeset
267 + newValue);
jurzua
parents:
diff changeset
268 }
jurzua
parents:
diff changeset
269
jurzua
parents:
diff changeset
270 } else {
jurzua
parents:
diff changeset
271 // there is no value, but this is different from a null
jurzua
parents:
diff changeset
272 // value.
jurzua
parents:
diff changeset
273 setSubmittedValue(component, RIConstants.NO_VALUE);
jurzua
parents:
diff changeset
274 }
jurzua
parents:
diff changeset
275 }
jurzua
parents:
diff changeset
276
jurzua
parents:
diff changeset
277 }
jurzua
parents:
diff changeset
278
jurzua
parents:
diff changeset
279
jurzua
parents:
diff changeset
280 @Override
jurzua
parents:
diff changeset
281 public void encodeBegin(FacesContext context, UIComponent component)
jurzua
parents:
diff changeset
282 throws IOException {
jurzua
parents:
diff changeset
283
jurzua
parents:
diff changeset
284 rendererParamsNotNull(context, component);
jurzua
parents:
diff changeset
285
jurzua
parents:
diff changeset
286 }
jurzua
parents:
diff changeset
287
jurzua
parents:
diff changeset
288
jurzua
parents:
diff changeset
289 @Override
jurzua
parents:
diff changeset
290 public void encodeEnd(FacesContext context, UIComponent component)
jurzua
parents:
diff changeset
291 throws IOException {
jurzua
parents:
diff changeset
292
jurzua
parents:
diff changeset
293 rendererParamsNotNull(context, component);
jurzua
parents:
diff changeset
294
jurzua
parents:
diff changeset
295 if (!shouldEncode(component)) {
jurzua
parents:
diff changeset
296 return;
jurzua
parents:
diff changeset
297 }
jurzua
parents:
diff changeset
298
jurzua
parents:
diff changeset
299 renderSelect(context, component);
jurzua
parents:
diff changeset
300
jurzua
parents:
diff changeset
301 }
jurzua
parents:
diff changeset
302
jurzua
parents:
diff changeset
303
jurzua
parents:
diff changeset
304 @Override
jurzua
parents:
diff changeset
305 public Object getConvertedValue(FacesContext context, UIComponent component,
jurzua
parents:
diff changeset
306 Object submittedValue)
jurzua
parents:
diff changeset
307 throws ConverterException {
jurzua
parents:
diff changeset
308
jurzua
parents:
diff changeset
309 if (component instanceof UISelectMany) {
jurzua
parents:
diff changeset
310 // need to set the 'TARGET_COMPONENT_ATTRIBUTE_NAME' request attr so the
jurzua
parents:
diff changeset
311 // coerce-value call in the jsf-api UISelectMany.matchValue will work
jurzua
parents:
diff changeset
312 // (need a better way to determine the currently processing UIComponent ...)
jurzua
parents:
diff changeset
313 RequestStateManager.set(context,
jurzua
parents:
diff changeset
314 RequestStateManager.TARGET_COMPONENT_ATTRIBUTE_NAME,
jurzua
parents:
diff changeset
315 component);
jurzua
parents:
diff changeset
316 return convertSelectManyValue(context,
jurzua
parents:
diff changeset
317 ((UISelectMany) component),
jurzua
parents:
diff changeset
318 (String[]) submittedValue);
jurzua
parents:
diff changeset
319 } else {
jurzua
parents:
diff changeset
320 return convertSelectOneValue(context,
jurzua
parents:
diff changeset
321 ((UISelectOne) component),
jurzua
parents:
diff changeset
322 (String) submittedValue);
jurzua
parents:
diff changeset
323 }
jurzua
parents:
diff changeset
324
jurzua
parents:
diff changeset
325 }
jurzua
parents:
diff changeset
326
jurzua
parents:
diff changeset
327 // ------------------------------------------------------- Protected Methods
jurzua
parents:
diff changeset
328
jurzua
parents:
diff changeset
329
jurzua
parents:
diff changeset
330 /*
jurzua
parents:
diff changeset
331 * Converts the provided string array and places them into the correct provided model type.
jurzua
parents:
diff changeset
332 */
jurzua
parents:
diff changeset
333 protected Object convertSelectManyValuesForModel(FacesContext context,
jurzua
parents:
diff changeset
334 UISelectMany uiSelectMany,
jurzua
parents:
diff changeset
335 Class modelType,
jurzua
parents:
diff changeset
336 String[] newValues) {
jurzua
parents:
diff changeset
337
jurzua
parents:
diff changeset
338 if (modelType.isArray()) {
jurzua
parents:
diff changeset
339 return convertSelectManyValues(context,
jurzua
parents:
diff changeset
340 uiSelectMany,
jurzua
parents:
diff changeset
341 modelType,
jurzua
parents:
diff changeset
342 newValues);
jurzua
parents:
diff changeset
343 } else if (Collection.class.isAssignableFrom(modelType)) {
jurzua
parents:
diff changeset
344 Object[] values = (Object[]) convertSelectManyValues(context,
jurzua
parents:
diff changeset
345 uiSelectMany,
jurzua
parents:
diff changeset
346 Object[].class,
jurzua
parents:
diff changeset
347 newValues);
jurzua
parents:
diff changeset
348
jurzua
parents:
diff changeset
349 Collection targetCollection = null;
jurzua
parents:
diff changeset
350
jurzua
parents:
diff changeset
351 // see if the collectionType hint is available, if so, use that
jurzua
parents:
diff changeset
352 Object collectionTypeHint = uiSelectMany.getAttributes().get("collectionType");
jurzua
parents:
diff changeset
353 if (collectionTypeHint != null) {
jurzua
parents:
diff changeset
354 targetCollection = createCollectionFromHint(collectionTypeHint);
jurzua
parents:
diff changeset
355 } else {
jurzua
parents:
diff changeset
356 // try to get a new Collection to store the values based
jurzua
parents:
diff changeset
357 // by trying to create a clone
jurzua
parents:
diff changeset
358 Collection currentValue = (Collection) uiSelectMany.getValue();
jurzua
parents:
diff changeset
359 if (currentValue != null) {
jurzua
parents:
diff changeset
360 targetCollection = cloneValue(currentValue);
jurzua
parents:
diff changeset
361 }
jurzua
parents:
diff changeset
362
jurzua
parents:
diff changeset
363 // No cloned instance so if the modelType happens to represent a
jurzua
parents:
diff changeset
364 // concrete type (probably not the norm) try to reflect a
jurzua
parents:
diff changeset
365 // no-argument constructor and invoke if available.
jurzua
parents:
diff changeset
366 if (targetCollection == null) {
jurzua
parents:
diff changeset
367 //noinspection unchecked
jurzua
parents:
diff changeset
368 targetCollection =
jurzua
parents:
diff changeset
369 createCollection(currentValue, modelType);
jurzua
parents:
diff changeset
370 }
jurzua
parents:
diff changeset
371
jurzua
parents:
diff changeset
372 // No suitable instance to work with, make our best guess
jurzua
parents:
diff changeset
373 // based on the type.
jurzua
parents:
diff changeset
374 if (targetCollection == null) {
jurzua
parents:
diff changeset
375 //noinspection unchecked
jurzua
parents:
diff changeset
376 targetCollection = bestGuess(modelType, values.length);
jurzua
parents:
diff changeset
377 }
jurzua
parents:
diff changeset
378 }
jurzua
parents:
diff changeset
379
jurzua
parents:
diff changeset
380 //noinspection ManualArrayToCollectionCopy
jurzua
parents:
diff changeset
381 for (Object v : values) {
jurzua
parents:
diff changeset
382 //noinspection unchecked
jurzua
parents:
diff changeset
383 targetCollection.add(v);
jurzua
parents:
diff changeset
384 }
jurzua
parents:
diff changeset
385
jurzua
parents:
diff changeset
386 return targetCollection;
jurzua
parents:
diff changeset
387 } else if (Object.class.equals(modelType)) {
jurzua
parents:
diff changeset
388 return convertSelectManyValues(context,
jurzua
parents:
diff changeset
389 uiSelectMany,
jurzua
parents:
diff changeset
390 Object[].class,
jurzua
parents:
diff changeset
391 newValues);
jurzua
parents:
diff changeset
392 } else {
jurzua
parents:
diff changeset
393 throw new FacesException("Target model Type is no a Collection or Array");
jurzua
parents:
diff changeset
394 }
jurzua
parents:
diff changeset
395
jurzua
parents:
diff changeset
396 }
jurzua
parents:
diff changeset
397
jurzua
parents:
diff changeset
398
jurzua
parents:
diff changeset
399
jurzua
parents:
diff changeset
400
jurzua
parents:
diff changeset
401 protected Object convertSelectManyValues(FacesContext context,
jurzua
parents:
diff changeset
402 UISelectMany uiSelectMany,
jurzua
parents:
diff changeset
403 Class arrayClass,
jurzua
parents:
diff changeset
404 String[] newValues)
jurzua
parents:
diff changeset
405 throws ConverterException {
jurzua
parents:
diff changeset
406
jurzua
parents:
diff changeset
407 Object result;
jurzua
parents:
diff changeset
408 Converter converter;
jurzua
parents:
diff changeset
409 int len = (null != newValues ? newValues.length : 0);
jurzua
parents:
diff changeset
410
jurzua
parents:
diff changeset
411 Class elementType = arrayClass.getComponentType();
jurzua
parents:
diff changeset
412
jurzua
parents:
diff changeset
413 // Optimization: If the elementType is String, we don't need
jurzua
parents:
diff changeset
414 // conversion. Just return newValues.
jurzua
parents:
diff changeset
415 if (elementType.equals(String.class)) {
jurzua
parents:
diff changeset
416 return newValues;
jurzua
parents:
diff changeset
417 }
jurzua
parents:
diff changeset
418
jurzua
parents:
diff changeset
419 try {
jurzua
parents:
diff changeset
420 result = Array.newInstance(elementType, len);
jurzua
parents:
diff changeset
421 } catch (Exception e) {
jurzua
parents:
diff changeset
422 throw new ConverterException(e);
jurzua
parents:
diff changeset
423 }
jurzua
parents:
diff changeset
424
jurzua
parents:
diff changeset
425 // bail out now if we have no new values, returning our
jurzua
parents:
diff changeset
426 // oh-so-useful zero-length array.
jurzua
parents:
diff changeset
427 if (null == newValues) {
jurzua
parents:
diff changeset
428 return result;
jurzua
parents:
diff changeset
429 }
jurzua
parents:
diff changeset
430
jurzua
parents:
diff changeset
431 // obtain a converter.
jurzua
parents:
diff changeset
432
jurzua
parents:
diff changeset
433 // attached converter takes priority
jurzua
parents:
diff changeset
434 if (null == (converter = uiSelectMany.getConverter())) {
jurzua
parents:
diff changeset
435 // Otherwise, look for a by-type converter
jurzua
parents:
diff changeset
436 if (null == (converter = Util.getConverterForClass(elementType,
jurzua
parents:
diff changeset
437 context))) {
jurzua
parents:
diff changeset
438 // if that fails, and the attached values are of Object type,
jurzua
parents:
diff changeset
439 // we don't need conversion.
jurzua
parents:
diff changeset
440 if (elementType.equals(Object.class)) {
jurzua
parents:
diff changeset
441 return newValues;
jurzua
parents:
diff changeset
442 }
jurzua
parents:
diff changeset
443 StringBuffer valueStr = new StringBuffer();
jurzua
parents:
diff changeset
444 for (int i = 0; i < len; i++) {
jurzua
parents:
diff changeset
445 if (i == 0) {
jurzua
parents:
diff changeset
446 valueStr.append(newValues[i]);
jurzua
parents:
diff changeset
447 } else {
jurzua
parents:
diff changeset
448 valueStr.append(' ').append(newValues[i]);
jurzua
parents:
diff changeset
449 }
jurzua
parents:
diff changeset
450 }
jurzua
parents:
diff changeset
451 Object[] params = {
jurzua
parents:
diff changeset
452 valueStr.toString(),
jurzua
parents:
diff changeset
453 "null Converter"
jurzua
parents:
diff changeset
454 };
jurzua
parents:
diff changeset
455
jurzua
parents:
diff changeset
456 throw new ConverterException(MessageUtils.getExceptionMessage(
jurzua
parents:
diff changeset
457 MessageUtils.CONVERSION_ERROR_MESSAGE_ID, params));
jurzua
parents:
diff changeset
458 }
jurzua
parents:
diff changeset
459 }
jurzua
parents:
diff changeset
460
jurzua
parents:
diff changeset
461 assert(null != result);
jurzua
parents:
diff changeset
462 if (elementType.isPrimitive()) {
jurzua
parents:
diff changeset
463 for (int i = 0; i < len; i++) {
jurzua
parents:
diff changeset
464 if (elementType.equals(Boolean.TYPE)) {
jurzua
parents:
diff changeset
465 Array.setBoolean(result, i,
jurzua
parents:
diff changeset
466 ((Boolean) converter.getAsObject(context,
jurzua
parents:
diff changeset
467 uiSelectMany,
jurzua
parents:
diff changeset
468 newValues[i])));
jurzua
parents:
diff changeset
469 } else if (elementType.equals(Byte.TYPE)) {
jurzua
parents:
diff changeset
470 Array.setByte(result, i,
jurzua
parents:
diff changeset
471 ((Byte) converter.getAsObject(context,
jurzua
parents:
diff changeset
472 uiSelectMany,
jurzua
parents:
diff changeset
473 newValues[i])));
jurzua
parents:
diff changeset
474 } else if (elementType.equals(Double.TYPE)) {
jurzua
parents:
diff changeset
475 Array.setDouble(result, i,
jurzua
parents:
diff changeset
476 ((Double) converter.getAsObject(context,
jurzua
parents:
diff changeset
477 uiSelectMany,
jurzua
parents:
diff changeset
478 newValues[i])));
jurzua
parents:
diff changeset
479 } else if (elementType.equals(Float.TYPE)) {
jurzua
parents:
diff changeset
480 Array.setFloat(result, i,
jurzua
parents:
diff changeset
481 ((Float) converter.getAsObject(context,
jurzua
parents:
diff changeset
482 uiSelectMany,
jurzua
parents:
diff changeset
483 newValues[i])));
jurzua
parents:
diff changeset
484 } else if (elementType.equals(Integer.TYPE)) {
jurzua
parents:
diff changeset
485 Array.setInt(result, i,
jurzua
parents:
diff changeset
486 ((Integer) converter.getAsObject(context,
jurzua
parents:
diff changeset
487 uiSelectMany,
jurzua
parents:
diff changeset
488 newValues[i])));
jurzua
parents:
diff changeset
489 } else if (elementType.equals(Character.TYPE)) {
jurzua
parents:
diff changeset
490 Array.setChar(result, i,
jurzua
parents:
diff changeset
491 ((Character) converter.getAsObject(context,
jurzua
parents:
diff changeset
492 uiSelectMany,
jurzua
parents:
diff changeset
493 newValues[i])));
jurzua
parents:
diff changeset
494 } else if (elementType.equals(Short.TYPE)) {
jurzua
parents:
diff changeset
495 Array.setShort(result, i,
jurzua
parents:
diff changeset
496 ((Short) converter.getAsObject(context,
jurzua
parents:
diff changeset
497 uiSelectMany,
jurzua
parents:
diff changeset
498 newValues[i])));
jurzua
parents:
diff changeset
499 } else if (elementType.equals(Long.TYPE)) {
jurzua
parents:
diff changeset
500 Array.setLong(result, i,
jurzua
parents:
diff changeset
501 ((Long) converter.getAsObject(context,
jurzua
parents:
diff changeset
502 uiSelectMany,
jurzua
parents:
diff changeset
503 newValues[i])));
jurzua
parents:
diff changeset
504 }
jurzua
parents:
diff changeset
505 }
jurzua
parents:
diff changeset
506 } else {
jurzua
parents:
diff changeset
507 for (int i = 0; i < len; i++) {
jurzua
parents:
diff changeset
508 if (logger.isLoggable(Level.FINE)) {
jurzua
parents:
diff changeset
509 Object converted = converter.getAsObject(context,
jurzua
parents:
diff changeset
510 uiSelectMany,
jurzua
parents:
diff changeset
511 newValues[i]);
jurzua
parents:
diff changeset
512 logger.fine("String value: " + newValues[i] +
jurzua
parents:
diff changeset
513 " converts to : " + converted);
jurzua
parents:
diff changeset
514 }
jurzua
parents:
diff changeset
515 Array.set(result, i, converter.getAsObject(context,
jurzua
parents:
diff changeset
516 uiSelectMany,
jurzua
parents:
diff changeset
517 newValues[i]));
jurzua
parents:
diff changeset
518 }
jurzua
parents:
diff changeset
519 }
jurzua
parents:
diff changeset
520 return result;
jurzua
parents:
diff changeset
521
jurzua
parents:
diff changeset
522 }
jurzua
parents:
diff changeset
523
jurzua
parents:
diff changeset
524
jurzua
parents:
diff changeset
525 protected boolean renderOption(FacesContext context,
jurzua
parents:
diff changeset
526 UIComponent component,
jurzua
parents:
diff changeset
527 Converter converter,
jurzua
parents:
diff changeset
528 SelectItem curItem,
jurzua
parents:
diff changeset
529 Object currentSelections,
jurzua
parents:
diff changeset
530 Object[] submittedValues,
jurzua
parents:
diff changeset
531 OptionComponentInfo optionInfo) throws IOException {
jurzua
parents:
diff changeset
532
jurzua
parents:
diff changeset
533 Object valuesArray;
jurzua
parents:
diff changeset
534 Object itemValue;
jurzua
parents:
diff changeset
535 String valueString = getFormattedValue(context, component,
jurzua
parents:
diff changeset
536 curItem.getValue(), converter);
jurzua
parents:
diff changeset
537 boolean containsValue;
jurzua
parents:
diff changeset
538 if (submittedValues != null) {
jurzua
parents:
diff changeset
539 containsValue = containsaValue(submittedValues);
jurzua
parents:
diff changeset
540 if (containsValue) {
jurzua
parents:
diff changeset
541 valuesArray = submittedValues;
jurzua
parents:
diff changeset
542 itemValue = valueString;
jurzua
parents:
diff changeset
543 } else {
jurzua
parents:
diff changeset
544 valuesArray = currentSelections;
jurzua
parents:
diff changeset
545 itemValue = curItem.getValue();
jurzua
parents:
diff changeset
546 }
jurzua
parents:
diff changeset
547 } else {
jurzua
parents:
diff changeset
548 valuesArray = currentSelections;
jurzua
parents:
diff changeset
549 itemValue = curItem.getValue();
jurzua
parents:
diff changeset
550 }
jurzua
parents:
diff changeset
551
jurzua
parents:
diff changeset
552 boolean isSelected = isSelected(context, component, itemValue, valuesArray, converter);
jurzua
parents:
diff changeset
553 if (optionInfo.isHideNoSelection()
jurzua
parents:
diff changeset
554 && curItem.isNoSelectionOption()
jurzua
parents:
diff changeset
555 && currentSelections != null
jurzua
parents:
diff changeset
556 && !isSelected) {
jurzua
parents:
diff changeset
557 return false;
jurzua
parents:
diff changeset
558 }
jurzua
parents:
diff changeset
559
jurzua
parents:
diff changeset
560 ResponseWriter writer = context.getResponseWriter();
jurzua
parents:
diff changeset
561 assert (writer != null);
jurzua
parents:
diff changeset
562 writer.writeText("\t", component, null);
jurzua
parents:
diff changeset
563 writer.startElement("option", component);
jurzua
parents:
diff changeset
564 writer.writeAttribute("value", valueString, "value");
jurzua
parents:
diff changeset
565
jurzua
parents:
diff changeset
566 if (isSelected) {
jurzua
parents:
diff changeset
567 writer.writeAttribute("selected", true, "selected");
jurzua
parents:
diff changeset
568 }
jurzua
parents:
diff changeset
569
jurzua
parents:
diff changeset
570 // if the component is disabled, "disabled" attribute would be rendered
jurzua
parents:
diff changeset
571 // on "select" tag, so don't render "disabled" on every option.
jurzua
parents:
diff changeset
572 if ((!optionInfo.isDisabled()) && curItem.isDisabled()) {
jurzua
parents:
diff changeset
573 writer.writeAttribute("disabled", true, "disabled");
jurzua
parents:
diff changeset
574 }
jurzua
parents:
diff changeset
575
jurzua
parents:
diff changeset
576
jurzua
parents:
diff changeset
577 //jurzua
jurzua
parents:
diff changeset
578 if(StringUtils.isNotEmpty(curItem.getStyle())){
jurzua
parents:
diff changeset
579 writer.writeAttribute("style", curItem.getStyle(), curItem.getStyle());
jurzua
parents:
diff changeset
580 }
jurzua
parents:
diff changeset
581
jurzua
parents:
diff changeset
582
jurzua
parents:
diff changeset
583 String labelClass;
jurzua
parents:
diff changeset
584 if (optionInfo.isDisabled() || curItem.isDisabled()) {
jurzua
parents:
diff changeset
585 labelClass = optionInfo.getDisabledClass();
jurzua
parents:
diff changeset
586 } else {
jurzua
parents:
diff changeset
587 labelClass = optionInfo.getEnabledClass();
jurzua
parents:
diff changeset
588 }
jurzua
parents:
diff changeset
589 if (labelClass != null) {
jurzua
parents:
diff changeset
590 writer.writeAttribute("class", labelClass, "labelClass");
jurzua
parents:
diff changeset
591 }
jurzua
parents:
diff changeset
592
jurzua
parents:
diff changeset
593 if (curItem.isEscape()) {
jurzua
parents:
diff changeset
594 String label = curItem.getLabel();
jurzua
parents:
diff changeset
595 if (label == null) {
jurzua
parents:
diff changeset
596 label = valueString;
jurzua
parents:
diff changeset
597 }
jurzua
parents:
diff changeset
598 writer.writeText(label, component, "label");
jurzua
parents:
diff changeset
599 } else {
jurzua
parents:
diff changeset
600 writer.write(curItem.getLabel());
jurzua
parents:
diff changeset
601 }
jurzua
parents:
diff changeset
602 writer.endElement("option");
jurzua
parents:
diff changeset
603 writer.writeText("\n", component, null);
jurzua
parents:
diff changeset
604 return true;
jurzua
parents:
diff changeset
605 }
jurzua
parents:
diff changeset
606
jurzua
parents:
diff changeset
607
jurzua
parents:
diff changeset
608 protected void writeDefaultSize(ResponseWriter writer, int itemCount)
jurzua
parents:
diff changeset
609 throws IOException {
jurzua
parents:
diff changeset
610
jurzua
parents:
diff changeset
611 // if size is not specified default to 1.
jurzua
parents:
diff changeset
612 writer.writeAttribute("size", "1", "size");
jurzua
parents:
diff changeset
613
jurzua
parents:
diff changeset
614 }
jurzua
parents:
diff changeset
615
jurzua
parents:
diff changeset
616
jurzua
parents:
diff changeset
617 protected boolean containsaValue(Object valueArray) {
jurzua
parents:
diff changeset
618
jurzua
parents:
diff changeset
619 if (null != valueArray) {
jurzua
parents:
diff changeset
620 int len = Array.getLength(valueArray);
jurzua
parents:
diff changeset
621 for (int i = 0; i < len; i++) {
jurzua
parents:
diff changeset
622 Object value = Array.get(valueArray, i);
jurzua
parents:
diff changeset
623 if (value != null && !(value.equals(RIConstants.NO_VALUE))) {
jurzua
parents:
diff changeset
624 return true;
jurzua
parents:
diff changeset
625 }
jurzua
parents:
diff changeset
626 }
jurzua
parents:
diff changeset
627 }
jurzua
parents:
diff changeset
628 return false;
jurzua
parents:
diff changeset
629
jurzua
parents:
diff changeset
630 }
jurzua
parents:
diff changeset
631
jurzua
parents:
diff changeset
632
jurzua
parents:
diff changeset
633 protected Object getCurrentSelectedValues(UIComponent component) {
jurzua
parents:
diff changeset
634
jurzua
parents:
diff changeset
635 if (component instanceof UISelectMany) {
jurzua
parents:
diff changeset
636 UISelectMany select = (UISelectMany) component;
jurzua
parents:
diff changeset
637 Object value = select.getValue();
jurzua
parents:
diff changeset
638 if (value == null) {
jurzua
parents:
diff changeset
639 return null;
jurzua
parents:
diff changeset
640 } else if (value instanceof Collection) {
jurzua
parents:
diff changeset
641 return ((Collection) value).toArray();
jurzua
parents:
diff changeset
642 } else if (value.getClass().isArray()) {
jurzua
parents:
diff changeset
643 if (Array.getLength(value) == 0) {
jurzua
parents:
diff changeset
644 return null;
jurzua
parents:
diff changeset
645 }
jurzua
parents:
diff changeset
646 } else if (!value.getClass().isArray()) {
jurzua
parents:
diff changeset
647 logger.warning(
jurzua
parents:
diff changeset
648 "The UISelectMany value should be an array or a collection type, the actual type is " +
jurzua
parents:
diff changeset
649 value.getClass().getName());
jurzua
parents:
diff changeset
650 }
jurzua
parents:
diff changeset
651
jurzua
parents:
diff changeset
652 return value;
jurzua
parents:
diff changeset
653 }
jurzua
parents:
diff changeset
654
jurzua
parents:
diff changeset
655 UISelectOne select = (UISelectOne) component;
jurzua
parents:
diff changeset
656 Object val = select.getValue();
jurzua
parents:
diff changeset
657 if (val != null) {
jurzua
parents:
diff changeset
658 return new Object[] { val };
jurzua
parents:
diff changeset
659 }
jurzua
parents:
diff changeset
660 return null;
jurzua
parents:
diff changeset
661
jurzua
parents:
diff changeset
662 }
jurzua
parents:
diff changeset
663
jurzua
parents:
diff changeset
664
jurzua
parents:
diff changeset
665 // To derive a selectOne type component from this, override
jurzua
parents:
diff changeset
666 // these methods.
jurzua
parents:
diff changeset
667 protected String getMultipleText(UIComponent component) {
jurzua
parents:
diff changeset
668
jurzua
parents:
diff changeset
669 if (component instanceof UISelectMany) {
jurzua
parents:
diff changeset
670 return " multiple ";
jurzua
parents:
diff changeset
671 }
jurzua
parents:
diff changeset
672 return "";
jurzua
parents:
diff changeset
673
jurzua
parents:
diff changeset
674 }
jurzua
parents:
diff changeset
675
jurzua
parents:
diff changeset
676 protected Object[] getSubmittedSelectedValues(UIComponent component) {
jurzua
parents:
diff changeset
677
jurzua
parents:
diff changeset
678 if (component instanceof UISelectMany) {
jurzua
parents:
diff changeset
679 UISelectMany select = (UISelectMany) component;
jurzua
parents:
diff changeset
680 return (Object[]) select.getSubmittedValue();
jurzua
parents:
diff changeset
681 }
jurzua
parents:
diff changeset
682
jurzua
parents:
diff changeset
683 UISelectOne select = (UISelectOne) component;
jurzua
parents:
diff changeset
684 Object val = select.getSubmittedValue();
jurzua
parents:
diff changeset
685 if (val != null) {
jurzua
parents:
diff changeset
686 return new Object[] { val };
jurzua
parents:
diff changeset
687 }
jurzua
parents:
diff changeset
688 return null;
jurzua
parents:
diff changeset
689
jurzua
parents:
diff changeset
690 }
jurzua
parents:
diff changeset
691
jurzua
parents:
diff changeset
692
jurzua
parents:
diff changeset
693 protected boolean isSelected(FacesContext context,
jurzua
parents:
diff changeset
694 UIComponent component,
jurzua
parents:
diff changeset
695 Object itemValue,
jurzua
parents:
diff changeset
696 Object valueArray,
jurzua
parents:
diff changeset
697 Converter converter) {
jurzua
parents:
diff changeset
698
jurzua
parents:
diff changeset
699 if (itemValue == null && valueArray == null) {
jurzua
parents:
diff changeset
700 return true;
jurzua
parents:
diff changeset
701 }
jurzua
parents:
diff changeset
702 if (null != valueArray) {
jurzua
parents:
diff changeset
703 if (!valueArray.getClass().isArray()) {
jurzua
parents:
diff changeset
704 logger.warning("valueArray is not an array, the actual type is " +
jurzua
parents:
diff changeset
705 valueArray.getClass());
jurzua
parents:
diff changeset
706 return valueArray.equals(itemValue);
jurzua
parents:
diff changeset
707 }
jurzua
parents:
diff changeset
708 int len = Array.getLength(valueArray);
jurzua
parents:
diff changeset
709 for (int i = 0; i < len; i++) {
jurzua
parents:
diff changeset
710 Object value = Array.get(valueArray, i);
jurzua
parents:
diff changeset
711 if (value == null && itemValue == null) {
jurzua
parents:
diff changeset
712 return true;
jurzua
parents:
diff changeset
713 } else {
jurzua
parents:
diff changeset
714 if ((value == null) ^ (itemValue == null)) {
jurzua
parents:
diff changeset
715 continue;
jurzua
parents:
diff changeset
716 }
jurzua
parents:
diff changeset
717 Object compareValue;
jurzua
parents:
diff changeset
718 if (converter == null) {
jurzua
parents:
diff changeset
719 compareValue = coerceToModelType(context,
jurzua
parents:
diff changeset
720 itemValue,
jurzua
parents:
diff changeset
721 value.getClass());
jurzua
parents:
diff changeset
722 } else {
jurzua
parents:
diff changeset
723 compareValue = itemValue;
jurzua
parents:
diff changeset
724 if (compareValue instanceof String && !(value instanceof String)) {
jurzua
parents:
diff changeset
725 // type mismatch between the time and the value we're
jurzua
parents:
diff changeset
726 // comparing. Invoke the Converter.
jurzua
parents:
diff changeset
727 compareValue = converter.getAsObject(context,
jurzua
parents:
diff changeset
728 component,
jurzua
parents:
diff changeset
729 (String) compareValue);
jurzua
parents:
diff changeset
730 }
jurzua
parents:
diff changeset
731 }
jurzua
parents:
diff changeset
732
jurzua
parents:
diff changeset
733 if (value.equals(compareValue)) {
jurzua
parents:
diff changeset
734 return (true);
jurzua
parents:
diff changeset
735 }
jurzua
parents:
diff changeset
736 }
jurzua
parents:
diff changeset
737 }
jurzua
parents:
diff changeset
738 }
jurzua
parents:
diff changeset
739 return false;
jurzua
parents:
diff changeset
740
jurzua
parents:
diff changeset
741 }
jurzua
parents:
diff changeset
742
jurzua
parents:
diff changeset
743
jurzua
parents:
diff changeset
744 protected int renderOptions(FacesContext context,
jurzua
parents:
diff changeset
745 UIComponent component,
jurzua
parents:
diff changeset
746 Iterator<SelectItem> items)
jurzua
parents:
diff changeset
747 throws IOException {
jurzua
parents:
diff changeset
748
jurzua
parents:
diff changeset
749 ResponseWriter writer = context.getResponseWriter();
jurzua
parents:
diff changeset
750 assert(writer != null);
jurzua
parents:
diff changeset
751
jurzua
parents:
diff changeset
752 Converter converter = null;
jurzua
parents:
diff changeset
753 if(component instanceof ValueHolder) {
jurzua
parents:
diff changeset
754 converter = ((ValueHolder)component).getConverter();
jurzua
parents:
diff changeset
755 }
jurzua
parents:
diff changeset
756 int count = 0;
jurzua
parents:
diff changeset
757 Object currentSelections = getCurrentSelectedValues(component);
jurzua
parents:
diff changeset
758 Object[] submittedValues = getSubmittedSelectedValues(component);
jurzua
parents:
diff changeset
759 Map<String,Object> attributes = component.getAttributes();
jurzua
parents:
diff changeset
760 boolean componentDisabled = Util.componentIsDisabled(component);
jurzua
parents:
diff changeset
761
jurzua
parents:
diff changeset
762 OptionComponentInfo optionInfo =
jurzua
parents:
diff changeset
763 new OptionComponentInfo((String) attributes.get("disabledClass"),
jurzua
parents:
diff changeset
764 (String) attributes.get("enabledClass"),
jurzua
parents:
diff changeset
765 componentDisabled,
jurzua
parents:
diff changeset
766 isHideNoSelection(component));
jurzua
parents:
diff changeset
767 RequestStateManager.set(context,
jurzua
parents:
diff changeset
768 RequestStateManager.TARGET_COMPONENT_ATTRIBUTE_NAME,
jurzua
parents:
diff changeset
769 component);
jurzua
parents:
diff changeset
770 while (items.hasNext()) {
jurzua
parents:
diff changeset
771 SelectItem item = items.next();
jurzua
parents:
diff changeset
772
jurzua
parents:
diff changeset
773 if (item instanceof SelectItemGroup) {
jurzua
parents:
diff changeset
774 // render OPTGROUP
jurzua
parents:
diff changeset
775 writer.startElement("optgroup", component);
jurzua
parents:
diff changeset
776 writer.writeAttribute("label", item.getLabel(), "label");
jurzua
parents:
diff changeset
777
jurzua
parents:
diff changeset
778 // if the component is disabled, "disabled" attribute would be rendered
jurzua
parents:
diff changeset
779 // on "select" tag, so don't render "disabled" on every option.
jurzua
parents:
diff changeset
780 if ((!componentDisabled) && item.isDisabled()) {
jurzua
parents:
diff changeset
781 writer.writeAttribute("disabled", true, "disabled");
jurzua
parents:
diff changeset
782 }
jurzua
parents:
diff changeset
783 count++;
jurzua
parents:
diff changeset
784 // render options of this group.
jurzua
parents:
diff changeset
785 SelectItem[] itemsArray =
jurzua
parents:
diff changeset
786 ((SelectItemGroup) item).getSelectItems();
jurzua
parents:
diff changeset
787 for (int i = 0; i < itemsArray.length; ++i) {
jurzua
parents:
diff changeset
788 if (renderOption(context,
jurzua
parents:
diff changeset
789 component,
jurzua
parents:
diff changeset
790 converter,
jurzua
parents:
diff changeset
791 itemsArray[i],
jurzua
parents:
diff changeset
792 currentSelections,
jurzua
parents:
diff changeset
793 submittedValues,
jurzua
parents:
diff changeset
794 optionInfo)) {
jurzua
parents:
diff changeset
795 count++;
jurzua
parents:
diff changeset
796 }
jurzua
parents:
diff changeset
797 }
jurzua
parents:
diff changeset
798 writer.endElement("optgroup");
jurzua
parents:
diff changeset
799 } else {
jurzua
parents:
diff changeset
800 if (renderOption(context,
jurzua
parents:
diff changeset
801 component,
jurzua
parents:
diff changeset
802 converter,
jurzua
parents:
diff changeset
803 item,
jurzua
parents:
diff changeset
804 currentSelections,
jurzua
parents:
diff changeset
805 submittedValues,
jurzua
parents:
diff changeset
806 optionInfo)) {
jurzua
parents:
diff changeset
807 count ++;
jurzua
parents:
diff changeset
808 }
jurzua
parents:
diff changeset
809 }
jurzua
parents:
diff changeset
810 }
jurzua
parents:
diff changeset
811
jurzua
parents:
diff changeset
812 return count;
jurzua
parents:
diff changeset
813
jurzua
parents:
diff changeset
814 }
jurzua
parents:
diff changeset
815
jurzua
parents:
diff changeset
816
jurzua
parents:
diff changeset
817 // Render the "select" portion..
jurzua
parents:
diff changeset
818 //
jurzua
parents:
diff changeset
819 protected void renderSelect(FacesContext context,
jurzua
parents:
diff changeset
820 UIComponent component) throws IOException {
jurzua
parents:
diff changeset
821
jurzua
parents:
diff changeset
822 ResponseWriter writer = context.getResponseWriter();
jurzua
parents:
diff changeset
823 assert(writer != null);
jurzua
parents:
diff changeset
824
jurzua
parents:
diff changeset
825 if (logger.isLoggable(Level.FINER)) {
jurzua
parents:
diff changeset
826 logger.log(Level.FINER, "Rendering 'select'");
jurzua
parents:
diff changeset
827 }
jurzua
parents:
diff changeset
828 writer.startElement("select", component);
jurzua
parents:
diff changeset
829 writeIdAttributeIfNecessary(context, writer, component);
jurzua
parents:
diff changeset
830 writer.writeAttribute("name", component.getClientId(context),
jurzua
parents:
diff changeset
831 "clientId");
jurzua
parents:
diff changeset
832 // render styleClass attribute if present.
jurzua
parents:
diff changeset
833 String styleClass;
jurzua
parents:
diff changeset
834 if (null !=
jurzua
parents:
diff changeset
835 (styleClass =
jurzua
parents:
diff changeset
836 (String) component.getAttributes().get("styleClass"))) {
jurzua
parents:
diff changeset
837 writer.writeAttribute("class", styleClass, "styleClass");
jurzua
parents:
diff changeset
838 }
jurzua
parents:
diff changeset
839 if (!getMultipleText(component).equals("")) {
jurzua
parents:
diff changeset
840 writer.writeAttribute("multiple", true, "multiple");
jurzua
parents:
diff changeset
841 }
jurzua
parents:
diff changeset
842
jurzua
parents:
diff changeset
843 // Determine how many option(s) we need to render, and update
jurzua
parents:
diff changeset
844 // the component's "size" attribute accordingly; The "size"
jurzua
parents:
diff changeset
845 // attribute will be rendered as one of the "pass thru" attributes
jurzua
parents:
diff changeset
846 Iterator<SelectItem> items = RenderKitUtils.getSelectItems(context, component);
jurzua
parents:
diff changeset
847
jurzua
parents:
diff changeset
848 // render the options to a buffer now so that we can determine
jurzua
parents:
diff changeset
849 // the size
jurzua
parents:
diff changeset
850 FastStringWriter bufferedWriter = new FastStringWriter(128);
jurzua
parents:
diff changeset
851 context.setResponseWriter(writer.cloneWithWriter(bufferedWriter));
jurzua
parents:
diff changeset
852 int count = renderOptions(context, component, items);
jurzua
parents:
diff changeset
853 context.setResponseWriter(writer);
jurzua
parents:
diff changeset
854 // If "size" is *not* set explicitly, we have to default it correctly
jurzua
parents:
diff changeset
855 Integer size = (Integer) component.getAttributes().get("size");
jurzua
parents:
diff changeset
856 if (size == null || size == Integer.MIN_VALUE) {
jurzua
parents:
diff changeset
857 size = count;
jurzua
parents:
diff changeset
858 }
jurzua
parents:
diff changeset
859 writeDefaultSize(writer, size);
jurzua
parents:
diff changeset
860
jurzua
parents:
diff changeset
861 RenderKitUtils.renderPassThruAttributes(context,
jurzua
parents:
diff changeset
862 writer,
jurzua
parents:
diff changeset
863 component,
jurzua
parents:
diff changeset
864 ATTRIBUTES,
jurzua
parents:
diff changeset
865 getNonOnChangeBehaviors(component));
jurzua
parents:
diff changeset
866 RenderKitUtils.renderXHTMLStyleBooleanAttributes(writer,
jurzua
parents:
diff changeset
867 component);
jurzua
parents:
diff changeset
868
jurzua
parents:
diff changeset
869 RenderKitUtils.renderOnchange(context, component, false);
jurzua
parents:
diff changeset
870
jurzua
parents:
diff changeset
871 // Now, write the buffered option content
jurzua
parents:
diff changeset
872 writer.write(bufferedWriter.toString());
jurzua
parents:
diff changeset
873
jurzua
parents:
diff changeset
874 writer.endElement("select");
jurzua
parents:
diff changeset
875
jurzua
parents:
diff changeset
876 }
jurzua
parents:
diff changeset
877
jurzua
parents:
diff changeset
878 protected Object coerceToModelType(FacesContext ctx,
jurzua
parents:
diff changeset
879 Object value,
jurzua
parents:
diff changeset
880 Class itemValueType) {
jurzua
parents:
diff changeset
881
jurzua
parents:
diff changeset
882 Object newValue;
jurzua
parents:
diff changeset
883 try {
jurzua
parents:
diff changeset
884 ExpressionFactory ef = ctx.getApplication().getExpressionFactory();
jurzua
parents:
diff changeset
885 newValue = ef.coerceToType(value, itemValueType);
jurzua
parents:
diff changeset
886 } catch (ELException ele) {
jurzua
parents:
diff changeset
887 newValue = value;
jurzua
parents:
diff changeset
888 } catch (IllegalArgumentException iae) {
jurzua
parents:
diff changeset
889 // If coerceToType fails, per the docs it should throw
jurzua
parents:
diff changeset
890 // an ELException, however, GF 9.0 and 9.0u1 will throw
jurzua
parents:
diff changeset
891 // an IllegalArgumentException instead (see GF issue 1527).
jurzua
parents:
diff changeset
892 newValue = value;
jurzua
parents:
diff changeset
893 }
jurzua
parents:
diff changeset
894
jurzua
parents:
diff changeset
895 return newValue;
jurzua
parents:
diff changeset
896
jurzua
parents:
diff changeset
897 }
jurzua
parents:
diff changeset
898
jurzua
parents:
diff changeset
899
jurzua
parents:
diff changeset
900 /**
jurzua
parents:
diff changeset
901 * @param collection a Collection instance
jurzua
parents:
diff changeset
902 *
jurzua
parents:
diff changeset
903 * @return a new <code>Collection</code> instance or null if the instance
jurzua
parents:
diff changeset
904 * cannot be created
jurzua
parents:
diff changeset
905 */
jurzua
parents:
diff changeset
906 protected Collection createCollection(Collection collection,
jurzua
parents:
diff changeset
907 Class<? extends Collection> fallBackType) {
jurzua
parents:
diff changeset
908
jurzua
parents:
diff changeset
909 Class<? extends Collection> lookupClass =
jurzua
parents:
diff changeset
910 ((collection != null) ? collection.getClass() : fallBackType);
jurzua
parents:
diff changeset
911
jurzua
parents:
diff changeset
912 if (!lookupClass.isInterface()
jurzua
parents:
diff changeset
913 && !Modifier.isAbstract(lookupClass.getModifiers())) {
jurzua
parents:
diff changeset
914 try {
jurzua
parents:
diff changeset
915 return lookupClass.newInstance();
jurzua
parents:
diff changeset
916 } catch (Exception e) {
jurzua
parents:
diff changeset
917 if (logger.isLoggable(Level.SEVERE)) {
jurzua
parents:
diff changeset
918 logger.log(Level.SEVERE,
jurzua
parents:
diff changeset
919 "Unable to create new Collection instance for type "
jurzua
parents:
diff changeset
920 + lookupClass.getName(),
jurzua
parents:
diff changeset
921 e);
jurzua
parents:
diff changeset
922 }
jurzua
parents:
diff changeset
923 }
jurzua
parents:
diff changeset
924 }
jurzua
parents:
diff changeset
925
jurzua
parents:
diff changeset
926 return null;
jurzua
parents:
diff changeset
927
jurzua
parents:
diff changeset
928 }
jurzua
parents:
diff changeset
929
jurzua
parents:
diff changeset
930
jurzua
parents:
diff changeset
931 /**
jurzua
parents:
diff changeset
932 * <p>
jurzua
parents:
diff changeset
933 * Utility method to invoke the the <code>clone</code> method on the provided
jurzua
parents:
diff changeset
934 * value.
jurzua
parents:
diff changeset
935 * </p>
jurzua
parents:
diff changeset
936 *
jurzua
parents:
diff changeset
937 * @param value the value to clone
jurzua
parents:
diff changeset
938 * @return the result of invoking <code>clone()</code> or <code>null</code>
jurzua
parents:
diff changeset
939 * if the value could not be cloned or does not implement the
jurzua
parents:
diff changeset
940 * {@link Cloneable} interface
jurzua
parents:
diff changeset
941 */
jurzua
parents:
diff changeset
942 protected Collection cloneValue(Object value) {
jurzua
parents:
diff changeset
943
jurzua
parents:
diff changeset
944 if (value instanceof Cloneable) {
jurzua
parents:
diff changeset
945 // even though Clonable marks an instance of a Class as being
jurzua
parents:
diff changeset
946 // safe to call .clone(), .clone() by default is protected.
jurzua
parents:
diff changeset
947 // The Collection classes that do implement Clonable do so at variable
jurzua
parents:
diff changeset
948 // locations within the class hierarchy, so we're stuck having to
jurzua
parents:
diff changeset
949 // use reflection.
jurzua
parents:
diff changeset
950 Method clone =
jurzua
parents:
diff changeset
951 ReflectionUtils.lookupMethod(value.getClass(), "clone");
jurzua
parents:
diff changeset
952 if (clone != null) {
jurzua
parents:
diff changeset
953 try {
jurzua
parents:
diff changeset
954 Collection c = (Collection) clone.invoke(value);
jurzua
parents:
diff changeset
955 c.clear();
jurzua
parents:
diff changeset
956 return c;
jurzua
parents:
diff changeset
957 } catch (Exception e) {
jurzua
parents:
diff changeset
958 if (logger.isLoggable(Level.SEVERE)) {
jurzua
parents:
diff changeset
959 logger.log(Level.SEVERE,
jurzua
parents:
diff changeset
960 "Unable to clone collection type: {0}",
jurzua
parents:
diff changeset
961 value.getClass().getName());
jurzua
parents:
diff changeset
962 logger.log(Level.SEVERE, e.toString(), e);
jurzua
parents:
diff changeset
963 }
jurzua
parents:
diff changeset
964 }
jurzua
parents:
diff changeset
965 } else {
jurzua
parents:
diff changeset
966 // no public clone method
jurzua
parents:
diff changeset
967 if (logger.isLoggable(Level.FINE)) {
jurzua
parents:
diff changeset
968 logger.log(Level.FINE,
jurzua
parents:
diff changeset
969 "Type {0} implements Cloneable, but has no public clone method.",
jurzua
parents:
diff changeset
970 value.getClass().getName());
jurzua
parents:
diff changeset
971 }
jurzua
parents:
diff changeset
972 }
jurzua
parents:
diff changeset
973 }
jurzua
parents:
diff changeset
974
jurzua
parents:
diff changeset
975 return null;
jurzua
parents:
diff changeset
976
jurzua
parents:
diff changeset
977 }
jurzua
parents:
diff changeset
978
jurzua
parents:
diff changeset
979
jurzua
parents:
diff changeset
980 /**
jurzua
parents:
diff changeset
981 * @param type the target model type
jurzua
parents:
diff changeset
982 * @param initialSize the initial size of the <code>Collection</code>
jurzua
parents:
diff changeset
983 * @return a <code>Collection</code> instance that best matches
jurzua
parents:
diff changeset
984 * <code>type</code>
jurzua
parents:
diff changeset
985 */
jurzua
parents:
diff changeset
986 protected Collection bestGuess(Class<? extends Collection> type,
jurzua
parents:
diff changeset
987 int initialSize) {
jurzua
parents:
diff changeset
988
jurzua
parents:
diff changeset
989 if (SortedSet.class.isAssignableFrom(type)) {
jurzua
parents:
diff changeset
990 return new TreeSet();
jurzua
parents:
diff changeset
991 } else if (Queue.class.isAssignableFrom(type)) {
jurzua
parents:
diff changeset
992 return new LinkedList();
jurzua
parents:
diff changeset
993 } else if (Set.class.isAssignableFrom(type)) {
jurzua
parents:
diff changeset
994 return new HashSet(initialSize);
jurzua
parents:
diff changeset
995 } else {
jurzua
parents:
diff changeset
996 // this covers the where type is List or Collection
jurzua
parents:
diff changeset
997 return new ArrayList(initialSize);
jurzua
parents:
diff changeset
998 }
jurzua
parents:
diff changeset
999
jurzua
parents:
diff changeset
1000 }
jurzua
parents:
diff changeset
1001
jurzua
parents:
diff changeset
1002
jurzua
parents:
diff changeset
1003 /**
jurzua
parents:
diff changeset
1004 * <p>
jurzua
parents:
diff changeset
1005 * Create a collection from the provided hint.
jurzua
parents:
diff changeset
1006 * @param collectionTypeHint the Collection type as either a String or Class
jurzua
parents:
diff changeset
1007 * @return a new Collection instance
jurzua
parents:
diff changeset
1008 */
jurzua
parents:
diff changeset
1009 protected Collection createCollectionFromHint(Object collectionTypeHint) {
jurzua
parents:
diff changeset
1010
jurzua
parents:
diff changeset
1011 Class<? extends Collection> collectionType;
jurzua
parents:
diff changeset
1012 if (collectionTypeHint instanceof Class) {
jurzua
parents:
diff changeset
1013 //noinspection unchecked
jurzua
parents:
diff changeset
1014 collectionType = (Class<? extends Collection>) collectionTypeHint;
jurzua
parents:
diff changeset
1015 } else if (collectionTypeHint instanceof String) {
jurzua
parents:
diff changeset
1016 try {
jurzua
parents:
diff changeset
1017 //noinspection unchecked
jurzua
parents:
diff changeset
1018 collectionType = Util.loadClass((String) collectionTypeHint,
jurzua
parents:
diff changeset
1019 this);
jurzua
parents:
diff changeset
1020 } catch (ClassNotFoundException cnfe) {
jurzua
parents:
diff changeset
1021 throw new FacesException(cnfe);
jurzua
parents:
diff changeset
1022 }
jurzua
parents:
diff changeset
1023 } else {
jurzua
parents:
diff changeset
1024 // RELEASE_PENDING (i18n)
jurzua
parents:
diff changeset
1025 throw new FacesException(
jurzua
parents:
diff changeset
1026 "'collectionType' should resolve to type String or Class. Found: "
jurzua
parents:
diff changeset
1027 + collectionTypeHint.getClass().getName());
jurzua
parents:
diff changeset
1028 }
jurzua
parents:
diff changeset
1029
jurzua
parents:
diff changeset
1030 Collection c = createCollection(null, collectionType);
jurzua
parents:
diff changeset
1031 if (c == null) {
jurzua
parents:
diff changeset
1032 // RELEASE_PENDING (i18n)
jurzua
parents:
diff changeset
1033 throw new FacesException("Unable to create collection type " + collectionType);
jurzua
parents:
diff changeset
1034 }
jurzua
parents:
diff changeset
1035 return c;
jurzua
parents:
diff changeset
1036
jurzua
parents:
diff changeset
1037 }
jurzua
parents:
diff changeset
1038
jurzua
parents:
diff changeset
1039
jurzua
parents:
diff changeset
1040 protected boolean isHideNoSelection(UIComponent component) {
jurzua
parents:
diff changeset
1041
jurzua
parents:
diff changeset
1042 Object result = component.getAttributes().get("hideNoSelectionOption");
jurzua
parents:
diff changeset
1043 return ((result != null) ? (Boolean) result : false);
jurzua
parents:
diff changeset
1044
jurzua
parents:
diff changeset
1045 }
jurzua
parents:
diff changeset
1046
jurzua
parents:
diff changeset
1047 } // end of class MenuRenderer