com.google.api.explorer.client.embedded.EmbeddedParameterFormPresenter.java Source code

Java tutorial

Introduction

Here is the source code for com.google.api.explorer.client.embedded.EmbeddedParameterFormPresenter.java

Source

/*
 * Copyright (C) 2010 Google Inc.
 *
 * 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.google.api.explorer.client.embedded;

import com.google.api.explorer.client.AuthManager;
import com.google.api.explorer.client.AuthManager.AuthToken;
import com.google.api.explorer.client.base.ApiMethod;
import com.google.api.explorer.client.base.ApiRequest;
import com.google.api.explorer.client.base.ApiResponse;
import com.google.api.explorer.client.base.ApiService;
import com.google.api.explorer.client.base.ExplorerConfig;
import com.google.api.explorer.client.base.Schema;
import com.google.api.explorer.client.base.rest.RestApiRequest;
import com.google.api.explorer.client.routing.UrlBuilder;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;

/**
 * Presenter to handle to logic of the parameter form UI.
 *
 * @author jasonhall@google.com (Jason Hall)
 */
public class EmbeddedParameterFormPresenter {

    /**
     * Display object that can be controlled by the presenter.
     */
    public interface Display {
        /**
         * Set the method that should be shown in the display.
         *
         * @param service Service which contains the method to be shown.
         * @param method Method object which should be shown.
         * @param sortedParams Parameters that should be shown in the parameter form, in their final
         *        order.
         * @param paramValues Pre-defined values for the parameters that should be pre-filled in the
         *        request.
         * @param bodyText Text that should be shown in the body editor of the form.
         */
        void setMethod(ApiService service, ApiMethod method, SortedMap<String, Schema> sortedParams,
                Multimap<String, String> paramValues, String bodyText);

        /**
         * Returns the values from the form which are filled in.
         */
        Multimap<String, String> getParameterValues();

        /**
         * Returns the text from the request body editor as a serialized string.
         */
        String getBodyText();

        /**
         * Set the executing status on the display, which should give the user some sort of visual
         * indication that the user should anticipate a result.
         */
        void setExecuting(boolean executing);
    }

    /**
     * Interface that should be invoked when the parameter form has completed a request.
     *
     */
    public interface RequestFinishedCallback {
        /**
         * Method which is invoked when a request is about to be executed.
         *
         * @param request Request object which is about to be executed.
         */
        public void starting(ApiRequest request);

        /**
         * Method which is invoked when a request has been completed.
         *
         * @param request Request object which was executed.
         * @param response Response object which was generated from the request result.
         * @param startTime Time at which the request was started.
         * @param endTime Time at which the request completed.
         */
        public void finished(ApiRequest request, ApiResponse response, long startTime, long endTime);
    }

    private final AuthManager authManager;
    private final Display display;
    private ApiMethod method;
    private ApiService service;
    private RequestFinishedCallback callback;

    public EmbeddedParameterFormPresenter(AuthManager authManager, Display display,
            RequestFinishedCallback callback) {

        this.authManager = authManager;
        this.display = display;
        this.callback = callback;
    }

    public void selectMethod(ApiService service, ApiMethod method, Multimap<String, String> params) {
        this.method = Preconditions.checkNotNull(method);
        this.service = Preconditions.checkNotNull(service);

        Map<String, Schema> parameters = method.getParameters();
        SortedMap<String, Schema> sortedParams;
        if (parameters != null) {
            sortedParams = ImmutableSortedMap.copyOf(parameters,
                    new ParameterComparator(method.getParameterOrder()));
        } else {
            sortedParams = ImmutableSortedMap.of();
        }

        display.setMethod(service, method, sortedParams, params, getRequestBodyParam(params));
    }

    /**
     * Returns the request body specified by the "resource" key of the parameters block specified.
     */
    private String getRequestBodyParam(Multimap<String, String> params) {
        Collection<String> body = params.get(UrlBuilder.BODY_QUERY_PARAM_KEY);
        return body.isEmpty() ? null : Iterables.getLast(body);
    }

