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  
20  package org.apache.myfaces.tobago.internal.renderkit.renderer;
21  
22  import org.apache.myfaces.tobago.context.Markup;
23  import org.apache.myfaces.tobago.internal.component.AbstractUIMessages;
24  import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
25  import org.apache.myfaces.tobago.renderkit.RendererBase;
26  import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
27  import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
28  import org.apache.myfaces.tobago.renderkit.html.Arias;
29  import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
30  import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
31  import org.apache.myfaces.tobago.renderkit.html.HtmlButtonTypes;
32  import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
33  import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
34  import org.apache.myfaces.tobago.renderkit.html.HtmlRoleValues;
35  import org.apache.myfaces.tobago.util.ComponentUtils;
36  import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  import javax.faces.application.FacesMessage;
41  import javax.faces.context.FacesContext;
42  import java.io.IOException;
43  import java.lang.invoke.MethodHandles;
44  import java.util.List;
45  
46  public class MessagesRenderer<T extends AbstractUIMessages> extends RendererBase<T> {
47  
48    private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
49  
50    @Override
51    public void encodeEndInternal(final FacesContext facesContext, final T component) throws IOException {
52  
53      if (component.isConfirmation()) {
54        LOG.warn("'confirmation' is currently not supported for tc:messages!");
55      }
56  
57      final TobagoResponseWriter writer = getResponseWriter(facesContext);
58  
59      if (LOG.isDebugEnabled()) {
60        LOG.debug("facesContext is " + facesContext.getClass().getName());
61      }
62      final List<AbstractUIMessages.Item> messageList = component.createMessageList(facesContext);
63  
64      // with id
65        /*String focusId = null;
66        Iterator clientIds;
67        if (ComponentUtils.getBooleanAttribute(messages, Attributes.globalOnly)) {
68          ArrayList<String> list = new ArrayList<String>(1);
69          list.add(null);
70          clientIds = list.iterator();
71        } else {
72          clientIds = facesContext.getClientIdsWithMessages();
73        }*/
74  
75      writer.startElement(HtmlElements.TOBAGO_MESSAGES);
76      writer.writeIdAttribute(component.getClientId(facesContext));
77      final Markup markup = component.getMarkup();
78      writer.writeClassAttribute(
79          TobagoClass.MESSAGES,
80          TobagoClass.MESSAGES.createMarkup(markup),
81          component.getCustomClass());
82  
83      FacesMessage.Severity lastSeverity = null;
84      boolean first = true;
85  
86      for (final AbstractUIMessages.Item item : messageList) {
87        final FacesMessage message = item.getFacesMessage();
88        final FacesMessage.Severity severity = message.getSeverity();
89  
90        if (!first && lastSeverity != severity) {
91          writer.endElement(HtmlElements.DIV);
92        }
93  
94        if (first || lastSeverity != severity) {
95          writer.startElement(HtmlElements.DIV);
96          writer.writeClassAttribute(
97              BootstrapClass.ALERT, BootstrapClass.ALERT_DISMISSIBLE, BootstrapClass.alert(severity));
98          HtmlRendererUtils.writeDataAttributes(facesContext, writer, component);
99          writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.ALERT.toString(), false);
100 
101         writer.startElement(HtmlElements.BUTTON);
102         writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
103         writer.writeClassAttribute(BootstrapClass.BTN_CLOSE);
104         writer.writeAttribute(DataAttributes.DISMISS, "alert", false);
105         writer.writeAttribute(Arias.ACTIVEDESCENDANT, "Close", false); // todo: i18n
106         writer.endElement(HtmlElements.BUTTON);
107       }
108 
109       encodeMessage(writer, component, message, item.getClientId());
110 
111       lastSeverity = severity;
112       first = false;
113     }
114     if (messageList.size() > 0) {
115       writer.endElement(HtmlElements.DIV); // close open tag from for-loop
116     }
117     if (component.getFor() == null) {
118       final String id = component.getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "messagesExists";
119       writer.startElement(HtmlElements.INPUT);
120       writer.writeAttribute(HtmlAttributes.VALUE, Boolean.TRUE.toString(), false);
121       writer.writeAttribute(HtmlAttributes.ID, id, false);
122       writer.writeAttribute(HtmlAttributes.NAME, id, false);
123       writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
124       writer.endElement(HtmlElements.INPUT);
125     }
126     writer.endElement(HtmlElements.TOBAGO_MESSAGES);
127 /*
128       while(clientIds.hasNext()) {
129         String clientId = (String) clientIds.next();
130         encodeMessagesForId(facesContext, writer, clientId, showSummary, showDetail);
131         if (focusId == null) {
132           focusId = clientId;
133         }
134       }
135   todo: don't forget: focus
136       if (focusId != null) {
137         ComponentUtils.findPage(facesContext, messages).setFocusId(focusId);
138       }
139 */
140   }
141 
142   private void encodeMessage(
143       final TobagoResponseWriter writer, final AbstractUIMessages messages, final FacesMessage message,
144       final String clientId)
145       throws IOException {
146 
147     final String summary = message.getSummary();
148     final String detail = message.getDetail();
149     final boolean showSummary = summary != null && messages.isShowSummary() && summary.length() > 0;
150     final boolean showDetails = detail != null && messages.isShowDetail() && detail.length() > 0;
151     writer.startElement(HtmlElements.LABEL);
152     if (clientId != null) {
153       writer.writeAttribute(HtmlAttributes.FOR, clientId, false);
154     }
155     writer.writeAttribute(HtmlAttributes.TITLE, detail, true);
156 
157     if (showSummary && showDetails && !summary.equals(detail)) {
158       writer.startElement(HtmlElements.STRONG);
159       writer.writeText(summary);
160       writer.endElement(HtmlElements.STRONG);
161       writer.writeText(detail);
162     } else if (showSummary) {
163       writer.writeText(summary);
164     } else if (showDetails) {
165       writer.writeText(detail);
166     } else {
167       writer.writeText(message.getSeverity().toString());
168     }
169     writer.endElement(HtmlElements.LABEL);
170 
171     message.rendered();
172   }
173 }