View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.shared.renderkit.html;
20  
21  import java.io.IOException;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Map;
25  import java.util.NoSuchElementException;
26  import java.util.logging.Level;
27  import java.util.logging.Logger;
28  
29  import javax.faces.application.FacesMessage;
30  import javax.faces.component.UIComponent;
31  import javax.faces.component.UIMessages;
32  import javax.faces.component.UIViewRoot;
33  import javax.faces.component.behavior.ClientBehavior;
34  import javax.faces.component.behavior.ClientBehaviorHolder;
35  import javax.faces.component.html.HtmlMessages;
36  import javax.faces.context.FacesContext;
37  import javax.faces.context.ResponseWriter;
38  
39  import org.apache.myfaces.shared.renderkit.JSFAttr;
40  import org.apache.myfaces.shared.renderkit.RendererUtils;
41  import org.apache.myfaces.shared.util.NullIterator;
42  
43  /**
44   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
45   * @version $Revision: 1298418 $ $Date: 2012-03-08 14:54:27 +0000 (Thu, 08 Mar 2012) $
46   */
47  public abstract class HtmlMessagesRendererBase
48          extends HtmlMessageRendererBase
49  {
50      //private static final Log log = LogFactory.getLog(HtmlMessagesRendererBase.class);
51      private static final Logger log = Logger.getLogger(HtmlMessagesRendererBase.class.getName());
52  
53      protected static final String LAYOUT_LIST  = "list";
54      protected static final String LAYOUT_TABLE = "table";
55  
56      protected void renderMessages(FacesContext facesContext,
57                                    UIComponent messages)
58              throws IOException
59      {
60          renderMessages(facesContext, messages, false);
61      }
62  
63      protected void renderMessages(FacesContext facesContext,
64              UIComponent messages, boolean alwaysRenderSpan)
65              throws IOException
66      {
67          renderMessages(facesContext, messages, alwaysRenderSpan, false);
68      }
69  
70      protected void renderMessages(FacesContext facesContext,
71                                    UIComponent messages, boolean alwaysRenderSpan, 
72                                    boolean renderDivWhenNoMessagesAndIdSet)
73              throws IOException
74      {
75          // check the for attribute
76          String forAttr = getFor(messages);
77          UIComponent forComponent = null;
78          if(forAttr != null && !"".equals(forAttr))
79          {
80              forComponent = messages.findComponent(forAttr);
81              if (forComponent == null)
82              {
83                  log.severe("Could not render Messages. Unable to find component '"
84                          + forAttr + "' (calling findComponent on component '" 
85                          + messages.getClientId(facesContext)
86                          + "'). If the provided id was correct, wrap the message and its "
87                          + "component into an h:panelGroup or h:panelGrid.");
88                  return;
89              }
90          }
91          
92          MessagesIterator messagesIterator = new MessagesIterator(facesContext,
93                  isGlobalOnly(messages), isRedisplay(messages), forComponent);
94  
95          if (messagesIterator.hasNext())
96          {
97              String layout = getLayout(messages);
98              if (layout == null)
99              {
100                 if (log.isLoggable(Level.FINE))
101                 {
102                     log.fine("No messages layout given, using default layout 'list'.");
103                 }
104                 renderList(facesContext, messages, messagesIterator);
105             }
106             else if (layout.equalsIgnoreCase(LAYOUT_TABLE))
107             {
108                 renderTable(facesContext, messages, messagesIterator);
109             }
110             else
111             {
112                 if (log.isLoggable(Level.WARNING) && !layout.equalsIgnoreCase(LAYOUT_LIST))
113                 {
114                     log.warning("Unsupported messages layout '" + layout + "' - using default layout 'list'.");
115                 }
116                 renderList(facesContext, messages, messagesIterator);
117             }
118         }
119         else
120         {
121             if (renderDivWhenNoMessagesAndIdSet && messages.getId() != null && 
122                     !messages.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
123             {
124                 ResponseWriter writer = facesContext.getResponseWriter();
125                 writer.startElement(HTML.DIV_ELEM, messages);
126                 writer.writeAttribute(HTML.ID_ATTR, messages.getClientId(facesContext), null);
127                 writer.endElement(HTML.DIV_ELEM);
128             }
129         }
130         
131         if (!renderDivWhenNoMessagesAndIdSet && alwaysRenderSpan)
132         {
133             Object forceSpan = messages.getAttributes().get("forceSpan");
134             boolean b = forceSpan instanceof Boolean ? (Boolean) forceSpan : Boolean.valueOf(forceSpan.toString());
135             if (b)
136             {
137                 ResponseWriter writer = facesContext.getResponseWriter();
138     
139                 writer.startElement(HTML.SPAN_ELEM, null);
140                 writer.writeAttribute(HTML.ID_ATTR,messages.getClientId(facesContext),null);
141                 if(messages.getAttributes().get(JSFAttr.STYLE_CLASS_ATTR)!=null)
142                 {
143                     writer.writeAttribute(
144                             HTML.CLASS_ATTR, messages.getAttributes().get(JSFAttr.STYLE_CLASS_ATTR), null);
145                 }
146                 if(messages.getAttributes().get(JSFAttr.STYLE_ATTR)!=null)
147                 {
148                     writer.writeAttribute(HTML.STYLE_ATTR, messages.getAttributes().get(JSFAttr.STYLE_ATTR), null);
149                 }
150                 writer.endElement(HTML.SPAN_ELEM);
151             }
152         }
153     }
154 
155 
156     private void renderList(FacesContext facesContext,
157                             UIComponent messages,
158                             MessagesIterator messagesIterator)
159             throws IOException
160     {
161         ResponseWriter writer = facesContext.getResponseWriter();
162 
163         writer.startElement(HTML.UL_ELEM, messages);
164 
165         Map<String, List<ClientBehavior>> behaviors = null;
166         if (messages instanceof ClientBehaviorHolder)
167         {
168             behaviors = ((ClientBehaviorHolder) messages).getClientBehaviors();
169         }
170         
171         if (behaviors != null && !behaviors.isEmpty())
172         {
173             writer.writeAttribute(HTML.ID_ATTR, messages.getClientId(facesContext), null);
174         }
175         else
176         {
177             HtmlRendererUtils.writeIdIfNecessary(writer, messages, facesContext);
178         }         
179         HtmlRendererUtils.renderHTMLAttributes(writer, messages, HTML.UNIVERSAL_ATTRIBUTES_WITHOUT_STYLE);
180 
181         HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_ATTR, HTML.STYLE_ATTR, getComponentStyle(messages));
182         HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_CLASS_ATTR, HTML.STYLE_CLASS_ATTR, 
183                 getComponentStyleClass(messages));
184 
185         while(messagesIterator.hasNext())
186         {
187             writer.startElement(org.apache.myfaces.shared.renderkit.html.HTML.LI_ELEM, messages);
188             
189             FacesMessage facesMessage = (FacesMessage)messagesIterator.next();
190             // determine style and style class
191             String[] styleAndClass = getStyleAndStyleClass(messages, facesMessage.getSeverity());
192             String style = styleAndClass[0];
193             String styleClass = styleAndClass[1];
194             
195             HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_ATTR, HTML.STYLE_ATTR, style);
196             HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_CLASS_ATTR, HTML.STYLE_CLASS_ATTR, styleClass);
197             
198             renderSingleFacesMessage(facesContext,
199                     messages,
200                     facesMessage,
201                     messagesIterator.getClientId(),false,false,false);
202             writer.endElement(HTML.LI_ELEM);
203         }
204 
205         writer.endElement(HTML.UL_ELEM);
206     }
207 
208 
209     private void renderTable(FacesContext facesContext,
210                              UIComponent messages,
211                              MessagesIterator messagesIterator)
212             throws IOException
213     {
214         ResponseWriter writer = facesContext.getResponseWriter();
215 
216         writer.startElement(HTML.TABLE_ELEM, messages);
217         
218         Map<String, List<ClientBehavior>> behaviors = null;
219         if (messages instanceof ClientBehaviorHolder)
220         {
221             behaviors = ((ClientBehaviorHolder) messages).getClientBehaviors();
222         }
223         
224         if (behaviors != null && !behaviors.isEmpty())
225         {
226             writer.writeAttribute(HTML.ID_ATTR, messages.getClientId(facesContext), null);
227         }
228         else
229         {
230             HtmlRendererUtils.writeIdIfNecessary(writer, messages, facesContext);
231         }         
232         HtmlRendererUtils.renderHTMLAttributes(writer, messages, HTML.UNIVERSAL_ATTRIBUTES_WITHOUT_STYLE);
233         
234         HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_ATTR, HTML.STYLE_ATTR, getComponentStyle(messages));
235         HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_CLASS_ATTR, HTML.STYLE_CLASS_ATTR, 
236                 getComponentStyleClass(messages));
237         
238         while(messagesIterator.hasNext())
239         {
240             writer.startElement(HTML.TR_ELEM, messages);
241             writer.startElement(HTML.TD_ELEM, messages);
242             
243             FacesMessage facesMessage = (FacesMessage)messagesIterator.next();
244             // determine style and style class
245             String[] styleAndClass = getStyleAndStyleClass(messages, facesMessage.getSeverity());
246             String style = styleAndClass[0];
247             String styleClass = styleAndClass[1];
248             
249             HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_ATTR, HTML.STYLE_ATTR, style);
250             HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_CLASS_ATTR, HTML.STYLE_CLASS_ATTR, styleClass);
251             
252             renderSingleFacesMessage(facesContext,
253                     messages,
254                     facesMessage,
255                     messagesIterator.getClientId(),false,false,false);
256 
257             writer.endElement(HTML.TD_ELEM);
258             writer.endElement(HTML.TR_ELEM);
259         }
260 
261         writer.endElement(HTML.TABLE_ELEM);
262     }
263 
264 
265     public static String[] getStyleAndStyleClass(UIComponent messages,
266                                              FacesMessage.Severity severity)
267     {
268         String style = null;
269         String styleClass = null;
270         if (messages instanceof HtmlMessages)
271         {
272             if (severity == FacesMessage.SEVERITY_INFO)
273             {
274                 style = ((HtmlMessages)messages).getInfoStyle();
275                 styleClass = ((HtmlMessages)messages).getInfoClass();
276             }
277             else if (severity == FacesMessage.SEVERITY_WARN)
278             {
279                 style = ((HtmlMessages)messages).getWarnStyle();
280                 styleClass = ((HtmlMessages)messages).getWarnClass();
281             }
282             else if (severity == FacesMessage.SEVERITY_ERROR)
283             {
284                 style = ((HtmlMessages)messages).getErrorStyle();
285                 styleClass = ((HtmlMessages)messages).getErrorClass();
286             }
287             else if (severity == FacesMessage.SEVERITY_FATAL)
288             {
289                 style = ((HtmlMessages)messages).getFatalStyle();
290                 styleClass = ((HtmlMessages)messages).getFatalClass();
291             }
292 
293             //if (style == null)
294             //{
295             //    style = ((HtmlMessages)messages).getStyle();
296             //}
297 
298             //if (styleClass == null)
299             //{
300             //    styleClass = ((HtmlMessages)messages).getStyleClass();
301             //}
302         }
303         else
304         {
305             Map attr = messages.getAttributes();
306             if (severity == FacesMessage.SEVERITY_INFO)
307             {
308                 style = (String)attr.get(org.apache.myfaces.shared.renderkit.JSFAttr.INFO_STYLE_ATTR);
309                 styleClass = (String)attr.get(org.apache.myfaces.shared.renderkit.JSFAttr.INFO_CLASS_ATTR);
310             }
311             else if (severity == FacesMessage.SEVERITY_WARN)
312             {
313                 style = (String)attr.get(org.apache.myfaces.shared.renderkit.JSFAttr.WARN_STYLE_ATTR);
314                 styleClass = (String)attr.get(org.apache.myfaces.shared.renderkit.JSFAttr.WARN_CLASS_ATTR);
315             }
316             else if (severity == FacesMessage.SEVERITY_ERROR)
317             {
318                 style = (String)attr.get(org.apache.myfaces.shared.renderkit.JSFAttr.ERROR_STYLE_ATTR);
319                 styleClass = (String)attr.get(org.apache.myfaces.shared.renderkit.JSFAttr.ERROR_CLASS_ATTR);
320             }
321             else if (severity == FacesMessage.SEVERITY_FATAL)
322             {
323                 style = (String)attr.get(org.apache.myfaces.shared.renderkit.JSFAttr.FATAL_STYLE_ATTR);
324                 styleClass = (String)attr.get(JSFAttr.FATAL_CLASS_ATTR);
325             }
326 
327             //if (style == null)
328             //{
329             //    style = (String)attr.get(org.apache.myfaces.shared.renderkit.JSFAttr.STYLE_ATTR);
330             //}
331 
332             //if (styleClass == null)
333             //{
334             //    styleClass = (String)attr.get(org.apache.myfaces.shared.renderkit.JSFAttr.STYLE_CLASS_ATTR);
335             //}
336         }
337 
338         return new String[] {style, styleClass};
339     }
340     
341     protected String getComponentStyleClass(UIComponent messages)
342     {
343         String styleClass = null;
344         if (messages instanceof HtmlMessages)
345         {
346             styleClass = ((HtmlMessages)messages).getStyleClass();
347         }
348         else
349         {
350             Map attr = messages.getAttributes();
351             styleClass = (String)attr.get(org.apache.myfaces.shared.renderkit.JSFAttr.STYLE_CLASS_ATTR);
352         }
353         return styleClass;
354     }
355     
356     protected String getComponentStyle(UIComponent messages)
357     {
358         String style = null;
359         if (messages instanceof HtmlMessages)
360         {
361             style = ((HtmlMessages)messages).getStyle();
362         }
363         else
364         {
365             Map attr = messages.getAttributes();
366             style = (String)attr.get(org.apache.myfaces.shared.renderkit.JSFAttr.STYLE_ATTR);
367         }
368         return style;
369     }
370 
371     protected String getTitle(UIComponent component)
372     {
373         if (component instanceof HtmlMessages)
374         {
375             return ((HtmlMessages)component).getTitle();
376         }
377         else
378         {
379             return (String)component.getAttributes().get(org.apache.myfaces.shared.renderkit.JSFAttr.TITLE_ATTR);
380         }
381     }
382 
383     protected boolean isTooltip(UIComponent component)
384     {
385         if (component instanceof HtmlMessages)
386         {
387             return ((HtmlMessages)component).isTooltip();
388         }
389         else
390         {
391             return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(component, 
392                     org.apache.myfaces.shared.renderkit.JSFAttr.TOOLTIP_ATTR, false);
393         }
394     }
395 
396     protected boolean isShowSummary(UIComponent component)
397     {
398         if (component instanceof UIMessages)
399         {
400             return ((UIMessages)component).isShowSummary();
401         }
402         else
403         {
404             return RendererUtils.getBooleanAttribute(component, JSFAttr.SHOW_SUMMARY_ATTR, false);
405         }
406     }
407 
408     protected boolean isShowDetail(UIComponent component)
409     {
410         if (component instanceof UIMessages)
411         {
412             return ((UIMessages)component).isShowDetail();
413         }
414         else
415         {
416             return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(
417                     component, JSFAttr.SHOW_DETAIL_ATTR, false);
418         }
419     }
420 
421     protected boolean isGlobalOnly(UIComponent component)
422     {
423         if (component instanceof UIMessages)
424         {
425             return ((UIMessages)component).isGlobalOnly();
426         }
427         else
428         {
429             return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(
430                     component, JSFAttr.GLOBAL_ONLY_ATTR, false);
431         }
432     }
433 
434     protected String getLayout(UIComponent component)
435     {
436         if (component instanceof HtmlMessages)
437         {
438             return ((HtmlMessages)component).getLayout();
439         }
440         else
441         {
442             return (String)component.getAttributes().get(JSFAttr.LAYOUT_ATTR);
443         }
444     }
445     
446     protected String getFor(UIComponent component)
447     {
448         if (component instanceof UIMessages)
449         {
450             return ((UIMessages) component).getFor();
451         }
452  
453         return (String) component.getAttributes().get(JSFAttr.FOR_ATTR); 
454     }
455 
456     protected boolean isRedisplay(UIComponent component)
457     {
458         if (component instanceof UIMessages)
459         {
460             return ((UIMessages) component).isRedisplay();
461         }
462 
463         return org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanAttribute(
464                 component, org.apache.myfaces.shared.renderkit.JSFAttr.REDISPLAY_ATTR, true);
465         
466     }
467 
468     private static class MessagesIterator implements Iterator
469     {
470         private FacesContext _facesContext;
471         private Iterator _globalMessagesIterator;
472         private Iterator _clientIdsWithMessagesIterator;
473         private Iterator _componentMessagesIterator = null;
474         private String _clientId = null;
475         private boolean _redisplay;
476         private Object _next;
477 
478         public MessagesIterator(FacesContext facesContext, boolean globalOnly, boolean redisplay,
479                 UIComponent forComponent)
480         {
481             _facesContext = facesContext;
482             // The for attribute is mutually exclusive with globalOnly and take precedence if used.
483             if(forComponent != null)
484             {
485                 _clientId = forComponent.getClientId(facesContext);
486                 _componentMessagesIterator = facesContext.getMessages(_clientId);
487                 _globalMessagesIterator = org.apache.myfaces.shared.util.NullIterator.instance();
488                 _clientIdsWithMessagesIterator = org.apache.myfaces.shared.util.NullIterator.instance();
489             }
490             else 
491             {
492                 if (globalOnly)
493                 {
494                     _globalMessagesIterator = facesContext.getMessages(null);
495                     _clientIdsWithMessagesIterator = NullIterator.instance();
496                 }
497                 else
498                 {
499                     _globalMessagesIterator = org.apache.myfaces.shared.util.NullIterator.instance();
500                     _clientIdsWithMessagesIterator = facesContext.getClientIdsWithMessages();
501                 }
502                 _componentMessagesIterator = null;
503                 _clientId = null;
504             }
505             
506             _redisplay = redisplay;
507             _next = null;
508         }
509 
510         public boolean hasNext()
511         {
512             if(_next != null)
513             {
514                 return true;
515             }
516             if(_globalMessagesIterator.hasNext()) 
517             {
518                 do
519                 {
520                     _next = _globalMessagesIterator.next();
521                     if(_redisplay || !((FacesMessage)_next).isRendered())
522                     {
523                         return true;
524                     }
525                 }
526                 while(_globalMessagesIterator.hasNext());
527             }
528             if(_componentMessagesIterator != null && _componentMessagesIterator.hasNext()) 
529             {
530                 do
531                 {
532                     _next = _componentMessagesIterator.next();
533                     if(_redisplay || !((FacesMessage)_next).isRendered())
534                     {
535                         return true;
536                     }
537                 }
538                 while(_componentMessagesIterator.hasNext());
539             }
540             if(_clientIdsWithMessagesIterator.hasNext()) 
541             {
542                 do
543                 {
544                     _clientId = (String) _clientIdsWithMessagesIterator.next();
545                     _componentMessagesIterator = _facesContext.getMessages(_clientId);
546                     while(_componentMessagesIterator.hasNext()) 
547                     {
548                         _next = _componentMessagesIterator.next();
549                         if(_redisplay || !((FacesMessage)_next).isRendered())
550                         {
551                             return true;
552                         }
553                     }
554                 }
555                 while(_clientIdsWithMessagesIterator.hasNext());
556                 
557             }
558             _next = null;
559             return false;
560         }
561 
562         public Object next()
563         {
564             if(this.hasNext()) 
565             {
566                 Object ret = _next;
567                 _next = null;
568                 return ret;
569             }
570             throw new NoSuchElementException();
571         }
572 
573         public void remove()
574         {
575             throw new UnsupportedOperationException(this.getClass().getName() + " UnsupportedOperationException");
576         }
577 
578         public String getClientId()
579         {
580             return _clientId;
581         }
582     }
583 
584 }