/** * Copyright 2014-2017 Riccardo Massera (TheCoder4.Eu) and Stephan Rauh (http://www.beyondjava.net). * * This file is part of BootsFaces. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.bootsfaces.component.message; import java.io.IOException; import java.util.List; import javax.faces.application.FacesMessage; import javax.faces.application.FacesMessage.Severity; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.render.FacesRenderer; import net.bootsfaces.expressions.ExpressionResolver; import net.bootsfaces.render.CoreRenderer; import net.bootsfaces.render.Responsive; /** This class generates the HTML code of <b:message />. */ @FacesRenderer(componentFamily = "net.bootsfaces.component", rendererType = "net.bootsfaces.component.message.Message") public class MessageRenderer extends CoreRenderer { private static boolean escapeWarningHasBeenShown = false; /** * This methods generates the HTML code of the current b:message. * * @param context * the FacesContext. * @param component * the current b:message. * @throws IOException * thrown if something goes wrong when writing the HTML code. */ @Override public void encodeBegin(FacesContext context, UIComponent component) throws IOException { if (!component.isRendered()) { return; } Message message = (Message) component; String forValue = message.getFor(); if (null == forValue || forValue.length() == 0) forValue = "@previous"; forValue = ExpressionResolver.getComponentIDs(context, message, forValue); List<FacesMessage> messageList = context.getMessageList(forValue); ResponseWriter rw = context.getResponseWriter(); int numberOfDivs = 0; boolean idHasBeenRendered = false; String responsiveStyleClass = Responsive.getResponsiveStyleClass(message, false).trim(); String clientId = message.getClientId(context); if (!responsiveStyleClass.isEmpty()) { numberOfDivs++; rw.startElement("div", component); writeAttribute(rw, "class", responsiveStyleClass); writeAttribute(rw, "id", clientId); idHasBeenRendered = true; } if (!messageList.isEmpty()) { numberOfDivs++; rw.startElement("div", message); if (!idHasBeenRendered) { writeAttribute(rw, "id", clientId); } if (null != message.getDir()) { rw.writeAttribute("dir", message.getDir(), "dir"); } String styleClass = message.getStyleClass(); if (null != styleClass && styleClass.length() > 0) styleClass = styleClass + " "; else styleClass = ""; String severityClass = findHighestSeverityClass(messageList, message); // alert-danger styleClass += "alert " + severityClass + " bf-message"; writeAttribute(rw, "class", styleClass.trim()); String style = message.getStyle(); if (null == style) style = ""; else if (!style.endsWith(";")) style += ";"; String severityStyle = findHighestSeverityStyle(messageList, message); if (null == severityStyle) severityStyle = ""; else if (!severityStyle.endsWith(";")) severityStyle += ";"; writeAttribute(rw, "style", style + severityStyle); writeAttribute(rw, "role", "alert"); boolean onlyMostSevere = message.isOnlyMostSevere(); FacesMessage mostSevere = null; if (onlyMostSevere) { for (FacesMessage msg : messageList) { if (null == mostSevere) { mostSevere = msg; } else if (msg.getSeverity().getOrdinal() > mostSevere.getSeverity().getOrdinal()) { mostSevere = msg; } } } boolean firstMessage = true; for (FacesMessage msg : messageList) { if (onlyMostSevere && msg != mostSevere) { continue; } if (!firstMessage) { if (message.isLineBreak()) { rw.append(message.getLineBreakTag()); } } firstMessage = false; if (message.isShowIcon()) { rw.startElement("span", component); writeAttribute(rw, "class", findHighestSeverityIcon(messageList, message) + " bf-message-icon"); writeAttribute(rw, "aria-hidden", "true"); rw.endElement("span"); } if (message.isShowSummary() && msg.getSummary() != null && !msg.getSummary().equals(msg.getDetail())) { rw.startElement("span", component); writeAttribute(rw, "class", "bf-message-summary"); if (message.isEscape()) { rw.writeText(msg.getSummary(), null); } else { warnOnFirstUse(); rw.write(msg.getSummary()); } rw.endElement("span"); } if (message.isShowDetail() && msg.getDetail() != null) { rw.startElement("span", component); writeAttribute(rw, "class", "bf-message-detail"); if (message.isEscape()) { rw.writeText(msg.getDetail(), null); } else { warnOnFirstUse(); rw.write(msg.getDetail()); } rw.endElement("span"); } msg.rendered(); } } for (int i = numberOfDivs; i > 0; i--) { rw.endElement("div"); } } public static void warnOnFirstUse() { if (!escapeWarningHasBeenShown) { System.out.println( "One of your application's component deactivates HTML and JavaScript escaping. This is discouraged because it might be a security issue if not used carefully. Use at own risk."); escapeWarningHasBeenShown = true; } } private String findHighestSeverityClass(List<FacesMessage> messageList, Message message) { boolean hasFatal = false; boolean hasError = false; boolean hasWarning = false; for (FacesMessage msg : messageList) { Severity severity = msg.getSeverity(); if (msg.isRendered() && !message.isRedisplay()) { continue; } if (severity.equals(FacesMessage.SEVERITY_WARN)) hasWarning = true; else if (severity.equals(FacesMessage.SEVERITY_ERROR)) hasError = true; else if (severity.equals(FacesMessage.SEVERITY_FATAL)) hasFatal = true; } if (hasFatal) return ("alert-danger " + (message.getFatalClass() == null ? "" : message.getFatalClass())); if (hasError) return ("alert-danger " + (message.getErrorClass() == null ? "" : message.getErrorClass())); if (hasWarning) return ("alert-warning " + (message.getWarnClass() == null ? "" : message.getWarnClass())); return ("alert-info " + (message.getInfoClass() == null ? "" : message.getInfoClass())); } private String findHighestSeverityStyle(List<FacesMessage> messageList, Message message) { boolean hasFatal = false; boolean hasError = false; boolean hasWarning = false; for (FacesMessage msg : messageList) { Severity severity = msg.getSeverity(); if (msg.isRendered() && !message.isRedisplay()) { continue; } if (severity.equals(FacesMessage.SEVERITY_WARN)) hasWarning = true; else if (severity.equals(FacesMessage.SEVERITY_ERROR)) hasError = true; else if (severity.equals(FacesMessage.SEVERITY_FATAL)) hasFatal = true; } if (hasFatal) return message.getFatalStyle(); if (hasError) return message.getErrorStyle(); if (hasWarning) return message.getWarnStyle(); return message.getInfoStyle(); } private String findHighestSeverityIcon(List<FacesMessage> messageList, Message message) { boolean hasFatal = false; boolean hasError = false; boolean hasWarning = false; for (FacesMessage msg : messageList) { Severity severity = msg.getSeverity(); if (msg.isRendered() && !message.isRedisplay()) { continue; } if (severity.equals(FacesMessage.SEVERITY_WARN)) hasWarning = true; else if (severity.equals(FacesMessage.SEVERITY_ERROR)) hasError = true; else if (severity.equals(FacesMessage.SEVERITY_FATAL)) hasFatal = true; } if (hasFatal) return "bficon bficon-error-circle-o";// "fa fa-exclamation-circle"; if (hasError) return "bficon bficon-error-circle-o";// "fa fa-exclamation-circle"; if (hasWarning) return "bficon bficon-warning-triangle-o";// "fa // fa-exclamation-triangle"; return "bficon bficon-info";// "fa fa-info-circle"; } }