/*
* 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.server.invoke;
import java.util.ArrayList;
import java.util.List;
import rpc.shared.data.Serializer;
import rpc.shared.data.SerializerException;
import rpc.shared.data.Type;
/**
* Layer for calling an {@link Invokable} with serialized values.
*/
public class Invoker {
private Serializer serializer;
/**
* Initialize {@code Invoker}.
*
* @param serializer Serializer.
*/
public Invoker(Serializer serializer) {
this.serializer = serializer;
}
/**
* Get required argument types for calling an {@code Invokable} or raise
* an {@link InvokerException} if not possible.
*
* @param invokable Invokable.
* @return List of argument types.
* @throws InvokerException
*/
private List<Type> getArgumentTypeList(Invokable invokable)
throws InvokerException {
List<Type> argumentTypeList;
try {
argumentTypeList = invokable.getArgumentTypeList();
} catch (Exception exception) {
throw new InvokerException(
InvokerException.Reason.INVOKABLE_EXCEPTION, exception);
}
return argumentTypeList;
}
/**
* Deserialize arguments for calling an {@code Invokable} or raise
* an {@link InvokerException} if not possible.
*
* @param argumentPayloadList Serialized arguments.
* @param argumentTypeList Required argument types.
* @return Deserialized arguments.
* @throws InvokerException
*/
private List<Object> getArgumentList(
List<String> argumentPayloadList,
List<Type> argumentTypeList) throws InvokerException {
if (argumentTypeList.size() != argumentPayloadList.size()) {
throw new InvokerException(
InvokerException.Reason.INCOMPATIBLE_ARGUMENTS);
}
List<Object> argumentList = new ArrayList<Object>();
int n = argumentTypeList.size();
for (int i = 0; i < n; i++) {
Type expected = argumentTypeList.get(i);
String payload = argumentPayloadList.get(i);
try {
Object object = serializer.deserialize(payload, expected);
if (!expected.isInstance(object)) {
throw new InvokerException(
InvokerException.Reason.INCOMPATIBLE_ARGUMENTS);
}
argumentList.add(object);
} catch (SerializerException exception) {
throw new InvokerException(
InvokerException.Reason.INVALID_PAYLOAD, exception);
}
}
return argumentList;
}
/**
* Invoke an {@link Invokable}.
*
* @param invokable Invokable to invoke.
* @param argumentPayloadList Serialized arguments.
* @return Serialized return value.
* @throws InvokerException
*/
public String invoke(
Invokable invokable,
List<String> argumentPayloadList) throws InvokerException {
List<Object> argumentList = getArgumentList(
argumentPayloadList, getArgumentTypeList(invokable));
Object returnValue;
Object[] arguments = argumentList.toArray(
new Object[argumentList.size()]);
try {
returnValue = invokable.invoke(arguments);
} catch (Exception exception) {
exception.printStackTrace();
throw new InvokerException(
InvokerException.Reason.INVOKABLE_EXCEPTION, exception);
}
try {
return serializer.serialize(returnValue);
} catch (SerializerException exception) {
throw new InvokerException(
InvokerException.Reason.UNSUPPORTED_RETURN_VALUE, exception);
}
}
}