package net.fortytwo.sesametools.ldserver.query;
import info.aduna.iteration.CloseableIteration;
import org.openrdf.query.BindingSet;
import org.openrdf.query.MalformedQueryException;
import org.openrdf.query.QueryEvaluationException;
import org.openrdf.query.QueryResultHandlerException;
import org.openrdf.query.impl.MapBindingSet;
import org.openrdf.query.parser.ParsedBooleanQuery;
import org.openrdf.query.parser.ParsedQuery;
import org.openrdf.query.parser.sparql.SPARQLParser;
import org.openrdf.query.resultio.TupleQueryResultWriter;
import org.openrdf.query.resultio.sparqljson.SPARQLResultsJSONWriter;
import org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLWriter;
import org.openrdf.sail.SailConnection;
import org.openrdf.sail.SailException;
import org.restlet.data.MediaType;
import org.restlet.representation.Variant;
import java.io.OutputStream;
import java.util.LinkedList;
import java.util.List;
/**
* @author Joshua Shinavier (http://fortytwo.net)
*/
public class SparqlTools {
public enum SparqlResultFormat {
// Note: the XML format is defined first, so that it is the default format.
XML("application/sparql-results+xml"),
JSON("application/sparql-results+json");
private static List<Variant> VARIANTS;
private final MediaType mediaType;
SparqlResultFormat(final String mimeType) {
mediaType = new MediaType(mimeType);
}
public MediaType getMediaType() {
return mediaType;
}
public static SparqlResultFormat lookup(final MediaType mediaType) {
for (SparqlResultFormat f : SparqlResultFormat.values()) {
if (f.mediaType.equals(mediaType)) {
return f;
}
}
return null;
}
public static List<Variant> getVariants() {
if (null == VARIANTS) {
VARIANTS = new LinkedList<>();
for (SparqlResultFormat f : SparqlResultFormat.values()) {
VARIANTS.add(new Variant(f.mediaType));
}
}
return VARIANTS;
}
}
private static final String BASE_URI = "http://example.org/bogusBaseURI";
private static ParsedQuery parseQuery(final String query) throws MalformedQueryException {
SPARQLParser parser = new SPARQLParser();
return parser.parseQuery(query, BASE_URI);
}
public static synchronized CloseableIteration<? extends BindingSet, QueryEvaluationException>
evaluateQuery(final ParsedQuery query,
final SailConnection sc) throws QueryException {
MapBindingSet bindings = new MapBindingSet();
boolean includeInferred = false;
try {
return sc.evaluate(query.getTupleExpr(), query.getDataset(), bindings, includeInferred);
} catch (SailException e) {
throw new QueryException(e);
}
}
public static void executeQuery(final String queryStr,
final SailConnection sc,
final OutputStream out,
final int limit,
final SparqlResultFormat format) throws QueryException {
TupleQueryResultWriter w;
switch (format) {
case JSON:
w = new SPARQLResultsJSONWriter(out);
break;
case XML:
w = new SPARQLResultsXMLWriter(out);
break;
default:
throw new QueryException(new Throwable("bad query result format: " + format));
}
try {
final ParsedQuery query = parseQuery(queryStr);
try (CloseableIteration<? extends BindingSet, QueryEvaluationException> iter = evaluateQuery(query, sc)) {
if (query instanceof ParsedBooleanQuery) {
w.handleBoolean(iter.hasNext());
} else {
final List<String> columnHeaders = new LinkedList<>();
columnHeaders.addAll(query.getTupleExpr().getBindingNames());
// FIXME: *do* specify the column headers
// columnHeaders.add("post");
// columnHeaders.add("content");
// columnHeaders.add("screen_name");
w.startQueryResult(columnHeaders);
int count = 0;
while (iter.hasNext() && count < limit) {
w.handleSolution(iter.next());
count++;
}
w.endQueryResult();
}
} catch (QueryEvaluationException | QueryResultHandlerException e) {
throw new QueryException(e);
}
} catch (MalformedQueryException | QueryEvaluationException e) {
throw new QueryException(e);
}
}
}