use of org.wikidata.query.rdf.blazegraph.mwapi.ApiTemplate.OutputVariable in project wikidata-query-rdf by wikimedia.
the class MWApiServiceCall method parseResponse.
/**
* Parse XML response from WM API.
*
* @param responseStream Response body as stream
* @param binding Current binding set.
* @return Set of resulting bindings, or null if none found.
* @throws SAXException on error
* @throws IOException on error
* @throws XPathExpressionException on error
*/
public ResultWithContinue parseResponse(InputStream responseStream, IBindingSet binding) throws SAXException, IOException, XPathExpressionException {
if (outputVars.isEmpty()) {
return null;
}
Document doc = docBuilder.get().parse(responseStream);
XPath path = xpath.get();
ImmutableMap<String, String> searchContinue = parseContinue(doc, path);
// FIXME: we're re-compiling it each time. Should probably do it only
// once per template.
// Note though that XPathExpression is not thread-safe. Maybe use ThreadLocal?
XPathExpression itemsXPath = path.compile(template.getItemsPath());
NodeList nodes = (NodeList) itemsXPath.evaluate(doc, XPathConstants.NODESET);
if (nodes.getLength() == 0) {
return null;
}
IBindingSet[] results = new IBindingSet[nodes.getLength()];
final Map<OutputVariable, XPathExpression> compiledVars = new HashMap<>();
// Thanks, Oracle!
for (OutputVariable var : outputVars) {
compiledVars.put(var, xpath.get().compile(var.getPath()));
}
for (int i = 0; i < nodes.getLength(); i++) {
final Node node = nodes.item(i);
results[i] = binding.copy(null);
for (Map.Entry<OutputVariable, XPathExpression> var : compiledVars.entrySet()) {
final IConstant constant;
if (var.getKey().isOrdinal()) {
constant = makeConstant(lexiconRelation.getValueFactory(), i);
results[i].set(var.getKey().getVar(), constant);
continue;
}
final Node value = (Node) var.getValue().evaluate(node, XPathConstants.NODE);
if (value != null && value.getNodeValue() != null) {
if (var.getKey().isURI()) {
constant = makeConstant(lexiconRelation.getValueFactory(), var.getKey().getURI(value.getNodeValue()));
} else {
constant = makeConstant(lexiconRelation.getValueFactory(), value.getNodeValue());
}
results[i].set(var.getKey().getVar(), constant);
}
}
}
return new ResultWithContinue(results, searchContinue);
}
use of org.wikidata.query.rdf.blazegraph.mwapi.ApiTemplate.OutputVariable in project wikidata-query-rdf by wikimedia.
the class MWApiServiceCallUnitTest method testEmptyVars.
@Test
public void testEmptyVars() throws Exception {
List<OutputVariable> outputVars = Lists.newArrayList();
InputStream responseStream = new ByteArrayInputStream("not even xml".getBytes("UTF-8"));
Object results = createCall(outputVars).parseResponse(responseStream, binding);
assertNull(results);
}
use of org.wikidata.query.rdf.blazegraph.mwapi.ApiTemplate.OutputVariable in project wikidata-query-rdf by wikimedia.
the class MWApiServiceCallUnitTest method testResults.
@Test
public void testResults() throws Exception {
List<OutputVariable> outputVars = ImmutableList.of(new OutputVariable(makeVariable("var"), "@name"), new OutputVariable(makeVariable("header"), "/api/header/@value"), new OutputVariable(OutputVariable.Type.ITEM, makeVariable("item"), "@id"));
when(template.getItemsPath()).thenReturn("/api/result");
InputStream responseStream = new ByteArrayInputStream("<api><header value=\"heading\"></header><result name=\"result1\" id=\"Q1\"></result><result name=\"result2\"></result></api>".getBytes("UTF-8"));
Iterator<IBindingSet> results = createCall(outputVars).parseResponse(responseStream, binding).getResultIterator();
assertTrue(results.hasNext());
IBindingSet result = results.next();
assertThat(result, binds("var", "result1"));
assertThat(result, binds("header", "heading"));
assertThat(result, bindsItem("item", "Q1"));
result = results.next();
assertThat(result, binds("var", "result2"));
assertThat(result, binds("header", "heading"));
assertFalse(results.hasNext());
}
use of org.wikidata.query.rdf.blazegraph.mwapi.ApiTemplate.OutputVariable in project wikidata-query-rdf by wikimedia.
the class MWApiServiceCallUnitTest method testResultsMissingVar.
@Test
public void testResultsMissingVar() throws Exception {
List<OutputVariable> outputVars = ImmutableList.of(new OutputVariable(makeVariable("var"), "@name"), new OutputVariable(makeVariable("data"), "text()"), new OutputVariable(makeVariable("header"), "/api/header/@value"));
when(template.getItemsPath()).thenReturn("/api/result");
InputStream responseStream = new ByteArrayInputStream("<api><header value=\"heading\"></header><result name=\"result1\">datadata</result><result>we need moar data</result></api>".getBytes("UTF-8"));
Iterator<IBindingSet> results = createCall(outputVars).parseResponse(responseStream, binding).getResultIterator();
assertTrue(results.hasNext());
IBindingSet result = results.next();
assertThat(result, binds("var", "result1"));
assertThat(result, binds("data", "datadata"));
assertThat(result, binds("header", "heading"));
result = results.next();
assertThat(result, notBinds("var"));
assertThat(result, binds("data", "we need moar data"));
assertThat(result, binds("header", "heading"));
assertFalse(results.hasNext());
}
use of org.wikidata.query.rdf.blazegraph.mwapi.ApiTemplate.OutputVariable in project wikidata-query-rdf by wikimedia.
the class ApiTemplateUnitTest method testServiceOutput.
@Test
public void testServiceOutput() throws Exception {
JsonNode json = parseJson(JSON_CONFIG);
ApiTemplate template = ApiTemplate.fromJSON(json);
assertThat(template.getItemsPath(), equalTo("/api/query/pages/page/categories/cl"));
JoinGroupNode patterns = new JoinGroupNode();
// predefined variable
patterns.addArg(new StatementPatternNode(new VarNode("somevar"), createURI(ApiTemplate.OutputVariable.Type.STRING.predicate()), createURI(paramNameToURI("category"))));
// User-defined variable
patterns.addArg(new StatementPatternNode(new VarNode("var2"), createURI(ApiTemplate.OutputVariable.Type.URI.predicate()), createConstant("@somedata")));
// User-defined path variable
patterns.addArg(new StatementPatternNode(new VarNode("var3"), createURI(ApiTemplate.OutputVariable.Type.ITEM.predicate()), createConstant("item/@wikibase_id")));
// Variable with ordinal
patterns.addArg(new StatementPatternNode(new VarNode("var4"), createURI(ApiTemplate.OutputVariable.Type.ORDINAL.predicate()), createConstant("goat")));
ServiceNode serviceNode = new ServiceNode(createConstant("test"), patterns);
List<OutputVariable> outputs = template.getOutputVars(serviceNode);
assertThat(outputs.size(), equalTo(4));
// Pre-defined variable
OutputVariable var = outputs.get(0);
assertThat(var.getName(), equalTo("somevar"));
assertThat(var.getPath(), equalTo("@title"));
assertFalse(var.isOrdinal());
// User-defined variable
var = outputs.get(1);
assertThat(var.getName(), equalTo("var2"));
assertThat(var.getPath(), equalTo("@somedata"));
assertTrue(var.isURI());
assertFalse(var.isOrdinal());
assertThat(var.getURI("http://test.com/"), instanceOf(URI.class));
// URI keeps the case
assertThat(var.getURI("http://test.com/test").toString(), endsWith("test"));
// User-defined variable which is an item
var = outputs.get(2);
assertThat(var.getName(), equalTo("var3"));
assertThat(var.getPath(), equalTo("item/@wikibase_id"));
assertTrue(var.isURI());
assertFalse(var.isOrdinal());
assertThat(var.getURI("test"), instanceOf(URI.class));
// T172642: Item URIs will be uppercased
assertThat(var.getURI("test").toString(), endsWith("TEST"));
// Ordinal
var = outputs.get(3);
assertThat(var.getName(), equalTo("var4"));
assertThat(var.getPath(), equalTo("."));
assertFalse(var.isURI());
assertTrue(var.isOrdinal());
}
Aggregations