/*
* Copyright (C) 2013-2014 Sony Computer Science Laboratories, Inc. All Rights Reserved.
* Copyright (C) 2014 Sony Corporation. All Rights Reserved.
*/
package com.sonycsl.wamp.role;
import com.sonycsl.wamp.WampError;
import com.sonycsl.wamp.WampLog;
import com.sonycsl.wamp.WampPeer;
import com.sonycsl.wamp.message.WampCallMessage;
import com.sonycsl.wamp.message.WampErrorMessage;
import com.sonycsl.wamp.message.WampMessage;
import com.sonycsl.wamp.message.WampMessageFactory;
import com.sonycsl.wamp.message.WampMessageType;
import com.sonycsl.wamp.message.WampRegisterMessage;
import com.sonycsl.wamp.message.WampUnregisterMessage;
import com.sonycsl.wamp.message.WampYieldMessage;
import org.json.JSONObject;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
abstract public class WampDealer extends WampRole {
private static final String TAG = WampDealer.class.getSimpleName();
private final Map<String, RegisterInfo> mCallees = new ConcurrentHashMap<String, WampDealer.RegisterInfo>();
private final Map<Integer, CallInfo> mCallers = new ConcurrentHashMap<Integer, WampDealer.CallInfo>();
private int mRegistraionId = 0;
private int mInvocationRequestId = 0;
@Override
public final String getRoleName() {
return "dealer";
}
@Override
public final boolean resolveTxMessageImpl(WampPeer receiver, WampMessage msg) {
return false;
}
@Override
public final boolean resolveRxMessageImpl(WampPeer transmitter, WampMessage msg,
OnReplyListener listener) {
if (msg.isRegisterMessage()) {
return resolveRegisterMessage(transmitter, msg, listener);
}
if (msg.isUnregisterMessage()) {
return resolveUnregisterMessage(transmitter, msg, listener);
}
if (msg.isCallMessage()) {
return resolveCallMessage(transmitter, msg, listener);
}
if (msg.isYieldMessage()) {
return resolveYieldMessage(transmitter, msg, listener);
}
if (msg.isErrorMessage()) {
return resolveErrorMessage(transmitter, msg, listener);
}
return false;
}
private static final class RegisterInfo {
private final WampPeer mCallee;
private final int mRegistraionId;
public RegisterInfo(WampPeer callee, int registrationId) {
mCallee = callee;
mRegistraionId = registrationId;
}
public WampPeer getCallee() {
return mCallee;
}
public int getRegistraionId() {
return mRegistraionId;
}
}
private boolean resolveRegisterMessage(WampPeer transmitter, WampMessage msg,
OnReplyListener listener) {
WampRegisterMessage reg = msg.asRegisterMessage();
if (mCallees.containsKey(reg.getProcedure())) {
listener.onReply(transmitter,
WampMessageFactory.createError(msg.getMessageType(), -1, new JSONObject(),
WampError.PROCEDURE_ALREADY_EXISTS));
return true;
}
int registrationId = ++mRegistraionId;
mCallees.put(reg.getProcedure(), new RegisterInfo(transmitter, registrationId));
listener.onReply(transmitter,
WampMessageFactory.createRegistered(reg.getRequestId(), registrationId));
return true;
}
private boolean resolveUnregisterMessage(WampPeer transmitter, WampMessage msg,
OnReplyListener listener) {
WampUnregisterMessage unreg = msg.asUnregisterMessage();
int registraionId = unreg.getRegistrationId();
for (Entry<String, RegisterInfo> entry : mCallees.entrySet()) {
if (entry.getValue().getRegistraionId() == registraionId) {
listener.onReply(entry.getValue().getCallee(),
WampMessageFactory.createUnregistered(unreg.getRequestId()));
mCallees.remove(entry.getKey());
break;
}
}
return true;
}
private static final class CallInfo {
private final WampPeer mCaller;
private final int mRequestId;
public CallInfo(WampPeer caller, int requestId) {
mCaller = caller;
mRequestId = requestId;
}
public WampPeer getCaller() {
return mCaller;
}
public int getRequestId() {
return mRequestId;
}
}
private boolean resolveCallMessage(WampPeer transmitter, WampMessage msg,
OnReplyListener listener) {
WampCallMessage call = msg.asCallMessage();
if (!mCallees.containsKey(call.getProcedure())) {
WampLog.e(TAG, "No such procedure: " + call.getProcedure());
listener.onReply(transmitter,
WampMessageFactory.createError(msg.getMessageType(), call.getRequestId(),
new JSONObject(), WampError.NO_SUCH_PROCEDURE));
return true;
}
RegisterInfo info = mCallees.get(call.getProcedure());
int requestId = ++mInvocationRequestId;
mCallers.put(requestId, new CallInfo(transmitter, call.getRequestId()));
listener.onReply(info.getCallee(),
createInvocationMessage(requestId, info.getRegistraionId(), call));
return true;
}
private WampMessage createInvocationMessage(int requestId, int registrationId,
WampCallMessage msg) {
if (msg.hasArgumentsKw()) {
return WampMessageFactory.createInvocation(requestId, registrationId,
createInvocationDetails(msg.getOptions()), msg.getArguments(),
msg.getArgumentsKw());
}
if (msg.hasArguments()) {
return WampMessageFactory.createInvocation(requestId, registrationId,
createInvocationDetails(msg.getOptions()), msg.getArguments());
}
return WampMessageFactory.createInvocation(requestId, registrationId,
createInvocationDetails(msg.getOptions()));
}
abstract protected JSONObject createInvocationDetails(JSONObject callOptions);
private boolean resolveYieldMessage(WampPeer transmitter, WampMessage msg,
OnReplyListener listener) {
WampYieldMessage yield = msg.asYieldMessage();
int invocationRequestId = yield.getRequestId();
if (!mCallers.containsKey(invocationRequestId)) {
return false;
}
CallInfo info = mCallers.get(invocationRequestId);
listener.onReply(info.getCaller(), createResultMessage(info.getRequestId(), yield));
mCallers.remove(invocationRequestId);
return true;
}
private WampMessage createResultMessage(int requestId, WampYieldMessage msg) {
if (msg.hasArgumentsKw()) {
return WampMessageFactory.createResult(requestId, new JSONObject(), msg.getArguments(),
msg.getArgumentsKw());
}
if (msg.hasArguments()) {
return WampMessageFactory.createResult(requestId, new JSONObject(), msg.getArguments());
}
return WampMessageFactory.createResult(requestId, new JSONObject());
}
private boolean resolveErrorMessage(WampPeer transmitter, WampMessage msg,
OnReplyListener listener) {
WampErrorMessage errorMsg = msg.asErrorMessage();
int callRequestId = errorMsg.getRequestId();
if (!mCallers.containsKey(callRequestId)) {
return false;
}
if (errorMsg.getRequestType() != WampMessageType.INVOCATION) {
return false;
}
CallInfo info = mCallers.get(callRequestId);
listener.onReply(info.getCaller(), createErrorMessage(info.getRequestId(), errorMsg));
mCallers.remove(callRequestId);
return true;
}
private WampMessage createErrorMessage(int requestId, WampErrorMessage msg) {
if (msg.hasArgumentsKw()) {
return WampMessageFactory.createError(WampMessageType.CALL, requestId,
new JSONObject(), msg.getUri(), msg.getArguments(), msg.getArgumentsKw());
}
if (msg.hasArguments()) {
return WampMessageFactory.createError(WampMessageType.CALL, requestId,
new JSONObject(), msg.getUri(), msg.getArguments());
}
return WampMessageFactory.createError(WampMessageType.CALL, requestId,
new JSONObject(), msg.getUri());
}
}