View Javadoc

1   package org.seasar.cubby.tags;
2   
3   import java.io.IOException;
4   import java.util.Collection;
5   import java.util.Map;
6   import java.util.Map.Entry;
7   
8   import javax.servlet.jsp.JspException;
9   import javax.servlet.jsp.JspTagException;
10  import javax.servlet.jsp.JspWriter;
11  import javax.servlet.jsp.PageContext;
12  
13  import org.seasar.cubby.util.CubbyFunctions;
14  import org.seasar.cubby.util.CubbyHelperFunctions;
15  import org.seasar.framework.log.Logger;
16  import org.seasar.framework.message.MessageFormatter;
17  
18  /**
19   * selectを出力するタグ
20   * 
21   * @author agata
22   * 
23   */
24  public class SelectTag extends DynamicAttributesTagSupport {
25  
26  	private static final Logger logger = Logger.getLogger(SelectTag.class);
27  
28  	/**
29  	 * option要素リスト
30  	 */
31  	private Object items;
32  	/**
33  	 * optionのラベルのプロパティ名
34  	 */
35  	private String labelProperty;
36  	/**
37  	 * optionの値のプロパティ名
38  	 */
39  	private String valueProperty;
40  	/**
41  	 * 空のoption要素を出力するかどうか。
42  	 */
43  	private boolean emptyOption = true;
44  	/**
45  	 * 空のoption要素を出力した場合のラベル文字列
46  	 */
47  	private String emptyOptionLabel;
48  
49  	public Object getItems() {
50  		return items;
51  	}
52  
53  	/**
54  	 * option要素リストをセットします。
55  	 * 
56  	 * @param items
57  	 *            option要素リスト
58  	 */
59  	public void setItems(final Object items) {
60  		this.items = items;
61  	}
62  
63  	/**
64  	 * optionのラベルのプロパティ名をセットします。
65  	 * 
66  	 * @param labelProperty
67  	 *            optionのラベルのプロパティ名
68  	 */
69  	public void setLabelProperty(final String labelProperty) {
70  		this.labelProperty = labelProperty;
71  	}
72  
73  	/**
74  	 * optionのラベルのプロパティ名をセットします。
75  	 * 
76  	 * @param valueProperty
77  	 *            optionのラベルのプロパティ名
78  	 */
79  	public void setValueProperty(final String valueProperty) {
80  		this.valueProperty = valueProperty;
81  	}
82  
83  	/**
84  	 * 空のoption要素を出力するかどうかをセットします。
85  	 * 
86  	 * @param emptyOption
87  	 *            空のoption要素を出力するかどうか
88  	 */
89  	public void setEmptyOption(final boolean emptyOption) {
90  		this.emptyOption = emptyOption;
91  	}
92  
93  	/**
94  	 * 空のoption要素を出力した場合のラベル文字列をセットします。
95  	 * 
96  	 * @param emptyOptionLabel
97  	 *            空のoption要素を出力した場合のラベル文字列
98  	 */
99  	public void setEmptyOptionLabel(final String emptyOptionLabel) {
100 		this.emptyOptionLabel = emptyOptionLabel;
101 	}
102 	/**
103 	 * タグの処理
104 	 */
105 	@SuppressWarnings("unchecked")
106 	@Override
107 	public void doTag() throws JspException, IOException {
108 		final Object form = getJspContext().getAttribute("__form",
109 				PageContext.REQUEST_SCOPE);
110 		final Object value = CubbyHelperFunctions.formValue(
111 				getDynamicAttribute(), form, getJspContext(), "value");
112 		getJspContext().setAttribute("value", value, PageContext.PAGE_SCOPE);
113 		final Map<?, ?> fieldErros = (Map<?, ?>) getJspContext().getAttribute(
114 				"fieldErrors", PageContext.REQUEST_SCOPE);
115 		if (fieldErros.get(getDynamicAttribute().get("name")) != null) {
116 			CubbyHelperFunctions.addClassName(getDynamicAttribute(),
117 					"fieldError");
118 		}
119 		final JspWriter out = getJspContext().getOut();
120 		out.write("<select ");
121 		out.write(CubbyHelperFunctions.toAttr(getDynamicAttribute()));
122 		out.write(">\n");
123 
124 		if (emptyOption) {
125 			out.write("<option value=\"\">");
126 			out.write(CubbyFunctions.out(emptyOptionLabel));
127 			out.write("</option>\n");
128 		}
129 
130 		if (items.getClass().isArray()) {
131 			final OptionWriter optionWriter = new OptionWriter(
132 					new BeanItemAdaptor());
133 			for (final Object item : (Object[]) items) {
134 				optionWriter.write(out, item, value);
135 			}
136 		} else {
137 			final OptionWriter optionWriter;
138 			final Collection<?> collection;
139 			if (items instanceof Collection) {
140 				optionWriter = new OptionWriter(new BeanItemAdaptor());
141 				collection = (Collection<?>) items;
142 			} else if (items instanceof Map) {
143 				optionWriter = new OptionWriter(new EntryItemAdaptor());
144 				collection = ((Map<?, ?>) items).entrySet();
145 			} else {
146 				throw new JspTagException(MessageFormatter.getMessage(
147 						"ECUB1001", new Object[] { "items", items.getClass() }));
148 			}
149 			for (final Object item : collection) {
150 				optionWriter.write(out, item, value);
151 			}
152 		}
153 
154 		out.write("</select>\n");
155 	}
156 
157 	static class OptionWriter {
158 
159 		private final ItemAdaptor itemAdaptor;
160 
161 		OptionWriter(final ItemAdaptor itemAdaptor) {
162 			this.itemAdaptor = itemAdaptor;
163 		}
164 
165 		public void write(final JspWriter out, final Object item,
166 				final Object value) throws IOException {
167 			out.write("<option value=\"");
168 			final String itemValue = DynamicAttributesTagSupport
169 					.toString(itemAdaptor.getItemValue(item));
170 			final String labelValue = DynamicAttributesTagSupport
171 					.toString(itemAdaptor.getLabelValue(item));
172 			out.write(CubbyFunctions.out(itemValue));
173 			out.write("\" ");
174 			out.write(selected(itemValue, value));
175 			out.write(">");
176 			out.write(CubbyFunctions.out(labelValue));
177 			out.write("</option>\n");
178 		}
179 
180 		private String selected(final String value, final Object values) {
181 			if (value == null || values == null) {
182 				return "";
183 			}
184 			if (CubbyHelperFunctions.isChecked(value, values)) {
185 				return "selected=\"true\"";
186 			} else {
187 				return "";
188 			}
189 		}
190 	}
191 
192 	interface ItemAdaptor {
193 
194 		Object getItemValue(Object item);
195 
196 		Object getLabelValue(Object item);
197 
198 	}
199 
200 	class BeanItemAdaptor implements ItemAdaptor {
201 
202 		public BeanItemAdaptor() throws JspTagException {
203 			if (valueProperty == null) {
204 				throw new JspTagException(MessageFormatter.getMessage(
205 						"ECUB1002", new Object[] { "items", "valueProperty" }));
206 			}
207 		}
208 
209 		public Object getItemValue(final Object item) {
210 			return CubbyHelperFunctions.property(item, valueProperty);
211 		}
212 
213 		public Object getLabelValue(final Object item) {
214 			final Object labelValue;
215 			if (labelProperty == null) {
216 				labelValue = getItemValue(item);
217 			} else {
218 				labelValue = CubbyHelperFunctions.property(item, labelProperty);
219 			}
220 			return labelValue;
221 		}
222 
223 	}
224 
225 	class EntryItemAdaptor implements ItemAdaptor {
226 
227 		public EntryItemAdaptor() {
228 			if (valueProperty != null) {
229 				logger.log("WCUB1001", new Object[] { "items",
230 						Map.class.getSimpleName(), "valueProperty",
231 						valueProperty,
232 						Entry.class.getSimpleName() + "#getKey()" });
233 			}
234 			if (labelProperty != null) {
235 				logger.log("WCUB1002", new Object[] { "items",
236 						Map.class.getSimpleName(), "labelProperty",
237 						labelProperty,
238 						Entry.class.getSimpleName() + "#getValue()" });
239 			}
240 		}
241 
242 		public Object getItemValue(final Object item) {
243 			return ((Entry<?, ?>) item).getKey();
244 		}
245 
246 		public Object getLabelValue(final Object item) {
247 			return ((Entry<?, ?>) item).getValue();
248 		}
249 
250 	}
251 
252 }