package io.vertx.core.eventbus.impl;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.eventbus.MessageCodec;
import io.vertx.core.eventbus.ReplyException;
import io.vertx.core.eventbus.impl.codecs.*;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class CodecManager {
public static final MessageCodec<String, String> PING_MESSAGE_CODEC = new PingMessageCodec();
public static final MessageCodec<String, String> NULL_MESSAGE_CODEC = new NullMessageCodec();
public static final MessageCodec<String, String> STRING_MESSAGE_CODEC = new StringMessageCodec();
public static final MessageCodec<Buffer, Buffer> BUFFER_MESSAGE_CODEC = new BufferMessageCodec();
public static final MessageCodec<JsonObject, JsonObject> JSON_OBJECT_MESSAGE_CODEC = new JsonObjectMessageCodec();
public static final MessageCodec<JsonArray, JsonArray> JSON_ARRAY_MESSAGE_CODEC = new JsonArrayMessageCodec();
public static final MessageCodec<byte[], byte[]> BYTE_ARRAY_MESSAGE_CODEC = new ByteArrayMessageCodec();
public static final MessageCodec<Integer, Integer> INT_MESSAGE_CODEC = new IntMessageCodec();
public static final MessageCodec<Long, Long> LONG_MESSAGE_CODEC = new LongMessageCodec();
public static final MessageCodec<Float, Float> FLOAT_MESSAGE_CODEC = new FloatMessageCodec();
public static final MessageCodec<Double, Double> DOUBLE_MESSAGE_CODEC = new DoubleMessageCodec();
public static final MessageCodec<Boolean, Boolean> BOOLEAN_MESSAGE_CODEC = new BooleanMessageCodec();
public static final MessageCodec<Short, Short> SHORT_MESSAGE_CODEC = new ShortMessageCodec();
public static final MessageCodec<Character, Character> CHAR_MESSAGE_CODEC = new CharMessageCodec();
public static final MessageCodec<Byte, Byte> BYTE_MESSAGE_CODEC = new ByteMessageCodec();
public static final MessageCodec<ReplyException, ReplyException> REPLY_EXCEPTION_MESSAGE_CODEC = new ReplyExceptionMessageCodec();
private final MessageCodec[] systemCodecs;
private final ConcurrentMap<String, MessageCodec> userCodecMap = new ConcurrentHashMap<>();
private final ConcurrentMap<Class, MessageCodec> defaultCodecMap = new ConcurrentHashMap<>();
public CodecManager() {
this.systemCodecs = codecs(NULL_MESSAGE_CODEC, PING_MESSAGE_CODEC, STRING_MESSAGE_CODEC, BUFFER_MESSAGE_CODEC, JSON_OBJECT_MESSAGE_CODEC, JSON_ARRAY_MESSAGE_CODEC,
BYTE_ARRAY_MESSAGE_CODEC, INT_MESSAGE_CODEC, LONG_MESSAGE_CODEC, FLOAT_MESSAGE_CODEC, DOUBLE_MESSAGE_CODEC,
BOOLEAN_MESSAGE_CODEC, SHORT_MESSAGE_CODEC, CHAR_MESSAGE_CODEC, BYTE_MESSAGE_CODEC, REPLY_EXCEPTION_MESSAGE_CODEC);
}
public MessageCodec lookupCodec(Object body, String codecName) {
MessageCodec codec;
if (codecName != null) {
codec = userCodecMap.get(codecName);
if (codec == null) {
throw new IllegalArgumentException("No message codec for name: " + codecName);
}
} else if (body == null) {
codec = NULL_MESSAGE_CODEC;
} else if (body instanceof String) {
codec = STRING_MESSAGE_CODEC;
} else if (body instanceof Buffer) {
codec = BUFFER_MESSAGE_CODEC;
} else if (body instanceof JsonObject) {
codec = JSON_OBJECT_MESSAGE_CODEC;
} else if (body instanceof JsonArray) {
codec = JSON_ARRAY_MESSAGE_CODEC;
} else if (body instanceof byte[]) {
codec = BYTE_ARRAY_MESSAGE_CODEC;
} else if (body instanceof Integer) {
codec = INT_MESSAGE_CODEC;
} else if (body instanceof Long) {
codec = LONG_MESSAGE_CODEC;
} else if (body instanceof Float) {
codec = FLOAT_MESSAGE_CODEC;
} else if (body instanceof Double) {
codec = DOUBLE_MESSAGE_CODEC;
} else if (body instanceof Boolean) {
codec = BOOLEAN_MESSAGE_CODEC;
} else if (body instanceof Short) {
codec = SHORT_MESSAGE_CODEC;
} else if (body instanceof Character) {
codec = CHAR_MESSAGE_CODEC;
} else if (body instanceof Byte) {
codec = BYTE_MESSAGE_CODEC;
} else if (body instanceof ReplyException) {
codec = defaultCodecMap.get(body.getClass());
if (codec == null) {
codec = REPLY_EXCEPTION_MESSAGE_CODEC;
}
} else {
codec = defaultCodecMap.get(body.getClass());
if (codec == null) {
throw new IllegalArgumentException("No message codec for type: " + body.getClass());
}
}
return codec;
}
public MessageCodec getCodec(String codecName) {
return userCodecMap.get(codecName);
}
public void registerCodec(MessageCodec codec) {
Objects.requireNonNull(codec, "codec");
Objects.requireNonNull(codec.name(), "code.name()");
checkSystemCodec(codec);
if (userCodecMap.containsKey(codec.name())) {
throw new IllegalStateException("Already a codec registered with name " + codec.name());
}
userCodecMap.put(codec.name(), codec);
}
public void unregisterCodec(String name) {
Objects.requireNonNull(name);
userCodecMap.remove(name);
}
public <T> void registerDefaultCodec(Class<T> clazz, MessageCodec<T, ?> codec) {
Objects.requireNonNull(clazz);
Objects.requireNonNull(codec, "codec");
Objects.requireNonNull(codec.name(), "code.name()");
checkSystemCodec(codec);
if (defaultCodecMap.containsKey(clazz)) {
throw new IllegalStateException("Already a default codec registered for class " + clazz);
}
if (userCodecMap.containsKey(codec.name())) {
throw new IllegalStateException("Already a codec registered with name " + codec.name());
}
defaultCodecMap.put(clazz, codec);
userCodecMap.put(codec.name(), codec);
}
public void unregisterDefaultCodec(Class clazz) {
Objects.requireNonNull(clazz);
MessageCodec codec = defaultCodecMap.remove(clazz);
if (codec != null) {
userCodecMap.remove(codec.name());
}
}
public MessageCodec[] systemCodecs() {
return systemCodecs;
}
private void checkSystemCodec(MessageCodec codec) {
if (codec.systemCodecID() != -1) {
throw new IllegalArgumentException("Can't register a system codec");
}
}
private MessageCodec[] codecs(MessageCodec... codecs) {
MessageCodec[] arr = new MessageCodec[codecs.length];
for (MessageCodec codec: codecs) {
arr[codec.systemCodecID()] = codec;
}
return arr;
}
}