All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.larmic.butterfaces.component.behavior.JsfAjaxRequest Maven / Gradle / Ivy

package de.larmic.butterfaces.component.behavior;

import de.larmic.butterfaces.util.StringUtils;

import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UINamingContainer;
import javax.faces.component.behavior.AjaxBehavior;
import javax.faces.component.behavior.ClientBehavior;
import javax.faces.context.FacesContext;
import java.util.*;

import static de.larmic.butterfaces.util.StringUtils.isNotEmpty;
import static java.util.Objects.requireNonNull;

/**
 * Builds an ajax request call that depends on the JSF Javascript API under https://docs.oracle.com/cd/E17802_01/j2ee/javaee/javaserverfaces/2.0/docs/js-api/symbols/jsf.ajax.html#.request
 */
public class JsfAjaxRequest {

    private final String source;
    private String event;
    private String execute;
    private String render;
    private List onEventHandlers = new ArrayList<>();
    private List onErrorHandlers = new ArrayList<>();
    private String params;
    private String behaviorEvent;

    /**
     * Constructor.
     *
     * @param source     the DOM element that triggered this Ajax request, or an id string of the element to use as the triggering
     *                   element
     * @param isIdString if set to true the source string will be wrapped in ''
     */
    public JsfAjaxRequest(String source, boolean isIdString) {
        requireNonNull(source, "source attribute may not be empty!");
        if (isIdString) {
            this.source = "'" + source + "'";
        } else {
            this.source = source;
        }
    }

    public JsfAjaxRequest(String source, boolean isIdString, AjaxBehavior ajaxBehavior, String event) {
        this(source, isIdString);

        if (!ajaxBehavior.isDisabled()) {
            if (ajaxBehavior.getExecute() != null) {
                this.setExecute(StringUtils.joinWithSpaceSeparator(ajaxBehavior.getExecute()));
            }
            if (ajaxBehavior.getRender() != null) {
                this.setRenderAsList(ajaxBehavior.getRender());
            }
            if (ajaxBehavior.getOnevent() != null) {
                this.addOnEventHandler(ajaxBehavior.getOnevent());
            }
            if (ajaxBehavior.getOnerror() != null) {
                this.addOnErrorHandler(ajaxBehavior.getOnerror());
            }
            this.setEvent(event);
            this.setBehaviorEvent(event);
        }
    }

    /**
     * @param event The DOM event that triggered this Ajax request.
     * @return the actual instance of {@link JsfAjaxRequest}
     */
    public JsfAjaxRequest setEvent(String event) {
        this.event = event;
        return this;
    }

    /**
     * @param execute space seperated list of client identifiers
     * @return the actual instance of {@link JsfAjaxRequest}
     */
    public JsfAjaxRequest setExecute(String execute) {
        this.execute = execute;
        return this;
    }

    /**
     * @param render space seperated list of client identifiers
     * @return the actual instance of {@link JsfAjaxRequest}
     */
    public JsfAjaxRequest setRender(String render) {
        this.render = render;
        return this;
    }

    public JsfAjaxRequest setRender(final UIComponentBase component, final String eventName) {
        this.render = StringUtils.joinWithSpaceSeparator(createRerenderIds(component, eventName));
        return this;
    }

    // Returns the resolved (client id) for a particular id.
    public static String getResolvedId(final UIComponent component, final String id) {
        if (id.equals("@all") || id.equals("@none") || id.equals("@form") || id.equals("@this")) {
            return id;
        }

        UIComponent resolvedComponent = component.findComponent(id);
        if (resolvedComponent == null) {
            final FacesContext context = FacesContext.getCurrentInstance();
            if (context != null && id.charAt(0) == UINamingContainer.getSeparatorChar(context)) {
                return id.substring(1);
            }
            return id;
        }

        return resolvedComponent.getClientId();
    }

    /**
     * @param renderIds list of client identifiers
     * @return the actual instance of {@link JsfAjaxRequest}
     */
    public JsfAjaxRequest setRenderAsList(final Collection renderIds) {
        final StringBuilder renderBuilder = new StringBuilder();

        if (!renderIds.isEmpty()) {
            final Iterator iterator = renderIds.iterator();
            while (iterator.hasNext()) {
                renderBuilder.append(iterator.next());

                if (iterator.hasNext()) {
                    renderBuilder.append(" ");
                }
            }
            render = renderBuilder.toString();
        }
        return this;
    }

    public JsfAjaxRequest addRender(final String render) {
        if (StringUtils.isNotEmpty(render)) {
            this.render = this.render == null ? render : this.render + " " + render;
        }
        return this;
    }

    /**
     * @param params object containing parameters to include in the request
     * @return the actual instance of {@link JsfAjaxRequest}
     */
    public JsfAjaxRequest setParams(String params) {
        this.params = params;
        return this;
    }

    /**
     * @param behaviorEvent ??
     * @return the actual instance of {@link JsfAjaxRequest}
     */
    public JsfAjaxRequest setBehaviorEvent(String behaviorEvent) {
        this.behaviorEvent = behaviorEvent;
        return this;
    }

