package org.codesharp.traffic;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public abstract class Node {
private MessageHandle handle;
private NodeProxy next;
private Map<Object, Connection> nodes = new HashMap<Object, Connection>();
private Map<Object, Connection[]> routes = new HashMap<Object, Connection[]>();
private Random random = new Random();
public Node(MessageHandle handle) {
this.handle = handle;
}
public abstract Object flag();
protected abstract void process(Object msg);
public void setNext(NodeProxy next) {
this.next = next;
}
public void accept(Connection conn) {
this.nodes.put(conn.id(), conn);
// FIXME connection list
this.routes.put(conn.flag(), new Connection[] { conn });
}
public void onMessage(Object msg, Connection from) {
byte cmd = this.handle.getCommand(msg);
switch (cmd) {
case Commands.MSG:
this.internalOnMessage(this.handle.append(msg, from.id()), from);
break;
case Commands.ACK:
this.internalOnAck(msg);
break;
default:
Asserter.throwUnsupportedCommand(cmd);
break;
}
}
protected void internalOnMessage(Object msg, Connection from) {
Object dst = this.handle.getDestination(msg);
// FIXME dst match with flag, should be included in route()
if (this.flag().equals(dst)) {
this.process(msg);
return;
}
Connection conn = this.route(dst, from);
if (conn != null) {
conn.send(msg);
return;
}
if (this.next != null) {
this.next.send(msg);
return;
}
this.internalOnAck(this.handle.unknownDestination(msg));
System.out.println("[ERROR] drop msg as unknown destination: " + dst);
}
protected void internalOnAck(Object msg) {
Object next = this.handle.getNext(msg);
if (next == null) {
this.process(msg);
return;
}
Connection n = this.nodes.get(next);
if (n != null)
n.send(msg);
else
System.out.println("[ERROR] drop msg as next broken: " + next);
}
protected Connection route(Object dst, Connection from) {
Connection[] nodes = this.routes.get(dst);
return nodes != null && nodes.length > 0 ?
nodes[this.random.nextInt(nodes.length)] : null;
}
}