1 package org.apache.velocity.tools.struts; 2 3 /* 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 22 import java.util.ArrayList; 23 import java.util.Iterator; 24 import java.util.List; 25 import org.apache.struts.action.ActionMessage; 26 import org.apache.struts.action.ActionMessages; 27 import org.apache.struts.util.MessageResources; 28 import org.apache.velocity.tools.Scope; 29 import org.apache.velocity.tools.config.DefaultKey; 30 import org.apache.velocity.tools.config.ValidScope; 31 32 /** 33 * <p> 34 * This tool deals with Struts action messages. A few important aspects about action 35 * messages are:</p> 36 * <ul> 37 * <li>Action message strings are looked up in the message resources. Support 38 * for internationalized messages is provided.</li> 39 * <li>Action messages can have up to five replacement parameters.</li> 40 * <li>Actions have an attribute <code>property</code> that describes the category of 41 * message. This allows the view designer to place action messages precisely where they are 42 * wanted. Several methods of this tool provide a parameter 43 * <code>property</code> that allows to select a specific category of messages to operate 44 * on. Without the <code>property</code> parameter, methods operate on all action messages.</li> 45 * </ul> 46 * 47 * <p>See the Struts User's Guide, section 48 * <a href="http://struts.apache.org/1.3.8/userGuide/building_view.html">Building View Components</a> 49 * for more information on this topic.</p> 50 * 51 * <p><pre> 52 * Template example(s): 53 * #if( $messages.exist() ) 54 * #foreach( $e in $messages.all ) 55 * $e <br> 56 * #end 57 * #end 58 * 59 * Toolbox configuration: 60 * <tools> 61 * <toolbox scope="request"> 62 * <tool class="org.apache.velocity.tools.struts.ActionMessagesTool"/> 63 * </toolbox> 64 * </tools> 65 * </pre></p> 66 * 67 * <p>This tool should only be used in the request scope.</p> 68 * 69 * @author <a href="mailto:sidler@teamup.com">Gabe Sidler</a> 70 * @author Nathan Bubna 71 * @since VelocityTools 1.1 72 * @version $Id: ActionMessagesTool.java 601976 2007-12-07 03:50:51Z nbubna $ 73 */ 74 @DefaultKey("messages") 75 @ValidScope(Scope.REQUEST) 76 public class ActionMessagesTool extends MessageResourcesTool 77 { 78 /** A reference to the queued action messages. */ 79 protected ActionMessages actionMsgs; 80 81 82 protected ActionMessages getActionMessages() 83 { 84 if (this.actionMsgs == null) 85 { 86 this.actionMsgs = StrutsUtils.getMessages(this.request); 87 } 88 return this.actionMsgs; 89 } 90 91 92 /*************************** Public Methods ***********************/ 93 94 /** 95 * <p>Returns <code>true</code> if there are action messages queued, 96 * otherwise <code>false</code>.</p> 97 */ 98 public boolean exist() 99 { 100 if (getActionMessages() == null) 101 { 102 return false; 103 } 104 return !actionMsgs.isEmpty(); 105 } 106 107 108 /** 109 * <p>Returns true if there are action messages queued for the specified 110 * category of messages, otherwise <code>false</code>.</p> 111 * 112 * @param property the category of messages to check for 113 */ 114 public boolean exist(String property) 115 { 116 if (getActionMessages() == null) 117 { 118 return false; 119 } 120 return (actionMsgs.size(property) > 0); 121 } 122 123 124 /** 125 * Returns the number of action messages queued. 126 */ 127 public int getSize() 128 { 129 if (getActionMessages() == null) 130 { 131 return 0; 132 } 133 return actionMsgs.size(); 134 } 135 136 137 /** 138 * Returns the number of action messages queued for a particular property. 139 * 140 * @param property the category of messages to check for 141 */ 142 public int getSize(String property) 143 { 144 if (getActionMessages() == null) 145 { 146 return 0; 147 } 148 return actionMsgs.size(property); 149 } 150 151 152 /** 153 * <p> 154 * This a convenience method and the equivalent of 155 * <code>$messages.get($messages.globalName)</code>. 156 * </p> 157 * <p> 158 * Returns the set of localized action messages as an 159 * list of strings for all action messages queued of the 160 * global category or <code>null</code> if no messages 161 * are queued for the specified category. If the message 162 * resources don't contain an action message for a 163 * particular message key, the key itself is used. 164 * </p> 165 * 166 * @return a list of all messages stored under the "global" property 167 */ 168 public List getGlobal() 169 { 170 return get(getGlobalName()); 171 } 172 173 174 /** 175 * Returns the set of localized action messages as an 176 * <code>java.util.List</code> of strings for all actionMsgs 177 * queued or <code>null</code> if no messages are queued. 178 * If the message resources don't contain a message for a 179 * particular key, the key itself is used as the message. 180 */ 181 public List getAll() 182 { 183 return get(null); 184 } 185 186 187 /** 188 * Returns a List of all queued action messages using 189 * the specified message resource bundle. 190 * 191 * @param bundle the message resource bundle to use 192 * @see #getAll() 193 */ 194 public List getAll(String bundle) 195 { 196 return get(null, bundle); 197 } 198 199 200 /** 201 * Returns the set of localized action messages as an 202 * <code>java.util.List</code> of strings for all actionMsgs 203 * queued of the specified category or <code>null</code> 204 * if no messages are queued for the specified category. If the 205 * message resources don't contain a message for a particular 206 * key, the key itself is used as the message. 207 * 208 * @param property the category of actionMsgs to operate on 209 */ 210 public List get(String property) 211 { 212 return get(property, null); 213 } 214 215 216 /** 217 * Returns the set of localized action messages as a 218 * <code>java.util.List</code> of strings for all action messages 219 * queued of the specified category or <code>null</code> 220 * if no action messages are queued for the specified category. If the 221 * message resources don't contain an action message for a particular 222 * action key, the key itself is used as action message. 223 * 224 * @param property the category of actionMsgs to operate on 225 * @param bundle the message resource bundle to use 226 */ 227 public List get(String property, String bundle) 228 { 229 ActionMessages actionMsgs = getActionMessages(); 230 if (actionMsgs == null || actionMsgs.isEmpty()) 231 { 232 return null; 233 } 234 235 Iterator msgs; 236 if (property == null) 237 { 238 msgs = actionMsgs.get(); 239 } 240 else 241 { 242 msgs = actionMsgs.get(property); 243 } 244 245 if (!msgs.hasNext()) 246 { 247 return null; 248 } 249 250 MessageResources res = getResources(bundle); 251 List list = new ArrayList(); 252 253 while (msgs.hasNext()) 254 { 255 ActionMessage msg = (ActionMessage)msgs.next(); 256 257 String message = null; 258 if (res != null && msg.isResource()) 259 { 260 message = 261 res.getMessage(getLocale(), msg.getKey(), msg.getValues()); 262 263 if (message == null) 264 { 265 LOG.warn("ActionMessagesTool : Message for key " + msg.getKey() + 266 " could not be found in message resources."); 267 } 268 } 269 270 if (message == null) 271 { 272 // if the resource bundle wasn't found or 273 // ActionMessage.isResource() returned false or the key 274 // wasn't found in the resources, then use the key 275 message = msg.getKey(); 276 } 277 list.add(message); 278 } 279 return list; 280 } 281 282 283 /** 284 * Returns the default "GLOBAL" category name that can be used for 285 * messages that are not associated with a particular property. 286 */ 287 public String getGlobalName() 288 { 289 return ActionMessages.GLOBAL_MESSAGE; 290 } 291 292 }