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 java.io.PrintWriter;
017    import java.io.StringWriter;
018    
019    import org.apache.hivemind.ApplicationRuntimeException;
020    import org.apache.tapestry.AbstractComponent;
021    import org.apache.tapestry.IAsset;
022    import org.apache.tapestry.IMarkupWriter;
023    import org.apache.tapestry.IRequestCycle;
024    import org.apache.tapestry.markup.MarkupWriterSource;
025    import org.apache.tapestry.util.ContentType;
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(
068                    HTMLMessages.stringOrIAssetExpected(),
069                    this.getLocation(), null); 
070                    
071            String url;
072            if (href instanceof String)
073            {
074                url = (String) href;
075            }
076            else
077            {
078                url = ((IAsset)href).buildURL();
079            }
080                    
081            RelationBean bean = new RelationBean();           
082            bean.setHref(url);
083            bean.setMedia(getMedia());
084            bean.setRel(getRel());
085            bean.setRev(getRev());
086            bean.setTitle(getTitle());
087            bean.setType(getType());
088            shell.addRelation(bean);        
089        }   
090        
091        protected void renderStyleTag(Shell shell, IMarkupWriter writer, IRequestCycle cycle)
092        {
093            StringWriter sWriter = new StringWriter();
094            IMarkupWriter nested = getMarkupWriterSource().newMarkupWriter(new PrintWriter(sWriter),
095                    new ContentType(writer.getContentType()));
096            nested.begin("style");
097            nested.attribute("type", "text/css");
098            if (getMedia()!=null)
099                nested.attribute("media", getMedia());
100            if (getTitle()!=null)
101                nested.attribute("title", getTitle());        
102            
103            renderBody(nested, cycle);
104            nested.close();
105    
106            shell.includeAdditionalContent(sWriter.toString());
107        }    
108        
109        public abstract boolean getUseBody();
110        
111        public abstract Object getHref();
112    
113        public abstract String getRel();
114        
115        public abstract String getRev();  
116        
117        public abstract String getType();
118        
119        public abstract String getTitle();
120            
121        public abstract String getMedia();
122        
123        /* injected */
124        public abstract MarkupWriterSource getMarkupWriterSource();
125    
126    }