/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.sys.document.web.renderers; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.tagext.Tag; import org.apache.struts.Globals; import org.apache.struts.taglib.html.ErrorsTag; import org.kuali.kfs.sys.KFSKeyConstants; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.rice.core.api.config.property.ConfigurationService; import org.kuali.rice.krad.util.KRADConstants; /** * Renders any errors associated with an accounting line group */ public class GroupErrorsRenderer implements Renderer { private List<String> errorsRendered; private List<String> warningsRendered; private List<String> infoRendered; private String errorKeyMatch; private int colSpan = -1; private ErrorsTag errorTag = new ErrorsTag(); /** * Cleans up the errorPropertyList, the sectionTitle, the errorsRendered (so you'd better read that first), * and the ErrorTag used to display the errors * @see org.kuali.kfs.sys.document.web.renderers.Renderer#clear() */ public void clear() { errorsRendered = null; warningsRendered = null; infoRendered = null; errorKeyMatch = null; colSpan = -1; cleanUpErrorTag(); } /** * Cleans up the ErrorTag */ protected void cleanUpErrorTag() { errorTag.setPageContext(null); errorTag.setParent(null); errorTag.setProperty(null); } /** * Renders the errors, warnings, and messages for this page * @see org.kuali.kfs.sys.document.web.renderers.Renderer#render(javax.servlet.jsp.PageContext, javax.servlet.jsp.tagext.Tag) */ public void render(PageContext pageContext, Tag parentTag) throws JspException { renderMessages(pageContext, parentTag, KFSKeyConstants.MESSAGE_ACCOUNTING_LINES_ERROR_SECTION_TITLE, getErrorPropertyList(pageContext), "errormark.gif", "error", getErrorsRendered(), Globals.ERROR_KEY); renderMessages(pageContext, parentTag, KFSKeyConstants.MESSAGE_ACCOUNTING_LINES_WARNING_SECTION_TITLE, getWarningPropertyList(pageContext), "warning.png", "warning", getWarningsRendered(), "WarningActionMessages"); renderMessages(pageContext, parentTag, KFSKeyConstants.MESSAGE_ACCOUNTING_LINES_INFORMATION_SECTION_TITLE, getInfoPropertyList(pageContext), "info.png", "info", getInfoRendered(), "InfoActionMessages"); } /** * Renders a group of messages * @param pageContext the page context to render to * @param parentTag the name of the parent tag requesting this rendering * @param titleConstant the Key Constant to text for the title * @param propertyList the list of properties to display * @param sectionMarkGraphicName the file name of the mark graphic to display * @param sectionGraphicAlt the wording to be used in the "alt" section of the mark graphic * @throws JspException thrown if rendering cannot be successfully completed */ protected void renderMessages(PageContext pageContext, Tag parentTag, String titleConstant, List propertyList, String sectionMarkGraphicName, String sectionGraphicAlt, List<String> keysRendered, String requestScopeBeanNameContainingMessages ) throws JspException { JspWriter out = pageContext.getOut(); try { final List<String> matchingKeys = getMatchingKeys(propertyList, getKeysToMatch()); if (matchingKeys.size() > 0) { out.write(buildTableRowAndCellOpening()); out.write(buildSectionTitle(titleConstant, sectionMarkGraphicName, sectionGraphicAlt)); } for (String matchingKey : matchingKeys) { out.write(buildKeyComment(matchingKey, sectionGraphicAlt)); if (!keysRendered.contains(matchingKey)) { errorTag.setPageContext(pageContext); errorTag.setParent(parentTag); errorTag.setProperty(matchingKey); errorTag.setName(requestScopeBeanNameContainingMessages); errorTag.doStartTag(); errorTag.doEndTag(); keysRendered.add(matchingKey); } } if (matchingKeys.size() > 0) { out.write(buildTableRowAndCellClosing()); } } catch (IOException ioe) { throw new JspException("Difficulty while rendering errors for group", ioe); } } /** * Builds the HTML String for a section title * @param titleConstant the Key Constant to find the text for the title * @param sectionMarkGraphicName the name of the graphic file to use * @param sectionGraphicAlt the alt for the graphic * @return the String to output as HTML for the section title */ protected String buildSectionTitle(String titleConstant, String sectionMarkGraphicName, String sectionGraphicAlt) { final ConfigurationService configurationService = SpringContext.getBean(ConfigurationService.class); final String titleMessage = configurationService.getPropertyValueAsString(titleConstant); final String riceImageUrl = configurationService.getPropertyValueAsString(KRADConstants.EXTERNALIZABLE_IMAGES_URL_KEY); StringBuilder sectionTitle = new StringBuilder(); sectionTitle.append("<img src=\"") .append(riceImageUrl) .append(sectionMarkGraphicName) .append("\" alt=\"") .append(sectionGraphicAlt) .append("\" /><strong>") .append(titleMessage) .append("</strong>"); return sectionTitle.toString(); } /** * Builds an HTML comment, useful for debugging, which dumps out the message key being displayed * @param matchingKey the key to display * @param sectionGraphicAlt the alt for this section, we'll reuse it for the comments * @return the String to output for the key comment */ protected String buildKeyComment(String matchingKey, String sectionGraphicAlt) { StringBuilder keyComment = new StringBuilder(); keyComment.append("\n<!-- ") .append(sectionGraphicAlt) .append(" key = '") .append(matchingKey) .append("' -->\n"); return keyComment.toString(); } /** * @return the HTML for the table row and cell and div to open the error display */ protected String buildTableRowAndCellOpening() { StringBuilder html = new StringBuilder(); html.append("<tr>"); html.append("<td colspan=\""); html.append(colSpan); html.append("\">"); html.append("<div class=\"left-errmsg-tab\">"); return html.toString(); } /** * @return the HTML for the table row and cell and div which closes the error display */ protected String buildTableRowAndCellClosing() { StringBuilder html = new StringBuilder(); html.append("</div>"); html.append("</td>"); html.append("</tr>"); return html.toString(); } /** * Returns a list of all error keys that should be rendered * @param keysToMatch the keys that this group will match * @return a List of all error keys this group will match */ protected List<String> getMatchingKeys(List messagePropertyList, String[] keysToMatch) { List<String> matchingKeys = new ArrayList<String>(); if (messagePropertyList != null && messagePropertyList.size() > 0) { for (Object keyAsObject : messagePropertyList) { String key = (String)keyAsObject; if (matchesGroup(key, keysToMatch)) { matchingKeys.add(key); } } } return matchingKeys; } /** * @return the list of individual keys or wildcard keys that this group will match */ protected String[] getKeysToMatch() { return errorKeyMatch.split(","); } /** * Determines if the given error key matches the keyToMatch - either because the two keys are * equal, or if the keyToMatch is a wildcard key and would wildcard match the key * @param key the error key to match * @param keyToMatch one of the error keys this group will display * @return true if the keys match, false if not */ protected boolean foundKeyMatch(String key, String keyToMatch) { return key.equals(keyToMatch) || (keyToMatch.endsWith("*") && key.startsWith(keyToMatch.replaceAll("\\*", ""))); } /** * Determines if the given key matches any error key associated with this group * @param key the error key that may or may not be displayed here * @param keysToMatch the keys that this group will match against * @return true if this group can display the given key, false otherwise */ protected boolean matchesGroup(String key, String[] keysToMatch) { for (String keyToMatch : keysToMatch) { if (foundKeyMatch(key, keyToMatch)) return true; } return false; } /** * Looks up the InfoPropertyList from the generating request * @param pageContext the pageContext which this tag is rendering to * @return the ErrorPropertyList from the request */ public List getErrorPropertyList(PageContext pageContext) { return (List)pageContext.getRequest().getAttribute("ErrorPropertyList"); } /** * Looks up the InfoPropertyList from the generating request * @param pageContext the pageContext which this tag is rendering to * @return the WarningPropertyList from the request */ protected List getWarningPropertyList(PageContext pageContext) { return (List)pageContext.getRequest().getAttribute("WarningPropertyList"); } /** * Looks up the InfoPropertyList from the generating request * @param pageContext the pageContext which this tag is rendering to * @return the InfoPropertyList from the request */ protected List getInfoPropertyList(PageContext pageContext) { return (List)pageContext.getRequest().getAttribute("InfoPropertyList"); } /** * Gets the errorsRendered attribute. * @return Returns the errorsRendered. */ public List<String> getErrorsRendered() { if (errorsRendered == null) { errorsRendered = new ArrayList<String>(); } return errorsRendered; } /** * Gets the warningsRendered attribute. * @return Returns the warningsRendered. */ public List<String> getWarningsRendered() { if (warningsRendered == null) { warningsRendered = new ArrayList<String>(); } return warningsRendered; } /** * Gets the infoRendered attribute. * @return Returns the infoRendered. */ public List<String> getInfoRendered() { if (infoRendered == null) { infoRendered = new ArrayList<String>(); } return infoRendered; } /** * Gets the errorKeyMatch attribute. * @return Returns the errorKeyMatch. */ public String getErrorKeyMatch() { return errorKeyMatch; } /** * Sets the errorKeyMatch attribute value. * @param errorKeyMatch The errorKeyMatch to set. */ public void setErrorKeyMatch(String errorKeyMatch) { this.errorKeyMatch = errorKeyMatch; } /** * Gets the colSpan attribute. * @return Returns the colSpan. */ public int getColSpan() { return colSpan; } /** * Sets the colSpan attribute value. * @param colSpan The colSpan to set. */ public void setColSpan(int colSpan) { this.colSpan = colSpan; } }