Coverage Report - org.seasar.teeda.core.render.html.HtmlCommandLinkRenderer
 
Classes in this File Line Coverage Branch Coverage Complexity
HtmlCommandLinkRenderer
98%
113/115
78%
28/36
2.667
 
 1  
 /*
 2  
  * Copyright 2004-2011 the Seasar Foundation and the Others.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 13  
  * either express or implied. See the License for the specific language
 14  
  * governing permissions and limitations under the License.
 15  
  */
 16  
 package org.seasar.teeda.core.render.html;
 17  
 
 18  
 import java.io.IOException;
 19  
 import java.io.UnsupportedEncodingException;
 20  
 import java.net.URLEncoder;
 21  
 import java.util.Iterator;
 22  
 import java.util.Map;
 23  
 
 24  
 import javax.faces.application.ViewHandler;
 25  
 import javax.faces.component.NamingContainer;
 26  
 import javax.faces.component.UIComponent;
 27  
 import javax.faces.component.UIForm;
 28  
 import javax.faces.component.UIParameter;
 29  
 import javax.faces.component.html.HtmlCommandLink;
 30  
 import javax.faces.context.FacesContext;
 31  
 import javax.faces.context.ResponseWriter;
 32  
 import javax.faces.event.ActionEvent;
 33  
 import javax.faces.internal.IgnoreAttribute;
 34  
 import javax.faces.internal.UIComponentUtil;
 35  
 
 36  
 import org.seasar.teeda.core.JsfConstants;
 37  
 import org.seasar.teeda.core.render.AbstractRenderer;
 38  
 import org.seasar.teeda.core.util.ExternalContextUtil;
 39  
 import org.seasar.teeda.core.util.FacesContextUtil;
 40  
 import org.seasar.teeda.core.util.HtmlFormRendererUtil;
 41  
 import org.seasar.teeda.core.util.JavaScriptPermissionUtil;
 42  
 import org.seasar.teeda.core.util.JavaScriptUtil;
 43  
 import org.seasar.teeda.core.util.RendererUtil;
 44  
 
 45  
 /**
 46  
  * @author manhole
 47  
  * @author shot
 48  
  */
 49  46
 public class HtmlCommandLinkRenderer extends AbstractRenderer {
 50  
 
 51  
     public static final String COMPONENT_FAMILY = "javax.faces.Command";
 52  
 
 53  
     public static final String RENDERER_TYPE = "javax.faces.Link";
 54  
 
 55  
     private static final String HIDDEN_FIELD_NAME_SUFFIX = "__link_clicked__";
 56  
 
 57  46
     private final IgnoreAttribute ignoreComponent = new IgnoreAttribute();
 58  
     {
 59  46
         ignoreComponent.addAttributeName(JsfConstants.ID_ATTR);
 60  46
         ignoreComponent.addAttributeName(JsfConstants.VALUE_ATTR);
 61  46
         ignoreComponent.addAttributeName(JsfConstants.ONCLICK_ATTR);
 62  46
         ignoreComponent.addAttributeName(JsfConstants.ACTION_ATTR);
 63  46
         ignoreComponent.addAttributeName(JsfConstants.IMMEDIATE_ATTR);
 64  46
         ignoreComponent.addAttributeName(JsfConstants.HREF_ATTR);
 65  46
     }
 66  
 
 67  
     public void encodeBegin(FacesContext context, UIComponent component)
 68  
             throws IOException {
 69  19
         assertNotNull(context, component);
 70  17
         if (!component.isRendered()) {
 71  1
             return;
 72  
         }
 73  16
         encodeHtmlCommandLinkBegin(context, (HtmlCommandLink) component);
 74  15
     }
 75  
 
 76  
     protected void encodeHtmlCommandLinkBegin(FacesContext context,
 77  
             HtmlCommandLink commandLink) throws IOException {
 78  16
         ResponseWriter writer = context.getResponseWriter();
 79  16
         writer.startElement(JsfConstants.ANCHOR_ELEM, commandLink);
 80  16
         RendererUtil.renderIdAttributeIfNecessary(writer, commandLink,
 81  
                 getIdForRender(context, commandLink));
 82  
 
 83  16
         if (JavaScriptPermissionUtil.isJavaScriptPermitted(context)) {
 84  15
             encodeHtmlCommandLinkWithJavaScript(context, writer, commandLink);
 85  
         } else {
 86  1
             encodeHtmlCommandLinkWithoutJavaScript(context, writer, commandLink);
 87  
         }
 88  15
     }
 89  
 
 90  
     protected void encodeHtmlCommandLinkWithJavaScript(FacesContext context,
 91  
             ResponseWriter writer, HtmlCommandLink commandLink)
 92  
             throws IOException {
 93  15
         final UIForm parentForm = UIComponentUtil.findParentForm(commandLink);
 94  14
         final String formId = getIdForRender(context, parentForm);
 95  
 
 96  14
         RendererUtil.renderAttribute(writer, JsfConstants.HREF_ATTR, "#");
 97  
 
 98  14
         final StringBuffer sb = new StringBuffer(320);
 99  14
         final String onclick = commandLink.getOnclick();
 100  14
         if (onclick != null) {
 101  2
             sb.append(onclick);
 102  2
             if (!onclick.endsWith(";")) {
 103  1
                 sb.append(";");
 104  
             }
 105  
         }
 106  14
         final String formName = parentForm.getId();
 107  14
         final String functionName = JavaScriptUtil
 108  
                 .getClearHiddenCommandFormParamsFunctionName(formName) +
 109  
                 "();";
 110  14
         sb.append(functionName).append("var f = document.forms['").append(
 111  
                 formId).append("'];");
 112  
 
 113  14
         final String hiddenFieldName = getHiddenFieldName(formId);
 114  14
         sb.append(" f['").append(hiddenFieldName).append("'].value = '")
 115  
                 .append(commandLink.getClientId(context)).append("';");
 116  
 
 117  14
         HtmlFormRenderer.setCommandLinkHiddenParameter(parentForm,
 118  
                 hiddenFieldName, null);
 119  
 
 120  14
         for (final Iterator it = commandLink.getChildren().iterator(); it
 121  21
                 .hasNext();) {
 122  7
             final UIComponent child = (UIComponent) it.next();
 123  7
             if (child instanceof UIParameter) {
 124  7
                 final UIParameter p = ((UIParameter) child);
 125  7
                 final String name = p.getName();
 126  7
                 final Object value = p.getValue();
 127  7
                 sb.append(" f['" + name + "'].value = '").append(
 128  
                         String.valueOf(value)).append("';");
 129  7
                 HtmlFormRenderer.setCommandLinkHiddenParameter(parentForm,
 130  
                         name, null);
 131  
             }
 132  
         }
 133  
 
 134  14
         final String target = commandLink.getTarget();
 135  14
         if (target != null && target.trim().length() > 0) {
 136  2
             sb.append(" f.target = '").append(target).append("';");
 137  
         }
 138  
 
 139  14
         sb.append(" if (f.onsubmit) { f.onsubmit(); } f.submit();").append(
 140  
                 functionName).append(" return false;");
 141  14
         RendererUtil.renderAttribute(writer, JsfConstants.ONCLICK_ATTR, sb
 142  
                 .toString());
 143  
 
 144  
         //renderRemainAttributes(commandLink, writer);
 145  14
         renderRemainAttributes(commandLink, writer, ignoreComponent);
 146  
 
 147  14
         Object value = commandLink.getValue();
 148  14
         if (value != null) {
 149  4
             writer.writeText(value.toString(), JsfConstants.VALUE_ATTR);
 150  
         }
 151  14
     }
 152  
 
 153  
     protected void encodeHtmlCommandLinkWithoutJavaScript(FacesContext context,
 154  
             ResponseWriter writer, HtmlCommandLink commandLink)
 155  
             throws IOException {
 156  
         //TODO PortletSupport
 157  1
         ViewHandler viewHandler = FacesContextUtil.getViewHandler(context);
 158  1
         String viewId = context.getViewRoot().getViewId();
 159  1
         String path = viewHandler.getActionURL(context, viewId);
 160  1
         StringBuffer hrefBuf = new StringBuffer(100);
 161  1
         hrefBuf.append(path);
 162  1
         if (path.indexOf("?") == -1) {
 163  1
             hrefBuf.append("?");
 164  
         } else {
 165  0
             hrefBuf.append("&");
 166  
         }
 167  1
         UIForm parentForm = UIComponentUtil.findParentForm(commandLink);
 168  
 
 169  1
         final String formSubmitKey = HtmlFormRendererUtil.getFormSubmitKey(
 170  
                 context, parentForm);
 171  1
         hrefBuf.append(formSubmitKey).append("=").append(formSubmitKey).append(
 172  
                 "&");
 173  
 
 174  1
         final String formId = getIdForRender(context, parentForm);
 175  1
         final String hiddenFieldName = getHiddenFieldName(formId);
 176  1
         hrefBuf.append(hiddenFieldName).append("=").append(
 177  
                 commandLink.getClientId(context));
 178  1
         if (commandLink.getChildCount() > 0) {
 179  1
             addChildParametersToHref(commandLink, hrefBuf, writer
 180  
                     .getCharacterEncoding());
 181  
         }
 182  
 
 183  1
         String href = ExternalContextUtil.encodeActionURL(context, hrefBuf
 184  
                 .toString());
 185  1
         writer.writeURIAttribute(JsfConstants.HREF_ATTR, href, null);
 186  1
         Object value = commandLink.getValue();
 187  1
         if (value != null) {
 188  1
             writer.writeText(value.toString(), JsfConstants.VALUE_ATTR);
 189  
         }
 190  1
     }
 191  
 
 192  
     private void addChildParametersToHref(UIComponent linkComponent,
 193  
             StringBuffer hrefBuf, String charEncoding) throws IOException {
 194  1
         for (Iterator it = linkComponent.getChildren().iterator(); it.hasNext();) {
 195  1
             UIComponent child = (UIComponent) it.next();
 196  1
             if (child instanceof UIParameter) {
 197  1
                 UIParameter param = (UIParameter) child;
 198  1
                 String name = param.getName();
 199  1
                 Object value = param.getValue();
 200  1
                 addParameterToHref(name, value, hrefBuf, charEncoding);
 201  
             }
 202  
         }
 203  1
     }
 204  
 
 205  
     private static void addParameterToHref(String name, Object value,
 206  
             StringBuffer hrefBuf, String charEncoding)
 207  
             throws UnsupportedEncodingException {
 208  1
         if (name == null) {
 209  0
             throw new IllegalArgumentException(
 210  
                     "Unnamed parameter value not allowed within command link.");
 211  
         }
 212  1
         hrefBuf.append("&");
 213  1
         hrefBuf.append(URLEncoder.encode(name, charEncoding));
 214  1
         hrefBuf.append("=");
 215  1
         if (value != null) {
 216  1
             hrefBuf.append(URLEncoder.encode(value.toString(), charEncoding));
 217  
         }
 218  1
     }
 219  
 
 220  
     private String getHiddenFieldName(final String formId) {
 221  19
         return formId + NamingContainer.SEPARATOR_CHAR +
 222  
                 HIDDEN_FIELD_NAME_SUFFIX;
 223  
     }
 224  
 
 225  
     public void encodeEnd(FacesContext context, UIComponent component)
 226  
             throws IOException {
 227  18
         assertNotNull(context, component);
 228  16
         if (!component.isRendered()) {
 229  1
             return;
 230  
         }
 231  15
         encodeHtmlCommandLinkEnd(context, (HtmlCommandLink) component);
 232  15
     }
 233  
 
 234  
     protected void encodeHtmlCommandLinkEnd(FacesContext context,
 235  
             HtmlCommandLink commandLink) throws IOException {
 236  15
         ResponseWriter writer = context.getResponseWriter();
 237  15
         writer.endElement(JsfConstants.ANCHOR_ELEM);
 238  15
     }
 239  
 
 240  
     public void decode(FacesContext context, UIComponent component) {
 241  6
         assertNotNull(context, component);
 242  4
         decodeHtmlCommandLink(context, (HtmlCommandLink) component);
 243  4
     }
 244  
 
 245  
     protected void decodeHtmlCommandLink(FacesContext context,
 246  
             HtmlCommandLink commandLink) {
 247  4
         Map paramMap = context.getExternalContext().getRequestParameterMap();
 248  4
         String clientId = commandLink.getClientId(context);
 249  
 
 250  4
         UIForm parentForm = UIComponentUtil.findParentForm(commandLink);
 251  4
         String formId = getIdForRender(context, parentForm);
 252  4
         String hiddenFieldName = getHiddenFieldName(formId);
 253  4
         String entry = (String) paramMap.get(hiddenFieldName);
 254  4
         if (clientId.equals(entry)) {
 255  1
             commandLink.queueEvent(new ActionEvent(commandLink));
 256  
         }
 257  4
     }
 258  
 
 259  
     public boolean getRendersChildren() {
 260  16
         return true;
 261  
     }
 262  
 
 263  
 }