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 using
020     * {@link TagTestModule#createNestedTag}. You do not need to create them 
021     * 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         * after processing the tag lifecycle. Defaults to <code>false</code>. 
028         * It's 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         * to call this method, because the tag instances are not pooled and 
031         * reused during a test run.
032         * This method sets the <code>doRelease</code> flag for this tag but
033         * does not set the flag for child tags.
034         * @param doRelease should release be called, default is <code>false</code>
035         */
036        public void setDoRelease(boolean doRelease);
037        
038        /**
039         * Specify if the <code>release</code> method should be called
040         * after processing the tag lifecycle. Defaults to <code>false</code>. 
041         * It's the container behaviour to call <code>release</code> when the tag
042         * goes back to the pool. It's usually not necessary in the tests
043         * to call this method, because the tag instances are not pooled and 
044         * reused during a test run.
045         * This method sets the <code>doRelease</code> flag for this
046         * tag and all child tags recursively.
047         * @param doRelease should release be called, default is <code>false</code>
048         */
049        public void setDoReleaseRecursive(boolean doRelease);
050        
051        /**
052         * Populates the attributes of the underlying tag. The setters
053         * of the tag are called. Please note that child tags are not
054         * populated.
055         */
056        public void populateAttributes();
057        
058        /**
059         * Performs the tag lifecycle. All <code>doBody</code> and <code>doTag</code> 
060         * methods are called as  in the real web container. The evaluation of the body 
061         * is simulated by performing the lifecycle recursively for all childs of the 
062         * <code>NestedTag</code>. Calls <code>release</code> on the tag after
063         * processing the tag lifecycle, if <code>doRelease</code> is <code>true</code> 
064         * (use {@link #setDoRelease(boolean)}).
065         * @return the result of the final <code>doEndTag</code> call
066         */
067        public int doLifecycle() throws JspException;
068        
069        /**
070         * Returns the wrapped tag (the testee).
071         * @return the wrapped tag
072         */
073        public TagSupport getTag();
074        
075        /**
076         * Returns the wrapped tag (the testee).
077         * @return the wrapped tag
078         */
079        public JspTag getWrappedTag();
080        
081        /**
082         * Removes all childs.
083         */
084        public void removeChilds();
085         
086        /**
087         * Returns the <code>List</code> of childs.
088         * @return the <code>List</code> of childs
089         */
090        public List getChilds();
091         
092        /**
093         * Returns a child specified by its index.
094         * @param index the index
095         * @return the child
096         */
097        public Object getChild(int index);
098          
099        /**
100         * Adds a text child simulating static body content.
101         * @param text the static text
102         */
103        public void addTextChild(String text);
104        
105        /**
106         * Adds a dynamic child simulating scriptlets and
107         * EL expressions. Check out
108         * {@link com.mockrunner.tag.TagUtil#evalBody(List, Object)}
109         * for details about child handling.
110         * @param child the dynamic child instance
111         */
112        public void addDynamicChild(DynamicChild child);
113         
114        /**
115         * Adds a tag child simulating nested tags.
116         * The corresponding <code>NestedTag</code> will be created 
117         * automatically wrapping the specified tag. An empty attribute 
118         * <code>Map</code> will be used for the tag.
119         * @param tag the tag class
120         */  
121        public NestedTag addTagChild(Class tag);
122         
123        /**
124         * Adds a tag child simulating nested tags.
125         * The corresponding <code>NestedTag</code> will be created 
126         * automatically wrapping the specified tag. The attributes 
127         * <code>Map</code>  contains the attributes of this tag 
128         * (<i>propertyname</i> maps to <i>propertyvalue</i>).
129         * @param tag the tag class
130         * @param attributeMap the attribute map
131         */     
132        public NestedTag addTagChild(Class tag, Map attributeMap);
133        
134        /**
135         * Adds a tag child simulating nested tags.
136         * <code>NestedTag</code> will be created automatically
137         * wrapping the specified tag. An empty attribute <code>Map</code> 
138         * will be used for the tag.
139         * @param tag the tag
140         */  
141        public NestedTag addTagChild(TagSupport tag);
142         
143        /**
144         * Adds a tag child simulating nested tags.
145         * The corresponding <code>NestedTag</code> will be created 
146         * automatically wrapping the specified tag. The attributes 
147         * <code>Map</code>  contains the attributes of this tag 
148         * (<i>propertyname</i> maps to <i>propertyvalue</i>).
149         * @param tag the tag
150         * @param attributeMap the attribute map
151         */     
152        public NestedTag addTagChild(TagSupport tag, Map attributeMap);
153        
154        /**
155         * Adds a tag child simulating nested tags.
156         * <code>NestedTag</code> will be created automatically
157         * wrapping the specified tag. An empty attribute <code>Map</code> 
158         * will be used for the tag.
159         * @param tag the tag
160         */  
161        public NestedTag addTagChild(JspTag tag);
162         
163        /**
164         * Adds a tag child simulating nested tags.
165         * The corresponding <code>NestedTag</code> will be created 
166         * automatically wrapping the specified tag. The attributes 
167         * <code>Map</code>  contains the attributes of this tag 
168         * (<i>propertyname</i> maps to <i>propertyvalue</i>).
169         * @param tag the tag
170         * @param attributeMap the attribute map
171         */     
172        public NestedTag addTagChild(JspTag tag, Map attributeMap);
173    }