com.mobicage.rogerthat.Api.java Source code

Java tutorial

Introduction

Here is the source code for com.mobicage.rogerthat.Api.java

Source

/*
 * Copyright (c) 2011-2014, MOBICAGE NV
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 * must display the following acknowledgement:
 * This product includes software developed by Mobicage NV.
 * 4. Neither the name of the Mobicage NV nor the
 * names of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY MOBICAGE NV ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL MOBICAGE NV BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @@license_version:1.7@@
 */

package com.mobicage.rogerthat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.Proxy;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.UUID;
import java.util.logging.Logger;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import com.mobicage.rogerthat.calls.friend.GetBroadcastAudienceRequest;
import com.mobicage.rogerthat.calls.friend.GetBroadcastAudienceResponse;
import com.mobicage.rogerthat.calls.friend.GetFriendStatusRequest;
import com.mobicage.rogerthat.calls.friend.GetFriendStatusResponse;
import com.mobicage.rogerthat.calls.friend.InviteFriendRequest;
import com.mobicage.rogerthat.calls.friend.InviteFriendResponse;
import com.mobicage.rogerthat.calls.friend.ListFriendsRequest;
import com.mobicage.rogerthat.calls.friend.ListFriendsResponse;
import com.mobicage.rogerthat.calls.friend.RemoveFriendRequest;
import com.mobicage.rogerthat.calls.friend.RemoveFriendResponse;
import com.mobicage.rogerthat.calls.messaging.BroadcastRequest;
import com.mobicage.rogerthat.calls.messaging.BroadcastResponse;
import com.mobicage.rogerthat.calls.messaging.SealRequest;
import com.mobicage.rogerthat.calls.messaging.SealResponse;
import com.mobicage.rogerthat.calls.messaging.SendFormRequest;
import com.mobicage.rogerthat.calls.messaging.SendFormResponse;
import com.mobicage.rogerthat.calls.messaging.SendRequest;
import com.mobicage.rogerthat.calls.messaging.SendResponse;
import com.mobicage.rogerthat.calls.messaging.StartFlowRequest;
import com.mobicage.rogerthat.calls.messaging.StartFlowResponse;
import com.mobicage.rogerthat.calls.qr.CreateQRRequest;
import com.mobicage.rogerthat.calls.qr.CreateQRResponse;
import com.mobicage.rogerthat.calls.qr.ListQRTemplatesRequest;
import com.mobicage.rogerthat.calls.qr.ListQRTemplatesResponse;
import com.mobicage.rogerthat.calls.system.DelUserDataRequest;
import com.mobicage.rogerthat.calls.system.DelUserDataResponse;
import com.mobicage.rogerthat.calls.system.DeleteFlowRequest;
import com.mobicage.rogerthat.calls.system.DeleteFlowResponse;
import com.mobicage.rogerthat.calls.system.DeleteIdentityRequest;
import com.mobicage.rogerthat.calls.system.DeleteIdentityResponse;
import com.mobicage.rogerthat.calls.system.DeleteMenuItemRequest;
import com.mobicage.rogerthat.calls.system.DeleteMenuItemResponse;
import com.mobicage.rogerthat.calls.system.GetIdentityRequest;
import com.mobicage.rogerthat.calls.system.GetIdentityResponse;
import com.mobicage.rogerthat.calls.system.GetInfoRequest;
import com.mobicage.rogerthat.calls.system.GetInfoResponse;
import com.mobicage.rogerthat.calls.system.GetLanguagesRequest;
import com.mobicage.rogerthat.calls.system.GetLanguagesResponse;
import com.mobicage.rogerthat.calls.system.GetStatisticsRequest;
import com.mobicage.rogerthat.calls.system.GetStatisticsResponse;
import com.mobicage.rogerthat.calls.system.GetStatusRequest;
import com.mobicage.rogerthat.calls.system.GetStatusResponse;
import com.mobicage.rogerthat.calls.system.GetTranslationsRequest;
import com.mobicage.rogerthat.calls.system.GetTranslationsResponse;
import com.mobicage.rogerthat.calls.system.GetUserDataRequest;
import com.mobicage.rogerthat.calls.system.GetUserDataResponse;
import com.mobicage.rogerthat.calls.system.ListBrandingsRequest;
import com.mobicage.rogerthat.calls.system.ListBrandingsResponse;
import com.mobicage.rogerthat.calls.system.ListBroadcastTypesRequest;
import com.mobicage.rogerthat.calls.system.ListBroadcastTypesResponse;
import com.mobicage.rogerthat.calls.system.ListIdentitiesRequest;
import com.mobicage.rogerthat.calls.system.ListIdentitiesResponse;
import com.mobicage.rogerthat.calls.system.ListMessageFlowsRequest;
import com.mobicage.rogerthat.calls.system.ListMessageFlowsResponse;
import com.mobicage.rogerthat.calls.system.PublishChangesRequest;
import com.mobicage.rogerthat.calls.system.PublishChangesResponse;
import com.mobicage.rogerthat.calls.system.PutAvatarRequest;
import com.mobicage.rogerthat.calls.system.PutAvatarResponse;
import com.mobicage.rogerthat.calls.system.PutBroadcastTypesRequest;
import com.mobicage.rogerthat.calls.system.PutBroadcastTypesResponse;
import com.mobicage.rogerthat.calls.system.PutCallbackRequest;
import com.mobicage.rogerthat.calls.system.PutCallbackResponse;
import com.mobicage.rogerthat.calls.system.PutFlowRequest;
import com.mobicage.rogerthat.calls.system.PutFlowResponse;
import com.mobicage.rogerthat.calls.system.PutIdentityRequest;
import com.mobicage.rogerthat.calls.system.PutIdentityResponse;
import com.mobicage.rogerthat.calls.system.PutMenuItemRequest;
import com.mobicage.rogerthat.calls.system.PutMenuItemResponse;
import com.mobicage.rogerthat.calls.system.PutReservedMenuItemLabelRequest;
import com.mobicage.rogerthat.calls.system.PutReservedMenuItemLabelResponse;
import com.mobicage.rogerthat.calls.system.PutTranslationsRequest;
import com.mobicage.rogerthat.calls.system.PutTranslationsResponse;
import com.mobicage.rogerthat.calls.system.PutUserDataRequest;
import com.mobicage.rogerthat.calls.system.PutUserDataResponse;
import com.mobicage.rogerthat.calls.system.StoreBrandingRequest;
import com.mobicage.rogerthat.calls.system.StoreBrandingResponse;
import com.mobicage.rogerthat.calls.system.ValidateCallbackConfigurationRequest;
import com.mobicage.rogerthat.calls.system.ValidateCallbackConfigurationResponse;

