001/*
002 * (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Anahide Tchertchian
016 */
017package org.nuxeo.ecm.platform.ui.web.component.document;
018
019import java.io.IOException;
020import java.net.URLEncoder;
021import java.util.logging.Level;
022
023import javax.faces.component.UIComponent;
024import javax.faces.context.FacesContext;
025import javax.faces.context.ResponseWriter;
026
027import org.apache.commons.lang.StringUtils;
028import org.nuxeo.ecm.platform.ui.web.rest.RestHelper;
029import org.nuxeo.ecm.platform.ui.web.tag.fn.Functions;
030
031import com.sun.faces.renderkit.Attribute;
032import com.sun.faces.renderkit.AttributeManager;
033import com.sun.faces.renderkit.RenderKitUtils;
034import com.sun.faces.renderkit.html_basic.OutputLinkRenderer;
035
036/**
037 * Overrides default output link renderer so that URL parameters passed through f:param tags are not added twice, since
038 * the component already takes them into account when building the URL.
039 *
040 * @see RestDocumentLink
041 * @since 5.4.2
042 */
043public class RestDocumentLinkRenderer extends OutputLinkRenderer {
044
045    /**
046     * Returns an empty parameters list because parameters are already taken care of in the computed URL.
047     */
048    @Override
049    protected Param[] getParamList(UIComponent command) {
050        return new Param[0];
051    }
052
053    private static final Attribute[] PASSTHROUGHATTRIBUTES = AttributeManager.getAttributes(AttributeManager.Key.OUTPUTLINK);
054
055    @Override
056    protected void renderAsActive(FacesContext context, UIComponent component) throws IOException {
057
058        String hrefVal = getCurrentValue(context, component);
059
060        if (logger.isLoggable(Level.FINE)) {
061            logger.fine("Value to be rendered " + hrefVal);
062        }
063
064        // suppress rendering if "rendered" property on the output is
065        // false
066        if (!component.isRendered()) {
067            if (logger.isLoggable(Level.FINE)) {
068                logger.fine("End encoding component " + component.getId() + " since "
069                        + "rendered attribute is set to false ");
070            }
071            return;
072        }
073        ResponseWriter writer = context.getResponseWriter();
074        assert (writer != null);
075        writer.startElement("a", component);
076        String writtenId = writeIdAttributeIfNecessary(context, writer, component);
077        if (null != writtenId) {
078            writer.writeAttribute("name", writtenId, "name");
079        }
080        // render an empty value for href if it is not specified
081        if (null == hrefVal || 0 == hrefVal.length()) {
082            hrefVal = "";
083        }
084
085        // Write Anchor attributes
086        Param paramList[] = getParamList(component);
087        StringBuffer sb = new StringBuffer();
088        sb.append(hrefVal);
089        boolean paramWritten = false;
090        for (int i = 0, len = paramList.length; i < len; i++) {
091            String pn = paramList[i].name;
092            if (pn != null && pn.length() != 0) {
093                String pv = paramList[i].value;
094                sb.append((paramWritten) ? '&' : '?');
095                sb.append(URLEncoder.encode(pn, "UTF-8"));
096                sb.append('=');
097                if (pv != null && pv.length() != 0) {
098                    sb.append(URLEncoder.encode(pv, "UTF-8"));
099                }
100                paramWritten = true;
101            }
102        }
103
104        String url;
105        Boolean isNewConversation = ((RestDocumentLink) component).getNewConversation();
106        if (!Boolean.TRUE.equals(isNewConversation) && !StringUtils.isBlank(sb.toString())) {
107            url = sb.toString();
108            String urlNewConversation = RestHelper.addCurrentConversationParameters(sb.toString());
109            url += getFragment(component);
110            urlNewConversation += getFragment(component);
111            url = context.getExternalContext().encodeResourceURL(url);
112            urlNewConversation = context.getExternalContext().encodeResourceURL(urlNewConversation);
113            String onclickJS = "if(!(event.ctrlKey||event.shiftKey||event.metaKey||event.button==1)){this.href='"
114                    + Functions.javaScriptEscape(urlNewConversation) + "'}";
115            writer.writeAttribute("onclick", onclickJS, "onclick");
116        } else {
117            sb.append(getFragment(component));
118            url = context.getExternalContext().encodeResourceURL(sb.toString());
119        }
120
121        writer.writeURIAttribute("href", url, "href");
122
123        RenderKitUtils.renderPassThruAttributes(context, writer, component, PASSTHROUGHATTRIBUTES);
124        RenderKitUtils.renderXHTMLStyleBooleanAttributes(writer, component);
125
126        String target = (String) component.getAttributes().get("target");
127        if (target != null && target.trim().length() != 0) {
128            writer.writeAttribute("target", target, "target");
129        }
130
131        writeCommonLinkAttributes(writer, component);
132
133        writer.flush();
134    }
135}