package io.nextop.client; import io.nextop.Message; import io.nextop.Route; import io.nextop.WireValue; import java.util.HashMap; import java.util.Map; public final class MessageControl { public static enum Direction { SEND, RECEIVE } public static enum Type { // FIXME // SUBSCRIBE, // <-> // UNSUBSCRIBE, // <-> MESSAGE, ERROR, COMPLETE } public static MessageControl send(Message message) { return send(Type.MESSAGE, message); } public static MessageControl send(Type type, Route route) { Message spec = Message.newBuilder().setRoute(route).build(); return send(type, spec); } public static MessageControl send(Type type, Message message) { return create(Direction.SEND, type, message); } public static MessageControl receive(Message message) { return receive(Type.MESSAGE, message); } public static MessageControl receive(Type type, Route route) { Message spec = Message.newBuilder().setRoute(route).build(); return receive(type, spec); } public static MessageControl receive(Type type, Message message) { return create(Direction.RECEIVE, type, message); } public static MessageControl create(Direction dir, Type type, Message message) { if (null == dir) { throw new IllegalArgumentException(); } if (null == type) { throw new IllegalArgumentException(); } if (null == message) { throw new IllegalArgumentException(); } return new MessageControl(dir, type, message); } /////// SERIALIZATION /////// private static final int S_VERSION = 1; private static final String S_KEY_VERSION = "version"; private static final String S_KEY_DIR = "dir"; private static final String S_KEY_TYPE = "type"; private static final String S_KEY_MESSAGE = "message"; public static WireValue toWireValue(MessageControl mc) { Map<Object, Object> map = new HashMap<Object, Object>(32); map.put(S_KEY_VERSION, S_VERSION); // v1 map.put(S_KEY_DIR, mc.dir.toString()); map.put(S_KEY_TYPE, mc.type.toString()); map.put(S_KEY_MESSAGE, mc.message); return WireValue.of(map); } public static MessageControl fromWireValue(WireValue value) { Map<WireValue, WireValue> map = value.asMap(); int version = map.get(S_KEY_VERSION).asInt(); switch (version) { default: // from the future // attempt to parse it as the last known version // (if fails, the parsing will error out) if (version < S_VERSION) { throw new IllegalArgumentException(); } // else fall through case 1: Direction dir = Direction.valueOf(map.get(S_KEY_DIR).asString()); Type type = Type.valueOf(map.get(S_KEY_TYPE).asString()); Message message = map.get(S_KEY_MESSAGE).asMessage(); return new MessageControl(dir, type, message); } } public final Direction dir; public final Type type; public final Message message; MessageControl(Direction dir, Type type, Message message) { this.dir = dir; this.type = type; this.message = message; } @Override public String toString() { return String.format("%s %s %s", dir, type, message); } @Override public int hashCode() { int c = dir.hashCode(); c = 31 * c + type.hashCode(); c = 31 * c + message.hashCode(); return c; } @Override public boolean equals(Object o) { if (!(o instanceof MessageControl)) { return false; } MessageControl b = (MessageControl) o; return dir.equals(b.dir) && type.equals(b.type) && message.equals(b.message); } }