001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.kfs.sys.document.web.renderers; 017 018 import java.io.IOException; 019 import java.util.ArrayList; 020 import java.util.List; 021 022 import javax.servlet.jsp.JspException; 023 import javax.servlet.jsp.JspWriter; 024 import javax.servlet.jsp.PageContext; 025 import javax.servlet.jsp.tagext.Tag; 026 027 import org.apache.struts.taglib.html.ErrorsTag; 028 import org.kuali.kfs.sys.KFSKeyConstants; 029 import org.kuali.kfs.sys.context.SpringContext; 030 import org.kuali.rice.kns.service.KualiConfigurationService; 031 import org.kuali.rice.kns.util.KNSConstants; 032 033 /** 034 * Renders any errors associated with an accounting line group 035 */ 036 public class GroupErrorsRenderer implements Renderer { 037 private List<String> errorsRendered; 038 private List<String> warningsRendered; 039 private List<String> infoRendered; 040 private String errorKeyMatch; 041 private int colSpan = -1; 042 private ErrorsTag errorTag = new ErrorsTag(); 043 044 /** 045 * Cleans up the errorPropertyList, the sectionTitle, the errorsRendered (so you'd better read that first), 046 * and the ErrorTag used to display the errors 047 * @see org.kuali.kfs.sys.document.web.renderers.Renderer#clear() 048 */ 049 public void clear() { 050 errorsRendered = null; 051 warningsRendered = null; 052 infoRendered = null; 053 errorKeyMatch = null; 054 colSpan = -1; 055 056 cleanUpErrorTag(); 057 } 058 059 /** 060 * Cleans up the ErrorTag 061 */ 062 protected void cleanUpErrorTag() { 063 errorTag.setPageContext(null); 064 errorTag.setParent(null); 065 errorTag.setProperty(null); 066 } 067 068 /** 069 * Renders the errors, warnings, and messages for this page 070 * @see org.kuali.kfs.sys.document.web.renderers.Renderer#render(javax.servlet.jsp.PageContext, javax.servlet.jsp.tagext.Tag) 071 */ 072 public void render(PageContext pageContext, Tag parentTag) throws JspException { 073 renderMessages(pageContext, parentTag, KFSKeyConstants.MESSAGE_ACCOUNTING_LINES_ERROR_SECTION_TITLE, getErrorPropertyList(pageContext), "errormark.gif", "error", getErrorsRendered()); 074 renderMessages(pageContext, parentTag, KFSKeyConstants.MESSAGE_ACCOUNTING_LINES_WARNING_SECTION_TITLE, getWarningPropertyList(pageContext), "warning.png", "warning", getWarningsRendered()); 075 renderMessages(pageContext, parentTag, KFSKeyConstants.MESSAGE_ACCOUNTING_LINES_INFORMATION_SECTION_TITLE, getInfoPropertyList(pageContext), "info.png", "info", getInfoRendered()); 076 } 077 078 /** 079 * Renders a group of messages 080 * @param pageContext the page context to render to 081 * @param parentTag the name of the parent tag requesting this rendering 082 * @param titleConstant the Key Constant to text for the title 083 * @param propertyList the list of properties to display 084 * @param sectionMarkGraphicName the file name of the mark graphic to display 085 * @param sectionGraphicAlt the wording to be used in the "alt" section of the mark graphic 086 * @throws JspException thrown if rendering cannot be successfully completed 087 */ 088 protected void renderMessages(PageContext pageContext, Tag parentTag, String titleConstant, List propertyList, String sectionMarkGraphicName, String sectionGraphicAlt, List<String> keysRendered) throws JspException { 089 JspWriter out = pageContext.getOut(); 090 091 try { 092 final List<String> matchingKeys = getMatchingKeys(propertyList, getKeysToMatch()); 093 if (matchingKeys.size() > 0) { 094 out.write(buildTableRowAndCellOpening()); 095 out.write(buildSectionTitle(titleConstant, sectionMarkGraphicName, sectionGraphicAlt)); 096 } 097 098 for (String matchingKey : matchingKeys) { 099 out.write(buildKeyComment(matchingKey, sectionGraphicAlt)); 100 if (!keysRendered.contains(matchingKey)) { 101 errorTag.setPageContext(pageContext); 102 errorTag.setParent(parentTag); 103 errorTag.setProperty(matchingKey); 104 105 errorTag.doStartTag(); 106 errorTag.doEndTag(); 107 108 keysRendered.add(matchingKey); 109 } 110 } 111 112 if (matchingKeys.size() > 0) { 113 out.write(buildTableRowAndCellClosing()); 114 } 115 } 116 catch (IOException ioe) { 117 throw new JspException("Difficulty while rendering errors for group", ioe); 118 } 119 } 120 121 /** 122 * Builds the HTML String for a section title 123 * @param titleConstant the Key Constant to find the text for the title 124 * @param sectionMarkGraphicName the name of the graphic file to use 125 * @param sectionGraphicAlt the alt for the graphic 126 * @return the String to output as HTML for the section title 127 */ 128 protected String buildSectionTitle(String titleConstant, String sectionMarkGraphicName, String sectionGraphicAlt) { 129 final KualiConfigurationService configurationService = SpringContext.getBean(KualiConfigurationService.class); 130 final String titleMessage = configurationService.getPropertyString(titleConstant); 131 final String riceImageUrl = configurationService.getPropertyString(KNSConstants.EXTERNALIZABLE_IMAGES_URL_KEY); 132 133 StringBuilder sectionTitle = new StringBuilder(); 134 135 sectionTitle.append("<img src=\"") 136 .append(riceImageUrl) 137 .append(sectionMarkGraphicName) 138 .append("\" alt=\"") 139 .append(sectionGraphicAlt) 140 .append("\" /><strong>") 141 .append(titleMessage) 142 .append("</strong>"); 143 144 return sectionTitle.toString(); 145 } 146 147 /** 148 * Builds an HTML comment, useful for debugging, which dumps out the message key being displayed 149 * @param matchingKey the key to display 150 * @param sectionGraphicAlt the alt for this section, we'll reuse it for the comments 151 * @return the String to output for the key comment 152 */ 153 protected String buildKeyComment(String matchingKey, String sectionGraphicAlt) { 154 StringBuilder keyComment = new StringBuilder(); 155 156 keyComment.append("\n<!-- ") 157 .append(sectionGraphicAlt) 158 .append(" key = '") 159 .append(matchingKey) 160 .append("' -->\n"); 161 162 return keyComment.toString(); 163 } 164 165 /** 166 * @return the HTML for the table row and cell and div to open the error display 167 */ 168 protected String buildTableRowAndCellOpening() { 169 StringBuilder html = new StringBuilder(); 170 html.append("<tr>"); 171 html.append("<td colspan=\""); 172 html.append(colSpan); 173 html.append("\">"); 174 html.append("<div class=\"left-errmsg-tab\">"); 175 return html.toString(); 176 } 177 178 /** 179 * @return the HTML for the table row and cell and div which closes the error display 180 */ 181 protected String buildTableRowAndCellClosing() { 182 StringBuilder html = new StringBuilder(); 183 html.append("</div>"); 184 html.append("</td>"); 185 html.append("</tr>"); 186 return html.toString(); 187 } 188 189 /** 190 * Returns a list of all error keys that should be rendered 191 * @param keysToMatch the keys that this group will match 192 * @return a List of all error keys this group will match 193 */ 194 protected List<String> getMatchingKeys(List messagePropertyList, String[] keysToMatch) { 195 List<String> matchingKeys = new ArrayList<String>(); 196 197 if (messagePropertyList != null && messagePropertyList.size() > 0) { 198 for (Object keyAsObject : messagePropertyList) { 199 String key = (String)keyAsObject; 200 if (matchesGroup(key, keysToMatch)) { 201 matchingKeys.add(key); 202 } 203 } 204 } 205 206 return matchingKeys; 207 } 208 209 /** 210 * @return the list of individual keys or wildcard keys that this group will match 211 */ 212 protected String[] getKeysToMatch() { 213 return errorKeyMatch.split(","); 214 } 215 216 /** 217 * Determines if the given error key matches the keyToMatch - either because the two keys are 218 * equal, or if the keyToMatch is a wildcard key and would wildcard match the key 219 * @param key the error key to match 220 * @param keyToMatch one of the error keys this group will display 221 * @return true if the keys match, false if not 222 */ 223 protected boolean foundKeyMatch(String key, String keyToMatch) { 224 return key.equals(keyToMatch) || (keyToMatch.endsWith("*") && key.startsWith(keyToMatch.replaceAll("\\*", ""))); 225 } 226 227 /** 228 * Determines if the given key matches any error key associated with this group 229 * @param key the error key that may or may not be displayed here 230 * @param keysToMatch the keys that this group will match against 231 * @return true if this group can display the given key, false otherwise 232 */ 233 protected boolean matchesGroup(String key, String[] keysToMatch) { 234 for (String keyToMatch : keysToMatch) { 235 if (foundKeyMatch(key, keyToMatch)) return true; 236 } 237 return false; 238 } 239 240 /** 241 * Looks up the InfoPropertyList from the generating request 242 * @param pageContext the pageContext which this tag is rendering to 243 * @return the ErrorPropertyList from the request 244 */ 245 public List getErrorPropertyList(PageContext pageContext) { 246 return (List)pageContext.getRequest().getAttribute("ErrorPropertyList"); 247 } 248 249 /** 250 * Looks up the InfoPropertyList from the generating request 251 * @param pageContext the pageContext which this tag is rendering to 252 * @return the WarningPropertyList from the request 253 */ 254 protected List getWarningPropertyList(PageContext pageContext) { 255 return (List)pageContext.getRequest().getAttribute("WarningPropertyList"); 256 } 257 258 /** 259 * Looks up the InfoPropertyList from the generating request 260 * @param pageContext the pageContext which this tag is rendering to 261 * @return the InfoPropertyList from the request 262 */ 263 protected List getInfoPropertyList(PageContext pageContext) { 264 return (List)pageContext.getRequest().getAttribute("InfoPropertyList"); 265 } 266 267 /** 268 * Gets the errorsRendered attribute. 269 * @return Returns the errorsRendered. 270 */ 271 public List<String> getErrorsRendered() { 272 if (errorsRendered == null) { 273 errorsRendered = new ArrayList<String>(); 274 } 275 return errorsRendered; 276 } 277 278 /** 279 * Gets the warningsRendered attribute. 280 * @return Returns the warningsRendered. 281 */ 282 public List<String> getWarningsRendered() { 283 if (warningsRendered == null) { 284 warningsRendered = new ArrayList<String>(); 285 } 286 return warningsRendered; 287 } 288 289 /** 290 * Gets the infoRendered attribute. 291 * @return Returns the infoRendered. 292 */ 293 public List<String> getInfoRendered() { 294 if (infoRendered == null) { 295 infoRendered = new ArrayList<String>(); 296 } 297 return infoRendered; 298 } 299 300 /** 301 * Gets the errorKeyMatch attribute. 302 * @return Returns the errorKeyMatch. 303 */ 304 public String getErrorKeyMatch() { 305 return errorKeyMatch; 306 } 307 308 /** 309 * Sets the errorKeyMatch attribute value. 310 * @param errorKeyMatch The errorKeyMatch to set. 311 */ 312 public void setErrorKeyMatch(String errorKeyMatch) { 313 this.errorKeyMatch = errorKeyMatch; 314 } 315 316 /** 317 * Gets the colSpan attribute. 318 * @return Returns the colSpan. 319 */ 320 public int getColSpan() { 321 return colSpan; 322 } 323 324 /** 325 * Sets the colSpan attribute value. 326 * @param colSpan The colSpan to set. 327 */ 328 public void setColSpan(int colSpan) { 329 this.colSpan = colSpan; 330 } 331 332 }