1 /** 2 * Copyright 2005-2012 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.rice.krad.uif.element; 17 18 import org.apache.commons.lang.StringUtils; 19 import org.kuali.rice.krad.datadictionary.parse.BeanTag; 20 import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute; 21 import org.kuali.rice.krad.datadictionary.validator.ValidationTrace; 22 import org.kuali.rice.krad.datadictionary.validator.Validator; 23 import org.kuali.rice.krad.uif.component.Component; 24 import org.kuali.rice.krad.uif.util.MessageStructureUtils; 25 import org.kuali.rice.krad.uif.view.View; 26 import org.kuali.rice.krad.util.KRADConstants; 27 28 import java.util.List; 29 30 /** 31 * Encapsulates a text message to be displayed 32 * 33 * <p> 34 * The <code>Message</code> is used to display static text in the user 35 * interface 36 * </p> 37 * 38 * @author Kuali Rice Team (rice.collab@kuali.org) 39 */ 40 @BeanTag(name = "message") 41 public class Message extends ContentElementBase { 42 private static final long serialVersionUID = 4090058533452450395L; 43 44 private String messageText; 45 private boolean generateSpan; 46 47 private List<Component> inlineComponents; 48 private List<Component> messageComponentStructure; 49 50 public Message() { 51 super(); 52 53 generateSpan = true; 54 } 55 56 /** 57 * Message perfom apply model parses message text for rich text functionality if the messageText contains 58 * [ or ] special characters 59 * 60 * @see Component#performApplyModel(org.kuali.rice.krad.uif.view.View, Object, org.kuali.rice.krad.uif.component.Component) 61 */ 62 @Override 63 public void performApplyModel(View view, Object model, Component parent) { 64 super.performApplyModel(view, model, parent); 65 66 //if messageText contains the special characters [] then parse and fill in the messageComponentStructure 67 //but if messageComponentStructure has already been set it overrides messageText by default 68 if (messageText != null && messageText.contains(KRADConstants.MessageParsing.LEFT_TOKEN) && 69 messageText.contains(KRADConstants.MessageParsing.RIGHT_TOKEN) && 70 (messageComponentStructure == null || messageComponentStructure.isEmpty())) { 71 72 messageComponentStructure = MessageStructureUtils.parseMessage(this.getId(), this.getMessageText(), 73 this.getInlineComponents(), view, true); 74 75 if (messageComponentStructure != null) { 76 for (Component component : messageComponentStructure) { 77 view.getViewHelperService().performComponentInitialization(view, model, component); 78 } 79 } 80 } 81 82 } 83 84 /** 85 * @see Component#performFinalize(org.kuali.rice.krad.uif.view.View, Object, org.kuali.rice.krad.uif.component.Component) 86 */ 87 @Override 88 public void performFinalize(View view, Object model, Component parent) { 89 super.performFinalize(view, model, parent); 90 //Message needs to be aware of its own parent because it now contains content that can have validation 91 this.addDataAttribute("parent", parent.getId()); 92 } 93 94 /** 95 * @see org.kuali.rice.krad.uif.component.ComponentBase#getComponentsForLifecycle() 96 */ 97 @Override 98 public List<Component> getComponentsForLifecycle() { 99 List<Component> components = super.getComponentsForLifecycle(); 100 101 if (messageComponentStructure != null) { 102 for (Component component : messageComponentStructure) { 103 components.add(component); 104 } 105 } 106 107 return components; 108 } 109 110 /** 111 * Override to render only if the message text has been given or there is a conditional expression on the 112 * message text 113 * 114 * @see org.kuali.rice.krad.uif.component.ComponentBase#isRender() 115 */ 116 @Override 117 public boolean isRender() { 118 boolean render = super.isRender(); 119 120 if (render) { 121 render = getPropertyExpressions().containsKey("messageText") || (StringUtils.isNotBlank(messageText) 122 && !StringUtils.equals(messageText, " ")); 123 } 124 125 return render; 126 } 127 128 /** 129 * Text that makes up the message that will be displayed. 130 * 131 * <p>If special characters [] are detected the message inserts special content at that location. 132 * The types of features supported are (note that <> are not part of the content below, 133 * they specify placeholders): 134 * <ul> 135 * <li>[id=<component id>] - insert component with id specified at that location in the message</li> 136 * <li>[n] - insert component at index n from the inlineComponent list</li> 137 * <li>[<html tag>][/<html tag>] - insert html content directly into the message content at that 138 * location, 139 * without the need to escape the <> characters in xml</li> 140 * <li>[color=<html color code/name>][/color] - wrap content in color tags to make text that color 141 * in the message</li> 142 * <li>[css=<css classes>][/css] - apply css classes specified to the wrapped content - same as wrapping 143 * the content in span with class property set</li> 144 * </ul> 145 * If the [] characters are needed in message text, they need to be declared with an escape character: \\[ \\] 146 * </p> 147 * 148 * @return String message text 149 */ 150 @BeanTagAttribute(name = "messageText") 151 public String getMessageText() { 152 return this.messageText; 153 } 154 155 /** 156 * Setter for the message text 157 * 158 * @param messageText 159 */ 160 public void setMessageText(String messageText) { 161 this.messageText = messageText; 162 } 163 164 /** 165 * If true, generate the span around this message (default). When false, skip span generation for this 166 * message - this has the additional effect the css classes/style classes will be lost for this message. 167 * 168 * @return true if generating a wrapping span, false otherwise 169 */ 170 @BeanTagAttribute(name = "generateSpan") 171 public boolean isGenerateSpan() { 172 return generateSpan; 173 } 174 175 /** 176 * Sets the generate span flag 177 * 178 * @param generateSpan 179 */ 180 public void setGenerateSpan(boolean generateSpan) { 181 this.generateSpan = generateSpan; 182 } 183 184 /** 185 * The message component structure is a list of components which represent the components that make up a message 186 * when using rich message functionality. 187 * 188 * <p>The structure represents the parsed messageText when not set. Normally this structure is setup by the Message 189 * class and <b>SHOULD NOT BE SET</b> in xml, unless full control over the structure is needed. </p> 190 * 191 * @return list of components which represent the message structure 192 */ 193 public List<Component> getMessageComponentStructure() { 194 return messageComponentStructure; 195 } 196 197 /** 198 * Set the message component structure. This will override/ignore messageText when set. Normally 199 * this <b>SHOULD NOT BE SET</b> by the xml configuration. 200 * 201 * @param messageComponentStructure list of components which represent the message structure 202 */ 203 public void setMessageComponentStructure(List<Component> messageComponentStructure) { 204 this.messageComponentStructure = messageComponentStructure; 205 } 206 207 /** 208 * The inlineComponents are a list of components in order by index. 209 * 210 * <p>inlineComponents is only used when the message is using rich message functionality. A message 211 * with [0] will reference component at index 0 of this list and insert it at that place in the message, 212 * and likewise [1] will reference item 1, etc. If the index referenced is out of bounds (or list doesnt exist), 213 * an error will be thrown during message parse.</p> 214 * 215 * @return the inlineComponents to be filled in at indexes referenced by [n] in the message 216 */ 217 @BeanTagAttribute(name = "inlineComponents", type = BeanTagAttribute.AttributeType.LISTBEAN) 218 public List<Component> getInlineComponents() { 219 return inlineComponents; 220 } 221 222 /** 223 * Set the inlineComponents to be filled in at indexes referenced by [n] in the message 224 * 225 * @param inlineComponents the inlineComponents to be filled in at indexes referenced by [n] in the message 226 */ 227 public void setInlineComponents(List<Component> inlineComponents) { 228 this.inlineComponents = inlineComponents; 229 } 230 231 /** 232 * @see org.kuali.rice.krad.uif.component.Component#completeValidation 233 */ 234 @Override 235 public void completeValidation(ValidationTrace tracer) { 236 tracer.addBean(this); 237 238 // Checks that text is set 239 if (getMessageText() == null) { 240 if (Validator.checkExpressions(this, "messageText")) { 241 String currentValues[] = {"messageText =" + getMessageText()}; 242 tracer.createWarning("MessageText should be set", currentValues); 243 } 244 } 245 246 super.completeValidation(tracer.getCopy()); 247 } 248 }