public class Api {

    public static final String DEFAULT_IDENTITY = "+default+";

    private static final Logger log = Logger.getLogger(Api.class.getName());

    private String apiKey;
    private String apiLocation = "https://rogerth.at/api/1";
    private String proxyHost;
    private int proxyPort;
    private boolean logging = false;

    /**
     * Sets the Rogerth.at Messenger API Key
     * 
     * @param apiKey
     */
    public void setApiKey(final String apiKey) {
        this.apiKey = apiKey;
    }

    /**
     * Sets the Rogerth.at Messenger API location. **WARNING** Should only be used for development purposes!!!
     * 
     * @param apiLocation
     */
    public void setApiLocation(final String apiLocation) {
        this.apiLocation = apiLocation;
    }

    /**
     * Enables logging of requests.
     * 
     * @param logging
     */
    public void setLogging(final boolean logging) {
        this.logging = logging;
    }

    /**
     * Sends a message using the default identity of the service.
     * 
     * @param request
     * @return SendResponse
     * @throws RogerthatAPIException
     */
    public SendResponse sendMessage(SendRequest request) throws RogerthatAPIException {
        final String id = UUID.randomUUID().toString();
        return sendMessage(id, request);
    }

    /**
     * Sends a message using the specified identity of the service.
     * 
     * @param apiCallId
     * @param request
     * @return SendResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public SendResponse sendMessage(String apiCallId, SendRequest request) throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "messaging.send");
        req.put("params", request.toJSONObject());
        return new SendResponse((String) wireRequest(req));
    }

    /**
     * Sends a message containing a form using the default identity of the service.
     * 
     * @param request
     * @return SendFormResponse
     * @throws RogerthatAPIException
     */
    public SendFormResponse sendForm(SendFormRequest request) throws RogerthatAPIException {
        final String id = UUID.randomUUID().toString();
        return sendForm(id, request);
    }

    /**
     * Sends a message containing a form using the specified identity of the service.
     * 
     * @param apiCallId
     * @param request
     * @return SendFormResponse
     * @throws RogerthatAPIException
     */

