/*
* Copyright (C) 2013-2014 Sony Computer Science Laboratories, Inc. All Rights Reserved.
* Copyright (C) 2014 Sony Corporation. All Rights Reserved.
*/
package com.sonycsl.wamp;
import com.sonycsl.wamp.message.WampMessage;
import com.sonycsl.wamp.role.WampRole;
import com.sonycsl.wamp.role.WampRole.OnReplyListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
abstract public class WampPeer {
public interface Callback {
public void preConnect(WampPeer connecter, WampPeer connectee);
public void postConnect(WampPeer connecter, WampPeer connectee);
public void preTransmit(WampPeer transmitter, WampMessage msg);
public void postTransmit(WampPeer transmitter, WampMessage msg);
public void preReceive(WampPeer receiver, WampMessage msg);
public void postReceive(WampPeer receiver, WampMessage msg);
}
private static class Callbacks implements Callback {
private Set<Callback> callbacks = new HashSet<WampPeer.Callback>();
public boolean add(Callback callback) {
synchronized (callbacks) {
return callbacks.add(callback);
}
}
public void remove(Callback callback) {
synchronized (callbacks) {
callbacks.remove(callback);
}
}
@Override
public void preConnect(WampPeer connecter, WampPeer connectee) {
synchronized (callbacks) {
for (Callback callback : callbacks) {
callback.preConnect(connecter, connectee);
}
}
}
@Override
public void postConnect(WampPeer connecter, WampPeer connectee) {
synchronized (callbacks) {
for (Callback callback : callbacks) {
callback.postConnect(connecter, connectee);
}
}
}
@Override
public void preTransmit(WampPeer transmitter, WampMessage msg) {
synchronized (callbacks) {
for (Callback callback : callbacks) {
callback.preTransmit(transmitter, msg);
}
}
}
@Override
public void postTransmit(WampPeer transmitter, WampMessage msg) {
synchronized (callbacks) {
for (Callback callback : callbacks) {
callback.postTransmit(transmitter, msg);
}
}
}
@Override
public void preReceive(WampPeer receiver, WampMessage msg) {
synchronized (callbacks) {
for (Callback callback : callbacks) {
callback.preReceive(receiver, msg);
}
}
}
@Override
public void postReceive(WampPeer receiver, WampMessage msg) {
synchronized (callbacks) {
for (Callback callback : callbacks) {
callback.postReceive(receiver, msg);
}
}
}
}
private ArrayList<WampPeer> mReceivers = new ArrayList<WampPeer>();
private Set<WampRole> mRoleSet;
private Callbacks mCallbacks = new Callbacks();
public WampPeer() {
}
abstract protected Set<WampRole> getRoleSet();
public void setCallback(Callback callback) {
mCallbacks.add(callback);
}
public void removeCallback(Callback callback) {
mCallbacks.remove(callback);
}
public final void connect(final WampPeer receiver) {
if (mReceivers.contains(receiver)) {
return;
}
mReceivers.add(receiver);
receiver.connect(this);
new Thread(new Runnable() {
@Override
public void run() {
mCallbacks.preConnect(WampPeer.this, receiver);
onConnected(receiver);
mCallbacks.postConnect(WampPeer.this, receiver);
}
}).start();
// TODO: Avoid to get multiple role instance.
if (mRoleSet != null) {
return;
}
mRoleSet = getRoleSet();
if (mRoleSet == null) {
throw new NullPointerException("Role is null");
}
}
public void transmit(WampMessage msg) {
if (msg == null) {
throw new IllegalArgumentException("message should not be null");
}
if (mReceivers.size() == 0) {
return;
}
boolean transmitted = false;
for (WampPeer receiver : mReceivers) {
for (WampRole role : mRoleSet) {
if (role.resolveTxMessage(receiver, msg)) {
transmitted = true;
mCallbacks.preTransmit(WampPeer.this, msg);
receiver.onReceive(WampPeer.this, msg);
onTransmitted(receiver, msg);
mCallbacks.postTransmit(WampPeer.this, msg);
break;
}
}
}
// TODO: Throw transmit exception not to handle message
if (!transmitted) {
throw new UnsupportedOperationException(msg.toString() + ", " + this.toString()
+ ", roleSet=" + mRoleSet);
}
}
private void onReceive(final WampPeer transmitter, final WampMessage msg) {
if (msg == null) {
throw new IllegalArgumentException("message should not be null");
}
OnReplyListener listener = new OnReplyListener() {
@Override
public void onReply(WampPeer receiver, WampMessage reply) {
receiver.onReceive(WampPeer.this, reply);
}
};
for (WampRole role : mRoleSet) {
if (role.resolveRxMessage(transmitter, msg, listener)) {
notifyOnReceive(transmitter, msg);
return;
}
}
// TODO: return error
throw new UnsupportedOperationException(msg.toString() + ", " + this.toString()
+ ", roleSet=" + mRoleSet);
}
private void notifyOnReceive(final WampPeer transmitter, final WampMessage msg) {
new Thread(new Runnable() {
@Override
public void run() {
if (mCallbacks != null) {
mCallbacks.preReceive(WampPeer.this, msg);
}
onReceived(msg);
if (mCallbacks != null) {
mCallbacks.postReceive(WampPeer.this, msg);
}
}
}).start();
}
abstract protected void onConnected(WampPeer peer);
abstract protected void onTransmitted(WampPeer peer, WampMessage msg);
abstract protected void onReceived(WampMessage msg);
}