package com.zendesk.maxwell.row;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ValueNode;
import com.zendesk.maxwell.errors.ParseException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
public class RowMapDeserializer extends StdDeserializer<RowMap> {
private static ObjectMapper mapper;
public RowMapDeserializer() {
this(null);
}
public RowMapDeserializer(Class<?> vc) {
super(vc);
}
@Override
public RowMap deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
JsonNode type = node.get("type");
if (type == null) {
throw new ParseException("`type` is required and cannot be null.");
}
JsonNode database = node.get("database");
if (database == null) {
throw new ParseException("`database` is required and cannot be null.");
}
JsonNode table = node.get("table");
if (table == null) {
throw new ParseException("`table` is required and cannot be null.");
}
JsonNode ts = node.get("ts");
if (ts == null) {
throw new ParseException("`ts` is required and cannot be null.");
}
JsonNode xid = node.get("xid");
JsonNode data = node.get("data");
JsonNode oldData = node.get("old");
RowMap rowMap = new RowMap(
type.asText(),
database.asText(),
table.asText(),
ts.asLong(),
new ArrayList<String>(),
null
);
if (xid != null) {
rowMap.setXid(xid.asLong());
}
if (data instanceof ObjectNode) {
Iterator keys = data.fieldNames();
if (keys != null) {
while (keys.hasNext()) {
String key = (String) keys.next();
JsonNode value = data.get(key);
if (value.isValueNode()) {
ValueNode valueNode = (ValueNode) value;
rowMap.putData(key, getValue(valueNode));
}
}
}
} else {
throw new ParseException("`data` is required and cannot be null.");
}
if (oldData instanceof ObjectNode) {
Iterator keys = oldData.fieldNames();
if (keys != null) {
while (keys.hasNext()) {
String key = (String) keys.next();
JsonNode value = oldData.get(key);
if (value.isValueNode()) {
ValueNode valueNode = (ValueNode) value;
rowMap.putOldData(key, getValue(valueNode));
}
}
}
}
return rowMap;
}
private Object getValue(ValueNode value)
{
if (value.isNull()) {
return null;
}
if (value.isBoolean()) {
return value.asBoolean();
}
if (value.canConvertToInt()) {
return value.asInt();
}
if (value.canConvertToLong()) {
return value.asLong();
}
return value.asText();
}
private static ObjectMapper getMapper()
{
if (mapper == null) {
mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(RowMap.class, new RowMapDeserializer());
mapper.registerModule(module);
}
return mapper;
}
public static RowMap createFromString(String json) throws IOException
{
return getMapper().readValue(json, RowMap.class);
}
}