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

org.butterfaces.component.behavior.JsfAjaxRequest Maven / Gradle / Ivy

There is a newer version: 3.5.0
Show newest version
/*
 * Copyright Lars Michaelis and Stephan Zerhusen 2016.
 * Distributed under the MIT License.
 * (See accompanying file README.md file or copy at http://opensource.org/licenses/MIT)
 */
package org.butterfaces.component.behavior;

import org.butterfaces.util.StringJoiner;
import org.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.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

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
 *
 * @author Lars Michaelis, Stephan Zerhusen
 */
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;
    private String delay;
    private boolean resetValues;

    /**
     * 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;
        }
    }

    /**
     * Creates {@link JsfAjaxRequest} using given {@link AjaxBehavior} to set ajax parameters.
     * 

* TODO maybe remove {@link AjaxBehavior} and find it by myself by using event string? */ public JsfAjaxRequest(final UIComponentBase component, AjaxBehavior ajaxBehavior, String event) { this(component.getClientId(), true); if (!ajaxBehavior.isDisabled()) { if (ajaxBehavior.getExecute() != null) { execute = convertStringListToJoinedString(ajaxBehavior.getExecute(), component); } if (ajaxBehavior.getRender() != null) { render = convertStringListToJoinedString(ajaxBehavior.getRender(), component); } if (ajaxBehavior.getOnevent() != null) { this.addOnEventHandler(ajaxBehavior.getOnevent()); } if (ajaxBehavior.getOnerror() != null) { this.addOnErrorHandler(ajaxBehavior.getOnerror()); } try { if (StringUtils.isNotEmpty(ajaxBehavior.getDelay())) { delay = ajaxBehavior.getDelay(); } resetValues = ajaxBehavior.isResetValues(); } catch (NoSuchMethodError e) { // do nothing. Delay and resetValues is supported by JSF 2.2.x } 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 delay delay in ms * @return the actual instance of {@link JsfAjaxRequest} */ public JsfAjaxRequest setDelay(String delay) { this.delay = delay; 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 = StringJoiner.on(' ').join(createRerenderIds(component, eventName)).toString(); return this; } public JsfAjaxRequest setResetValues(boolean resetValues) { this.resetValues = resetValues; 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 (StringUtils.isNotEmpty(event)) { sb.append(", '").append(event).append("'"); } if (hasOptions()) { sb.append(", {"); boolean isAtLeastOneOptionSet = false; if (StringUtils.isNotEmpty(execute)) { sb.append("execute: '").append(execute).append("'"); isAtLeastOneOptionSet = true; } if (StringUtils.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 (StringUtils.isNotEmpty(delay)) { writeSeparatorIfNecessary(sb, isAtLeastOneOptionSet); sb.append("delay: '").append(delay).append("'"); isAtLeastOneOptionSet = true; } if (resetValues) { writeSeparatorIfNecessary(sb, isAtLeastOneOptionSet); sb.append("resetValues: '").append(resetValues).append("'"); isAtLeastOneOptionSet = true; } if (StringUtils.isNotEmpty(params)) { writeSeparatorIfNecessary(sb, isAtLeastOneOptionSet); sb.append("params: ").append(params); isAtLeastOneOptionSet = true; } if (StringUtils.isNotEmpty(params)) { writeSeparatorIfNecessary(sb, isAtLeastOneOptionSet); sb.append("'butterfaces.params': ").append(params); isAtLeastOneOptionSet = true; } if (StringUtils.isNotEmpty(behaviorEvent)) { writeSeparatorIfNecessary(sb, isAtLeastOneOptionSet); sb.append("'javax.faces.behavior.event': '").append(behaviorEvent).append("'"); } sb.append("}"); } sb.append(");"); return sb.toString(); } 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 static String getResolvedId(final UIComponentBase 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(); } 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 StringUtils.isNotEmpty(execute) || StringUtils.isNotEmpty(render) || StringUtils.isNotEmpty(delay) || resetValues || !onEventHandlers.isEmpty() || !onErrorHandlers.isEmpty() || StringUtils.isNotEmpty(params) || StringUtils.isNotEmpty(behaviorEvent); } /** * @return a space joined string of given clientIds. */ private String convertStringListToJoinedString(final Collection clientIds) { return convertStringListToJoinedString(clientIds, null); } /** * @return a space joined string of given clientIds. If component is set all clientIds will be resolved to get full * qualified client id. */ private String convertStringListToJoinedString(final Collection clientIds, final UIComponentBase component) { if (clientIds.isEmpty()) { return null; } StringJoiner joiner = StringJoiner.on(' '); for (String clientId : clientIds) { if (StringUtils.isNotEmpty(clientId)) { if (component != null) { joiner = joiner.join(getResolvedId(component, clientId)); } else { joiner = joiner.join(clientId); } } } return joiner.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy