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 }