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