    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 jakarta.servlet.jsp.*;
    022import jakarta.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;
    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(final 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(final 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(final 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}