package com.flipkart.foxtrot.sql.responseprocessors; import com.fasterxml.jackson.databind.JsonNode; import com.flipkart.foxtrot.sql.responseprocessors.model.FieldHeader; import com.flipkart.foxtrot.sql.responseprocessors.model.FlatRepresentation; import com.flipkart.foxtrot.sql.responseprocessors.model.MetaData; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import java.util.*; public class FlatteningUtils { private static final String DEFAULT_SEPARATOR = "."; public static FlatRepresentation genericParse(JsonNode response) { List<FieldHeader> headers = Lists.newArrayList(); Map<String, MetaData> docFields = generateFieldMappings(null, response); Map<String, Object> row = Maps.newTreeMap(); for(Map.Entry<String, MetaData> docField : docFields.entrySet()) { row.put(docField.getKey(), docField.getValue().getData()); headers.add(new FieldHeader(docField.getKey(), 20)); } return new FlatRepresentation(headers, Collections.singletonList(row)); } public static FlatRepresentation genericMultiRowParse(JsonNode response, final List<String> predefinedHeaders, final String sortField) { List<FieldHeader> headers = Lists.newArrayList(); List<Map<String, Object>> rows = Lists.newArrayList(); Map<String, Integer> headerData = Maps.newTreeMap(); for(JsonNode arrayElement : response) { //Map<String, MetaData> tmpFields = generateFieldMappings(parentField, arrayElement); //fields.putAll(tmpFields); Map<String, MetaData> element = generateFieldMappings(null, arrayElement); Map<String, Object> row = Maps.newHashMap(); for(Map.Entry<String, MetaData> elementData : element.entrySet()) { if(!headerData.containsKey(elementData.getKey())) { headerData.put(elementData.getKey(), elementData.getValue().getLength()); } headerData.put(elementData.getKey(), Math.max(elementData.getValue().getLength(), headerData.get(elementData.getKey()))); row.put(elementData.getKey(), elementData.getValue().getData()); } rows.add(row); } if(null != sortField && !sortField.isEmpty()) { Collections.sort(rows, new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> lhs, Map<String, Object> rhs) { return lhs.get(sortField).toString().compareTo(rhs.get(sortField).toString()); } }); } if(null != predefinedHeaders && !predefinedHeaders.isEmpty()) { for (String predefinedHeader : predefinedHeaders) { if (headerData.containsKey(predefinedHeader)) { headers.add(new FieldHeader(predefinedHeader, headerData.get(predefinedHeader))); } } } else { for (String definedHeaders : headerData.keySet()) { if (headerData.containsKey(definedHeaders)) { headers.add(new FieldHeader(definedHeaders, headerData.get(definedHeaders))); } } } return new FlatRepresentation(headers, rows); } public static Map<String, MetaData> generateFieldMappings(String parentField, JsonNode jsonNode) { return generateFieldMappings(parentField, jsonNode, DEFAULT_SEPARATOR); } public static Map<String, MetaData> generateFieldMappings(String parentField, JsonNode jsonNode, final String separator) { Map<String, MetaData> fields = Maps.newTreeMap(); if(null == jsonNode) { System.out.println("NULL for " + parentField); return Collections.emptyMap(); } if(jsonNode.isArray()) { for(JsonNode arrayElement : jsonNode) { Map<String, MetaData> tmpFields = generateFieldMappings(parentField, arrayElement, separator); fields.putAll(tmpFields); } } Iterator<Map.Entry<String, JsonNode>> iterator = jsonNode.fields(); while (iterator.hasNext()) { Map.Entry<String, JsonNode> entry = iterator.next(); String currentField = (parentField == null) ? entry.getKey() : (String.format("%s%s%s", parentField, separator, entry.getKey())); if (entry.getValue().isObject() || entry.getValue().isArray()) { fields.putAll(generateFieldMappings(currentField, entry.getValue(), separator)); } else { fields.put(currentField, new MetaData(entry.getValue(), entry.getValue().toString().length())); } } return fields; } }