package org.wikibrain.core.dao.live;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.wikibrain.core.dao.DaoException;
import org.wikibrain.core.lang.Language;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* utility class used by LiveAPIQuery to parse QueryReply objects from raw query output JSON
* author: derian
*/
public class QueryParser {
JsonParser jp = new JsonParser();
/**
* Retrieves the string necessary to append to a query URL to retrieve pages starting after the last page
* retrieved in the previous query. If the last page alphabetically was retrieved in the previous query, there will be
* no continue string.
* @param queryResult represents the raw text output of the previous query
* @param queryType
* @param prefix
* @return the query continue string, or "" if no continue string is found
*/
public String getContinue(String queryResult, String queryType, String prefix) {
String continueParam = prefix + "continue";
JsonElement continueElem = jp.parse(queryResult).getAsJsonObject().get("query-continue");
if (continueElem == null) {
return "";
}
return continueElem.getAsJsonObject().get(queryType).getAsJsonObject().get(continueParam).getAsString();
}
/**
* adds QueryReply objects parsed from raw query result text to an input QueryReply list
* @param lang
* @param queryResult raw text output of query
* @param queryResultDataSection //section of queryResult in which values of interest can be found
* @param values list to which parsed QueryReply objects should be added
* @throws DaoException
*/
public void getQueryReturnValues(Language lang, String queryResult, String queryResultDataSection, List<QueryReply> values) throws DaoException {
//get JSON object representing query reply
JsonObject queryReplyObject = parseQueryObject(queryResult, "query");
//parse desired values from JSON object into QueryReplies and add to values
JsonElement dataSectionElem = queryReplyObject.get(queryResultDataSection);
if (dataSectionElem == null) {
throw new DaoException("No section \"" + queryResultDataSection + "\" found in reply text:" +
"\n" + queryResult);
}
if (dataSectionElem.isJsonArray()) {
JsonArray array = getJsonArrayFromQueryObject(queryReplyObject, queryResultDataSection);
getValuesFromJsonArray(array, values);
}
else {
JsonObject object = getJsonObjectFromQueryObject(queryReplyObject, queryResultDataSection);
getValuesFromJsonObject(object, values);
}
}
/**
*
* @param text raw query output JSON
* @return JSON object representing the query result
*/
public JsonObject parseQueryObject(String text, String value) {
try {
return jp.parse(text).getAsJsonObject().get(value).getAsJsonObject();
}
catch (Exception e) {
System.out.println(e.getMessage());
System.out.println("Input text: \n" + text);
return null;
}
}
public JsonArray parseJsonArray(String text) {
return jp.parse(text).getAsJsonArray();
}
/**
* utility method used to get a JSON object containing desired query information
* @param queryObject
* @param newObjectKey text representing the key of the new object to return
* @return a new JSON object within the input queryObject
* @throws DaoException
*/
private JsonObject getJsonObjectFromQueryObject(JsonObject queryObject, String newObjectKey) throws DaoException {
if (queryObject.get(newObjectKey).isJsonObject()) {
return queryObject.get(newObjectKey).getAsJsonObject();
}
else {
throw new DaoException("Requested JSON can't be parsed into object");
}
}
/**
* utility method used to get a JSON array containing desired query information
* @param queryObject
* @param arrayRoot text representing the name of the array
* @return a JSON array within the input queryObject
* @throws DaoException
*/
private JsonArray getJsonArrayFromQueryObject(JsonObject queryObject, String arrayRoot) throws DaoException {
if (queryObject.get(arrayRoot).isJsonArray()) {
return queryObject.get(arrayRoot).getAsJsonArray();
}
else {
throw new DaoException("Requested JSON can't be parsed into array");
}
}
/**
* The following two methods take either a JSON object or JSON array containing desired information
* from a query result. Page ID, title, namespace, redirect, and disambiguation information are retrieved from each
* page in the result, and used to create a QueryReply which is added to values
*/
private void getValuesFromJsonObject(JsonObject jo, List<QueryReply> values) {
Set<Map.Entry<String, JsonElement>> valueSet = jo.entrySet();
for (Map.Entry<String, JsonElement> entry: valueSet) {
QueryReply reply = getQueryReplyFromJsonElement(entry.getValue());
values.add(reply);
}
}
private void getValuesFromJsonArray(JsonArray ja, List<QueryReply> values) {
for (JsonElement elem : ja) {
QueryReply reply = getQueryReplyFromJsonElement(elem);
values.add(reply);
}
}
/**
* parses a QueryReply object from a JsonElement representing a page from a query result
* @param queryReplyPage JsonElement representing page of query result
* @return QueryReply containing useful information about this page
*/
private QueryReply getQueryReplyFromJsonElement(JsonElement queryReplyPage) {
JsonObject entryValue = queryReplyPage.getAsJsonObject();
//fromid field used instead of pageid for all-links query
JsonElement entryPageid = entryValue.get("pageid") != null ? entryValue.get("pageid") : entryValue.get("fromid");
JsonElement entryTitle = entryValue.get("title");
JsonElement entryNamespace = entryValue.get("ns");
boolean isRedirect = entryValue.has("redirect");
int pageid = (entryPageid != null ? entryPageid.getAsInt() : -1);
String title = (entryTitle != null ? entryTitle.getAsString() : "");
boolean isDisambig = title.contains("(disambiguation)");
int namespace = (entryNamespace != null ? entryNamespace.getAsInt() : -1);
return new QueryReply(pageid, title, namespace, isRedirect, isDisambig);
}
}