<commit_before>package de.larmic.butterfaces.component.renderkit.html_basic.action;

import de.larmic.butterfaces.component.html.action.HtmlCommandLink;
import de.larmic.butterfaces.resolver.AjaxClientIdResolver;
import de.larmic.butterfaces.resolver.WebXmlParameters;
import de.larmic.butterfaces.util.StringUtils;

import javax.faces.component.*;
import javax.faces.component.behavior.AjaxBehavior;
import javax.faces.component.behavior.ClientBehaviorHolder;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.FacesRenderer;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.List;
import java.util.Map;

/**
 * Created by larmic on 16.09.14.
 */
@FacesRenderer(componentFamily = HtmlCommandLink.COMPONENT_FAMILY, rendererType = HtmlCommandLink.RENDERER_TYPE)
public class CommandLinkRenderer extends com.sun.faces.renderkit.html_basic.CommandLinkRenderer {

    private WebXmlParameters webXmlParameters;

    /**
     * Will be set in renderAsActive if f:ajax child with onevent attribute exists.
     */
    private String onEventCallback = null;

    @Override
    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
        this.onEventCallback = null;

        final HtmlCommandLink link = (HtmlCommandLink) component;
        final ResponseWriter writer = context.getResponseWriter();

        webXmlParameters = new WebXmlParameters(context.getExternalContext());

