package rl;
import com.ericsson.otp.erlang.*;
import com.erlang4j.api.IBinding;
import com.erlang4j.internal.messages.MessageComposer;
import com.erlang4j.internal.messages.MessageParser;
import java.io.IOException;
import java.lang.ref.Reference;
import java.util.Hashtable;
import java.util.concurrent.atomic.AtomicReference;
import static com.erlang4j.api.Erlang4jMessageLanguage.atom;
import static com.erlang4j.api.Erlang4jMessageLanguage.binding;
import static com.erlang4j.api.Erlang4jMessageLanguage.tuple;
/**
* Created by IntelliJ IDEA.
* User: user
* Date: 22.09.11
* Time: 11:21
* To change this template use File | Settings | File Templates.
*/
public class Interactor {
private Hashtable<String, Executable> handlers;
private ListenerThread listenerThread;
private OtpNode self;
private OtpMbox messageBox;
private String name;
private AtomicReference<OtpErlangTuple> parentRef;
public Interactor(String name, String nodename, String cookie) throws IOException {
this.name = name;
this.handlers = new Hashtable<String, Executable>();
this.self = new OtpNode(nodename, cookie);
this.messageBox = self.createMbox(name + "_sender");
this.parentRef = new AtomicReference<OtpErlangTuple>(tuple(atom("null"), atom(self.node())));
this.listenerThread = new ListenerThread(self.createMbox(name + "_inner"), handlers, parentRef);
}
public void AddHandler(String varName, Executable handler) {
handlers.put(varName, handler);
}
public void Start() {
listenerThread.start();
}
private class ListenerThread extends Thread {
private Hashtable<String, Executable> handlers;
private OtpMbox messageBox;
private AtomicReference<OtpErlangTuple> parentRef;
public ListenerThread(OtpMbox messageBox, Hashtable<String, Executable> handlers, AtomicReference<OtpErlangTuple> parentRef) {
this.handlers = handlers;
this.messageBox = messageBox;
this.parentRef = parentRef;
}
@Override
public void run() {
OtpErlangObject receivedObject;
while (true) {
try {
receivedObject = messageBox.receive();
} catch (OtpErlangExit otpErlangExit) {
otpErlangExit.printStackTrace();
continue;
} catch (OtpErlangDecodeException e) {
e.printStackTrace();
continue;
}
(new ExecuteThread(parentRef, receivedObject)).start();
}
}
private class ExecuteThread extends Thread {
private OtpErlangObject message;
private AtomicReference<OtpErlangTuple> parentRef;
public ExecuteThread(AtomicReference<OtpErlangTuple> parentRef, OtpErlangObject message) {
this.message = message;
this.parentRef = parentRef;
}
@Override
public void run() {
if (message instanceof OtpErlangTuple) {
MessageParser parser = new MessageParser();
IBinding parsed = parser.parse(message, "{ConversationID, set, Sender, FieldName, {Type, Value}}");
if (parsed.isValid()) {
if (parsed.getAtom("Type").equals("var")) {
OtpErlangObject valueE = parsed.getRaw("Value");
Object value = null;
if (valueE instanceof OtpErlangInt) {
try {
value = ((OtpErlangInt) valueE).intValue();
} catch (OtpErlangRangeException e) {
e.printStackTrace();
}
} else if (valueE instanceof OtpErlangString) {
value = ((OtpErlangString) valueE).stringValue();
} else if (valueE instanceof OtpErlangLong) {
value = ((OtpErlangLong) valueE).longValue();
if ((Long) value >= Integer.MIN_VALUE && (Long) value <= Integer.MAX_VALUE) {
value = new Integer(value.toString());
}
} else if (valueE instanceof OtpErlangDouble) {
value = ((OtpErlangDouble) valueE).doubleValue();
}
if (value != null) {
handlers.get(parsed.getAtom("FieldName")).Exec(value);
}
}
} else {
parsed = parser.parse(message, "{ConversationID, set_parent, Parent}");
if (parsed.isValid()) {
if (parsed.getRaw("Parent") instanceof OtpErlangTuple) {
parentRef.set((OtpErlangTuple)parsed.getRaw("Parent"));
}
}
}
}
}
}
}
public void SendSet(String name, Object value) {
OtpErlangObject dataToSend;
if (value instanceof String) {
dataToSend = new OtpErlangString((String) value);
} else if (value instanceof Integer) {
dataToSend = new OtpErlangInt((Integer) value);
} else {
dataToSend = null;
System.out.println("Unsupported type: " + value.getClass().toString());
}
if (dataToSend != null) {
MessageComposer composer = new MessageComposer(binding());
OtpErlangObject msg = composer.composeFromBinding(
"{ConversationID, set, {SenderProcess, SenderNode}, FieldName, {var, Value}}",
binding(
"ConversationID", self.createRef(),
"SenderProcess", atom(this.name + "_inner"),
"SenderNode", atom(self.node()),
"FieldName", atom(name),
"Value", value
));
messageBox.send(((OtpErlangAtom)parentRef.get().elementAt(0)).atomValue(), ((OtpErlangAtom)parentRef.get().elementAt(1)).atomValue(), msg); // Надо научиться обрабатывать set_parent
}
}
public void Exit() {
listenerThread.interrupt();
}
}