1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.renderkit.html.ext;
20
21 import java.io.IOException;
22 import java.text.MessageFormat;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27
28 import javax.faces.application.FacesMessage;
29 import javax.faces.component.NamingContainer;
30 import javax.faces.component.UIColumn;
31 import javax.faces.component.UIComponent;
32 import javax.faces.component.ValueHolder;
33 import javax.faces.component.html.HtmlOutputLabel;
34 import javax.faces.component.html.HtmlOutputText;
35 import javax.faces.context.FacesContext;
36 import javax.faces.context.ResponseWriter;
37
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.apache.myfaces.component.html.ext.HtmlMessage;
41 import org.apache.myfaces.component.html.ext.HtmlMessages;
42 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
43 import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
44 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlMessageRendererBase;
45
46
47
48
49
50
51
52
53
54
55 public class HtmlMessageRenderer
56 extends HtmlMessageRendererBase
57 {
58 private static final Log log = LogFactory.getLog(HtmlMessageRenderer.class);
59
60 private static final String OUTPUT_LABEL_MAP = HtmlMessageRenderer.class.getName() + ".OUTPUT_LABEL_MAP";
61
62 public void encodeEnd(FacesContext facesContext, UIComponent component)
63 throws IOException
64 {
65 super.encodeEnd(facesContext, component);
66 renderMessage(facesContext, component);
67
68 if (component instanceof HtmlMessage
69 && ((HtmlMessage)component).getForceSpan())
70 {
71 String forAttr = getFor(component);
72 HtmlMessage htmlMessage = (HtmlMessage) component;
73
74 UIComponent forComponent = component.findComponent(forAttr);
75
76 if (forComponent != null)
77 {
78 String forCompclientId = forComponent.getClientId(facesContext);
79
80 ResponseWriter writer = facesContext.getResponseWriter();
81 writer.startElement(HTML.SPAN_ELEM, null);
82 writer.writeAttribute(HTML.ID_ATTR, forCompclientId + "_msgFor", null);
83 if(htmlMessage.getStyleClass()!=null)
84 writer.writeAttribute(HTML.CLASS_ATTR,htmlMessage.getStyleClass(),null);
85 if(htmlMessage.getStyle()!=null)
86 writer.writeAttribute(HTML.STYLE_ATTR,htmlMessage.getStyle(),null);
87 writer.endElement(HTML.SPAN_ELEM);
88 }
89 }
90 }
91
92 protected String getSummary(FacesContext facesContext,
93 UIComponent message,
94 FacesMessage facesMessage,
95 String msgClientId)
96 {
97 String msgSummary = facesMessage.getSummary();
98 if (msgSummary == null) return null;
99
100 String inputLabel = null;
101 if (msgClientId != null) inputLabel = findInputLabel(facesContext, msgClientId);
102 if (inputLabel == null) inputLabel = "";
103
104 if(((message instanceof HtmlMessages && ((HtmlMessages) message).isReplaceIdWithLabel()) ||
105 (message instanceof HtmlMessage && ((HtmlMessage) message).isReplaceIdWithLabel()))&&
106 inputLabel.length()!=0)
107 msgSummary = msgSummary.replaceAll(findInputId(facesContext, msgClientId),inputLabel);
108
109
110 String summaryFormat;
111 if (message instanceof HtmlMessage)
112 {
113 summaryFormat = ((HtmlMessage)message).getSummaryFormat();
114 }
115 else
116 {
117 summaryFormat = (String)message.getAttributes().get("summaryFormat");
118 }
119
120 if (summaryFormat == null) return msgSummary;
121
122 MessageFormat format = new MessageFormat(summaryFormat, facesContext.getViewRoot().getLocale());
123
124 return format.format(new Object[] {msgSummary, inputLabel});
125 }
126
127 protected String getDetail(FacesContext facesContext,
128 UIComponent message,
129 FacesMessage facesMessage,
130 String msgClientId)
131 {
132 String msgDetail = facesMessage.getDetail();
133 if (msgDetail == null) return null;
134
135 String inputLabel = null;
136 if (msgClientId != null) inputLabel = findInputLabel(facesContext, msgClientId);
137 if (inputLabel == null) inputLabel = "";
138
139 if(((message instanceof HtmlMessages && ((HtmlMessages) message).isReplaceIdWithLabel()) ||
140 (message instanceof HtmlMessage && ((HtmlMessage) message).isReplaceIdWithLabel()))&&
141 inputLabel.length()!=0)
142 msgDetail = msgDetail.replaceAll(findInputId(facesContext, msgClientId),inputLabel);
143
144 String detailFormat;
145 if (message instanceof HtmlMessage)
146 {
147 detailFormat = ((HtmlMessage)message).getDetailFormat();
148 }
149 else
150 {
151 detailFormat = (String)message.getAttributes().get("detailFormat");
152 }
153
154 if (detailFormat == null) return msgDetail;
155
156 MessageFormat format = new MessageFormat(detailFormat, facesContext.getViewRoot().getLocale());
157 return format.format(new Object[] {msgDetail, inputLabel});
158 }
159
160
161 public static String findInputLabel(FacesContext facesContext, String inputClientId)
162 {
163 Map<String, MessageLabelInfo> outputLabelMap = getOutputLabelMap(facesContext);
164 MessageLabelInfo info = ((MessageLabelInfo)outputLabelMap.get(inputClientId));
165
166 if(info == null)
167 {
168 UIComponent comp = facesContext.getViewRoot().findComponent(inputClientId);
169
170 UIComponent parent=comp;
171
172 while(parent != null && !((parent=parent.getParent())instanceof UIColumn));
173
174 if(parent != null)
175 {
176 UIColumn column = (UIColumn) parent;
177
178 if(column.getHeader()!=null)
179 {
180 UIComponent header = column.getHeader();
181
182 return getComponentText(facesContext, header);
183 }
184 }
185 }
186
187 return info==null?null:info.getText(facesContext);
188 }
189
190 public static String findInputId(FacesContext facesContext, String inputClientId)
191 {
192 Map<String, MessageLabelInfo> outputLabelMap = getOutputLabelMap(facesContext);
193 MessageLabelInfo info = ((MessageLabelInfo)outputLabelMap.get(inputClientId));
194
195 UIComponent comp = null;
196
197 if(info == null)
198 {
199 comp = facesContext.getViewRoot().findComponent(inputClientId);
200 }
201 else
202 {
203 comp = info.getForComponent();
204 }
205
206 if ( comp == null ) return null;
207
208 if ( inputClientId.contains(NamingContainer.SEPARATOR_CHAR + "") ) {
209
210
211 return comp.getClientId(facesContext);
212 }
213 else {
214
215
216 return comp.getId();
217 }
218 }
219
220
221
222
223
224
225 @SuppressWarnings("unchecked")
226 private static Map<String, MessageLabelInfo> getOutputLabelMap(FacesContext facesContext)
227 {
228 Map<String, MessageLabelInfo> map = (Map<String, MessageLabelInfo>) facesContext.getExternalContext().getRequestMap().get(OUTPUT_LABEL_MAP);
229 if (map == null)
230 {
231 map = new HashMap<String, MessageLabelInfo>();
232 createOutputLabelMap(facesContext, facesContext.getViewRoot(), map);
233 facesContext.getExternalContext().getRequestMap().put(OUTPUT_LABEL_MAP, map);
234 }
235 return map;
236 }
237
238 private static void createOutputLabelMap(FacesContext facesContext,
239 UIComponent root,
240 Map<String, MessageLabelInfo> map)
241 {
242 for (Iterator<UIComponent> it = root.getFacetsAndChildren(); it.hasNext(); )
243 {
244 UIComponent child = (UIComponent)it.next();
245 if (child instanceof HtmlOutputLabel)
246 {
247 String forAttr = ((HtmlOutputLabel)child).getFor();
248 if (forAttr != null)
249 {
250 UIComponent input = child.findComponent(forAttr);
251 if (input == null)
252 {
253 log.warn("Unable to find component '" + forAttr + "' (calling findComponent on component '" + child.getClientId(facesContext) + "')");
254 }
255 else
256 {
257 if (child.getValueExpression("value") == null)
258 {
259
260
261 map.put(input.getClientId(facesContext),
262 new MessageDefferedLabelInfo(
263 input, child));
264 }
265 else
266 {
267 map.put(input.getClientId(facesContext),
268 new MessageTextLabelInfo(
269 input,getComponentText(facesContext, (HtmlOutputLabel)child)));
270 }
271 }
272 }
273 }
274 else
275 {
276 createOutputLabelMap(facesContext, child, map);
277 }
278 }
279 }
280
281 private static String getComponentText(FacesContext facesContext, UIComponent component)
282 {
283 String text = null;
284
285 if(component instanceof ValueHolder)
286 {
287 text= RendererUtils.getStringValue(facesContext, component);
288 }
289
290 if (text == null || text.length() < 1)
291 {
292 StringBuffer buf = new StringBuffer();
293 List<UIComponent> li = component.getChildren();
294
295 for (int i = 0; i < li.size(); i++)
296 {
297 UIComponent child = (UIComponent) li.get(i);
298
299 if(child instanceof HtmlOutputText)
300 {
301 String str = RendererUtils.getStringValue(facesContext, child);
302
303 if(str!=null)
304 buf.append(str);
305 }
306 }
307
308 text = buf.toString();
309 }
310 return text;
311 }
312
313 public static interface MessageLabelInfo
314 {
315 public UIComponent getForComponent();
316 public String getText(FacesContext context);
317 }
318
319 public final static class MessageTextLabelInfo implements MessageLabelInfo
320 {
321 private final UIComponent _forComponent;
322 private final String _text;
323
324 public MessageTextLabelInfo(final UIComponent forComponent, final String text)
325 {
326 _forComponent = forComponent;
327 _text = text;
328 }
329
330 public UIComponent getForComponent()
331 {
332 return _forComponent;
333 }
334
335 public String getText(FacesContext context)
336 {
337 return _text;
338 }
339 }
340
341 public final static class MessageDefferedLabelInfo implements MessageLabelInfo
342 {
343 private final UIComponent _forComponent;
344 private final UIComponent _labelComponent;
345 private String _text;
346
347 public MessageDefferedLabelInfo(final UIComponent forComponent, final UIComponent labelComponent)
348 {
349 _forComponent = forComponent;
350 _labelComponent = labelComponent;
351 }
352
353
354 public UIComponent getForComponent()
355 {
356 return _forComponent;
357 }
358
359 public String getText(FacesContext context)
360 {
361 if (_text == null)
362 {
363 _text = getComponentText(context, (HtmlOutputLabel)_labelComponent);
364 }
365 return _text;
366 }
367 }
368 }