1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.renderkit;
21
22 import org.apache.commons.lang.ArrayUtils;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25 import org.apache.myfaces.tobago.util.ComponentUtils;
26
27 import javax.faces.FacesException;
28 import javax.faces.component.UIComponent;
29 import javax.faces.component.UISelectMany;
30 import javax.faces.context.FacesContext;
31 import javax.faces.convert.Converter;
32 import javax.faces.convert.ConverterException;
33 import javax.faces.el.ValueBinding;
34 import java.lang.reflect.Array;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.List;
38
39 public class SelectManyRendererBase extends LayoutComponentRendererBase {
40
41 private static final Logger LOG = LoggerFactory.getLogger(SelectManyRendererBase.class);
42
43 public void decode(FacesContext facesContext, UIComponent component) {
44 if (ComponentUtils.isOutputOnly(component)) {
45 return;
46 }
47 if (component instanceof UISelectMany) {
48 UISelectMany uiSelectMany = (UISelectMany) component;
49
50 String[] newValues = (String[])
51 facesContext.getExternalContext().getRequestParameterValuesMap().get(uiSelectMany.getClientId(facesContext));
52 if (LOG.isDebugEnabled()) {
53 LOG.debug("decode: key='" + component.getClientId(facesContext)
54 + "' value='" + Arrays.toString(newValues) + "'");
55 LOG.debug("size ... '" + (newValues != null ? newValues.length : -1) + "'");
56 if (newValues != null) {
57 for (String newValue : newValues) {
58 LOG.debug("newValues[i] = '" + newValue + "'");
59 }
60 }
61 }
62
63 if (newValues == null) {
64 newValues = ArrayUtils.EMPTY_STRING_ARRAY;
65 }
66 uiSelectMany.setSubmittedValue(newValues);
67 }
68 }
69
70
71 public Object getConvertedValue(FacesContext facesContext, UIComponent component, Object submittedValue)
72 throws ConverterException {
73
74 if (submittedValue == null) {
75 return null;
76 } else {
77 if (!(submittedValue instanceof String[])) {
78 throw new ConverterException("Submitted value of type String[] for component : "
79 + component.getClientId(facesContext) + "expected");
80 }
81 }
82 return getConvertedUISelectManyValue(facesContext, (UISelectMany) component, (String[]) submittedValue);
83 }
84
85 private Object getConvertedUISelectManyValue(FacesContext facesContext,
86 UISelectMany component,
87 String[] submittedValue)
88 throws ConverterException {
89
90
91
92
93 if (submittedValue == null) {
94 throw new NullPointerException("submittedValue");
95 }
96
97 ValueBinding vb = component.getValueBinding("value");
98 Class valueType = null;
99 Class arrayComponentType = null;
100 if (vb != null) {
101 valueType = vb.getType(facesContext);
102 if (valueType != null && valueType.isArray()) {
103 arrayComponentType = valueType.getComponentType();
104 }
105 }
106
107 Converter converter = component.getConverter();
108 if (converter == null) {
109 if (valueType == null) {
110
111
112 return submittedValue;
113 }
114
115 if (List.class.isAssignableFrom(valueType)) {
116
117
118
119 return Arrays.asList(submittedValue);
120 }
121
122 if (arrayComponentType == null) {
123 throw new IllegalArgumentException("ValueBinding for UISelectMany must be of type List or Array");
124 }
125
126 if (String.class.equals(arrayComponentType)) {
127 return submittedValue;
128 }
129 if (Object.class.equals(arrayComponentType)) {
130 return submittedValue;
131 }
132
133 try {
134 converter = facesContext.getApplication().createConverter(arrayComponentType);
135 } catch (FacesException e) {
136 LOG.error("No Converter for type " + arrayComponentType.getName() + " found", e);
137 return submittedValue;
138 }
139 }
140
141
142
143 if (vb != null && arrayComponentType == null
144 && valueType != null && valueType.isArray()) {
145 if (submittedValue.length > 0) {
146 arrayComponentType = converter.getAsObject(facesContext, component, submittedValue[0]).getClass();
147 }
148 }
149
150 if (valueType == null) {
151
152
153 int len = submittedValue.length;
154 Object[] convertedValues = (Object[]) Array.newInstance(
155 arrayComponentType == null ? Object.class : arrayComponentType, len);
156 for (int i = 0; i < len; i++) {
157 convertedValues[i]
158 = converter.getAsObject(facesContext, component, submittedValue[i]);
159 }
160 return convertedValues;
161 }
162
163 if (List.class.isAssignableFrom(valueType)) {
164
165
166
167 int length = submittedValue.length;
168 List<Object> list = new ArrayList<Object>(length);
169 for (int i = 0; i < length; i++) {
170 list.add(converter.getAsObject(facesContext, component, submittedValue[i]));
171 }
172 return list;
173 }
174
175 if (arrayComponentType == null) {
176 throw new IllegalArgumentException("ValueBinding for UISelectMany must be of type List or Array");
177 }
178
179 if (arrayComponentType.isPrimitive()) {
180
181 int len = submittedValue.length;
182 Object convertedValues = Array.newInstance(arrayComponentType, len);
183 for (int i = 0; i < len; i++) {
184 Array.set(convertedValues, i,
185 converter.getAsObject(facesContext, component, submittedValue[i]));
186 }
187 return convertedValues;
188 } else {
189
190 int length = submittedValue.length;
191 List<Object> convertedValues = new ArrayList<Object>(length);
192 for (int i = 0; i < length; i++) {
193 convertedValues.add(i, converter.getAsObject(facesContext, component, submittedValue[i]));
194 }
195 return convertedValues.toArray((Object[]) Array.newInstance(arrayComponentType, length));
196 }
197 }
198
199 }