package org.jooq.impl;
import static org.jooq.impl.DSL.field;
import static org.jooq.impl.DSL.name;
import static org.jooq.impl.DefaultDataType.getDataType;
import static org.jooq.impl.SQLDataType.VARCHAR;
import static org.jooq.tools.StringUtils.defaultIfBlank;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.bind.DatatypeConverter;
import org.jooq.DSLContext;
import org.jooq.Field;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.tools.json.ContainerFactory;
import org.jooq.tools.json.JSONParser;
@SuppressWarnings({ "unchecked" })
final class JSONReader {
private final DSLContext ctx;
JSONReader(DSLContext ctx) {
this.ctx = ctx;
}
final Result<Record> read(String string) {
return read(new StringReader(string));
}
@SuppressWarnings("rawtypes")
final Result<Record> read(final Reader reader) {
try {
Object root = new JSONParser().parse(reader, new ContainerFactory() {
@Override
public Map createObjectContainer() {
return new LinkedHashMap();
}
@Override
public List createArrayContainer() {
return new ArrayList();
}
});
List<Field<?>> f = new ArrayList<>();
List<?> records;
Result<Record> result = null;
Map<String, Integer> fieldIndexes = null;
if (root instanceof Map) {
Map<String, Object> o1 = (Map<String, Object>) root;
List<Map<String, String>> fields = (List<Map<String, String>>) o1.get("fields");
if (fields != null) {
for (Map<String, String> field : fields) {
String catalog = field.get("catalog");
String schema = field.get("schema");
String table = field.get("table");
String name = field.get("name");
String type = field.get("type");
f.add(field(name(catalog, schema, table, name), getDataType(ctx.dialect(), defaultIfBlank(type, "VARCHAR"))));
}
result = ctx.newResult(f);
}
records = (List<?>) o1.get("records");
}
else {
records = (List<?>) root;
}
for (Object o3 : records) {
if (o3 instanceof Map) {
Map<String, Object> record = (Map<String, Object>) o3;
String[] values = new String[record.size()];
if (result == null) {
if (f.isEmpty())
for (String name : record.keySet())
f.add(field(name(name), VARCHAR));
result = ctx.newResult(f);
}
if (fieldIndexes == null) {
fieldIndexes = new HashMap<>();
int i = 0;
for (String name : record.keySet())
fieldIndexes.put(name, i++);
}
for (Entry<String, Object> entry : record.entrySet())
values[fieldIndexes.get(entry.getKey())] = "" + entry.getValue();
Record r = ctx.newRecord(f);
r.from(values);
result.add(r);
}
else {
List record = (List) o3;
if (result == null) {
if (f.isEmpty())
f.addAll(Arrays.asList(Tools.fields(record.size())));
result = ctx.newResult(f);
}
Record r = ctx.newRecord(f);
for (int i = 0; i < f.size(); i++)
if (f.get(i).getType() == byte[].class && record.get(i) instanceof String)
record.set(i, DatatypeConverter.parseBase64Binary((String) record.get(i)));
r.from(record);
result.add(r);
}
}
return result;
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}