Coverage Report - org.apache.tapestry.link.DefaultLinkRenderer
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultLinkRenderer
0%
0/61
0%
0/38
3.333
 
 1  
 // Copyright 2004, 2005 The Apache Software Foundation
 2  
 //
 3  
 // Licensed under the Apache License, Version 2.0 (the "License");
 4  
 // you may not use this file except in compliance with the License.
 5  
 // You may obtain a copy of the License at
 6  
 //
 7  
 //     http://www.apache.org/licenses/LICENSE-2.0
 8  
 //
 9  
 // Unless required by applicable law or agreed to in writing, software
 10  
 // distributed under the License is distributed on an "AS IS" BASIS,
 11  
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  
 // See the License for the specific language governing permissions and
 13  
 // limitations under the License.
 14  
 
 15  
 package org.apache.tapestry.link;
 16  
 
 17  
 import org.apache.hivemind.ApplicationRuntimeException;
 18  
 import org.apache.hivemind.HiveMind;
 19  
 import org.apache.tapestry.*;
 20  
 import org.apache.tapestry.components.ILinkComponent;
 21  
 import org.apache.tapestry.engine.ILink;
 22  
 import org.apache.tapestry.util.ScriptUtils;
 23  
 
 24  
 import java.util.HashMap;
 25  
 import java.util.List;
 26  
 import java.util.Map;
 27  
 
 28  
 /**
 29  
  * Default implementation of {@link org.apache.tapestry.link.ILinkRenderer},
 30  
  * which does nothing special. Can be used as a base class to provide additional
 31  
  * handling.
 32  
  * 
 33  
  * @since 3.0
 34  
  */
 35  
 
 36  0
 public class DefaultLinkRenderer implements ILinkRenderer
 37  
 {
 38  
 
 39  
     /**
 40  
      * A shared instance used as a default for any link that doesn't explicitly
 41  
      * override.
 42  
      */
 43  
 
 44  0
     public static final ILinkRenderer SHARED_INSTANCE = new DefaultLinkRenderer();
 45  
 
 46  
     public void renderLink(IMarkupWriter writer, IRequestCycle cycle, ILinkComponent linkComponent)
 47  
     {
 48  0
         IMarkupWriter wrappedWriter = null;
 49  
         
 50  0
         if (cycle.getAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME) != null)
 51  0
             throw new ApplicationRuntimeException(LinkMessages.noNesting(), linkComponent, null, null);
 52  
         
 53  0
         cycle.setAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME, linkComponent);
 54  
         
 55  0
         boolean hasBody = getHasBody();
 56  
 
 57  0
         boolean disabled = linkComponent.isDisabled() || cycle.isRewinding();
 58  
 
 59  0
         if (!disabled)
 60  
         {
 61  0
             if (hasBody)
 62  0
                 writer.begin(getElement());
 63  
             else 
 64  0
                 writer.beginEmpty(getElement());
 65  
             
 66  0
             linkComponent.renderAdditionalAttributes(writer, cycle);
 67  
             
 68  0
             writer.attribute(getUrlAttribute(), constructURL(linkComponent, cycle));
 69  
             
 70  0
             String target = linkComponent.getTarget();
 71  
             
 72  0
             if (HiveMind.isNonBlank(target))
 73  0
                 writer.attribute(getTargetAttribute(), target);
 74  
             
 75  0
             if (DirectLink.class.isInstance(linkComponent)) {
 76  0
                 DirectLink direct = (DirectLink)linkComponent;
 77  
                 
 78  0
                 renderAsyncParams(writer, cycle, direct);
 79  
             }
 80  
             
 81  0
             beforeBodyRender(writer, cycle, linkComponent);
 82  
             
 83  
             // Allow the wrapped components a chance to render.
 84  
             // Along the way, they may interact with this component
 85  
             // and cause the name variable to get set.
 86  
             
 87  0
             wrappedWriter = writer.getNestedWriter();
 88  0
         } else 
 89  0
             wrappedWriter = writer;
 90  
         
 91  0
         if (hasBody) 
 92  0
             linkComponent.renderBody(wrappedWriter, cycle);
 93  
         
 94  0
         if (!disabled) {
 95  
             
 96  0
             afterBodyRender(writer, cycle, linkComponent);
 97  
                         
 98  0
             if (hasBody) {
 99  0
                 wrappedWriter.close();
 100  
                 
 101  
                 // Close the <element> tag
 102  
                 
 103  0
                 writer.end();
 104  
             } else 
 105  0
                 writer.closeTag();
 106  
         }
 107  
         
 108  0
         cycle.removeAttribute(Tapestry.LINK_COMPONENT_ATTRIBUTE_NAME);
 109  0
     }
 110  
 
 111  
     /**
 112  
      * Converts the EngineServiceLink into a URI or URL. This implementation
 113  
      * gets the scheme and anchor from the component (both of which may be
 114  
      * null), and invokes
 115  
      * {@link ILink#getURL(String, String, int, String, boolean)}.
 116  
      */
 117  
 
 118  
     protected String constructURL(ILinkComponent component, IRequestCycle cycle)
 119  
     {
 120  0
         ILink link = component.getLink(cycle);
 121  
         
 122  0
         String scheme = component.getScheme();
 123  0
         Integer port = component.getPort();
 124  0
         int portI = (port == null) ? 0 : port.intValue();
 125  0
         String anchor = component.getAnchor();
 126  
         
 127  0
         return link.getURL(scheme, null, portI, anchor, true);
 128  
     }
 129  
 
 130  
     /**
 131  
      * Invoked after the href attribute has been written but before the body of
 132  
      * the link is rendered (but only if the link is not disabled).
 133  
      * <p>
 134  
      * This implementation does nothing.
 135  
      * </p>
 136  
      *
 137  
      * @param writer
 138  
      *          Markup writer.
 139  
      * @param cycle
 140  
      *          Current request cycle.
 141  
      * @param link
 142  
      *          The link component being rendered.
 143  
      */
 144  
 
 145  
     protected void beforeBodyRender(IMarkupWriter writer, IRequestCycle cycle, ILinkComponent link)
 146  
     {
 147  0
     }
 148  
 
 149  
     /**
 150  
      * Invoked after the body of the link is rendered, but before
 151  
      * {@link ILinkComponent#renderAdditionalAttributes(IMarkupWriter, IRequestCycle)}is
 152  
      * invoked (but only if the link is not disabled).
 153  
      * 
 154  
      * <p>
 155  
      * This implementation does nothing.
 156  
      * </p>
 157  
      * @param writer
 158  
      *          Markup writer.
 159  
      * @param cycle
 160  
      *          Current request cycle.
 161  
      * @param link
 162  
      *          The link component being rendered.
 163  
      */
 164  
 
 165  
     protected void afterBodyRender(IMarkupWriter writer, IRequestCycle cycle, ILinkComponent link)
 166  
     {
 167  0
     }
 168  
 
 169  
     /**
 170  
      * For {@link DirectLink} components only, manages writing out event handlers for link
 171  
      * if any of the dynamic (async/json/etc) parameters are set on the component.
 172  
      * 
 173  
      * <p>
 174  
      *  Will try to write the logic into the <code>onClick</code> attribute of the link 
 175  
      *  if not bound, otherwise it will render it using the {@link DirectLink#getScript()} script.
 176  
      * </p>
 177  
      * 
 178  
      * @param writer
 179  
      *          The writer to render attributes into.
 180  
      * @param cycle
 181  
      *          The current request cycle.
 182  
      * @param link
 183  
      *          The component link being rendered for.
 184  
      */
 185  
     protected void renderAsyncParams(IMarkupWriter writer, IRequestCycle cycle, DirectLink link)
 186  
     {
 187  0
         List comps = link.getUpdateComponents();
 188  
         
 189  0
         if (!link.isAsync() && !link.isJson() 
 190  
                 && (comps == null
 191  
                 || comps.size() <= 0))
 192  0
             return;
 193  
         
 194  0
         if (!link.isParameterBound("onclick") && !link.isParameterBound("onClick")) {
 195  0
             writer.attribute("onclick", 
 196  
                     "return tapestry.linkOnClick(this.href,'" + link.getClientId() + "', " + link.isJson() + ")");
 197  0
             return;
 198  
         }
 199  
         
 200  0
         PageRenderSupport prs = TapestryUtils.getPageRenderSupport(cycle, link);
 201  
         
 202  0
         if (prs == null)
 203  0
             return;
 204  
         
 205  0
         Map parms = new HashMap();
 206  
         
 207  0
         parms.put("component", link);
 208  0
         parms.put("json", Boolean.valueOf(link.isJson()));
 209  0
         parms.put("key", ScriptUtils.functionHash("onclick" + link.hashCode()));
 210  
         
 211  
         // execute script template
 212  
         
 213  0
         link.getScript().execute(link, cycle, prs, parms);
 214  0
     }
 215  
     
 216  
     /** @since 3.0 * */
 217  
 
 218  
     protected String getElement()
 219  
     {
 220  0
         return "a";
 221  
     }
 222  
 
 223  
     protected String getUrlAttribute()
 224  
     {
 225  0
         return "href";
 226  
     }
 227  
 
 228  
     protected String getTargetAttribute()
 229  
     {
 230  0
         return "target";
 231  
     }
 232  
 
 233  
     protected boolean getHasBody()
 234  
     {
 235  0
         return true;
 236  
     }
 237  
 }