/*
* WBI Indicator Explorer
*
* Copyright 2015 Sebastian Nogara <snogaraleal@gmail.com>
*
* This file is part of WBI.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package rpc.client;
import java.util.ArrayList;
import java.util.List;
import rpc.client.call.DefaultCallRequestClientSerializer;
import rpc.client.call.DefaultCallResponseClientSerializer;
import rpc.shared.call.CallRequest;
import rpc.shared.call.CallResponse;
import rpc.shared.call.InvalidPayload;
import rpc.shared.data.Serializer;
import rpc.shared.data.SerializerException;
import rpc.shared.data.Type;
/**
* RPC client.
*
* This is the highest-level class of the client-side package.
*
* Derived classes provide an appropriate implementation of the
* {@link #send(ClientRequest)} and {@link #cancel(ClientRequest)} methods.
*
* @see {@link HTTPClient} and {@link WebSocketClient}.
*/
public abstract class Client {
/**
* Client configuration.
*/
public static class Configuration {
/**
* Global {@link Serializer}.
*/
private Serializer serializer;
/**
* HTTP endpoint.
*/
private String httpURL;
/**
* WebSocket endpoint.
*/
private String wsURL;
/**
* Initialize {@link Client.Configuration}.
*
* @param serializer Global {@link Serializer}.
* @param httpURL HTTP endpoint.
* @param wsURL WebSocket endpoint.
*/
public Configuration(
Serializer serializer,
String httpURL, String wsURL) {
this.serializer = serializer;
this.httpURL = httpURL;
this.wsURL = wsURL;
}
/**
* Get global serializer.
*
* @return Global serializer.
*/
public Serializer getSerializer() {
return serializer;
}
/**
* Get HTTP endpoint.
*
* @return HTTP endpoint.
*/
public String httpURL() {
return httpURL;
}
/**
* Get WebSocket endpoint.
*
* @return WebSocket endpoint.
*/
public String wsURL() {
return wsURL;
}
}
/**
* Current client configuration.
*/
private static Configuration configuration;
/**
* Set {@link Client.Configuration}.
*
* @param config Client configuration.
*/
public static void setConfiguration(Configuration config) {
configuration = config;
}
/**
* Load {@link Client} class.
*
* @return New {@code Client} object.
*/
private static Client load() {
if (WebSocketClient.isSupported()) {
return new WebSocketClient(
configuration.getSerializer(),
configuration.wsURL());
} else {
return new HTTPClient(
configuration.getSerializer(),
configuration.httpURL());
}
}
private static Client client;
/**
* Get the single {@link Client} instance.
*
* @return {@code Client} instance.
*/
public static Client get() {
if (client == null) {
client = load();
}
return client;
}
protected static CallRequest.ClientSerializer requestSerializer =
new DefaultCallRequestClientSerializer();
protected static CallResponse.ClientSerializer responseSerializer =
new DefaultCallResponseClientSerializer();
protected Serializer serializer;
/**
* Initialize {@code Client}.
*/
public Client() {}
/**
* Initialize {@code Client} with the specified object serializer.
*
* @param serializer {@link Serializer}.
*/
public Client(Serializer serializer) {
this.serializer = serializer;
}
/**
* Send the specified {@link ClientRequest}.
*
* @param clientRequest RPC request.
*/
public abstract void send(ClientRequest<?> clientRequest);
/**
* Cancel the specified {@link ClientRequest}.
*
* @param clientRequest RPC request.
*/
public abstract void cancel(ClientRequest<?> clientRequest);
/**
* Build a low-level serializable {@link CallRequest} from a high-level
* {@link ClientRequest}.
*
* @param clientRequest RPC request.
* @return Serializable {@link CallRequest}.
* @throws SerializerException
*/
protected CallRequest buildCallRequest(ClientRequest<?> clientRequest)
throws SerializerException {
List<String> argumentPayloadList = new ArrayList<String>();
for (Object argument : clientRequest.getArguments()) {
argumentPayloadList.add(serializer.serialize(argument));
}
return new CallRequest(
clientRequest.getClassName(),
clientRequest.getMethodName(),
argumentPayloadList);
}
/**
* Serialize {@link CallRequest} to be sent.
*
* @param callRequest {@code CallRequest} to serialize.
* @return Serialized request.
*/
protected String toRequestMessage(CallRequest callRequest) {
return requestSerializer.serialize(callRequest);
}
/**
* Deserialize received {@link CallResponse}.
*
* @param message Serialized response.
* @return Deserialized {@code CallResponse}.
* @throws InvalidPayload
*/
protected CallResponse fromResponseMessage(String message)
throws InvalidPayload {
return responseSerializer.deserialize(message);
}
/**
* Deserialize {@link Serializable} object.
*
* @param payload Serialized contents.
* @param expected Expected object type.
* @return Deserialized {@code Serializable} object.
* @throws SerializerException
*/
protected Object deserialize(String payload, Type expected)
throws SerializerException {
return serializer.deserialize(payload, expected);
}
}