package com.workshare.msnos.core;
import static com.workshare.msnos.soup.Shorteners.shorten;
import java.util.Collections;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.workshare.msnos.core.Cloud.Internal;
import com.workshare.msnos.core.Cloud.Listener;
import com.workshare.msnos.core.cloud.MessageValidators;
import com.workshare.msnos.core.cloud.MessageValidators.Result;
import com.workshare.msnos.core.cloud.Multicaster;
import com.workshare.msnos.core.routing.Router;
import com.workshare.msnos.soup.json.Json;
public class Receiver {
private static final Logger log = LoggerFactory.getLogger(Receiver.class);
private static final Logger proto = LoggerFactory.getLogger("protocol");
private final Cloud cloud;
private final Set<Gateway> gates;
private final Multicaster caster;
private final MessageValidators validators;
private final Internal internal;
private final Router router;
Receiver(Cloud cloud, Set<Gateway> gates, Multicaster multicaster) {
this(cloud, gates, multicaster, new Router(cloud, gates));
}
Receiver(Cloud cloud, Set<Gateway> gates, Multicaster multicaster, Router router) {
this.cloud = cloud;
this.caster = multicaster;
this.gates = Collections.unmodifiableSet(gates);
this.internal = cloud.internal();
this.validators = cloud.validators();
this.router = router;
for (final Gateway gate : gates) {
gate.addListener(this.cloud, new Gateway.Listener() {
@Override
public void onMessage(Message message) {
final String gateName = gate.name();
process(message.fromGate(gateName), gateName);
}
});
}
}
public Set<Gateway> gateways() {
return gates;
}
public Multicaster caster() {
return caster;
}
public Listener addListener(Listener listener) {
log.debug("Adding listener: {}", listener);
return caster.addListener(listener);
}
public void removeListener(Listener listener) {
log.debug("Removing listener: {}", listener);
caster.removeListener(listener);
}
public void process(Message message, String gateName) {
Result result = validators.isReceivable(message);
if (!result.success()) {
logNN(message, gateName, result.reason());
return;
}
if (isAddressedToLocal(message)) {
logRX(message, gateName);
message.getData().process(message, internal);
cloud.postProcess(message);
caster.dispatch(message);
}
router.forward(message);
}
private boolean isAddressedToLocal(Message message) {
Iden to = message.getTo();
return cloud.getIden().equals(to) || cloud.containsLocalAgent(to);
}
private void logNN(Message msg, String gateName, String cause) {
if (!proto.isDebugEnabled())
return;
final String muid = shorten(msg.getUuid());
final String payload = Json.toJsonString(msg.getData());
Iden from = msg.getFrom();
if (internal.localAgents().containsKey(from))
proto.trace("R#({}): ={}= {} {} {} {} {} {}", shorten(gateName, 3), cause, msg.getType(), muid, msg.getWhen(), msg.getFrom(), msg.getTo(), payload);
else
proto.debug("R#({}): ={}= {} {} {} {} {} {}", shorten(gateName, 3), cause, msg.getType(), muid, msg.getWhen(), msg.getFrom(), msg.getTo(), payload);
}
private void logRX(Message msg, String gateName) {
if (!proto.isInfoEnabled())
return;
final String muid = shorten(msg.getUuid());
final String payload = Json.toJsonString(msg.getData());
proto.info("RX({}): {} {} {} {} {} {}", shorten(gateName, 3), msg.getType(), muid, msg.getWhen(), msg.getFrom(), msg.getTo(), payload);
}
}