org.eclipse.che.ide.jsonrpc.impl.ResponseDispatcher.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.che.ide.jsonrpc.impl.ResponseDispatcher.java

Source

/*******************************************************************************
 * Copyright (c) 2012-2016 Codenvy, S.A.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Codenvy, S.A. - initial API and implementation
 *******************************************************************************/
package org.eclipse.che.ide.jsonrpc.impl;

import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;

import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.promises.client.PromiseError;
import org.eclipse.che.api.promises.client.js.Executor;
import org.eclipse.che.api.promises.client.js.Promises;
import org.eclipse.che.api.promises.client.js.RejectFunction;
import org.eclipse.che.api.promises.client.js.ResolveFunction;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.util.loging.Log;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Dispatches incoming json rpc responses
 *
 * @author Dmitry Kuleshov
 */
@Singleton
public class ResponseDispatcher {
    private final Map<String, ResolveFunction> promises = new HashMap<>();
    private final Map<String, RejectFunction> rejectFunctions = new HashMap<>();
    private final Map<String, Class<?>> resultClasses = new HashMap<>();

    private final DtoFactory dtoFactory;

    @Inject
    public ResponseDispatcher(DtoFactory dtoFactory) {
        this.dtoFactory = dtoFactory;
    }

    /**
     * Dispatches json rpc response received from endpoint identified by a high
     * level identifier and represented as a json object.
     *
     * @param endpointId
     *         high level endpoint identifier
     * @param incomingJson
     *         json object
     */
    public void dispatch(String endpointId, JSONObject incomingJson) {
        Log.debug(getClass(), "Dispatching a response from: " + endpointId + ", json: " + incomingJson);

        final String id = getId(incomingJson);
        Log.debug(getClass(), "Extracted response id: " + id);

        final String key = endpointId + '@' + id;
        Log.debug(getClass(), "Combined response key: " + key);

        if (incomingJson.containsKey("result")) {
            Log.debug(getClass(), "It's a response with result field, processing result");

            final Class resultClass = resultClasses.get(key);
            Log.debug(getClass(), "Extracted response result class: " + resultClass);

            processResult(endpointId, id, resultClass, incomingJson.get("result"));
        } else {
            Log.debug(getClass(), "It's a response with error field, processing error");

            processError(endpointId, id, incomingJson.get("error"));
        }
    }

    /**
     * Register and get a promise that will be resolved when specified response
     * will be dispatched.
     *
     * @param endpointId
     *         high level endpoint identifier
     * @param id
     *         request identifier
     * @param resultClass
     *         class of request result that is contained within response
     *
     * @return promise with result dto
     */
    public <T> Promise<T> getPromise(final String endpointId, final String id, final Class<T> resultClass) {
        Log.debug(getClass(), "Registering single promise for: " + endpointId + ", request id: " + id
                + "result class: " + resultClass);

        return Promises.create(new Executor.ExecutorBody<T>() {
            @Override
            public void apply(ResolveFunction<T> resolve, RejectFunction reject) {
                promises.put(endpointId + '@' + id, resolve);
                resultClasses.put(endpointId + '@' + id, resultClass);
                rejectFunctions.put(endpointId + '@' + id, reject);
            }
        });
    }

    /**
     * Register and get a promise that will be resolved when specified response
     * will be dispatched. The response result is represented as list of objects
     * that has a type defined in a corresponding parameter.
     *
     * @param endpointId
     *         high level endpoint identifier
     * @param id
     *         request identifier
     * @param resultClass
     *         class of request result that is contained within response
     *
     * @return promise with result dto
     */
    public <T> Promise<List<T>> getListPromise(final String endpointId, final String id,
            final Class<T> resultClass) {
        Log.debug(getClass(), "Registering list of promises for: " + endpointId + ", request id: " + id
                + "result class: " + resultClass);

        return Promises.create(new Executor.ExecutorBody<List<T>>() {
            @Override
            public void apply(ResolveFunction<List<T>> resolve, RejectFunction reject) {
                promises.put(endpointId + '@' + id, resolve);
                resultClasses.put(endpointId + '@' + id, resultClass);
                rejectFunctions.put(endpointId + '@' + id, reject);
            }
        });
    }

    private <R> void applyObject(String combinedId, JSONObject result, Class<R> resultClass) {
        ResolveFunction<R> resolveFunction = promises.get(combinedId);
        final R dto = dtoFactory.createDtoFromJson(result.toString(), resultClass);
        resolveFunction.apply(dto);
    }

    private <R> void applyArray(String combinedId, JSONArray result, Class<R> resultClass) {
        ResolveFunction<List<R>> resolveFunction = promises.get(combinedId);
        final List<R> dto = dtoFactory.createListDtoFromJson(result.toString(), resultClass);
        resolveFunction.apply(dto);
    }

    private void processResult(String endpointId, String id, Class resultClass, JSONValue result) {
        final String combinedId = endpointId + '@' + id;
        final JSONObject resultObject = result.isObject();

        if (resultObject != null) {
            applyObject(combinedId, resultObject, resultClass);
        } else {
            final JSONArray resultArray = result.isArray();
            applyArray(combinedId, resultArray, resultClass);
        }
    }

    private void processError(final String endpointId, final String id, final JSONValue error) {
        rejectFunctions.get(endpointId + '@' + id).apply(new PromiseError() {
            @Override
            public String getMessage() {
                return error.toString();
            }

            @Override
            public Throwable getCause() {
                return null;
            }
        });
    }

    private String getId(JSONObject incomingJson) {
        final JSONValue idValue = incomingJson.get("id");
        final JSONString idString = idValue.isString();
        if (idString == null) {
            return Long.toString((long) idValue.isNumber().doubleValue());
        } else {
            return idString.stringValue();
        }
    }
}