001    package com.mockrunner.tag;
002    
003    import java.util.List;
004    import java.util.Map;
005    
006    import javax.servlet.jsp.JspException;
007    import javax.servlet.jsp.tagext.JspTag;
008    import javax.servlet.jsp.tagext.TagSupport;
009    
010    /**
011     * <code>NestedTag</code> is used to simulate tags with static body
012     * content and child tags. It can be used to test the interaction
013     * of different tags. A <code>NestedTag</code> always wraps a real tag
014     * class (the actual testee).
015     * {@link TagTestModule} works with <code>NestedTag</code> instances 
016     * internally. If you only want to test the ouptput of one single tag
017     * without interaction with other tags, you do not have to care about
018     * <code>NestedTag</code>. Use it, if you want to write sophisticated
019     * tests of body tags. <code>NestedTag</code> instances are created with
020     * the help of {@link TagTestModule#createNestedTag}. You do not need to
021     * create them on your own in the tests.
022     */
023    public interface NestedTag
024    {
025        /**
026         * Specify if the <code>release</code> method should be called
027         * before populating a tag. Defaults to <code>false</code>. It's
028         * the container behaviour to call <code>release</code> when the tag
029         * goes back to the pool. It's usually not necessary in the tests, 
030         * because the tag instances are not pooled and reused during a test run.
031         * Only sets the <code>doRelease</code> flag for this tag and
032         * leaves the flag for child tags.
033         * @param doRelease should release be called, default is <code>false</code>
034         */
035        public void setDoRelease(boolean doRelease);
036        
037        /**
038         * Specify if the <code>release</code> method should be called
039         * before populating a tag. Defaults to <code>false</code>. It's
040         * the container behaviour to call <code>release</code> when the tag
041         * goes back to the pool. It's usually not necessary in the tests, 
042         * because the tag instances are not pooled and reused during a test run.
043         * Recursively sets the <code>doRelease</code> flag for this
044         * tag and all childs.
045         * @param doRelease should release be called, default is <code>false</code>
046         */
047        public void setDoReleaseRecursive(boolean doRelease);
048        
049        /**
050         * Populates the attributes of the underlying tag. The setters
051         * of the tag are called. Please note that child tags are not
052         * populated.
053         */
054        public void populateAttributes();
055        
056        /**
057         * Performs the tags lifecycle. All <code>doBody</code> and <code>doTag</code> 
058         * methods are called as  in the real web container. The evaluation of the body 
059         * is simulated by performing the lifecycle recursively for all childs of the 
060         * <code>NestedTag</code>.
061         * @return the result of the final <code>doEndTag</code> call
062         */
063        public int doLifecycle() throws JspException;
064        
065        /**
066         * Returns the wrapped tag (the testee).
067         * @return the wrapped tag
068         */
069        public TagSupport getTag();
070        
071        /**
072         * Returns the wrapped tag (the testee).
073         * @return the wrapped tag
074         */
075        public JspTag getWrappedTag();
076        
077        /**
078         * Removes all childs.
079         */
080        public void removeChilds();
081         
082        /**
083         * Returns the <code>List</code> of childs.
084         * @return the <code>List</code> of childs
085         */
086        public List getChilds();
087         
088        /**
089         * Returns a child specified by its index.
090         * @param index the index
091         * @return the child
092         */
093        public Object getChild(int index);
094          
095        /**
096         * Adds a text child simulating static body content.
097         * @param text the static text
098         */
099        public void addTextChild(String text);
100        
101        /**
102         * Adds a dynamic child simulating scriptlets and
103         * EL expressions. Check out
104         * {@link com.mockrunner.tag.TagUtil#evalBody(List, Object)}
105         * for details about child handling.
106         * @param child the dynamic child instance
107         */
108        public void addDynamicChild(DynamicChild child);
109         
110        /**
111         * Adds a tag child simulating nested tags.
112         * The corresponding <code>NestedTag</code> will be created 
113         * automatically wrapping the specified tag. An empty attribute 
114         * <code>Map</code> will be used for the tag.
115         * @param tag the tag class
116         */  
117        public NestedTag addTagChild(Class tag);
118         
119        /**
120         * Adds a tag child simulating nested tags.
121         * The corresponding <code>NestedTag</code> will be created 
122         * automatically wrapping the specified tag. The attributes 
123         * <code>Map</code>  contains the attributes of this tag 
124         * (<i>propertyname</i> maps to <i>propertyvalue</i>).
125         * @param tag the tag class
126         * @param attributeMap the attribute map
127         */     
128        public NestedTag addTagChild(Class tag, Map attributeMap);
129        
130        /**
131         * Adds a tag child simulating nested tags.
132         * <code>NestedTag</code> will be created automatically
133         * wrapping the specified tag. An empty attribute <code>Map</code> 
134         * will be used for the tag.
135         * @param tag the tag
136         */  
137        public NestedTag addTagChild(TagSupport tag);
138         
139        /**
140         * Adds a tag child simulating nested tags.
141         * The corresponding <code>NestedTag</code> will be created 
142         * automatically wrapping the specified tag. The attributes 
143         * <code>Map</code>  contains the attributes of this tag 
144         * (<i>propertyname</i> maps to <i>propertyvalue</i>).
145         * @param tag the tag
146         * @param attributeMap the attribute map
147         */     
148        public NestedTag addTagChild(TagSupport tag, Map attributeMap);
149        
150        /**
151         * Adds a tag child simulating nested tags.
152         * <code>NestedTag</code> will be created automatically
153         * wrapping the specified tag. An empty attribute <code>Map</code> 
154         * will be used for the tag.
155         * @param tag the tag
156         */  
157        public NestedTag addTagChild(JspTag tag);
158         
159        /**
160         * Adds a tag child simulating nested tags.
161         * The corresponding <code>NestedTag</code> will be created 
162         * automatically wrapping the specified tag. The attributes 
163         * <code>Map</code>  contains the attributes of this tag 
164         * (<i>propertyname</i> maps to <i>propertyvalue</i>).
165         * @param tag the tag
166         * @param attributeMap the attribute map
167         */     
168        public NestedTag addTagChild(JspTag tag, Map attributeMap);
169    }