View Javadoc
1   /*
2    * Copyright 2008 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.sys.document.web.renderers;
17  
18  import java.io.IOException;
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import javax.servlet.jsp.JspException;
23  import javax.servlet.jsp.JspWriter;
24  import javax.servlet.jsp.PageContext;
25  import javax.servlet.jsp.tagext.Tag;
26  
27  import org.apache.struts.Globals;
28  import org.apache.struts.taglib.html.ErrorsTag;
29  import org.kuali.ole.sys.OLEKeyConstants;
30  import org.kuali.ole.sys.context.SpringContext;
31  import org.kuali.rice.core.api.config.property.ConfigurationService;
32  import org.kuali.rice.krad.util.KRADConstants;
33  
34  /**
35   * Renders any errors associated with an accounting line group
36   */
37  public class GroupErrorsRenderer implements Renderer {
38      private List<String> errorsRendered;
39      private List<String> warningsRendered;
40      private List<String> infoRendered;
41      private String errorKeyMatch;
42      private int colSpan = -1;
43      private ErrorsTag errorTag = new ErrorsTag();
44  
45      /**
46       * Cleans up the errorPropertyList, the sectionTitle, the errorsRendered (so you'd better read that first),
47       * and the ErrorTag used to display the errors
48       * @see org.kuali.ole.sys.document.web.renderers.Renderer#clear()
49       */
50      public void clear() {
51          errorsRendered = null;
52          warningsRendered = null;
53          infoRendered = null;
54          errorKeyMatch = null;
55          colSpan = -1;
56          
57          cleanUpErrorTag();
58      }
59      
60      /**
61       * Cleans up the ErrorTag
62       */
63      protected void cleanUpErrorTag() {
64          errorTag.setPageContext(null);
65          errorTag.setParent(null);
66          errorTag.setProperty(null);
67      }
68  
69      /**
70       * Renders the errors, warnings, and messages for this page
71       * @see org.kuali.ole.sys.document.web.renderers.Renderer#render(javax.servlet.jsp.PageContext, javax.servlet.jsp.tagext.Tag)
72       */
73      public void render(PageContext pageContext, Tag parentTag) throws JspException {
74          renderMessages(pageContext, parentTag, OLEKeyConstants.MESSAGE_ACCOUNTING_LINES_ERROR_SECTION_TITLE, getErrorPropertyList(pageContext), "errormark.gif", "error", getErrorsRendered(), Globals.ERROR_KEY);
75          renderMessages(pageContext, parentTag, OLEKeyConstants.MESSAGE_ACCOUNTING_LINES_WARNING_SECTION_TITLE, getWarningPropertyList(pageContext), "warning.png", "warning", getWarningsRendered(), "WarningActionMessages");
76          renderMessages(pageContext, parentTag, OLEKeyConstants.MESSAGE_ACCOUNTING_LINES_INFORMATION_SECTION_TITLE, getInfoPropertyList(pageContext), "info.png", "info", getInfoRendered(), "InfoActionMessages");
77      }
78      
79      /**
80       * Renders a group of messages
81       * @param pageContext the page context to render to
82       * @param parentTag the name of the parent tag requesting this rendering
83       * @param titleConstant the Key Constant to text for the title
84       * @param propertyList the list of properties to display
85       * @param sectionMarkGraphicName the file name of the mark graphic to display
86       * @param sectionGraphicAlt the wording to be used in the "alt" section of the mark graphic
87       * @throws JspException thrown if rendering cannot be successfully completed
88       */
89      protected void renderMessages(PageContext pageContext, Tag parentTag, String titleConstant, List propertyList, String sectionMarkGraphicName, String sectionGraphicAlt, List<String> keysRendered, String requestScopeBeanNameContainingMessages ) throws JspException {
90          JspWriter out = pageContext.getOut();
91          
92          try {
93              final List<String> matchingKeys = getMatchingKeys(propertyList, getKeysToMatch());
94              if (matchingKeys.size() > 0) {
95                  out.write(buildTableRowAndCellOpening());
96                  out.write(buildSectionTitle(titleConstant, sectionMarkGraphicName, sectionGraphicAlt));
97              }
98              
99              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 }