001    /* 
002        Licensed to the Apache Software Foundation (ASF) under one
003        or more contributor license agreements.  See the NOTICE file
004        distributed with this work for additional information
005        regarding copyright ownership.  The ASF licenses this file
006        to you under the Apache License, Version 2.0 (the
007        "License"); you may not use this file except in compliance
008        with the License.  You may obtain a copy of the License at
009    
010           http://www.apache.org/licenses/LICENSE-2.0
011    
012        Unless required by applicable law or agreed to in writing,
013        software distributed under the License is distributed on an
014        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015        KIND, either express or implied.  See the License for the
016        specific language governing permissions and limitations
017        under the License.  
018     */
019    package org.apache.wiki.tags;
020    
021    import javax.servlet.jsp.*;
022    import javax.servlet.jsp.tagext.*;
023    
024    /**
025     *  Generates tabbed page section: container for the Tab tag.
026     *  Works together with the tabbedSection javacript.
027     *
028     *  <P><B>Attributes</B></P>
029     *  <UL>
030     *    <LI>defaultTab - Page name to refer to.  Default is the current page.
031     *  </UL>
032     *
033     *  @since v2.3.63
034     */
035    // FIXME: Needs a bit more of explaining how this tag works.
036    public class TabbedSectionTag extends BodyTagSupport
037    {
038        private static final long serialVersionUID = 1702437933960026481L;
039        private String       m_defaultTabId;
040        private String       m_firstTabId;
041        private boolean      m_defaultTabFound = false;
042    
043        private StringBuffer m_buffer = new StringBuffer(BUFFER_SIZE);
044    
045        private static final int FIND_DEFAULT_TAB = 0;
046        private static final int GENERATE_TABMENU = 1;
047        private static final int GENERATE_TABBODY = 2;
048    
049        private static final int BUFFER_SIZE      = 1024;
050    
051        private              int m_state            = FIND_DEFAULT_TAB;
052    
053        /**
054         *  {@inheritDoc}
055         */
056        @Override
057        public void release()
058        {
059            super.release();
060            m_defaultTabId = m_firstTabId = null;
061            m_defaultTabFound = false;
062            m_buffer = new StringBuffer();
063            m_state = FIND_DEFAULT_TAB;
064        }
065    
066        /**
067         *  Set the id of the default tab (the tab which should be shown when
068         *  the page is first loaded).
069         *  
070         *  @param anDefaultTabId ID attribute of the default tab.
071         */
072        public void setDefaultTab(String anDefaultTabId)
073        {
074            m_defaultTabId = anDefaultTabId;
075        }
076    
077        // FIXME: I don't really understand what this does - so Dirk, please
078        //        add some documentation.
079        public boolean validateDefaultTab( String aTabId )
080        {
081            if( m_firstTabId == null ) m_firstTabId = aTabId;
082            if( aTabId.equals( m_defaultTabId ) ) m_defaultTabFound = true;
083    
084            return aTabId.equals( m_defaultTabId );
085        }
086    
087        /**
088         *  {@inheritDoc}
089         */
090        @Override
091        public int doStartTag() throws JspTagException
092        {
093            return EVAL_BODY_BUFFERED; /* always look inside */
094        }
095    
096        /**
097         *  Returns true, if the tab system is currently trying to
098         *  figure out which is the default tab.
099         *  
100         *  @return True, if finding the default tab.
101         */
102        public boolean isStateFindDefaultTab()
103        {
104            return m_state == FIND_DEFAULT_TAB;
105        }
106    
107        /**
108         *  Returns true, if the tab system is currently generating
109         *  the tab menu.
110         *  
111         *  @return True, if currently generating the menu itself.
112         */
113        public boolean isStateGenerateTabMenu()
114        {
115            return m_state == GENERATE_TABMENU;
116        }
117    
118        /**
119         *  Returns true, if the tab system is currently generating
120         *  the tab body.
121         *  
122         *  @return True, if the tab system is currently generating the tab body.
123         */
124        public boolean isStateGenerateTabBody()
125        {
126            return m_state == GENERATE_TABBODY;
127        }
128    
129    
130        /**
131         *  The tabbed section iterates 3 time through the underlying Tab tags
132         * - first it identifies the default tab (displayed by default)
133         * - second it generates the tabmenu markup (displays all tab-titles)
134         * - finally it generates the content of each tab.
135         * 
136         * @return {@inheritDoc}
137         * @throws {@inheritDoc}
138         */
139        @Override
140        public int doAfterBody() throws JspTagException
141        {
142            if( isStateFindDefaultTab() )
143            {
144                if( !m_defaultTabFound )
145                {
146                    m_defaultTabId = m_firstTabId;
147                }
148                m_state = GENERATE_TABMENU;
149                return EVAL_BODY_BUFFERED;
150            }
151            else if( isStateGenerateTabMenu() )
152            {
153                if( bodyContent != null )
154                {
155                    m_buffer.append( "<div class=\"tabmenu\">" );
156                    m_buffer.append( bodyContent.getString() );
157                    bodyContent.clearBody();
158                    m_buffer.append( "</div>\n" );
159                }
160                m_state = GENERATE_TABBODY;
161                return EVAL_BODY_BUFFERED;
162            }
163            else if( isStateGenerateTabBody() )
164            {
165                if( bodyContent != null )
166                {
167                    m_buffer.append( "<div class=\"tabs\">" );
168                    m_buffer.append( bodyContent.getString() );
169                    bodyContent.clearBody();
170                    m_buffer.append( "<div style=\"clear:both;\" ></div>\n</div>\n" );
171                }
172                return SKIP_BODY;
173            }
174            return SKIP_BODY;
175        }
176    
177        /**
178         *  {@inheritDoc}
179         */
180        @Override
181        public int doEndTag() throws JspTagException
182        {
183            try
184            {
185                if( m_buffer.length() > 0 )
186                {
187                    getPreviousOut().write( m_buffer.toString() );
188                }
189            }
190            catch(java.io.IOException e)
191            {
192                throw new JspTagException( "IO Error: " + e.getMessage() );
193            }
194    
195            //now reset some stuff for the next run -- ugh.
196            m_buffer    = new StringBuffer(BUFFER_SIZE);
197            m_state = FIND_DEFAULT_TAB;
198            m_defaultTabId    = null;
199            m_firstTabId      = null;
200            m_defaultTabFound = false;
201            return EVAL_PAGE;
202        }
203    
204    }