        if (!link.isDisabled()) {
            super.encodeBegin(context, component);
        } else {
            writer.startElement("span", component);
            writeIdAttributeIfNecessary(context, writer, component);
            writeCommonLinkAttributes(writer, component);
            if (StringUtils.isNotEmpty(link.getStyle())) {
                writer.writeAttribute("style", link.getStyle(), "style");
            }
            this.writeValue(component, writer);
        }
    }

    @Override
    protected boolean shouldWriteIdAttribute(UIComponent component) {
        return true;
    }

    @Override
    protected void writeCommonLinkAttributes(final ResponseWriter writer, final UIComponent component) throws IOException {
        final HtmlCommandLink link = (HtmlCommandLink) component;
        final String styleClass = (String) component.getAttributes().get("styleClass");

        final StringBuilder generatedStyleClass = new StringBuilder(StringUtils.isEmpty(styleClass) ? "" : styleClass);

        if (link.isDisabled()) {
            generatedStyleClass.append(" btn-disabled");
        }
        if (StringUtils.isEmpty(link.getGlyphicon())) {
            generatedStyleClass.append(" no-glyphicon");
        }

        if (generatedStyleClass.length() > 0) {
            writer.writeAttribute("class", generatedStyleClass.toString(), "styleClass");
        }
    }

    @Override
    public void decode(FacesContext context, UIComponent component) {
        final ExternalContext external = context.getExternalContext();
        final Map<String, String> params = external.getRequestParameterMap();
        final String resetValues = params.get("javax.faces.partial.resetValues");
        final String render = params.get("javax.faces.partial.render");

        if (StringUtils.isNotEmpty(resetValues) && StringUtils.isNotEmpty(render) && Boolean.valueOf(resetValues)) {
            final String[] split = render.split(" ");

            for (String clientId : split) {
                final UIComponent renderComponent = context.getViewRoot().findComponent(clientId);
                resetValues(renderComponent);
            }
        }

        super.decode(context, component);
    }

    private void resetValues(final UIComponent component) {
        if (component == null) {
            return;
        }

        for (UIComponent child : component.getChildren()) {
            resetValues(child);
        }

        if (component instanceof UIOutput) {
            ((UIOutput) component).resetValue();
        } else if (component instanceof EditableValueHolder) {
            ((EditableValueHolder) component).resetValue();
        }
    }

    @Override
    public void encodeEnd(final FacesContext context, final UIComponent component) throws IOException {
        final HtmlCommandLink link = (HtmlCommandLink) component;
        final ResponseWriter writer = context.getResponseWriter();

        if (!link.isDisabled()) {
            if (link.isAjaxDisableLinkOnRequest()) {
                writer.startElement("script", component);
                writer.writeText("function " + getOnEventListenerName(component) + "(data) {", null);
                if (StringUtils.isNotEmpty(onEventCallback)) {
                    writer.writeText("    " + onEventCallback + "(data);", null);
                }

                final String processingText = createAjaxProcessingText(link);
                final String processingGlyphicon = createAjaxProcessingGlypicon(link);

                final AjaxClientIdResolver ajaxClientIdResolver = new AjaxClientIdResolver(link);
                final String jQueryIDSelector = link.isAjaxDisableRenderRegionsOnRequest()
                        ? ajaxClientIdResolver.getjQueryRenderIDSelector() : "undefined";

                writer.writeText(
                        createDisableOnClickFunctionCall(link, processingText, processingGlyphicon, jQueryIDSelector),
                        null
                );

                writer.writeText("}", null);
                writer.endElement("script");
            }

            super.encodeEnd(context, component);
        } else {
            writer.endElement("span");
        }
    }

    private String createDisableOnClickFunctionCall(HtmlCommandLink link, String processingText,
                                                    String processingGlyphicon, String jQueryIDSelector) {
        StringBuffer sb = new StringBuffer();
        sb.append("    butter.link.disableOnClick(data, ");
        sb.append(link.isAjaxShowWaitingDotsOnRequest()).append(",");

        if (link.getValue() != null) {
            sb.append("'").append(link.getValue()).append("'");
        } else {
            sb.append("null");
        }
        sb.append(",'");

        sb.append(processingText).append("','");
        sb.append(link.getGlyphicon()).append("','");
        sb.append(processingGlyphicon).append("',");<commit_msg>#8 commandLink: reduce parent renderer calls<commit_after>package de.larmic.butterfaces.component.renderkit.html_basic.action;

import de.larmic.butterfaces.component.html.action.HtmlCommandLink;
import de.larmic.butterfaces.resolver.AjaxClientIdResolver;
import de.larmic.butterfaces.resolver.WebXmlParameters;
import de.larmic.butterfaces.util.StringUtils;

import javax.faces.component.*;
import javax.faces.component.behavior.AjaxBehavior;
import javax.faces.component.behavior.ClientBehaviorHolder;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.FacesRenderer;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.List;
import java.util.Map;

/**
 * Created by larmic on 16.09.14.
 */
@FacesRenderer(componentFamily = HtmlCommandLink.COMPONENT_FAMILY, rendererType = HtmlCommandLink.RENDERER_TYPE)
public class CommandLinkRenderer extends com.sun.faces.renderkit.html_basic.CommandLinkRenderer {

    private WebXmlParameters webXmlParameters;

    /**
     * Will be set in renderAsActive if f:ajax child with onevent attribute exists.
     */
    private String onEventCallback = null;

    @Override
    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
        this.onEventCallback = null;

        final HtmlCommandLink link = (HtmlCommandLink) component;
        final ResponseWriter writer = context.getResponseWriter();

        webXmlParameters = new WebXmlParameters(context.getExternalContext());

        if (!link.isDisabled()) {
            super.encodeBegin(context, component);
        } else {
            writer.startElement("span", component);
            writeIdAttributeIfNecessary(context, writer, component);
            writeCommonLinkAttributes(writer, component);
            if (StringUtils.isNotEmpty(link.getStyle())) {
                writer.writeAttribute("style", link.getStyle(), "style");
            }
            this.writeValue(component, writer);
        }
    }

    @Override
    protected boolean shouldWriteIdAttribute(UIComponent component) {
        return true;
    }

    @Override
    protected void writeCommonLinkAttributes(final ResponseWriter writer, final UIComponent component) throws IOException {
        final HtmlCommandLink link = (HtmlCommandLink) component;
        final String styleClass = (String) component.getAttributes().get("styleClass");

        final StringBuilder generatedStyleClass = new StringBuilder(StringUtils.isEmpty(styleClass) ? "" : styleClass);

        if (link.isDisabled()) {
            generatedStyleClass.append(" btn-disabled");
        }
        if (StringUtils.isEmpty(link.getGlyphicon())) {
            generatedStyleClass.append(" no-glyphicon");
        }

        if (generatedStyleClass.length() > 0) {
            writer.writeAttribute("class", generatedStyleClass.toString(), "styleClass");
        }
    }

    @Override
    public void decode(FacesContext context, UIComponent component) {
        final ExternalContext external = context.getExternalContext();
        final Map<String, String> params = external.getRequestParameterMap();
        final String resetValues = params.get("javax.faces.partial.resetValues");
        final String render = params.get("javax.faces.partial.render");

        if (StringUtils.isNotEmpty(resetValues) && StringUtils.isNotEmpty(render) && Boolean.valueOf(resetValues)) {
            final String[] split = render.split(" ");

            for (String clientId : split) {
                final UIComponent renderComponent = context.getViewRoot().findComponent(clientId);
                resetValues(renderComponent);
            }
        }

        super.decode(context, component);
    }

    private void resetValues(final UIComponent component) {
        if (component == null) {
            return;
        }

        for (UIComponent child : component.getChildren()) {
            resetValues(child);
        }

        if (component instanceof UIOutput) {
            ((UIOutput) component).resetValue();
        } else if (component instanceof EditableValueHolder) {
            ((EditableValueHolder) component).resetValue();
        }
    }

    @Override
    public void encodeEnd(final FacesContext context, final UIComponent component) throws IOException {
        final HtmlCommandLink link = (HtmlCommandLink) component;
        final ResponseWriter writer = context.getResponseWriter();

        if (!link.isDisabled()) {
            if (link.isAjaxDisableLinkOnRequest()) {
                writer.startElement("script", component);
                writer.writeText("function " + getOnEventListenerName(component) + "(data) {", null);
                if (StringUtils.isNotEmpty(onEventCallback)) {
                    writer.writeText("    " + onEventCallback + "(data);", null);
                }

                final String processingText = createAjaxProcessingText(link);
                final String processingGlyphicon = createAjaxProcessingGlypicon(link);

                final AjaxClientIdResolver ajaxClientIdResolver = new AjaxClientIdResolver(link);
                final String jQueryIDSelector = link.isAjaxDisableRenderRegionsOnRequest()
                        ? ajaxClientIdResolver.getjQueryRenderIDSelector() : "undefined";

                writer.writeText(
                        createDisableOnClickFunctionCall(link, processingText, processingGlyphicon, jQueryIDSelector),
                        null
                );

                writer.writeText("}", null);
                writer.endElement("script");
            }
            writer.endElement("a");
        } else {
            writer.endElement("span");
        }
    }

    private String createDisableOnClickFunctionCall(HtmlCommandLink link, String processingText,
                                                    String processingGlyphicon, String jQueryIDSelector) {
        StringBuffer sb = new StringBuffer();
        sb.append("    butter.link.disableOnClick(data, ");
        sb.append(link.isAjaxShowWaitingDotsOnRequest()).append(",");

        if (link.getValue() != null) {
            sb.append("'").append(link.getValue()).append("'");
        } else {
            sb.append("null");
        }
        sb.append(",'");

        sb.append(processingText).append("','");
        sb.append(link.getGlyphicon()).append("','");
        sb.append(processingGlyphicon).append("',");
{'fraction_non_alphanumeric': 0.10263704159298839, 'fraction_numerical': 0.0011532251864380717, 'mean_word_length': 2.7573656845753898, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2022221', 'n_tokens_mistral': 3287, 'n_tokens_neox': 3201, 'n_words': 643}