001 package com.mockrunner.tag; 002 003 import java.io.IOException; 004 import java.util.HashMap; 005 import java.util.List; 006 import java.util.Map; 007 008 import javax.servlet.jsp.JspContext; 009 import javax.servlet.jsp.JspException; 010 import javax.servlet.jsp.tagext.JspFragment; 011 import javax.servlet.jsp.tagext.JspTag; 012 import javax.servlet.jsp.tagext.SimpleTag; 013 import javax.servlet.jsp.tagext.SimpleTagSupport; 014 import javax.servlet.jsp.tagext.TagSupport; 015 016 import com.mockrunner.base.NestedApplicationException; 017 import com.mockrunner.mock.web.MockJspFragment; 018 019 /** 020 * Implementation of {@link NestedTag} wrapping tags of 021 * type <code>SimpleTag</code>. <code>NestedSimpleTag</code> instances 022 * are created with the help of {@link TagTestModule#createNestedTag}. 023 * You do not need to create them on your own in the tests. 024 */ 025 public class NestedSimpleTag extends SimpleTagSupport implements NestedTag 026 { 027 private SimpleTag tag; 028 private JspContext jspContext; 029 private JspFragment jspBody; 030 private Map attributes; 031 032 /** 033 * Constructor for a tag with an empty attribute map. 034 * @param tag the tag 035 * @param jspContext the corresponding <code>JspContext</code> 036 */ 037 public NestedSimpleTag(SimpleTag tag, JspContext jspContext) 038 { 039 this(tag, jspContext, new HashMap()); 040 } 041 042 /** 043 * Constructor for a tag with the specified attribute map. 044 * @param tag the tag 045 * @param jspContext the corresponding <code>JspContext</code> 046 * @param attributes the attribute map 047 */ 048 public NestedSimpleTag(SimpleTag tag, JspContext jspContext, Map attributes) 049 { 050 this.tag = tag; 051 this.jspContext = jspContext; 052 jspBody = new MockJspFragment(jspContext, tag); 053 tag.setJspContext(jspContext); 054 tag.setJspBody(jspBody); 055 this.attributes = attributes; 056 } 057 058 /** 059 * Constructor for a tag with an empty attribute map. 060 * @param tag the tag 061 * @param jspContext the corresponding <code>JspContext</code> 062 */ 063 public NestedSimpleTag(SimpleTagSupport tag, JspContext jspContext) 064 { 065 this(tag, jspContext, new HashMap()); 066 } 067 068 /** 069 * Constructor for a tag with the specified attribute map. 070 * @param tag the tag 071 * @param jspContext the corresponding <code>JspContext</code> 072 * @param attributes the attribute map 073 */ 074 public NestedSimpleTag(SimpleTagSupport tag, JspContext jspContext, Map attributes) 075 { 076 this((SimpleTag)tag, jspContext, attributes); 077 } 078 079 /** 080 * Implementation of {@link NestedTag#setDoRelease}. 081 * Does nothing in this case. 082 */ 083 public void setDoRelease(boolean doRelease) 084 { 085 086 } 087 088 /** 089 * Implementation of {@link NestedTag#setDoReleaseRecursive}. 090 * Does nothing in this case. 091 */ 092 public void setDoReleaseRecursive(boolean doRelease) 093 { 094 095 } 096 097 /** 098 * @inheritDoc 099 */ 100 public void populateAttributes() 101 { 102 TagUtil.populateTag(tag, attributes); 103 } 104 105 /** 106 * Implementation of {@link NestedTag#doLifecycle} for simple 107 * tags. Returns <code>-1</code> in this case, because 108 * <code>doTag()</code> does not have a return value. 109 */ 110 public int doLifecycle() throws JspException 111 { 112 try 113 { 114 populateAttributes(); 115 tag.doTag(); 116 } 117 catch(IOException exc) 118 { 119 throw new NestedApplicationException(exc); 120 } 121 return -1; 122 } 123 124 /** 125 * Implementation of {@link NestedTag#getTag}. 126 * Should not be called and throws a <code>RuntimeException</code>, 127 * because a simple tag is not an instance of <code>TagSupport</code>. 128 */ 129 public TagSupport getTag() 130 { 131 throw new RuntimeException("getTag() method cannot be called for simple tags."); 132 } 133 134 /** 135 * @inheritDoc 136 */ 137 public JspTag getWrappedTag() 138 { 139 return tag; 140 } 141 142 /** 143 * @inheritDoc 144 */ 145 public void removeChilds() 146 { 147 if(null != jspBody && jspBody instanceof MockJspFragment) 148 { 149 ((MockJspFragment)jspBody).removeChilds(); 150 } 151 } 152 153 /** 154 * @inheritDoc 155 */ 156 public List getChilds() 157 { 158 if(null != jspBody && jspBody instanceof MockJspFragment) 159 { 160 return ((MockJspFragment)jspBody).getChilds(); 161 } 162 return null; 163 } 164 165 /** 166 * @inheritDoc 167 */ 168 public Object getChild(int index) 169 { 170 if(null != jspBody && jspBody instanceof MockJspFragment) 171 { 172 return ((MockJspFragment)jspBody).getChild(index); 173 } 174 return null; 175 } 176 177 /** 178 * @inheritDoc 179 */ 180 public void addTextChild(String text) 181 { 182 if(null != jspBody && jspBody instanceof MockJspFragment) 183 { 184 ((MockJspFragment)jspBody).addTextChild(text); 185 } 186 } 187 188 /** 189 * @inheritDoc 190 */ 191 public void addDynamicChild(DynamicChild child) 192 { 193 if(null != jspBody && jspBody instanceof MockJspFragment) 194 { 195 ((MockJspFragment)jspBody).addDynamicChild(child); 196 } 197 } 198 199 /** 200 * @inheritDoc 201 */ 202 public NestedTag addTagChild(Class tag) 203 { 204 if(null != jspBody && jspBody instanceof MockJspFragment) 205 { 206 return ((MockJspFragment)jspBody).addTagChild(tag); 207 } 208 return null; 209 } 210 211 /** 212 * @inheritDoc 213 */ 214 public NestedTag addTagChild(Class tag, Map attributeMap) 215 { 216 if(null != jspBody && jspBody instanceof MockJspFragment) 217 { 218 return ((MockJspFragment)jspBody).addTagChild(tag, attributeMap); 219 } 220 return null; 221 } 222 223 /** 224 * @inheritDoc 225 */ 226 public NestedTag addTagChild(TagSupport tag) 227 { 228 return addTagChild(tag, new HashMap()); 229 } 230 231 /** 232 * @inheritDoc 233 */ 234 public NestedTag addTagChild(TagSupport tag, Map attributeMap) 235 { 236 return addTagChild((JspTag)tag, attributeMap); 237 } 238 239 /** 240 * @inheritDoc 241 */ 242 public NestedTag addTagChild(JspTag tag) 243 { 244 if(null != jspBody && jspBody instanceof MockJspFragment) 245 { 246 return ((MockJspFragment)jspBody).addTagChild(tag); 247 } 248 return null; 249 } 250 251 /** 252 * @inheritDoc 253 */ 254 public NestedTag addTagChild(JspTag tag, Map attributeMap) 255 { 256 if(null != jspBody && jspBody instanceof MockJspFragment) 257 { 258 return ((MockJspFragment)jspBody).addTagChild(tag, attributeMap); 259 } 260 return null; 261 } 262 263 /** 264 * Delegates to wrapped tag. 265 */ 266 public void doTag() throws JspException, IOException 267 { 268 tag.doTag(); 269 } 270 271 /** 272 * Returns the body fragment. 273 * @return the body fragment 274 */ 275 public JspFragment getJspBody() 276 { 277 return jspBody; 278 } 279 280 /** 281 * Returns the <code>JspContext</code>. 282 * @return the <code>JspContext</code> 283 */ 284 public JspContext getJspContext() 285 { 286 return jspContext; 287 } 288 289 /** 290 * Delegates to wrapped tag. 291 */ 292 public JspTag getParent() 293 { 294 return tag.getParent(); 295 } 296 297 /** 298 * Delegates to wrapped tag. 299 */ 300 public void setJspBody(JspFragment jspBody) 301 { 302 this.jspBody = jspBody; 303 tag.setJspBody(jspBody); 304 } 305 306 /** 307 * Delegates to wrapped tag. Also calls <code>setJspContext</code> 308 * on the body fragment, if the body fragment is an instance of 309 * {@link com.mockrunner.mock.web.MockJspFragment} 310 */ 311 public void setJspContext(JspContext jspContext) 312 { 313 this.jspContext = jspContext; 314 tag.setJspContext(jspContext); 315 if(null != jspBody && jspBody instanceof MockJspFragment) 316 { 317 ((MockJspFragment)jspBody).setJspContext(jspContext); 318 } 319 } 320 321 /** 322 * Delegates to wrapped tag. 323 */ 324 public void setParent(JspTag parent) 325 { 326 tag.setParent(parent); 327 } 328 329 /** 330 * Dumps the content of this and the nested tags. 331 */ 332 public String toString() 333 { 334 return TagUtil.dumpTag(this, new StringBuffer(), 0); 335 } 336 }