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