org.wicketstuff.js.ext.ExtEventAjaxBehavior.java Source code

Java tutorial

Introduction

Here is the source code for org.wicketstuff.js.ext.ExtEventAjaxBehavior.java

Source

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *  http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.wicketstuff.js.ext;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.AjaxAttributeName;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.attributes.CallbackParameter;
import org.apache.wicket.request.IRequestParameters;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.util.string.StringValue;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wicketstuff.js.ext.util.ExtEventListener;
import org.wicketstuff.js.ext.util.JSONIdentifier;

public class ExtEventAjaxBehavior extends AbstractDefaultAjaxBehavior {

    static final Logger log = LoggerFactory.getLogger(ExtEventAjaxBehavior.class);

    private final List<ExtEventListener> listeners = new ArrayList<ExtEventListener>();
    private final String[] parameters;

    /**
     * Creates an ExtJS Ajax behavior for a callback function without any parameters.
     */
    public ExtEventAjaxBehavior() {
        this.parameters = new String[0];
    }

    /**
     * Creates an ExtJS Ajax behavior for a callback function with the given parameter names.
     *
     * @param parameters the parameter names of the callback function of this behavior
     */
    public ExtEventAjaxBehavior(String... parameters) {
        this.parameters = parameters;
    }

    /**
     * @return the parameter names of the callback function of this behavior
     */
    public String[] getParameters() {
        return parameters;
    }

    @Override
    protected final void respond(AjaxRequestTarget target) {
        String[] parameters = getParameters();
        IRequestParameters parameterMap = RequestCycle.get().getRequest().getQueryParameters();
        Map<String, JSONArray> filtered = new HashMap<String, JSONArray>();
        for (String parameter : parameters) {
            List<StringValue> values = parameterMap.getParameterValues(parameter);
            if (values == null) {
                continue;
            }
            JSONArray jsonObjects = new JSONArray();
            try {
                for (StringValue stringValue : values) {
                    String value = stringValue.toString();
                    if (value.startsWith("[")) {
                        JSONTokener tokener = new JSONTokener(value);
                        JSONArray subVals = new JSONArray(tokener);
                        for (int i = 0; i < subVals.length(); i++) {
                            jsonObjects.put(subVals.get(i));
                        }
                    } else if (value.startsWith("{")) {
                        JSONTokener tokener = new JSONTokener(value);
                        jsonObjects.put(new JSONObject(tokener));
                    } else if ("null".equals(value)) {
                        jsonObjects.put(JSONObject.NULL);
                    } else {
                        jsonObjects.put(value);
                    }
                }
            } catch (JSONException e) {
                log.error("Could not parse request parameters", e);
            }
            filtered.put(parameter, jsonObjects);
        }
        handle(target, filtered);
    }

    private void handle(AjaxRequestTarget target, Map<String, JSONArray> parameters) {
        for (ExtEventListener listener : listeners) {
            listener.onEvent(target, parameters);
        }
    }

    /**
     * Encodes and adds the this.fireEvent method's parameters to the wickAjaxURL {@inheritDoc}
     */
    public final JSONIdentifier getEventScript() {
        CallbackParameter[] callbackParameters = new CallbackParameter[getParameters().length];
        int index = 0;
        for (String parameter : getParameters()) {
            final String stringifyNonStrings = "typeof " + parameter + " === 'string' ? " + parameter
                    + " : JSON.stringify(" + parameter + ")";
            callbackParameters[index] = CallbackParameter.converted(parameter, stringifyNonStrings);
            index++;
        }
        return new JSONIdentifier(getCallbackFunction(callbackParameters));
    }

    /**
     * FIXME: code copy &amp; pasted from wicket; the Component should not be rendered as attribute
     * as this will trigger a precondition check (whether an element with the markupId exists)
     *
     * Generates the body the {@linkplain #getCallbackFunction(CallbackParameter...) callback
     * function}. To embed this code directly into a piece of javascript, make sure any context
     * parameters are available as local variables, global variables or within the closure.
     *
     * @param extraParameters parameters for the callback
     * @return The body of the {@linkplain #getCallbackFunction(CallbackParameter...) callback
     *         function}.
     */
    public CharSequence getCallbackFunctionBody(CallbackParameter... extraParameters) {
        AjaxRequestAttributes attributes = getAttributes();
        attributes.setEventNames();
        CharSequence attrsJson = renderAjaxAttributes(getComponent().getPage(), attributes);
        StringBuilder sb = new StringBuilder();
        sb.append("var attrs = ");
        sb.append(attrsJson);
        sb.append(";\n");
        sb.append("var params = {");
        boolean first = true;
        for (CallbackParameter curExtraParameter : extraParameters) {
            if (curExtraParameter.getAjaxParameterName() != null) {
                if (!first)
                    sb.append(',');
                else
                    first = false;
                sb.append('\'').append(curExtraParameter.getAjaxParameterName()).append("': ")
                        .append(curExtraParameter.getAjaxParameterCode());
            }
        }
        sb.append("};\n");
        if (attributes.getExtraParameters().isEmpty())
            sb.append("attrs." + AjaxAttributeName.EXTRA_PARAMETERS + " = params;\n");
        else
            sb.append("attrs." + AjaxAttributeName.EXTRA_PARAMETERS + " = Wicket.merge(attrs."
                    + AjaxAttributeName.EXTRA_PARAMETERS + ", params);\n");
        sb.append("Wicket.Ajax.ajax(attrs);\n");
        return sb;
    }

    @Override
    protected CharSequence getPreconditionScript() {
        return "return true;";
    }

    public void addListener(final ExtEventListener listener) {
        listeners.add(listener);
    }
}