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 * @inheritDoc
086 */
087 public void setDoRelease(boolean doRelease)
088 {
089 this.doRelease = doRelease;
090 }
091
092 /**
093 * @inheritDoc
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 * @inheritDoc
110 */
111 public void populateAttributes()
112 {
113 TagUtil.populateTag(tag, attributes);
114 }
115
116 /**
117 * @inheritDoc
118 */
119 public int doLifecycle() throws JspException
120 {
121 populateAttributes();
122 int returnValue = -1;
123 try
124 {
125 int result = tag.doStartTag();
126 if(Tag.EVAL_BODY_INCLUDE == result)
127 {
128 TagUtil.evalBody(childs, pageContext);
129 if(tag instanceof IterationTag)
130 {
131 while(IterationTag.EVAL_BODY_AGAIN == doAfterBody())
132 {
133 TagUtil.evalBody(childs, pageContext);
134 }
135 }
136 }
137 returnValue = tag.doEndTag();
138 }
139 catch(Throwable exc)
140 {
141 TagUtil.handleException(tag, exc);
142 }
143 finally
144 {
145 TagUtil.handleFinally(tag);
146 }
147 if(doRelease) tag.release();
148 return returnValue;
149 }
150
151 /**
152 * @inheritDoc
153 * @throws <code>RuntimeException</code>, if the wrapped tag
154 * is not an instance of <code>TagSupport</code>
155 */
156 public TagSupport getTag()
157 {
158 checkTagSupport();
159 return (TagSupport)tag;
160 }
161
162 /**
163 * @inheritDoc
164 */
165 public JspTag getWrappedTag()
166 {
167 return tag;
168 }
169
170 /**
171 * @inheritDoc
172 */
173 public void removeChilds()
174 {
175 childs.clear();
176 }
177
178 /**
179 * @inheritDoc
180 */
181 public List getChilds()
182 {
183 return childs;
184 }
185
186 /**
187 * @inheritDoc
188 */
189 public Object getChild(int index)
190 {
191 return childs.get(index);
192 }
193
194 /**
195 * @inheritDoc
196 */
197 public void addTextChild(String text)
198 {
199 if(null == text) text = "";
200 childs.add(text);
201 }
202
203 /**
204 * @inheritDoc
205 */
206 public void addDynamicChild(DynamicChild child)
207 {
208 if(null == child) return;
209 childs.add(child);
210 }
211
212 /**
213 * @inheritDoc
214 */
215 public NestedTag addTagChild(Class tag)
216 {
217 return addTagChild(tag, new HashMap());
218 }
219
220 /**
221 * @inheritDoc
222 */
223 public NestedTag addTagChild(Class tag, Map attributeMap)
224 {
225 Object childTag = TagUtil.createNestedTagInstance(tag, this.pageContext, attributeMap);
226 return addChild(childTag);
227 }
228
229 /**
230 * @inheritDoc
231 */
232 public NestedTag addTagChild(TagSupport tag)
233 {
234 return addTagChild(tag, new HashMap());
235 }
236
237 /**
238 * @inheritDoc
239 */
240 public NestedTag addTagChild(TagSupport tag, Map attributeMap)
241 {
242 Object childTag = TagUtil.createNestedTagInstance(tag, this.pageContext, attributeMap);
243 return addChild(childTag);
244 }
245
246 /**
247 * @inheritDoc
248 */
249 public NestedTag addTagChild(JspTag tag)
250 {
251 return addTagChild(tag, new HashMap());
252 }
253
254 /**
255 * @inheritDoc
256 */
257 public NestedTag addTagChild(JspTag tag, Map attributeMap)
258 {
259 Object childTag = TagUtil.createNestedTagInstance(tag, this.pageContext, attributeMap);
260 return addChild(childTag);
261 }
262
263 /**
264 * Delegates to wrapped tag.
265 * @throws <code>RuntimeException</code>, if the wrapped tag
266 * is not an instance of <code>IterationTag</code>
267 */
268 public int doAfterBody() throws JspException
269 {
270 checkIterationTag();
271 return ((IterationTag)tag).doAfterBody();
272 }
273
274 /**
275 * Delegates to wrapped tag.
276 */
277 public int doEndTag() throws JspException
278 {
279 return tag.doEndTag();
280 }
281
282 /**
283 * Delegates to wrapped tag.
284 */
285 public int doStartTag() throws JspException
286 {
287 return tag.doStartTag();
288 }
289
290 /**
291 * Delegates to wrapped tag.
292 * @throws <code>RuntimeException</code>, if the wrapped tag
293 * is not an instance of <code>TagSupport</code>
294 */
295 public String getId()
296 {
297 checkTagSupport();
298 return ((TagSupport)tag).getId();
299 }
300
301 /**
302 * Delegates to wrapped tag.
303 */
304 public Tag getParent()
305 {
306 return tag.getParent();
307 }
308
309 /**
310 * Delegates to wrapped tag.
311 * @throws <code>RuntimeException</code>, if the wrapped tag
312 * is not an instance of <code>TagSupport</code>
313 */
314 public Object getValue(String key)
315 {
316 checkTagSupport();
317 return ((TagSupport)tag).getValue(key);
318 }
319
320 /**
321 * Delegates to wrapped tag.
322 * @throws <code>RuntimeException</code>, if the wrapped tag
323 * is not an instance of <code>TagSupport</code>
324 */
325 public Enumeration getValues()
326 {
327 checkTagSupport();
328 return ((TagSupport)tag).getValues();
329 }
330
331 /**
332 * Delegates to wrapped tag.
333 */
334 public void release()
335 {
336 tag.release();
337 }
338
339 /**
340 * Delegates to wrapped tag.
341 * @throws <code>RuntimeException</code>, if the wrapped tag
342 * is not an instance of <code>TagSupport</code>
343 */
344 public void removeValue(String value)
345 {
346 checkTagSupport();
347 ((TagSupport)tag).removeValue(value);
348 }
349
350 /**
351 * Delegates to wrapped tag.
352 * @throws <code>RuntimeException</code>, if the wrapped tag
353 * is not an instance of <code>TagSupport</code>
354 */
355 public void setId(String id)
356 {
357 checkTagSupport();
358 ((TagSupport)tag).setId(id);
359 }
360
361 /**
362 * Delegates to wrapped tag. Also calls <code>setPageContext</code>
363 * for all child tags.
364 */
365 public void setPageContext(PageContext pageContext)
366 {
367 this.pageContext = pageContext;
368 tag.setPageContext(pageContext);
369 for(int ii = 0; ii < childs.size(); ii++)
370 {
371 Object child = childs.get(ii);
372 if(child instanceof Tag)
373 {
374 ((Tag)child).setPageContext(pageContext);
375 }
376 else if(child instanceof SimpleTag)
377 {
378 ((SimpleTag)child).setJspContext(pageContext);
379 }
380 }
381 }
382
383 /**
384 * Delegates to wrapped tag.
385 */
386 public void setParent(Tag parent)
387 {
388 tag.setParent(parent);
389 }
390
391 /**
392 * Delegates to wrapped tag.
393 */
394 public void setValue(String key, Object value)
395 {
396 checkTagSupport();
397 ((TagSupport)tag).setValue(key, value);
398 }
399
400 /**
401 * Dumps the content of this and the nested tags.
402 */
403 public String toString()
404 {
405 return TagUtil.dumpTag(this, new StringBuffer(), 0);
406 }
407
408 private NestedTag addChild(Object childTag)
409 {
410 if(childTag instanceof Tag)
411 {
412 ((Tag)childTag).setParent(this.tag);
413 }
414 else if(childTag instanceof SimpleTag)
415 {
416 ((SimpleTag)childTag).setParent(this.tag);
417 }
418 childs.add(childTag);
419 return (NestedTag)childTag;
420 }
421
422 private void checkIterationTag()
423 {
424 if(!(tag instanceof IterationTag))
425 {
426 throw new RuntimeException("This method can only be called if the wrapped tag is an instance of IterationTag.");
427 }
428 }
429
430 private void checkTagSupport()
431 {
432 if(!(tag instanceof TagSupport))
433 {
434 throw new RuntimeException("This method can only be called if the wrapped tag is an instance of TagSupport.");
435 }
436 }
437 }