    @SuppressWarnings("unchecked")
    public SendFormResponse sendForm(String apiCallId, SendFormRequest request) throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "messaging.send_form");
        req.put("params", request.toJSONObject());
        return new SendFormResponse((String) wireRequest(req));
    }

    /**
     * When Rogerth.at users receive a message they can be presented a number of predefined answers. Rogerth.at users
     * can change their answer until the message is sealed. Only the sender can seal the message.
     * 
     * @param request
     * @return SealResponse
     * @throws RogerthatAPIException
     */
    public SealResponse sealMessage(SealRequest request) throws RogerthatAPIException {
        final String id = UUID.randomUUID().toString();
        return sealMessage(id, request);
    }

    /**
     * When Rogerth.at users receive a message they can be presented a number of predefined answers. Rogerth.at users
     * can change their answer until the message is sealed. Only the sender can seal the message.
     * 
     * @param apiCallId
     * @param request
     * @return SealResponse
     * @throws RogerthatAPIException
     */

    @SuppressWarnings("unchecked")
    public SealResponse sealMessage(String apiCallId, SealRequest request) throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "messaging.seal");
        req.put("params", request.toJSONObject());
        SealResponse response = (SealResponse) wireRequest(req);
        return response;
    }

    /**
     * TPS services can invite Rogerth.at users to become friends. The invitee receives a system message explaining that
     * the TPS wants to become friends. This invitation contains two buttons: Accept invitation and Decline invitation.
     * 
     * When the invitee clicks one of these buttons the service is notified via the service callback method receive
     * invitation result.
     * 
     * In case the invitee is not yet a Rogerth.at user, he receives an email in which he is invited to become a
     * Rogerth.at user on behalf of the service. Once he is registered, he is friends with the default identity of the
     * TPS.
     * 
     * @param request
     * @return InviteFriendResponse
     * @throws RogerthatAPIException
     */
    public InviteFriendResponse inviteFriend(InviteFriendRequest request) throws RogerthatAPIException {
        final String id = UUID.randomUUID().toString();
        return inviteFriend(id, request);
    }

    /**
     * TPS services can invite Rogerth.at users to become friends. The invitee receives a system message explaining that
     * the TPS wants to become friends. This invitation contains two buttons: Accept invitation and Decline invitation.
     * 
     * When the invitee clicks one of these buttons the service is notified via the service callback method receive
     * invitation result.
     * 
     * In case the invitee is not yet a Rogerth.at user, he receives an email in which he is invited to become a
     * Rogerth.at user on behalf of the service. Once he is registered, he is friends with the specified identity of the
     * TPS.
     * 
     * @param apiCallId
     * @param request
     * @return InviteFriendResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public InviteFriendResponse inviteFriend(String apiCallId, InviteFriendRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "friend.invite");
        req.put("params", request.toJSONObject());
        InviteFriendResponse response = (InviteFriendResponse) wireRequest(req);
        return response;
    }

    /**
     * If the TPS service no longer wants to interact anymore with an existing friend, the TPS can break the friendship
     * relation. Immediately after this call, messaging is no longer possible between the default identity of the
     * service and the friend in either direction.
     * 
     * @param request
     * @return RemoveFriendResponse
     * @throws RogerthatAPIException
     */
    public RemoveFriendResponse removeFriend(RemoveFriendRequest request) throws RogerthatAPIException {
        final String id = UUID.randomUUID().toString();
        return removeFriend(id, request);
    }

    /**
     * If the TPS service no longer wants to interact anymore with an existing friend, the TPS can break the friendship
     * relation. Immediately after this call, messaging is no longer possible between the default identity of the
     * service and the friend in either direction.
     * 
     * @param apiCallId
     * @param request
     * @return RemoveFriendResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public RemoveFriendResponse removeFriend(String apiCallId, RemoveFriendRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "friend.break_up");
        req.put("params", request.toJSONObject());
        RemoveFriendResponse response = (RemoveFriendResponse) wireRequest(req);
        return response;
    }

    /**
     * Creates a URI to a QR-Code image. If the image is scanned the user will be connected to the specified identity of
     * the service. Once the user and the service are connected it will result in a messaging.poke callback with this
     * tag.
     * 
     * @param request
     * @return CreateQRResponse
     * @throws RogerthatAPIException
     * @throws URISyntaxException
     */
    public CreateQRResponse createQR(CreateQRRequest request) throws RogerthatAPIException, URISyntaxException {
        final String id = UUID.randomUUID().toString();
        return createQR(id, request);
    }

    /**
     * Creates a URI to a QR-Code image. If the image is scanned the user will be connected to the specified identity of
     * the service. Once the user and the service are connected it will result in a messaging.poke callback with this
     * tag.
     * 
     * @param apiCallId
     * @param request
     * @return CreateQRResponse
     * @throws RogerthatAPIException
     * @throws URISyntaxException
     */
    @SuppressWarnings("unchecked")
    public CreateQRResponse createQR(String apiCallId, CreateQRRequest request)
            throws RogerthatAPIException, URISyntaxException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "qr.create");
        req.put("params", request.toJSONObject());
        CreateQRResponse response = CreateQRResponse.fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * List QR templates
     * 
     * @param request
     * @return ListQRTemplatesResponse
     * @throws RogerthatAPIException
     */
    public ListQRTemplatesResponse listQRTemplates(ListQRTemplatesRequest request) throws RogerthatAPIException {
        return listQRTemplates(UUID.randomUUID().toString(), request);
    }

    /**
     * List QR templates
     * 
     * @param apiCallId
     * @param request
     * @return ListQRTemplatesResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public ListQRTemplatesResponse listQRTemplates(String apiCallId, ListQRTemplatesRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "qr.list_templates");
        req.put("params", request.toJSONObject());
        ListQRTemplatesResponse response = ListQRTemplatesResponse.fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * Get the details of a service identity
     * 
     * @param request
     * @return GetIdentityResponse
     * @throws RogerthatAPIException
     */
    public GetIdentityResponse getIdentity(GetIdentityRequest request) throws RogerthatAPIException {
        return getIdentity(UUID.randomUUID().toString(), request);
    }

    /**
     * Get the details of a service identity
     * 
     * @param apiCallId
     * @param request
     * @return GetIdentityResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public GetIdentityResponse getIdentity(String apiCallId, GetIdentityRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.get_identity");
        req.put("params", request.toJSONObject());
        GetIdentityResponse response = GetIdentityResponse.fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * Add a new identity to your service, or update an existing one.
     * 
     * @param request
     * @return PutIdentityResponse
     * @throws RogerthatAPIException
     */
    public PutIdentityResponse putIdentity(PutIdentityRequest request) throws RogerthatAPIException {
        return putIdentity(UUID.randomUUID().toString(), request);
    }

    /**
     * Add a new identity to your service, or update an existing one.
     * 
     * @param apiCallId
     * @param request
     * @return PutIdentityResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public PutIdentityResponse putIdentity(String apiCallId, PutIdentityRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.put_identity");
        req.put("params", request.toJSONObject());
        PutIdentityResponse response = (PutIdentityResponse) wireRequest(req);
        return response;
    }

    /**
     * Set data which will be available between the connected user and the service identity.
     * 
     * @param request
     * @return PutUserDataResponse
     * @throws RogerthatAPIException
     */
    public PutUserDataResponse putUserData(PutUserDataRequest request) throws RogerthatAPIException {
        return putUserData(UUID.randomUUID().toString(), request);
    }

    /**
     * Set data which will be available between the connected user and the service identity.
     * 
     * @param apiCallId
     * @param request
     * @return PutUserDataResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public PutUserDataResponse putUserData(String apiCallId, PutUserDataRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.put_user_data");
        req.put("params", request.toJSONObject());
        PutUserDataResponse response = (PutUserDataResponse) wireRequest(req);
        return response;
    }

    /**
     * Get data from the user_data key-value store.
     * 
     * @param request
     * @return GetUserDataResponse
     * @throws RogerthatAPIException
     */
    public GetUserDataResponse getUserData(GetUserDataRequest request) throws RogerthatAPIException {
        return getUserData(UUID.randomUUID().toString(), request);
    }

    /**
     * Get data from the user_data key-value store.
     * 
     * @param apiCallId
     * @param request
     * @return GetUserDataResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public GetUserDataResponse getUserData(String apiCallId, GetUserDataRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.get_user_data");
        req.put("params", request.toJSONObject());
        return new GetUserDataResponse((String) wireRequest(req));
    }

    /**
     * Delete data from the user_data key-value store.
     * 
     * @param request
     * @return DelUserDataResponse
     * @throws RogerthatAPIException
     */
    public DelUserDataResponse delUserData(DelUserDataRequest request) throws RogerthatAPIException {
        return delUserData(UUID.randomUUID().toString(), request);
    }

    /**
     * Delete data from the user_data key-value store.
     * 
     * @param apiCallId
     * @param request
     * @return DelUserDataResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public DelUserDataResponse delUserData(String apiCallId, DelUserDataRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.del_user_data");
        req.put("params", request.toJSONObject());
        DelUserDataResponse response = (DelUserDataResponse) wireRequest(req);
        return response;
    }

    /**
     * Triggers the test.test callback function to be sent, in order to validate the callback setup configuration.
     * 
     * @param request
     * @return ValidateCallbackConfigurationResponse
     * @throws RogerthatAPIException
     */
    public ValidateCallbackConfigurationResponse validateCallbackConfiguration(
            ValidateCallbackConfigurationRequest request) throws RogerthatAPIException {
        return validateCallbackConfiguration(UUID.randomUUID().toString(), request);
    }

    /**
     * Triggers the test.test callback function to be sent, in order to validate the callback setup configuration.
     * 
     * @param apiCallId
     * @param request
     * @return ValidateCallbackConfigurationResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public ValidateCallbackConfigurationResponse validateCallbackConfiguration(String apiCallId,
            ValidateCallbackConfigurationRequest request) throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.validate_callback_configuration");
        req.put("params", request.toJSONObject());
        ValidateCallbackConfigurationResponse response = (ValidateCallbackConfigurationResponse) wireRequest(req);
        return response;
    }

    /**
     * Get the status of the service api configuration.
     * 
     * @param request
     * @return GetStatusResponse
     * @throws RogerthatAPIException
     */
    public GetStatusResponse getStatus(GetStatusRequest request) throws RogerthatAPIException {
        return getStatus(UUID.randomUUID().toString(), request);
    }

    /**
     * Get the status of the service api configuration.
     * 
     * @param apiCallId
     * @param request
     * @return GetStatusResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public GetStatusResponse getStatus(String apiCallId, GetStatusRequest request) throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.get_status");
        req.put("params", request.toJSONObject());
        GetStatusResponse response = GetStatusResponse.fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * Create or update a new message flow from an XML definition
     * 
     * @param request
     * @return PutFlowResponse
     * @throws RogerthatAPIException
     */
    public PutFlowResponse putFlow(PutFlowRequest request) throws RogerthatAPIException {
        final String id = UUID.randomUUID().toString();
        return putFlow(id, request);
    }

    /**
     * Create or update a new message flow from an XML definition
     * 
     * @param apiCallId
     * @param request
     * @return PutFlowResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public PutFlowResponse putFlow(String apiCallId, PutFlowRequest request) throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.put_flow");
        req.put("params", request.toJSONObject());
        PutFlowResponse response = PutFlowResponse.fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * Delete a flow from your service
     * 
     * @param request
     * @return DeleteFlowResponse
     * @throws RogerthatAPIException
     */
    public DeleteFlowResponse deleteFlow(DeleteFlowRequest request) throws RogerthatAPIException {
        return deleteFlow(UUID.randomUUID().toString(), request);
    }

    /**
     * Delete a flow from your service
     * 
     * @param apiCallId
     * @param request
     * @return DeleteFlowResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public DeleteFlowResponse deleteFlow(String apiCallId, DeleteFlowRequest request) throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.delete_flow");
        req.put("params", request.toJSONObject());
        return new DeleteFlowResponse((Boolean) wireRequest(req));
    }

    /**
     * List all string that are use in your service, and their translation (if present)
     * 
     * @param request
     * @result GetTranslationsResponse
     * @throws RogerthatAPIException
     */
    public GetTranslationsResponse getTranslations(GetTranslationsRequest request) throws RogerthatAPIException {
        return getTranslations(UUID.randomUUID().toString(), request);
    }

    /**
     * List all string that are use in your service, and their translation (if present)
     * 
     * @param apiCallId
     * @param request
     * @result GetTranslationsResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public GetTranslationsResponse getTranslations(String apiCallId, GetTranslationsRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.get_translations");
        req.put("params", request.toJSONObject());
        GetTranslationsResponse response = GetTranslationsResponse.fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * Update translations
     * 
     * @param request
     * @return PutTranslationsResponse
     * @throws RogerthatAPIException
     */
    public PutTranslationsResponse putTranslations(PutTranslationsRequest request) throws RogerthatAPIException {
        return putTranslations(UUID.randomUUID().toString(), request);
    }

    /**
     * Update translations
     * 
     * @param apiCallId
     * @param request
     * @return PutTranslationsResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public PutTranslationsResponse putTranslations(String apiCallId, PutTranslationsRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.put_translations");
        req.put("params", request.toJSONObject());
        PutTranslationsResponse response = (PutTranslationsResponse) wireRequest(req);
        return response;
    }

    /**
     * Get the statistics of the service api configuration.
     * 
     * @param request
     * @return GetStatisticsResponse
     * @throws RogerthatAPIException
     */
    public GetStatisticsResponse getStatistics(GetStatisticsRequest request) throws RogerthatAPIException {
        final String id = UUID.randomUUID().toString();
        return getStatistics(id, request);
    }

    /**
     * Get the statistics of the service api configuration.
     * 
     * @param apiCallId
     * @param request
     * @return GetStatisticsResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public GetStatisticsResponse getStatistics(String apiCallId, GetStatisticsRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.get_statistics");
        req.put("params", request.toJSONObject());
        GetStatisticsResponse response = GetStatisticsResponse.fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * Update the avatar
     * 
     * @param request
     * @return PutAvatarResponse
     * @throws RogerthatAPIException
     */
    public PutAvatarResponse putAvatar(PutAvatarRequest request) throws RogerthatAPIException {
        return putAvatar(UUID.randomUUID().toString(), request);
    }

    /**
     * Update the avatar
     * 
     * @param apiCallId
     * @param request
     * @return PutAvatarResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public PutAvatarResponse putAvatar(String apiCallId, PutAvatarRequest request) throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.put_avatar");
        req.put("params", request.toJSONObject());
        PutAvatarResponse response = (PutAvatarResponse) wireRequest(req);
        return response;
    }

    /**
     * List all the broadcast types you defined in your service
     * 
     * @param request
     * @result ListBroadcastTypesResponse
     * @throws RogerthatAPIException
     */
    public ListBroadcastTypesResponse listBroadcastTypes(ListBroadcastTypesRequest request)
            throws RogerthatAPIException {
        return listBroadcastTypes(UUID.randomUUID().toString(), request);
    }

    /**
     * List all the broadcast types you defined in your service
     * 
     * @param apiCallId
     * @param request
     * @result ListBroadcastTypesResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public ListBroadcastTypesResponse listBroadcastTypes(String apiCallId, ListBroadcastTypesRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.list_broadcast_types");
        req.put("params", request.toJSONObject());
        ListBroadcastTypesResponse response = ListBroadcastTypesResponse
                .fromJSONArray((JSONArray) wireRequest(req));
        return response;
    }

    /**
     * Configure the broadcast types of your service
     * 
     * @param request
     * @return PutBroadcastTypesResponse
     * @throws RogerthatAPIException
     */
    public PutBroadcastTypesResponse putBroadcastTypes(PutBroadcastTypesRequest request)
            throws RogerthatAPIException {
        return putBroadcastTypes(UUID.randomUUID().toString(), request);
    }

    /**
     * Configure the broadcast types of your service
     * 
     * @param apiCallId
     * @param request
     * @return PutBroadcastTypesResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public PutBroadcastTypesResponse putBroadcastTypes(String apiCallId, PutBroadcastTypesRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.put_broadcast_types");
        req.put("params", request.toJSONObject());
        PutBroadcastTypesResponse response = (PutBroadcastTypesResponse) wireRequest(req);
        return response;
    }

    /**
     * Enable or disable callbacks
     * 
     * @param request
     * @return PutCallbackResponse
     * @throws RogerthatAPIException
     */
    public PutCallbackResponse putCallback(PutCallbackRequest request) throws RogerthatAPIException {
        return putCallback(UUID.randomUUID().toString(), request);
    }

    /**
     * Enable or disable callbacks
     * 
     * @param apiCallId
     * @param request
     * @return PutCallbackResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public PutCallbackResponse putCallback(String apiCallId, PutCallbackRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.put_callback");
        req.put("params", request.toJSONObject());
        PutCallbackResponse response = (PutCallbackResponse) wireRequest(req);
        return response;
    }

    /**
     * Publish changes
     * 
     * @return PublishChangesResponse
     * @throws RogerthatAPIException
     */
    public PublishChangesResponse publishChanges(PublishChangesRequest request) throws RogerthatAPIException {
        return publishChanges(UUID.randomUUID().toString(), request);
    }

    /**
     * Publish changes
     * 
     * @param apiCallId
     * @return PublishChangesResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public PublishChangesResponse publishChanges(String apiCallId, PublishChangesRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.publish_changes");
        req.put("params", request.toJSONObject());
        PublishChangesResponse response = (PublishChangesResponse) wireRequest(req);
        return response;
    }

    /**
     * Get a summary of a service identity
     * 
     * @param request
     * @return GetInfoResponse
     * @throws RogerthatAPIException
     */
    public GetInfoResponse getInfo(GetInfoRequest request) throws RogerthatAPIException {
        return getInfo(UUID.randomUUID().toString(), request);
    }

    /**
     * Get a summary of a service identity
     * 
     * @param apiCallId
     * @param request
     * @return GetInfoResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public GetInfoResponse getInfo(String apiCallId, GetInfoRequest request) throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.get_info");
        req.put("params", request.toJSONObject());
        GetInfoResponse response = GetInfoResponse.fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * Delete service identity
     * 
     * @param request
     * @return DeleteIdentityResponse
     * @throws RogerthatAPIException
     */
    public DeleteIdentityResponse deleteIdentity(DeleteIdentityRequest request) throws RogerthatAPIException {
        return deleteIdentity(UUID.randomUUID().toString(), request);
    }

    /**
     * Delete service identity
     * 
     * @param apiCallId
     * @param request
     * @return DeleteIdentityResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public DeleteIdentityResponse deleteIdentity(String apiCallId, DeleteIdentityRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.delete_identity");
        req.put("params", request.toJSONObject());
        DeleteIdentityResponse response = (DeleteIdentityResponse) wireRequest(req);
        return response;
    }

    /**
     * List service identities
     * 
     * @param request
     * @return ListIdentitiesResponse
     * @throws RogerthatAPIException
     */
    public ListIdentitiesResponse listIdentities(ListIdentitiesRequest request) throws RogerthatAPIException {
        return listIdentities(UUID.randomUUID().toString(), request);
    }

    /**
     * List service identities
     * 
     * @param apiCallId
     * @param request
     * @return ListIdentitiesResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public ListIdentitiesResponse listIdentities(String apiCallId, ListIdentitiesRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.list_identities");
        req.put("params", request.toJSONObject());
        ListIdentitiesResponse response = ListIdentitiesResponse.fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * Create or update a menu item
     * 
     * @param request
     * @return PutMenuItemResponse
     * @throws RogertahtAPIException
     */
    public PutMenuItemResponse putMenuItem(PutMenuItemRequest request) throws RogerthatAPIException {
        return putMenuItem(UUID.randomUUID().toString(), request);
    }

    /**
     * Create or update a menu item
     * 
     * @param apiCallId
     * @param request
     * @return PutMenuItemResponse
     * @throws RogertahtAPIException
     */
    @SuppressWarnings("unchecked")
    public PutMenuItemResponse putMenuItem(String apiCallId, PutMenuItemRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.put_menu_item");
        req.put("params", request.toJSONObject());
        PutMenuItemResponse response = (PutMenuItemResponse) wireRequest(req);
        return response;
    }

    /**
     * Delete a menu item
     * 
     * @param request
     * @result DeleteMenuItemResponse
     * @throws RogerthatAPIException
     */
    public DeleteMenuItemResponse deleteMenuItem(DeleteMenuItemRequest request) throws RogerthatAPIException {
        return deleteMenuItem(UUID.randomUUID().toString(), request);
    }

    /**
     * Delete a menu item
     * 
     * @param apiCallId
     * @param request
     * @result DeleteMenuItemResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public DeleteMenuItemResponse deleteMenuItem(String apiCallId, DeleteMenuItemRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.delete_menu_item");
        req.put("params", request.toJSONObject());
        return new DeleteMenuItemResponse((Boolean) wireRequest(req));
    }

    /**
     * Updated the label of a reserved menu item
     * 
     * @param request
     * @return PutReservedMenuItemLabelResponse
     * @throws RogerthatAPIException
     */
    public PutReservedMenuItemLabelResponse putReservedMenuItemLabel(PutReservedMenuItemLabelRequest request)
            throws RogerthatAPIException {
        return putReservedMenuItemLabel(UUID.randomUUID().toString(), request);
    }

    /**
     * Updated the label of a reserved menu item
     * 
     * @param apiCallId
     * @param request
     * @return PutReservedMenuItemLabelResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public PutReservedMenuItemLabelResponse putReservedMenuItemLabel(String apiCallId,
            PutReservedMenuItemLabelRequest request) throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.put_reserved_menu_item_label");
        req.put("params", request.toJSONObject());
        PutReservedMenuItemLabelResponse response = (PutReservedMenuItemLabelResponse) wireRequest(req);
        return response;
    }

    /**
     * Upload screen branding
     * 
     * @param request
     * @return StoreBrandingResponse
     * @throws RogerthatAPIException
     */
    public StoreBrandingResponse storeBranding(StoreBrandingRequest request) throws RogerthatAPIException {
        return storeBranding(UUID.randomUUID().toString(), request);
    }

    /**
     * Upload screen branding
     * 
     * @param apiCallId
     * @param request
     * @return StoreBrandingResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public StoreBrandingResponse storeBranding(String apiCallId, StoreBrandingRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.store_branding");
        req.put("params", request.toJSONObject());
        StoreBrandingResponse response = StoreBrandingResponse.fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * Get all your brandings
     * 
     * @param request
     * @return ListBrandingsResponse
     * @throws RogerthatAPIException
     */
    public ListBrandingsResponse listBrandings(ListBrandingsRequest request) throws RogerthatAPIException {
        return listBrandings(UUID.randomUUID().toString(), request);
    }

    /**
     * Get all your brandings
     * 
     * @param apiCallId
     * @param request
     * @return ListBrandingsResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public ListBrandingsResponse listBrandings(String apiCallId, ListBrandingsRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.list_brandings");
        req.put("params", request.toJSONObject());
        ListBrandingsResponse response = ListBrandingsResponse.fromJSONArray((JSONArray) wireRequest(req));
        return response;
    }

    /**
     * Retrieves status of a user
     * 
     * @param request
     * @return GetFriendStatusResponse
     * @throws RogerthatAPIException
     */
    public GetFriendStatusResponse getFriendStatus(GetFriendStatusRequest request) throws RogerthatAPIException {
        return getFriendStatus(UUID.randomUUID().toString(), request);
    }

    /**
     * Retrieves status of a user
     * 
     * @param apiCallId
     * @param request
     * @return GetFriendStatusResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public GetFriendStatusResponse getFriendStatus(String apiCallId, GetFriendStatusRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "friend.get_status");
        req.put("params", request.toJSONObject());
        GetFriendStatusResponse response = GetFriendStatusResponse.fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * Retrieves friend list
     * 
     * @param request
     * @return ListFriendsResponse
     * @throws RogerthatAPIException
     */
    public ListFriendsResponse listFriends(ListFriendsRequest request) throws RogerthatAPIException {
        return listFriends(UUID.randomUUID().toString(), request);
    }

    /**
     * Retrieves friend list
     * 
     * @param apiCallId
     * @param request
     * @return ListFriendsResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public ListFriendsResponse listFriends(String apiCallId, ListFriendsRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "friend.list");
        req.put("params", request.toJSONObject());
        ListFriendsResponse response = ListFriendsResponse.fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * Retrieves users of a broadcast
     * 
     * @param request
     * @return GetBroadcastAudienceResponse
     * @throws RogerthatAPIException
     */
    public GetBroadcastAudienceResponse getBroadcastAudience(GetBroadcastAudienceRequest request)
            throws RogerthatAPIException {
        return getBroadcastAudience(UUID.randomUUID().toString(), request);
    }

    /**
     * Retrieves users of a broadcast
     * 
     * @param apiCallId
     * @param request
     * @return GetBroadcastAudienceResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public GetBroadcastAudienceResponse getBroadcastAudience(String apiCallId, GetBroadcastAudienceRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "friend.get_broadcast_audience");
        req.put("params", request.toJSONObject());
        GetBroadcastAudienceResponse response = GetBroadcastAudienceResponse
                .fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * Launch a message flow
     * 
     * @param request
     * @return StartFlowResponse
     * @throws RogerthatAPIException
     */
    public StartFlowResponse startFlow(StartFlowRequest request) throws RogerthatAPIException {
        return startFlow(UUID.randomUUID().toString(), request);
    }

    /**
     * Launch a message flow
     * 
     * @param apiCallId
     * @param request
     * @return StartFlowResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public StartFlowResponse startFlow(String apiCallId, StartFlowRequest request) throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "messaging.start_flow");
        req.put("params", request.toJSONObject());
        return new StartFlowResponse((String) wireRequest(req));
    }

    /**
     * List message request
     * 
     * @param request
     * @return ListMessageFlows
     * @throws RogerthatAPIException
     */
    public ListMessageFlowsResponse listMessageFlows(ListMessageFlowsRequest request) throws RogerthatAPIException {
        return listMessageFlows(UUID.randomUUID().toString(), request);
    }

    /**
     * List message flows
     * 
     * @param apiCallId
     * @param request
     * @return ListMessageFlowsResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public ListMessageFlowsResponse listMessageFlows(String apiCallId, ListMessageFlowsRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.list_message_flows");
        req.put("params", request.toJSONObject());
        return new ListMessageFlowsResponse((JSONArray) wireRequest(req));
    }

    /**
     * Return the default language and the supported languages of your service
     * 
     * @param request
     * @return GetLanguagesResponse
     * @throws RogerthatAPIException
     */
    public GetLanguagesResponse getLanguages(GetLanguagesRequest request) throws RogerthatAPIException {
        return getLanguages(UUID.randomUUID().toString(), request);
    }

    /**
     * Return the default language and the supported languages of your service
     * 
     * @param apiCallId
     * @param request
     * @return GetLanguagesResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public GetLanguagesResponse getLanguages(String apiCallId, GetLanguagesRequest request)
            throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "system.get_languages");
        req.put("params", request.toJSONObject());
        GetLanguagesResponse response = GetLanguagesResponse.fromJSONObject((JSONObject) wireRequest(req));
        return response;
    }

    /**
     * Broadcast a message to Rogerthat users
     * 
     * @param request
     * @return BroadcastResponse
     * @throws RogerthatAPIException
     */
    public BroadcastResponse broadcast(BroadcastRequest request) throws RogerthatAPIException {
        return broadcast(UUID.randomUUID().toString(), request);
    }

    /**
     * Broadcast a message to Rogerthat users
     * 
     * @param apiCallId
     * @param request
     * @return BroadcastResponse
     * @throws RogerthatAPIException
     */
    @SuppressWarnings("unchecked")
    public BroadcastResponse broadcast(String apiCallId, BroadcastRequest request) throws RogerthatAPIException {
        final JSONObject req = new JSONObject();
        req.put("id", apiCallId);
        req.put("method", "messaging.broadcast");
        req.put("params", request.toJSONObject());
        BroadcastResponse response = (BroadcastResponse) wireRequest(req);
        return response;
    }

    protected Object wireRequest(final JSONObject request) throws RogerthatAPIException {
        return wireRequest(request, 1);
    }

    @SuppressWarnings("unchecked")
    private Object wireRequest(final JSONObject request, final int attempt) throws RogerthatAPIException {
        final URL url;
        try {
            url = new URL(apiLocation);
        } catch (MalformedURLException e) {
            // Will never come here
            throw new RogerthatAPIException(e);
        }
        HttpURLConnection connection;
        try {
            if (proxyHost != null && proxyPort != 0) {
                // Adapt proxy settings
                Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
                connection = (HttpURLConnection) url.openConnection(proxy);
            } else {
                connection = (HttpURLConnection) url.openConnection();
            }
        } catch (IOException e) {
            throw new RogerthatAPIException(e);
        }
        try {
            connection.setDoOutput(true);
            try {
                connection.setRequestMethod("POST");
            } catch (ProtocolException e) {
                // Will never come here
                throw new RogerthatAPIException(e);
            }
            connection.setRequestProperty("X-Nuntiuz-API-Key", apiKey);
            connection.setRequestProperty("Content-type", "application/json-rpc; charset=utf-8");
            connection.setReadTimeout(30000);
            Writer writer;
            try {
                writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
                try {
                    String jsonString = request.toJSONString();
                    if (logging)
                        log.info("Sending request to Rogerthat:\n" + jsonString);
                    writer.write(jsonString);
                } finally {
                    writer.close();
                }
                switch (connection.getResponseCode()) {
                case HttpURLConnection.HTTP_OK:
                    InputStream is = connection.getInputStream();
                    try {
                        JSONObject result = (JSONObject) JSONValue
                                .parse(new BufferedReader(new InputStreamReader(is, "UTF-8")));
                        if (logging)
                            log.info("Result received from Rogerthat:\n" + result.toJSONString());
                        JSONObject error = (JSONObject) result.get("error");
                        if (error != null)
                            throw new RogerthatAPIException(Integer.parseInt(error.get("code").toString()),
                                    (String) error.get("message"), error);
                        else
                            return result.get("result");
                    } finally {
                        is.close();
                    }
                case HttpURLConnection.HTTP_UNAUTHORIZED:
                    throw new RogerthatAPIException(1000,
                            "Could not authenticate against Rogerth.at Messenger API! Check your api key.", null);
                case HttpURLConnection.HTTP_NOT_FOUND:
                    throw new RogerthatAPIException(1000, "Rogerth.at Messenger API method not found!", null);
                default:
                    if (attempt < 5)
                        return wireRequest(request, attempt + 1);
                    else
                        throw new RogerthatAPIException(1000, "Could not send call to Rogerth.at Messenger!", null);
                }
            } catch (IOException e) {
                // Will never come here
                throw new RogerthatAPIException(e);
            }
        } finally {
            connection.disconnect();
        }
    }

    /**
     * Sets the proxy server settings.
     * 
     * @param proxyHost
     * @param proxyPort
     */
    public void setProxy(String proxyHost, int proxyPort) {
        this.proxyHost = proxyHost;
        this.proxyPort = proxyPort;
    }
}