com.github.nmorel.gwtjackson.rest.api.RestRequestBuilder.java Source code

Java tutorial

Introduction

Here is the source code for com.github.nmorel.gwtjackson.rest.api.RestRequestBuilder.java

Source

/*
 * Copyright 2015 Nicolas Morel
 *
 * 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 com.github.nmorel.gwtjackson.rest.api;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.github.nmorel.gwtjackson.client.ObjectReader;
import com.github.nmorel.gwtjackson.client.ObjectWriter;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestBuilder.Method;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.URL;

/**
 * @author Nicolas Morel
 */
public class RestRequestBuilder<B, R> {

    private static String defaultApplicationPath = "";

    public static void setDefaultApplicationPath(String defaultApplicationPath) {
        if (null == defaultApplicationPath) {
            throw new IllegalArgumentException("Application path cannot be null");
        }
        RestRequestBuilder.defaultApplicationPath = defaultApplicationPath;
    }

    /**
     * HTTP method to use when opening a JavaScript XmlHttpRequest object.
     */
    private Method method;

    /**
     * Application path to concatenate before the url
     */
    private String applicationPath = defaultApplicationPath;

    /**
     * URL to use when opening a JavaScript XmlHttpRequest object.
     */
    private String url;

    /**
     * User to use when opening a JavaScript XmlHttpRequest object.
     */
    private String user;

    /**
     * Password to use when opening a JavaScript XmlHttpRequest object.
     */
    private String password;

    /**
     * Whether to include credentials for a Cross Origin Request.
     */
    private Boolean includeCredentials;

    /**
     * Timeout in milliseconds before the request timeouts and fails.
     */
    private Integer timeoutMillis;

    /**
     * Map of header name to value that will be added to the JavaScript
     * XmlHttpRequest object before sending a request.
     */
    private Map<String, String> headers;

    private Map<String, List<Object>> queryParams;

    private Map<String, Object> pathParams;

    private B body;

    private ObjectWriter<B> bodyConverter;

    private ObjectReader<R> responseConverter;

    private RestCallback<R> callback;

    public RestRequestBuilder() {
    }

    public RestRequestBuilder<B, R> method(Method method) {
        this.method = method;
        return this;
    }

    public RestRequestBuilder<B, R> applicationPath(String applicationPath) {
        this.applicationPath = applicationPath;
        return this;
    }

    public RestRequestBuilder<B, R> url(String url) {
        this.url = url;
        return this;
    }

    public RestRequestBuilder<B, R> user(String user) {
        this.user = user;
        return this;
    }

    public RestRequestBuilder<B, R> password(String password) {
        this.password = password;
        return this;
    }

    public RestRequestBuilder<B, R> includeCredentials(boolean includeCredentials) {
        this.includeCredentials = includeCredentials;
        return this;
    }

    public RestRequestBuilder<B, R> timeout(int timeoutMillis) {
        this.timeoutMillis = timeoutMillis;
        return this;
    }

    public RestRequestBuilder<B, R> addHeader(String name, String value) {
        if (null == headers) {
            headers = new LinkedHashMap<String, String>();
        }
        headers.put(name, value);
        return this;
    }

    public Map<String, String> getHeaders() {
        return headers;
    }

    /**
     * Special case where you want to add a query param without value like ?key1&key2=value
     *
     * @param name Name of the parameter
     *
     * @return this builder
     */
    public RestRequestBuilder<B, R> addQueryParam(String name) {
        List<Object> allValues = getQueryParams(name);
        allValues.add(null);
        return this;
    }

    /**
     * Add a query parameter. If a null value is passed, the param is ignored.
     *
     * @param name Name of the parameter
     * @param value Value of the parameter
     *
     * @return this builder
     */
    public RestRequestBuilder<B, R> addQueryParam(String name, Object value) {
        if (null != value) {
            List<Object> allValues = getQueryParams(name);
            allValues.add(value);
        }
        return this;
    }

    /**
     * Add a query parameter. If a null or empty collection is passed, the param is ignored.
     *
     * @param name Name of the parameter
     * @param values Value of the parameter
     *
     * @return this builder
     */
    public RestRequestBuilder<B, R> addQueryParam(String name, Collection<Object> values) {
        if (null != values) {
            List<Object> allValues = getQueryParams(name);
            allValues.addAll(values);
        }
        return this;
    }

