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 }