    public void submit() {
        Preconditions.checkState(method != null);
        final RestApiRequest req = new RestApiRequest(service, method);

        // If the user has declared a body, set it on the request.
        String body = display.getBodyText();
        if (!body.isEmpty()) {
            req.body = body;
            req.addHeader("Content-Type", "application/json");
        }

        Multimap<String, String> paramValues = display.getParameterValues();
        for (Map.Entry<String, String> entry : paramValues.entries()) {
            if (entry.getValue().isEmpty()) {
                continue;
            }
            req.getParamValues().put(entry.getKey(), entry.getValue());
        }

        // Do not send the API key if the service is a public-only API.
        req.setUseApiKey(!ExplorerConfig.PUBLIC_ONLY_APIS.contains(service.getName()));

        // Set the auth header if we have a token.
        AuthToken oauth2Token = authManager.getToken(service);
        if (oauth2Token != null) {
            req.addHeader("Authorization", "Bearer " + oauth2Token.getAuthToken());
        }

        display.setExecuting(true);

        final long start = System.currentTimeMillis();
        req.send(new AsyncCallback<ApiResponse>() {
            @Override
            public void onSuccess(ApiResponse response) {
                display.setExecuting(false);
                callback.finished(req, response, start, System.currentTimeMillis());
            }

            @Override
            public void onFailure(Throwable caught) {
                display.setExecuting(false);
                // TODO(jasonhall): Better error handling when request fails (i.e.,
                // cannot communicate at all).
                Window.alert("An error occured: " + caught.getMessage());
            }
        });

        // This has to be after the actual send so that the API key gets initialized properly.
        callback.starting(req);
    }

    /**
     * Comparator to sort parameter names. This checks the
     * {@link ApiMethod#getParameterOrder()} member for the explicit ordering,
     * then defaults to alphabetical order if neither are explicitly ordered.
     */
    @VisibleForTesting
    static class ParameterComparator implements Comparator<String> {
        private final List<String> parameterOrder;

        ParameterComparator(List<String> parameterOrder) {
            this.parameterOrder = parameterOrder == null ? ImmutableList.<String>of() : parameterOrder;
        }

        @Override
        public int compare(String o1, String o2) {
            int i1 = parameterOrder.indexOf(o1);
            int i2 = parameterOrder.indexOf(o2);

            if (i1 != -1) {
                if (i2 != -1) {
                    // Both are explicitly ordered, use relative ordering position to
                    // determine which goes first.
                    return i1 - i2;
                } else {
                    // Only o1 is explicitly ordered, it goes first.
                    return -1;
                }
            }

            if (i2 != -1) {
                // Only o2 is explicitly ordered, it goes first.
                return 1;
            }

            // Neither are explicitly ordered. Compare alphabetically.
            return o1.compareTo(o2);
        }
    }

    /**
     * Generate a String description in the form of:
     * <ul>
     * <li>Description, if available</li>
     * <li>Open parenthesis, then lowercase type, e.g., "(string"</li>
     * <li>Minimum and maximum, if available and within bounds, in the form of one
     * of:
     * <ul>
     * <li>2 - 10</li>
     * <li>2+</li>
     * <li>max 10</li>
     * </ul>
     * </li>
     * <li>Close paranthesis</li>
     */
    public static String generateDescriptionString(Schema param) {
        StringBuilder sb = new StringBuilder();
        String description = param.getDescription();
        String minimum = param.getMinimum();
        String maximum = param.getMaximum();

        // Don't bother displaying "0-4294967295" and just display "0+"
        if (maximum != null && maximum.length() > 9) {
            maximum = null;
        }
        // Likewise, don't bother displaying "-4294867295-0" and just
        // display "max 0"
        if (minimum != null && minimum.length() > 10) {
            minimum = null;
        }

        if (description != null) {
            sb.append(description).append(' ');
        }
        sb.append('(').append(param.getType().name().toLowerCase());
        if (minimum != null || maximum != null) {
            sb.append(", ");
        }
        if (minimum != null) {
            if (maximum != null) {
                sb.append(minimum).append('-').append(maximum);
            } else {
                sb.append(minimum).append("+");
            }
        } else if (maximum != null) {
            sb.append("max ").append(maximum);
        }
        sb.append(')');
        return sb.toString();
    }
}