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