001    // Copyright Aug 2, 2006 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    package org.apache.tapestry.html;
015    
016    import org.apache.hivemind.ApplicationRuntimeException;
017    import org.apache.tapestry.AbstractComponent;
018    import org.apache.tapestry.IAsset;
019    import org.apache.tapestry.IMarkupWriter;
020    import org.apache.tapestry.IRequestCycle;
021    import org.apache.tapestry.markup.MarkupWriterSource;
022    import org.apache.tapestry.util.ContentType;
023    
024    import java.io.PrintWriter;
025    import java.io.StringWriter;
026    
027    /**
028     * Works with the {@link Shell} component to define and append a 
029     * relationship between documents (typically a stylesheet) to 
030     * the HTML response. 
031     *
032     * @author Andreas Andreou
033     * @since 4.1.1
034     */
035    public abstract class Relation extends AbstractComponent
036    {
037        /**
038         * {@inheritDoc}
039         */
040        protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
041        {
042            if (!cycle.isRewinding())
043            {
044                Shell shell = Shell.get(cycle);
045    
046                if (shell == null)
047                    throw new ApplicationRuntimeException(
048                            HTMLMessages.shellComponentRequired(),
049                            this.getLocation(), null);
050    
051                if (getUseBody() && getHref() == null)
052                {
053                    renderStyleTag(shell, writer, cycle);
054                }
055                else
056                {
057                    renderLinkTag(shell, writer, cycle);
058                }
059            }
060        }
061    
062        protected void renderLinkTag(Shell shell, IMarkupWriter writer, IRequestCycle cycle)
063        {
064            Object href = getHref();
065            boolean ok = (href instanceof String) || (href instanceof IAsset);
066            if (!ok)
067                throw new ApplicationRuntimeException(HTMLMessages.stringOrIAssetExpected(), getLocation(), null);
068    
069            String url;
070            if (href instanceof String)
071            {
072                url = (String) href;
073            }
074            else
075            {
076                url = ((IAsset)href).buildURL();
077            }
078    
079            RelationBean bean = new RelationBean();
080            bean.setHref(url);
081            bean.setMedia(getMedia());
082            bean.setRel(getRel());
083            bean.setRev(getRev());
084            bean.setTitle(getTitle());
085            bean.setType(getType());
086            shell.addRelation(bean);
087        }
088    
089        protected void renderStyleTag(Shell shell, IMarkupWriter writer, IRequestCycle cycle)
090        {
091            // see if nothing (or nowhere) to include
092            if (getBody() == null || writer.getContentType() == null)
093            {
094                return;
095            }
096    
097            StringWriter sWriter = new StringWriter();
098            IMarkupWriter nested = getMarkupWriterSource().newMarkupWriter(new PrintWriter(sWriter),
099                                                                           new ContentType(writer.getContentType()));
100    
101            nested.begin("style");
102            nested.attribute("type", "text/css");
103    
104            if (getMedia()!=null)
105                nested.attribute("media", getMedia());
106            if (getTitle()!=null)
107                nested.attribute("title", getTitle());
108    
109            renderBody(nested, cycle);
110            nested.close();
111    
112            shell.includeAdditionalContent(sWriter.toString());
113        }
114    
115        public abstract boolean getUseBody();
116    
117        public abstract Object getHref();
118    
119        public abstract String getRel();
120    
121        public abstract String getRev();
122    
123        public abstract String getType();
124    
125        public abstract String getTitle();
126    
127        public abstract String getMedia();
128    
129        /* injected */
130        public abstract MarkupWriterSource getMarkupWriterSource();
131    
132    }