    /**
     * @param functionString function to callback for event
     * @return the actual instance of {@link JsfAjaxRequest}
     */
    public JsfAjaxRequest addOnEventHandler(String functionString) {
        if (StringUtils.isNotEmpty(functionString)) {
            onEventHandlers.add(functionString);
        }
        return this;
    }

    /**
     * @param functionString function to callback for error
     * @return the actual instance of {@link JsfAjaxRequest}
     */
    public JsfAjaxRequest addOnErrorHandler(String functionString) {
        if (StringUtils.isNotEmpty(functionString)) {
            onErrorHandlers.add(functionString);
        }
        return this;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("jsf.ajax.request(");
        sb.append(source);
        if (isNotEmpty(event)) {
            sb.append(", '").append(event).append("'");
        }
        if (hasOptions()) {
            sb.append(", {");

            boolean isAtLeastOneOptionSet = false;
            if (isNotEmpty(execute)) {
                sb.append("execute: '").append(execute).append("'");
                isAtLeastOneOptionSet = true;
            }

            if (isNotEmpty(render)) {
                writeSeparatorIfNecessary(sb, isAtLeastOneOptionSet);
                sb.append("render: '").append(render).append("'");
                isAtLeastOneOptionSet = true;
            }

            if (!onEventHandlers.isEmpty()) {
                writeSeparatorIfNecessary(sb, isAtLeastOneOptionSet);
                sb.append("onevent: ").append(renderFunctionCalls(onEventHandlers));
                isAtLeastOneOptionSet = true;
            }

            if (!onErrorHandlers.isEmpty()) {
                writeSeparatorIfNecessary(sb, isAtLeastOneOptionSet);
                sb.append("onerror: ").append(renderFunctionCalls(onErrorHandlers));
                isAtLeastOneOptionSet = true;
            }

            if (isNotEmpty(params)) {
                writeSeparatorIfNecessary(sb, isAtLeastOneOptionSet);
                sb.append("params: ").append(params);
                isAtLeastOneOptionSet = true;
            }

            if (isNotEmpty(behaviorEvent)) {
                writeSeparatorIfNecessary(sb, isAtLeastOneOptionSet);
                sb.append("'javax.faces.behavior.event': '").append(behaviorEvent).append("'");
            }

            sb.append("}");
        }
        sb.append(");");
        return sb.toString();
    }

    public static AjaxBehavior findFirstActiveAjaxBehavior(final UIComponentBase component, final String eventName) {
        if (component != null) {
            final List behaviors = component.getClientBehaviors().get(eventName);
            if (behaviors != null) {
                for (ClientBehavior behavior : behaviors) {
                    if (behavior instanceof AjaxBehavior && !((AjaxBehavior) behavior).isDisabled()) {
                        return (AjaxBehavior) behavior;
                    }
                }
            }
        }

        return null;
    }

    public static List createRerenderIds(final UIComponentBase component, final String eventName) {
        final List idsToRender = new ArrayList<>();
        final Map> behaviors = component.getClientBehaviors();
        final List refreshBehaviors = behaviors.get(eventName);

        if (refreshBehaviors == null) {
            return new ArrayList<>();
            //throw new IllegalArgumentException("Ajax event '" + eventName + "' not found on component '" + component.getClientId() + "'.");
        }

        boolean enabledAjaxEventFound = false;

        if (!refreshBehaviors.isEmpty()) {
            for (ClientBehavior refreshBehavior : refreshBehaviors) {
                if (refreshBehavior instanceof AjaxBehavior) {
                    final AjaxBehavior ajaxBehavior = (AjaxBehavior) refreshBehavior;

                    if (!ajaxBehavior.isDisabled()) {
                        if (ajaxBehavior.getRender() != null && !ajaxBehavior.getRender().isEmpty()) {
                            for (String singleRender : ajaxBehavior.getRender()) {
                                idsToRender.add(getResolvedId(component, singleRender));
                            }
                        }

                        enabledAjaxEventFound = true;
                    }
                }
            }
        }

        if (!enabledAjaxEventFound) {
            return new ArrayList<>();
            //throw new IllegalStateException("Ajax event '" + eventName + "' on component '" + component.getClientId() + "' is disabled.");
        }

        return idsToRender;
    }

    private void writeSeparatorIfNecessary(StringBuilder sb, boolean isAtLeastOneOptionSet) {
        if (isAtLeastOneOptionSet) {
            sb.append(", ");
        }
    }

    private String renderFunctionCalls(List functions) {
        final StringBuilder sb = new StringBuilder("function(data){");
        for (String function : functions) {
            sb.append(function);
            if (!function.contains(")")) {
                // this is not a function call, so call it manually
                sb.append("(data)");
            }
            sb.append(";");
        }
        sb.append("}");
        return sb.toString();
    }

    private boolean hasOptions() {
        return isNotEmpty(execute)
                || isNotEmpty(render)
                || !onEventHandlers.isEmpty()
                || !onErrorHandlers.isEmpty()
                || isNotEmpty(params)
                || isNotEmpty(behaviorEvent);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy