com.syncedsynapse.kore2.jsonrpc.ApiMethod.java Source code

Java tutorial

Introduction

Here is the source code for com.syncedsynapse.kore2.jsonrpc.ApiMethod.java

Source

/*
 * Copyright 2015 Synced Synapse. All rights reserved.
 *
 * 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.syncedsynapse.kore2.jsonrpc;

import android.os.Handler;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.syncedsynapse.kore2.jsonrpc.type.ApiParameter;
import com.syncedsynapse.kore2.utils.LogUtils;

import java.io.IOException;

/**
 * Abstract class base of all the JSON RPC API calls
 *
 * Every subclass represents a method on the JSON RPC API.
 *
 * Each subclass should implement constructors to represent each of the API call variations, and
 * call this class {@link #execute(HostConnection, ApiCallback, android.os.Handler) execute()}  to send
 * the call to the server.
 *
 * This class is a template which should be typed with the return type of specific the method call.
 */
public abstract class ApiMethod<T> {
    private static final String TAG = LogUtils.makeLogTag(ApiMethod.class);

    public static final String RESULT_NODE = "result";
    public static final String ERROR_NODE = "error";
    public static final String ID_NODE = "id";
    public static final String METHOD_NODE = "method";
    public static final String PARAMS_NODE = "params";

    /**
     * Id of the method call. Autoincremented for each method call
     */
    private static int lastId = 0;
    protected final int id;

    protected static final ObjectMapper objectMapper = new ObjectMapper();
    /**
     * Json object that will be used to generate the json representation of the current method call
     */
    protected final ObjectNode jsonRequest;

    /**
     * Constructor, sets up the necessary items to make the call later
     */
    public ApiMethod() {
        synchronized (this) {
            this.id = (++lastId % 10000);
        }

        // Create the rpc request object with the common fields according to JSON RPC spec
        jsonRequest = objectMapper.createObjectNode();
        jsonRequest.put("jsonrpc", "2.0");
        jsonRequest.put(METHOD_NODE, getMethodName());
        jsonRequest.put(ID_NODE, id);
    }

    /**
     * Returns the parameters node of the json request object
     * Creates one if necessary
     * @return Parameters node
     */
    protected ObjectNode getParametersNode() {
        ObjectNode params;
        if (jsonRequest.has(PARAMS_NODE)) {
            params = (ObjectNode) jsonRequest.get(PARAMS_NODE);
        } else {
            params = objectMapper.createObjectNode();
            jsonRequest.put(PARAMS_NODE, params);
        }

        return params;
    }

    /**
     * Adds a parameter to the request
     * @param parameter Parameter name
     * @param value Value to add
     */
    protected void addParameterToRequest(String parameter, int value) {
        getParametersNode().put(parameter, value);
    }

    /**
     * Adds a parameter to the request
     * @param parameter Parameter name
     * @param value Value to add
     */
    protected void addParameterToRequest(String parameter, String value) {
        if (value != null)
            getParametersNode().put(parameter, value);
    }

    /**
     * Adds a parameter to the request
     * @param parameter Parameter name
     * @param value Value to add
     */
    protected void addParameterToRequest(String parameter, Integer value) {
        if (value != null)
            getParametersNode().put(parameter, value);
    }

    /**
     * Adds a parameter to the request
     * @param parameter Parameter name
     * @param value Value to add
     */
    protected void addParameterToRequest(String parameter, Double value) {
        if (value != null)
            getParametersNode().put(parameter, value);
    }

    /**
     * Adds a parameter to the request
     * @param parameter Parameter name
     * @param value Value to add
     */
    protected void addParameterToRequest(String parameter, boolean value) {
        getParametersNode().put(parameter, value);
    }

    /**
     * Adds a parameter to the request
     * @param parameter Parameter name
     * @param values Values to add
     */
    protected void addParameterToRequest(String parameter, String[] values) {
        if (values != null) {
            final ArrayNode arrayNode = objectMapper.createArrayNode();
            for (int i = 0; i < values.length; i++) {
                arrayNode.add(values[i]);
            }
            getParametersNode().put(parameter, arrayNode);
        }
    }

    /**
     * Adds a parameter to the request
     * @param parameter Parameter name
     * @param value Value to add
     */
    protected void addParameterToRequest(String parameter, ApiParameter value) {
        if (value != null)
            getParametersNode().put(parameter, value.toJsonNode());
    }

    /**
     * Adds a parameter to the request
     * @param parameter Parameter name
     * @param value Value to add
     */
    protected void addParameterToRequest(String parameter, JsonNode value) {
        if (value != null)
            getParametersNode().put(parameter, value);
    }

    /**
    * Returns the id to identify the current method call.
    * An id is generated for each object that is created.
    * @return Method call id
    */
    public int getId() {
        return id;
    }

    /**
    * Returns the string json representation of the current method.
    * @return Json string representation of the current method
    */
    public String toJsonString() {
        return jsonRequest.toString();
    }

    /**
     * Returns the json object representation of the current method.
     * @return JsonObject representation of the current method
     */
    public ObjectNode toJsonObject() {
        return jsonRequest;
    }

    //   /**
    //    * Calls the method represented by this object on the server.
    //    * This call is always asynchronous. The results will be posted, through the callback parameter,
    //    * on the same thread that is calling this method.
    //    * Note: The current thread must have a Looper prepared, otherwise this will fail because we
    //    * try to get handler on the thread.
    //    *
    //    * @param hostConnection Host connection on which to call the method
    //    * @param callback Callbacks to post the response to
    //    */
    //   public void execute(HostConnection hostConnection, ApiCallback<T> callback) {
    //      execute(hostConnection, callback, new Handler(Looper.myLooper()));
    //   }

    /**
     * Calls the method represented by this object on the server.
     * This call is always asynchronous. The results will be posted, through the callback parameter,
     * on the specified handler.
     *
     * @param hostConnection Host connection on which to call the method
     * @param callback Callbacks to post the response to
     * @param handler Handler to invoke callbacks on
     */
    public void execute(HostConnection hostConnection, ApiCallback<T> callback, Handler handler) {
        if (hostConnection != null) {
            hostConnection.execute(this, callback, handler);
        } else {
            callback.onError(ApiException.API_NO_CONNECTION, "No connection specified.");
        }
    }

    /**
     * Returns the current method name
     * @return Current method name
     */
    public abstract String getMethodName();

    /**
     * Constructs an object of this method's return type from a json response.
     * This method must be implemented by each subcall to parse the json reponse and create
     * an return object of the appropriate type for this api method.
     *
     * @param jsonResult Json response obtained from a call
     * @return Result object of the appropriate type for this api method
     */
    public T resultFromJson(String jsonResult) throws ApiException {
        try {
            return resultFromJson((ObjectNode) objectMapper.readTree(jsonResult));
        } catch (JsonProcessingException e) {
            throw new ApiException(ApiException.INVALID_JSON_RESPONSE_FROM_HOST, e);
        } catch (IOException e) {
            throw new ApiException(ApiException.INVALID_JSON_RESPONSE_FROM_HOST, e);
        }
    }

    /**
     * Constructs an object of this method's return type from a json response.
     * This method must be implemented by each subcall to parse the json reponse and create
     * an return object of the appropriate type for this api method.
     *
     * @param jsonObject Json response obtained from a call
     * @return Result object of the appropriate type for this api method
     */
    public abstract T resultFromJson(ObjectNode jsonObject) throws ApiException;

    /**
     * Default callback for methods which the result doesnt matter
     */
    public static <T> ApiCallback<T> getDefaultActionCallback() {

        return new ApiCallback<T>() {
            @Override
            public void onSucess(T result) {
            }

            @Override
            public void onError(int errorCode, String description) {
                LogUtils.LOGD(TAG, "Got an error calling a method. Error code: " + errorCode + ", description: "
                        + description);
            }
        };
    }

}