    /**
     * Add a query parameter. If a null or empty array is passed, the param is ignored.
     *
     * @param name Name of the parameter
     * @param values Value of the parameter
     *
     * @return this builder
     */
    public RestRequestBuilder<B, R> addQueryParam(String name, Object[] values) {
        if (null != values) {
            List<Object> allValues = getQueryParams(name);
            for (Object value : values) {
                allValues.add(value);
            }
        }
        return this;
    }

    /**
     * Add a query parameter. If a null or empty collection is passed, the param is ignored.
     *
     * @param name Name of the parameter
     * @param values Value of the parameter
     *
     * @return this builder
     */
    public RestRequestBuilder<B, R> addQueryParam(String name, Iterable<Object> values) {
        if (null != values) {
            List<Object> allValues = getQueryParams(name);
            for (Object value : values) {
                allValues.add(value);
            }
        }
        return this;
    }

    private List<Object> getQueryParams(String name) {
        if (null == queryParams) {
            queryParams = new LinkedHashMap<String, List<Object>>();
        }
        List<Object> allValues = queryParams.get(name);
        if (null == allValues) {
            allValues = new ArrayList<Object>();
            queryParams.put(name, allValues);
        }
        return allValues;
    }

    public Map<String, List<Object>> getQueryParams() {
        return queryParams;
    }

    public RestRequestBuilder<B, R> addPathParam(String name, Object value) {
        if (null == pathParams) {
            pathParams = new LinkedHashMap<String, Object>();
        }
        pathParams.put(name, value);
        return this;
    }

    public Map<String, Object> getPathParams() {
        return pathParams;
    }

    public RestRequestBuilder<B, R> body(B body) {
        this.body = body;
        return this;
    }

    public RestRequestBuilder<B, R> bodyConverter(ObjectWriter<B> bodyConverter) {
        this.bodyConverter = bodyConverter;
        return this;
    }

    public RestRequestBuilder<B, R> responseConverter(ObjectReader<R> responseConverter) {
        this.responseConverter = responseConverter;
        return this;
    }

    public RestRequestBuilder<B, R> callback(RestCallback<R> callback) {
        this.callback = callback;
        return this;
    }

    public Request send() {
        if (null == method) {
            throw new IllegalArgumentException("The method is required");
        }
        if (null == url) {
            throw new IllegalArgumentException("The url is required");
        }

        String urlWithParams = url;
        if (null != pathParams && !pathParams.isEmpty()) {
            for (Entry<String, Object> pathParam : pathParams.entrySet()) {
                urlWithParams = urlWithParams.replace("{" + pathParam.getKey() + "}",
                        pathParam.getValue() == null ? "" : pathParam.getValue().toString());
            }
        }

        StringBuilder urlBuilder = new StringBuilder(applicationPath);
        if (!applicationPath.endsWith("/") && !urlWithParams.startsWith("/")) {
            urlBuilder.append('/');
        }
        urlBuilder.append(urlWithParams);

        if (null != queryParams && !queryParams.isEmpty()) {
            boolean first = true;
            for (Entry<String, List<Object>> params : queryParams.entrySet()) {
                String name = URL.encodeQueryString(params.getKey());
                if (null != params.getValue() && !params.getValue().isEmpty()) {
                    for (Object param : params.getValue()) {
                        if (first) {
                            urlBuilder.append('?');
                            first = false;
                        } else {
                            urlBuilder.append('&');
                        }
                        urlBuilder.append(name);
                        if (null != param) {
                            urlBuilder.append('=');
                            urlBuilder.append(URL.encodeQueryString(param.toString()));
                        }
                    }
                }
            }
        }

        RequestBuilder builder = new RequestBuilder(method, urlBuilder.toString());
        builder.setHeader("Content-Type", "application/json; charset=utf-8");
        builder.setHeader("Accept", "application/json");

        if (null != headers && !headers.isEmpty()) {
            for (Entry<String, String> header : headers.entrySet()) {
                builder.setHeader(header.getKey(), header.getValue());
            }
        }

        if (null != user) {
            builder.setUser(user);
        }

        if (null != password) {
            builder.setPassword(password);
        }

        if (null != includeCredentials) {
            builder.setIncludeCredentials(includeCredentials);
        }

        if (null != timeoutMillis) {
            builder.setTimeoutMillis(timeoutMillis);
        }

        if (null != body) {
            if (null != bodyConverter) {
                builder.setRequestData(bodyConverter.write(body));
            } else {
                builder.setRequestData(body.toString());
            }
        }

        builder.setCallback(new RestRequestCallback<R>(responseConverter, callback));

        try {
            return builder.send();
        } catch (RequestException e) {
            throw new RestException(e);
        }
    }

}