package eu.dnetlib.iis.common.counter; import static java.util.stream.Collectors.toList; import java.util.Arrays; import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import eu.dnetlib.iis.common.counter.PigCounters.JobCounters; /** * Parser of {@link PigCounters} from json string. * * @author madryk */ public class PigCountersParser { private static final String JOB_IDS_COUNTER_NAME = "JOB_GRAPH"; private static final String ALIASES_COUNTER_NAME = "Alias"; private static final char VALUES_SEPARATOR = ','; private final JsonParser jsonParser = new JsonParser(); //------------------------ LOGIC -------------------------- /** * Parses input pig counters in json format into {@link PigCounters} object. */ public PigCounters parse(String pigCountersJson) { JsonObject pigCountersJsonObject = jsonParser.parse(pigCountersJson).getAsJsonObject(); List<String> jobIds = extractJobIds(pigCountersJsonObject); List<JobCounters> jobCountersList = jobIds.stream() .map(jobId -> extractJobCounters(pigCountersJsonObject, jobId)) .collect(toList()); Map<String, String> rootLevelCounters = extractRootLevelCounters(pigCountersJsonObject); return new PigCounters(rootLevelCounters, jobCountersList); } //------------------------ PRIVATE -------------------------- /** * Extracts job ids from pig counters json. */ private List<String> extractJobIds(JsonObject pigCountersJsonObject) { JsonElement element = pigCountersJsonObject.get(JOB_IDS_COUNTER_NAME); return Lists.newArrayList(StringUtils.split(element.getAsString(), VALUES_SEPARATOR)); } /** * Extracts job counters from pig counters json. */ private JobCounters extractJobCounters(JsonObject pigCountersJsonObject, String jobId) { JsonObject jobCountersJson = pigCountersJsonObject.get(jobId).getAsJsonObject(); List<String> aliases = Arrays.asList(StringUtils.split(jobCountersJson.get(ALIASES_COUNTER_NAME).getAsString(), VALUES_SEPARATOR)); Map<String, String> counters = buildCountersFromJson(jobCountersJson); return new JobCounters(jobId, aliases, counters); } /** * Extracts root level counters from pig counter json */ private Map<String, String> extractRootLevelCounters(JsonObject pigCountersJsonObject) { return buildCountersFromJson(pigCountersJsonObject); } /** * Builds job counters map from json.<br/> * Method supports only primitive string values. Any counters * defined in json that doesn't follow this rule will * be omitted.<br/> * For example:<br/> * <code>buildCountersFromJson({"COUNTER_1": "aaa", "COUNTER_2": null, "COMPLEX_COUNTER": {"A": 1, "B": "bbb"})</code><br/> * will result in map with single element: <code>{"COUNTER_1": "aaa"}</code> */ private Map<String, String> buildCountersFromJson(JsonObject jsonCounters) { Map<String, String> counters = Maps.newHashMap(); for (Map.Entry<String, JsonElement> jsonCounter : jsonCounters.entrySet()) { JsonElement counterValue = jsonCounter.getValue(); if (counterValue.isJsonPrimitive() && counterValue.getAsJsonPrimitive().isString()) { counters.put(jsonCounter.getKey(), counterValue.getAsString()); } } return counters; } }