1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.seasar.cubby.tags;
17
18 import static org.seasar.cubby.tags.TagUtils.addClassName;
19 import static org.seasar.cubby.tags.TagUtils.errors;
20 import static org.seasar.cubby.tags.TagUtils.contains;
21 import static org.seasar.cubby.tags.TagUtils.multipleFormValues;
22 import static org.seasar.cubby.tags.TagUtils.outputValues;
23 import static org.seasar.cubby.tags.TagUtils.toAttr;
24
25 import java.io.IOException;
26 import java.util.Collection;
27 import java.util.Map;
28 import java.util.Map.Entry;
29
30 import javax.servlet.jsp.JspContext;
31 import javax.servlet.jsp.JspException;
32 import javax.servlet.jsp.JspTagException;
33 import javax.servlet.jsp.JspWriter;
34
35 import org.seasar.cubby.action.ActionErrors;
36 import org.seasar.cubby.util.CubbyFunctions;
37 import org.seasar.framework.beans.BeanDesc;
38 import org.seasar.framework.beans.PropertyDesc;
39 import org.seasar.framework.beans.factory.BeanDescFactory;
40 import org.seasar.framework.log.Logger;
41 import org.seasar.framework.message.MessageFormatter;
42
43
44
45
46
47
48
49
50 public class SelectTag extends DynamicAttributesTagSupport {
51
52 private static final Logger logger = Logger.getLogger(SelectTag.class);
53
54
55 private String name;
56
57
58 private Object items;
59
60
61 private String labelProperty;
62
63
64 private String valueProperty;
65
66
67
68
69 private Boolean emptyOption = Boolean.TRUE;
70
71
72
73
74 private String emptyOptionLabel;
75
76
77
78
79
80
81
82 public void setItems(final Object items) {
83 this.items = items;
84 }
85
86
87
88
89
90
91
92 public void setLabelProperty(final String labelProperty) {
93 this.labelProperty = labelProperty;
94 }
95
96
97
98
99
100
101
102 public void setValueProperty(final String valueProperty) {
103 this.valueProperty = valueProperty;
104 }
105
106
107
108
109
110
111
112 public void setEmptyOption(final Boolean emptyOption) {
113 this.emptyOption = emptyOption;
114 }
115
116
117
118
119
120
121
122 public void setEmptyOptionLabel(final String emptyOptionLabel) {
123 this.emptyOptionLabel = emptyOptionLabel;
124 }
125
126
127
128
129
130
131
132 public void setName(final String name) {
133 this.name = name;
134 }
135
136
137
138
139 @Override
140 public void doTag() throws JspException, IOException {
141 final JspContext context = this.getJspContext();
142 final JspWriter out = context.getOut();
143 final ActionErrors errors = errors(context);
144 final Map<String, Object> dyn = this.getDynamicAttribute();
145 final Map<String, String[]> outputValues = outputValues(context);
146
147 if (!errors.getFields().get(this.name).isEmpty()) {
148 addClassName(dyn, "fieldError");
149 }
150
151 final Object[] value = multipleFormValues(context, outputValues,
152 this.name);
153
154 out.write("<select name=\"");
155 out.write(this.name);
156 out.write("\" ");
157 out.write(toAttr(dyn));
158 out.write(">\n");
159
160 if (emptyOption) {
161 out.write("<option value=\"\">");
162 out.write(CubbyFunctions.out(emptyOptionLabel));
163 out.write("</option>\n");
164 }
165
166 if (items != null && items.getClass().isArray()) {
167 final OptionWriter optionWriter = new OptionWriter(
168 new BeanItemAdaptor());
169 for (final Object item : (Object[]) items) {
170 optionWriter.write(out, item, value);
171 }
172 } else {
173 final OptionWriter optionWriter;
174 final Collection<?> collection;
175 if (items instanceof Collection) {
176 optionWriter = new OptionWriter(new BeanItemAdaptor());
177 collection = (Collection<?>) items;
178 } else if (items instanceof Map) {
179 optionWriter = new OptionWriter(new EntryItemAdaptor());
180 collection = ((Map<?, ?>) items).entrySet();
181 } else {
182 throw new JspTagException(MessageFormatter.getMessage(
183 "ECUB1001", new Object[] { "items", items.getClass() }));
184 }
185 for (final Object item : collection) {
186 optionWriter.write(out, item, value);
187 }
188 }
189
190 out.write("</select>\n");
191 }
192
193 private static class OptionWriter {
194
195 private final ItemAdaptor itemAdaptor;
196
197 OptionWriter(final ItemAdaptor itemAdaptor) {
198 this.itemAdaptor = itemAdaptor;
199 }
200
201 void write(final JspWriter out, final Object item,
202 final Object value) throws IOException {
203 out.write("<option value=\"");
204 final String itemValue = DynamicAttributesTagSupport
205 .toString(itemAdaptor.getItemValue(item));
206 final String labelValue = DynamicAttributesTagSupport
207 .toString(itemAdaptor.getLabelValue(item));
208 out.write(CubbyFunctions.out(itemValue));
209 out.write("\" ");
210 out.write(selected(itemValue, value));
211 out.write(">");
212 out.write(CubbyFunctions.out(labelValue));
213 out.write("</option>\n");
214 }
215
216 private String selected(final String value, final Object values) {
217 if (value == null || values == null) {
218 return "";
219 }
220 if (contains(values, value)) {
221 return "selected=\"true\"";
222 } else {
223 return "";
224 }
225 }
226 }
227
228 private interface ItemAdaptor {
229
230
231
232
233
234
235
236
237 Object getItemValue(Object item);
238
239
240
241
242
243
244
245
246 Object getLabelValue(Object item);
247
248 }
249
250 private class BeanItemAdaptor implements ItemAdaptor {
251
252 BeanItemAdaptor() throws JspTagException {
253 if (valueProperty == null) {
254 throw new JspTagException(MessageFormatter.getMessage(
255 "ECUB1002", new Object[] { "items", "valueProperty" }));
256 }
257 }
258
259
260
261
262 public Object getItemValue(final Object item) {
263 return property(item, valueProperty);
264 }
265
266
267
268
269 public Object getLabelValue(final Object item) {
270 final Object labelValue;
271 if (labelProperty == null) {
272 labelValue = getItemValue(item);
273 } else {
274 labelValue = property(item, labelProperty);
275 }
276 return labelValue;
277 }
278
279 private Object property(final Object bean, final String propertyName) {
280 final BeanDesc beanDesc = BeanDescFactory.getBeanDesc(bean
281 .getClass());
282 final PropertyDesc propertyDesc = beanDesc
283 .getPropertyDesc(propertyName);
284 return propertyDesc.getValue(bean);
285 }
286
287 }
288
289 private class EntryItemAdaptor implements ItemAdaptor {
290
291 EntryItemAdaptor() {
292 if (valueProperty != null) {
293 logger.log("WCUB1001", new Object[] { "items",
294 Map.class.getSimpleName(), "valueProperty",
295 valueProperty,
296 Entry.class.getSimpleName() + "#getKey()" });
297 }
298 if (labelProperty != null) {
299 logger.log("WCUB1002", new Object[] { "items",
300 Map.class.getSimpleName(), "labelProperty",
301 labelProperty,
302 Entry.class.getSimpleName() + "#getValue()" });
303 }
304 }
305
306
307
308
309 public Object getItemValue(final Object item) {
310 return ((Entry<?, ?>) item).getKey();
311 }
312
313
314
315
316 public Object getLabelValue(final Object item) {
317 return ((Entry<?, ?>) item).getValue();
318 }
319
320 }
321
322 }