package eu.dnetlib.iis.wf.report; import java.util.List; import org.apache.hadoop.util.StringUtils; import com.google.common.collect.Lists; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import eu.dnetlib.iis.common.schemas.ReportEntry; /** * Appender of {@link ReportEntry} into json report. * * @author madryk */ public class ReportEntryJsonAppender { private final ReportValueJsonConverterManager reportValueJsonConverterManager = new ReportValueJsonConverterManager(); //------------------------ LOGIC -------------------------- /** * Appends {@link ReportEntry} into the passed json report.<br/> * * The key of the report param ({@link ReportEntry#getKey()}) defines * where the value ({@link ReportEntry#getValue()}) should be inserted * in report json structure.<br/> * The key is splitted by dots. Resulting values defines subsequent * fields in json.<br/> * For example:<br/> * <code>new ReportEntry("param1.paramA", ReportEntryType.COUNTER, "34")</code><br/> * will result in following json:<br/> * <code>{"param1": {"paramA": 34}}</code><br/> * If report entry key collides with passed json, then any * conflicting node will be replaced with new report entry * value. */ public void appendReportEntry(JsonObject jsonReport, ReportEntry reportEntry) { String[] jsonFieldHierarchy = StringUtils.split(reportEntry.getKey().toString(), '.'); insertValue(jsonReport, Lists.newArrayList(jsonFieldHierarchy), reportValueJsonConverterManager.convertValue(reportEntry)); } //------------------------ PRIVATE -------------------------- /** * Inserts json value into the passed json object under location defined by fieldHierarchy list.<br/> * For example:<br/> * If <code>jsonObject = {"aaa": {"ccc":1}}</code>, <code>fieldHierarchy = ["aaa", "bbb"]</code> and <code>value = {"a": 5}</code>, * then jsonObject will be modified to: <code>{"aaa": {"ccc":1, "bbb": {"a": 5}}}</code> */ private void insertValue(JsonObject jsonObject, List<String> fieldHierarchy, JsonElement value) { String headField = fieldHierarchy.get(0); List<String> tailFieldHierarchy = fieldHierarchy.subList(1, fieldHierarchy.size()); if (jsonObject.has(headField)) { JsonElement nextElement = jsonObject.get(headField); if (fieldHierarchy.size() == 1) { jsonObject.add(headField, value); } else if (!nextElement.isJsonObject()) { JsonElement elementWithValue = generateNode(tailFieldHierarchy, value); jsonObject.add(headField, elementWithValue); } else { insertValue(jsonObject.getAsJsonObject(headField), tailFieldHierarchy, value); } } else { JsonElement elementWithValue = generateNode(tailFieldHierarchy, value); jsonObject.add(headField, elementWithValue); } } /** * Generates json element with inserted passed value under location * defined by fieldHierarchy list.<br/> * For example:<br/> * If <code>fieldHierarchy = ["aaa", "bbb"]</code> and <code>value = {"a": 5}</code>, then * result of this method will be: <code>{"aaa": {"bbb": {"a": 5}}}</code>. */ private JsonElement generateNode(List<String> fieldHierarchy, JsonElement value) { JsonElement last = value; for (int i=fieldHierarchy.size()-1; i>=0; --i) { JsonObject parentJsonObject = new JsonObject(); parentJsonObject.add(fieldHierarchy.get(i), last); last = parentJsonObject; } return last; } }