001 package com.mockrunner.tag; 002 003 import java.util.ArrayList; 004 import java.util.Enumeration; 005 import java.util.HashMap; 006 import java.util.List; 007 import java.util.Map; 008 009 import javax.servlet.jsp.JspException; 010 import javax.servlet.jsp.PageContext; 011 import javax.servlet.jsp.tagext.IterationTag; 012 import javax.servlet.jsp.tagext.JspTag; 013 import javax.servlet.jsp.tagext.SimpleTag; 014 import javax.servlet.jsp.tagext.Tag; 015 import javax.servlet.jsp.tagext.TagSupport; 016 017 /** 018 * Implementation of {@link NestedTag} wrapping tags of 019 * type <code>Tag</code>. <code>NestedStandardTag</code> instances 020 * are created with the help of {@link TagTestModule#createNestedTag}. 021 * You do not need to create them on your own in the tests. 022 */ 023 public class NestedStandardTag extends TagSupport implements NestedTag 024 { 025 private Tag tag; 026 private PageContext pageContext; 027 private Map attributes; 028 private List childs; 029 private boolean doRelease; 030 031 /** 032 * Constructor for a tag with an empty attribute map. 033 * If the specified tag is not an instance of <code>TagSupport</code>, 034 * the methods that delegate to <code>TagSupport</code> specific methods 035 * throw an exception. 036 * @param tag the tag 037 * @param pageContext the corresponding <code>PageContext</code> 038 */ 039 public NestedStandardTag(Tag tag, PageContext pageContext) 040 { 041 this(tag, pageContext, new HashMap()); 042 } 043 044 /** 045 * Constructor for a tag with the specified attribute map. 046 * If the specified tag is not an instance of <code>TagSupport</code>, 047 * the methods that delegate to <code>TagSupport</code> specific methods 048 * throw an exception. 049 * @param tag the tag 050 * @param pageContext the corresponding <code>PageContext</code> 051 * @param attributes the attribute map 052 */ 053 public NestedStandardTag(Tag tag, PageContext pageContext, Map attributes) 054 { 055 this.tag = tag; 056 this.pageContext = pageContext; 057 tag.setPageContext(pageContext); 058 childs = new ArrayList(); 059 this.attributes = attributes; 060 doRelease = false; 061 } 062 063 /** 064 * Constructor for a tag with an empty attribute map. 065 * @param tag the tag 066 * @param pageContext the corresponding <code>PageContext</code> 067 */ 068 public NestedStandardTag(TagSupport tag, PageContext pageContext) 069 { 070 this(tag, pageContext, new HashMap()); 071 } 072 073 /** 074 * Constructor for a tag with the specified attribute map. 075 * @param tag the tag 076 * @param pageContext the corresponding <code>PageContext</code> 077 * @param attributes the attribute map 078 */ 079 public NestedStandardTag(TagSupport tag, PageContext pageContext, Map attributes) 080 { 081 this((Tag)tag, pageContext, attributes); 082 } 083 084 /** 085 * Implementation of {@link NestedTag#setDoRelease}. 086 */ 087 public void setDoRelease(boolean doRelease) 088 { 089 this.doRelease = doRelease; 090 } 091 092 /** 093 * Implementation of {@link NestedTag#setDoReleaseRecursive}. 094 */ 095 public void setDoReleaseRecursive(boolean doRelease) 096 { 097 this.doRelease = doRelease; 098 for(int ii = 0; ii < childs.size(); ii++) 099 { 100 Object child = childs.get(ii); 101 if(child instanceof NestedTag) 102 { 103 ((NestedTag)child).setDoReleaseRecursive(doRelease); 104 } 105 } 106 } 107 108 /** 109 * Implementation of {@link NestedTag#populateAttributes}. 110 */ 111 public void populateAttributes() 112 { 113 TagUtil.populateTag(tag, attributes, doRelease); 114 } 115 116 /** 117 * Implementation of {@link NestedTag#doLifecycle} for standard 118 * tags. 119 */ 120 public int doLifecycle() throws JspException 121 { 122 populateAttributes(); 123 int result = tag.doStartTag(); 124 if(Tag.EVAL_BODY_INCLUDE == result) 125 { 126 TagUtil.evalBody(childs, pageContext); 127 while(IterationTag.EVAL_BODY_AGAIN == doAfterBody()) 128 { 129 TagUtil.evalBody(childs, pageContext); 130 } 131 } 132 return tag.doEndTag(); 133 } 134 135 /** 136 * Implementation of {@link NestedTag#getTag}. 137 * @throws <code>RuntimeException</code>, if the wrapped tag 138 * is not an instance of <code>TagSupport</code> 139 */ 140 public TagSupport getTag() 141 { 142 checkTagSupport(); 143 return (TagSupport)tag; 144 } 145 146 /** 147 * Implementation of {@link NestedTag#getWrappedTag}. 148 */ 149 public JspTag getWrappedTag() 150 { 151 return tag; 152 } 153 154 /** 155 * Implementation of {@link NestedTag#removeChilds}. 156 */ 157 public void removeChilds() 158 { 159 childs.clear(); 160 } 161 162 /** 163 * Implementation of {@link NestedTag#getChilds}. 164 */ 165 public List getChilds() 166 { 167 return childs; 168 } 169 170 /** 171 * Implementation of {@link NestedTag#getChild}. 172 */ 173 public Object getChild(int index) 174 { 175 return childs.get(index); 176 } 177 178 /** 179 * Implementation of {@link NestedTag#addTextChild}. 180 */ 181 public void addTextChild(String text) 182 { 183 if(null == text) text = ""; 184 childs.add(text); 185 } 186 187 /** 188 * Implementation of {@link NestedTag#addDynamicChild}. 189 */ 190 public void addDynamicChild(DynamicChild child) 191 { 192 if(null == child) return; 193 childs.add(child); 194 } 195 196 /** 197 * Implementation of {@link NestedTag#addTagChild(Class)}. 198 */ 199 public NestedTag addTagChild(Class tag) 200 { 201 return addTagChild(tag, new HashMap()); 202 } 203 204 /** 205 * Implementation of {@link NestedTag#addTagChild(Class, Map)}. 206 */ 207 public NestedTag addTagChild(Class tag, Map attributeMap) 208 { 209 Object childTag = TagUtil.createNestedTagInstance(tag, this.pageContext, attributeMap); 210 return addChild(childTag); 211 } 212 213 /** 214 * Implementation of {@link NestedTag#addTagChild(TagSupport)}. 215 */ 216 public NestedTag addTagChild(TagSupport tag) 217 { 218 return addTagChild(tag, new HashMap()); 219 } 220 221 /** 222 * Implementation of {@link NestedTag#addTagChild(TagSupport, Map)}. 223 */ 224 public NestedTag addTagChild(TagSupport tag, Map attributeMap) 225 { 226 Object childTag = TagUtil.createNestedTagInstance(tag, this.pageContext, attributeMap); 227 return addChild(childTag); 228 } 229 230 /** 231 * Implementation of {@link NestedTag#addTagChild(JspTag)}. 232 */ 233 public NestedTag addTagChild(JspTag tag) 234 { 235 return addTagChild((TagSupport)tag); 236 } 237 238 /** 239 * Implementation of {@link NestedTag#addTagChild(JspTag, Map)}. 240 */ 241 public NestedTag addTagChild(JspTag tag, Map attributeMap) 242 { 243 Object childTag = TagUtil.createNestedTagInstance(tag, this.pageContext, attributeMap); 244 return addChild(childTag); 245 } 246 247 /** 248 * Delegates to wrapped tag. 249 * @throws <code>RuntimeException</code>, if the wrapped tag 250 * is not an instance of <code>IterationTag</code> 251 */ 252 public int doAfterBody() throws JspException 253 { 254 checkIterationTag(); 255 return ((IterationTag)tag).doAfterBody(); 256 } 257 258 /** 259 * Delegates to wrapped tag. 260 */ 261 public int doEndTag() throws JspException 262 { 263 return tag.doEndTag(); 264 } 265 266 /** 267 * Delegates to wrapped tag. 268 */ 269 public int doStartTag() throws JspException 270 { 271 return tag.doStartTag(); 272 } 273 274 /** 275 * Delegates to wrapped tag. 276 * @throws <code>RuntimeException</code>, if the wrapped tag 277 * is not an instance of <code>TagSupport</code> 278 */ 279 public String getId() 280 { 281 checkTagSupport(); 282 return ((TagSupport)tag).getId(); 283 } 284 285 /** 286 * Delegates to wrapped tag. 287 */ 288 public Tag getParent() 289 { 290 return tag.getParent(); 291 } 292 293 /** 294 * Delegates to wrapped tag. 295 * @throws <code>RuntimeException</code>, if the wrapped tag 296 * is not an instance of <code>TagSupport</code> 297 */ 298 public Object getValue(String key) 299 { 300 checkTagSupport(); 301 return ((TagSupport)tag).getValue(key); 302 } 303 304 /** 305 * Delegates to wrapped tag. 306 * @throws <code>RuntimeException</code>, if the wrapped tag 307 * is not an instance of <code>TagSupport</code> 308 */ 309 public Enumeration getValues() 310 { 311 checkTagSupport(); 312 return ((TagSupport)tag).getValues(); 313 } 314 315 /** 316 * Delegates to wrapped tag. 317 */ 318 public void release() 319 { 320 tag.release(); 321 } 322 323 /** 324 * Delegates to wrapped tag. 325 * @throws <code>RuntimeException</code>, if the wrapped tag 326 * is not an instance of <code>TagSupport</code> 327 */ 328 public void removeValue(String value) 329 { 330 checkTagSupport(); 331 ((TagSupport)tag).removeValue(value); 332 } 333 334 /** 335 * Delegates to wrapped tag. 336 * @throws <code>RuntimeException</code>, if the wrapped tag 337 * is not an instance of <code>TagSupport</code> 338 */ 339 public void setId(String id) 340 { 341 checkTagSupport(); 342 ((TagSupport)tag).setId(id); 343 } 344 345 /** 346 * Delegates to wrapped tag. Also calls <code>setPageContext</code> 347 * for all child tags. 348 */ 349 public void setPageContext(PageContext pageContext) 350 { 351 this.pageContext = pageContext; 352 tag.setPageContext(pageContext); 353 for(int ii = 0; ii < childs.size(); ii++) 354 { 355 Object child = childs.get(ii); 356 if(child instanceof Tag) 357 { 358 ((Tag)child).setPageContext(pageContext); 359 } 360 else if(child instanceof SimpleTag) 361 { 362 ((SimpleTag)child).setJspContext(pageContext); 363 } 364 } 365 } 366 367 /** 368 * Delegates to wrapped tag. 369 */ 370 public void setParent(Tag parent) 371 { 372 tag.setParent(parent); 373 } 374 375 /** 376 * Delegates to wrapped tag. 377 */ 378 public void setValue(String key, Object value) 379 { 380 checkTagSupport(); 381 ((TagSupport)tag).setValue(key, value); 382 } 383 384 /** 385 * Dumps the content of this and the nested tags. 386 */ 387 public String toString() 388 { 389 return TagUtil.dumpTag(this, new StringBuffer(), 0); 390 } 391 392 private NestedTag addChild(Object childTag) 393 { 394 if(childTag instanceof Tag) 395 { 396 ((Tag)childTag).setParent(this.tag); 397 } 398 else if(childTag instanceof SimpleTag) 399 { 400 ((SimpleTag)childTag).setParent(this.tag); 401 } 402 childs.add(childTag); 403 return (NestedTag)childTag; 404 } 405 406 private void checkIterationTag() 407 { 408 if(!(tag instanceof IterationTag)) 409 { 410 throw new RuntimeException("This method can only be called if the wrapped tag is an instance of IterationTag."); 411 } 412 } 413 414 private void checkTagSupport() 415 { 416 if(!(tag instanceof TagSupport)) 417 { 418 throw new RuntimeException("This method can only be called if the wrapped tag is an instance of TagSupport."); 419 } 420 } 421 }