001    // Copyright 2009 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry5.corelib.base;
016    
017    import org.apache.tapestry5.BindingConstants;
018    import org.apache.tapestry5.Block;
019    import org.apache.tapestry5.ComponentResources;
020    import org.apache.tapestry5.MarkupWriter;
021    import org.apache.tapestry5.annotations.Parameter;
022    import org.apache.tapestry5.annotations.SupportsInformalParameters;
023    import org.apache.tapestry5.ioc.annotations.Inject;
024    
025    /**
026     * Base class for {@link org.apache.tapestry5.corelib.components.If} and {@link org.apache.tapestry5.corelib.components.Unless}.
027     * Will render its body or the block from its else parameter.  If it renders anything and it has an element name, then
028     * it renders the element and its informal parameters.
029     */
030    @SupportsInformalParameters
031    public abstract class AbstractConditional
032    {
033        @Inject
034        private ComponentResources resources;
035    
036        /**
037         * Performs the test via the parameters; return true to render the body of the component, false to render the else
038         * block (or nothing).
039         *
040         * @return true to render body
041         */
042        protected abstract boolean test();
043    
044        /**
045         * An alternate {@link org.apache.tapestry5.Block} to render if {@link #test()} is false. The default, null, means
046         * render nothing in that situation.
047         */
048        @Parameter(name = "else", defaultPrefix = BindingConstants.LITERAL)
049        private Block elseBlock;
050    
051        private boolean renderTag;
052    
053        /**
054         * Returns null if the {@link #test()} is true, which allows normal rendering (of the body). If the test parameter
055         * is false, returns the else parameter (this may also be null).
056         */
057        Object beginRender(MarkupWriter writer)
058        {
059            Block toRender = test() ? resources.getBody() : elseBlock;
060    
061            String elementName = resources.getElementName();
062    
063            renderTag = toRender != null && elementName != null;
064    
065            if (renderTag)
066            {
067                writer.element(elementName);
068                resources.renderInformalParameters(writer);
069            }
070    
071            return toRender;
072        }
073    
074        /**
075         * If {@link #test()} is true, then the body is rendered, otherwise not. The component does not have a template or
076         * do any other rendering besides its body.
077         */
078        boolean beforeRenderBody()
079        {
080            return false;
081        }
082    
083        void afterRenderBody(MarkupWriter writer)
084        {
085            if (renderTag)
086                writer.end();
087        }
088    
089    
090    }