package com.acuitra.stages.question;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.core.MultivaluedMap;
import com.acuitra.ErrorCodes;
import com.acuitra.pipeline.Context;
import com.acuitra.pipeline.ContextWithJerseyClient;
import com.acuitra.question.core.Question;
import com.acuitra.stages.StageException;
import com.acuitra.stages.answer.RunSPARQLQueryStage;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.core.util.MultivaluedMapImpl;
/**
*
* Passes a natural language question to a Quepy webservice, and expects a SPARQL query to run to be returned
*
* @author nlothian
*
*/
public class QuepyStage extends AbstractQuestionStage {
private ContextWithJerseyClient<Question, List<String>> context;
private Question question;
private String quepyURL;
public QuepyStage(String quepyURL) {
super();
this.quepyURL = quepyURL;
}
@Override
public void loadContext(Context<Question, List<String>> ctx) {
this.question = ctx.getInput();
this.context = (ContextWithJerseyClient<Question, List<String>>) ctx;
}
@Override
public void execute() {
Client jerseyClient = context.getJerseyClient();
// setup the query
WebResource webResource = jerseyClient.resource(quepyURL);
MultivaluedMap<String, String> params = new MultivaluedMapImpl();
params.add("text", question.getQuestion());
// get the response
ClientResponse response = webResource.queryParams(params).type("application/x-www-form-urlencoded").get(ClientResponse.class);
String text = response.getEntity(String.class);
//System.out.println(text);
ObjectMapper mapper = new ObjectMapper();
try {
JsonNode rootNode = mapper.readTree(text);
String errorMessage = rootNode.path("error").asText();
if (!"".equals(errorMessage)) {
throw new StageException(errorMessage, ErrorCodes.COULD_NOT_UNDERSTAND_QUESTION);
}
// Note that we could have multiple answers (or the answer could be a list) and this only extracts the first result
String query = rootNode.path("query").asText();
// set the query where the Run Query stage expects it
List<String> queries = new ArrayList<>();
queries.add(query);
context.addOutput(RunSPARQLQueryStage.EXPECTED_INPUT_NAME, queries);
setOutput(text);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}