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 */
019package org.apache.wiki.tags;
020
021import javax.servlet.jsp.*;
022import 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.
036public 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}