/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.marmotta.platform.sparql.services.sparql;
import info.aduna.lang.FileFormat;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import org.apache.commons.lang3.StringUtils;
import org.apache.marmotta.commons.vocabulary.SPARQL_SD;
import org.apache.marmotta.platform.core.api.config.ConfigurationService;
import org.apache.marmotta.platform.core.api.templating.TemplatingService;
import org.apache.marmotta.platform.core.api.triplestore.SesameService;
import org.apache.marmotta.platform.core.exception.InvalidArgumentException;
import org.apache.marmotta.platform.core.exception.MarmottaException;
import org.apache.marmotta.platform.sparql.api.sparql.QueryType;
import org.apache.marmotta.platform.sparql.api.sparql.SparqlService;
import org.apache.marmotta.platform.sparql.services.sparqlio.rdf.SPARQLGraphResultWriter;
import org.apache.marmotta.platform.sparql.services.sparqlio.sparqlhtml.SPARQLHTMLSettings;
import org.apache.marmotta.platform.sparql.webservices.SparqlWebService;
import org.openrdf.model.BNode;
import org.openrdf.model.Resource;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.ValueFactory;
import org.openrdf.model.impl.ValueFactoryImpl;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.query.Binding;
import org.openrdf.query.BindingSet;
import org.openrdf.query.BooleanQuery;
import org.openrdf.query.GraphQuery;
import org.openrdf.query.MalformedQueryException;
import org.openrdf.query.Query;
import org.openrdf.query.QueryEvaluationException;
import org.openrdf.query.QueryLanguage;
import org.openrdf.query.QueryResultHandlerException;
import org.openrdf.query.TupleQuery;
import org.openrdf.query.TupleQueryResult;
import org.openrdf.query.TupleQueryResultHandlerException;
import org.openrdf.query.Update;
import org.openrdf.query.UpdateExecutionException;
import org.openrdf.query.parser.ParsedBooleanQuery;
import org.openrdf.query.parser.ParsedGraphQuery;
import org.openrdf.query.parser.ParsedQuery;
import org.openrdf.query.parser.ParsedTupleQuery;
import org.openrdf.query.parser.QueryParser;
import org.openrdf.query.parser.QueryParserUtil;
import org.openrdf.query.resultio.BooleanQueryResultFormat;
import org.openrdf.query.resultio.BooleanQueryResultWriter;
import org.openrdf.query.resultio.QueryResultFormat;
import org.openrdf.query.resultio.QueryResultIO;
import org.openrdf.query.resultio.QueryResultWriter;
import org.openrdf.query.resultio.TupleQueryResultFormat;
import org.openrdf.query.resultio.TupleQueryResultWriter;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.RepositoryResult;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFHandlerException;
import org.openrdf.rio.RDFWriter;
import org.openrdf.rio.RDFWriterRegistry;
import org.openrdf.rio.Rio;
import org.openrdf.rio.UnsupportedRDFormatException;
import org.slf4j.Logger;
/**
* Sparql Service implementation
*
* @author Sebastian Schaffert
* @author Sergio Fernández
*/
@ApplicationScoped
public class SparqlServiceImpl implements SparqlService {
/**
* @deprecated beginning with Sesame 2.8, use {@link RDFFormat#getStandardURI()} or {@link QueryResultFormat#etStandardURI()}
*/
@Deprecated
private static final Map<FileFormat, String> w3cFormatID = new HashMap<FileFormat, String>() {
private static final long serialVersionUID = 1L;
{
put(RDFFormat.JSONLD, "http://www.w3.org/ns/formats/JSON-LD");
put(RDFFormat.N3, "http://www.w3.org/ns/formats/N3");
put(RDFFormat.NTRIPLES, "http://www.w3.org/ns/formats/N-Triples");
put(RDFFormat.NQUADS, "http://www.w3.org/ns/formats/N-Quads");
put(RDFFormat.RDFA, "http://www.w3.org/ns/formats/RDFa");
put(RDFFormat.RDFJSON, "http://www.w3.org/ns/formats/RDF_JSON");
put(RDFFormat.RDFXML, "http://www.w3.org/ns/formats/RDF_XML");
put(RDFFormat.TURTLE, "http://www.w3.org/ns/formats/Turtle");
put(RDFFormat.TRIG, "http://www.w3.org/ns/formats/TriG");
put(TupleQueryResultFormat.CSV, "http://www.w3.org/ns/formats/SPARQL_Results_CSV");
put(TupleQueryResultFormat.JSON, "http://www.w3.org/ns/formats/SPARQL_Results_JSON");
put(TupleQueryResultFormat.TSV, "http://www.w3.org/ns/formats/SPARQL_Results_TSV");
put(TupleQueryResultFormat.SPARQL, "http://www.w3.org/ns/formats/SPARQL_Results_XML");
}};
/**
* Get the seam logger for issuing logging statements.
*/
@Inject
private Logger log;
@Inject
private ConfigurationService configurationService;
@Inject
private TemplatingService templatingService;
@Inject
private SesameService sesameService;
private ExecutorService executorService;
private long queryId = 0;
@PostConstruct
public void initialize() {
executorService = Executors.newCachedThreadPool(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "SPARQL Query Thread " + (++queryId));
}
});
}
@Override
public Query parseQuery(QueryLanguage language, String query) throws RepositoryException, MalformedQueryException {
Query sparqlQuery = null;
RepositoryConnection connection = sesameService.getConnection();
try {
connection.begin();
sparqlQuery = connection.prepareQuery(language, query);
connection.commit();
} finally {
connection.close();
}
return sparqlQuery;
}
@Override
public QueryType getQueryType(QueryLanguage language, String query) throws MalformedQueryException {
QueryParser parser = QueryParserUtil.createParser(language);
ParsedQuery parsedQuery = parser.parseQuery(query, configurationService.getServerUri() + SparqlWebService.PATH + "/" + SparqlWebService.SELECT);
if (parsedQuery instanceof ParsedTupleQuery) {
return QueryType.TUPLE;
} else if (parsedQuery instanceof ParsedBooleanQuery) {
return QueryType.BOOL;
} else if (parsedQuery instanceof ParsedGraphQuery) {
return QueryType.GRAPH;
} else {
return null;
}
}
@Override
@Deprecated
public void query(final QueryLanguage queryLanguage, final String query, final TupleQueryResultWriter tupleWriter, final BooleanQueryResultWriter booleanWriter, final SPARQLGraphResultWriter graphWriter, int timeoutInSeconds) throws MarmottaException, MalformedQueryException, QueryEvaluationException, TimeoutException {
log.debug("executing SPARQL query:\n{}", query);
Future<Boolean> future = executorService.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
long start = System.currentTimeMillis();
try {
RepositoryConnection connection = sesameService.getConnection();
try {
connection.begin();
Query sparqlQuery = connection.prepareQuery(queryLanguage, query);
if (sparqlQuery instanceof TupleQuery) {
query((TupleQuery) sparqlQuery, tupleWriter);
} else if (sparqlQuery instanceof BooleanQuery) {
query((BooleanQuery) sparqlQuery, booleanWriter);
} else if (sparqlQuery instanceof GraphQuery) {
query((GraphQuery) sparqlQuery, graphWriter.getOutputStream(), graphWriter.getFormat());
} else {
connection.rollback();
throw new InvalidArgumentException("SPARQL query type " + sparqlQuery.getClass() + " not supported!");
}
connection.commit();
} catch (Exception ex) {
connection.rollback();
throw ex;
} finally {
connection.close();
}
} catch(RepositoryException e) {
log.error("error while getting repository connection: {}", e);
throw new MarmottaException("error while getting repository connection", e);
} catch (QueryEvaluationException e) {
log.error("error while evaluating query: {}", e.getMessage());
throw new MarmottaException("error while writing query result in format ", e);
}
log.debug("SPARQL execution took {}ms", System.currentTimeMillis()-start);
return Boolean.TRUE;
}
});
try {
future.get(timeoutInSeconds, TimeUnit.SECONDS);
} catch (InterruptedException | TimeoutException e) {
log.info("SPARQL query execution aborted due to timeout");
future.cancel(true);
throw new TimeoutException("SPARQL query execution aborted due to timeout (" + configurationService.getIntConfiguration("sparql.timeout",60)+"s)");
} catch (ExecutionException e) {
log.info("SPARQL query execution aborted due to exception");
if(e.getCause() instanceof MarmottaException) {
throw (MarmottaException)e.getCause();
} else if(e.getCause() instanceof MalformedQueryException) {
throw (MalformedQueryException)e.getCause();
} else {
throw new MarmottaException("unknown exception while evaluating SPARQL query",e.getCause());
}
}
}
@Override
@Deprecated
public void query(final QueryLanguage queryLanguage, final String query, final QueryResultWriter writer, final int timeoutInSeconds) throws MarmottaException, MalformedQueryException, QueryEvaluationException, TimeoutException {
log.debug("executing SPARQL query:\n{}", query);
Future<Boolean> future = executorService.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
long start = System.currentTimeMillis();
try {
RepositoryConnection connection = sesameService.getConnection();
try {
connection.begin();
Query sparqlQuery = connection.prepareQuery(queryLanguage, query);
if (sparqlQuery instanceof TupleQuery) {
query((TupleQuery) sparqlQuery, (TupleQueryResultWriter)writer);
} else if (sparqlQuery instanceof BooleanQuery) {
query((BooleanQuery) sparqlQuery, (BooleanQueryResultWriter)writer);
} else if (sparqlQuery instanceof GraphQuery) {
query((GraphQuery) sparqlQuery, ((SPARQLGraphResultWriter)writer).getOutputStream(), ((SPARQLGraphResultWriter)writer).getFormat());
} else {
connection.rollback();
throw new InvalidArgumentException("SPARQL query type " + sparqlQuery.getClass() + " not supported!");
}
connection.commit();
} catch (Exception ex) {
connection.rollback();
throw ex;
} finally {
connection.close();
}
} catch(RepositoryException e) {
log.error("error while getting repository connection: {}", e);
throw new MarmottaException("error while getting repository connection", e);
} catch (QueryEvaluationException e) {
log.error("error while evaluating query: {}", e.getMessage());
throw new MarmottaException("error while writing query result in format ", e);
}
log.debug("SPARQL execution took {}ms", System.currentTimeMillis()-start);
return Boolean.TRUE;
}
});
try {
future.get(timeoutInSeconds, TimeUnit.SECONDS);
} catch (InterruptedException | TimeoutException e) {
log.info("SPARQL query execution aborted due to timeout");
future.cancel(true);
throw new TimeoutException("SPARQL query execution aborted due to timeout (" + timeoutInSeconds+"s)");
} catch (ExecutionException e) {
log.info("SPARQL query execution aborted due to exception");
if(e.getCause() instanceof MarmottaException) {
throw (MarmottaException)e.getCause();
} else if(e.getCause() instanceof MalformedQueryException) {
throw (MalformedQueryException)e.getCause();
} else {
throw new MarmottaException("unknown exception while evaluating SPARQL query",e.getCause());
}
}
}
@Override
public void query(final QueryLanguage language, final String query, final OutputStream output, final String format, int timeoutInSeconds) throws MarmottaException, TimeoutException, MalformedQueryException {
log.debug("executing SPARQL query:\n{}", query);
Future<Boolean> future = executorService.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
long start = System.currentTimeMillis();
try {
RepositoryConnection connection = sesameService.getConnection();
try {
connection.begin();
Query sparqlQuery = connection.prepareQuery(language, query);
if (sparqlQuery instanceof TupleQuery) {
query((TupleQuery)sparqlQuery, output, format);
} else if (sparqlQuery instanceof BooleanQuery) {
query((BooleanQuery)sparqlQuery, output, format);
} else if (sparqlQuery instanceof GraphQuery) {
query((GraphQuery)sparqlQuery, output, format);
} else {
throw new InvalidArgumentException("SPARQL query type " + sparqlQuery.getClass() + " not supported!");
}
connection.commit();
} catch (Exception ex) {
connection.rollback();
throw ex;
} finally {
connection.close();
}
} catch(RepositoryException e) {
log.error("error while getting repository connection: {}", e);
throw new MarmottaException("error while getting repository connection", e);
} catch (QueryEvaluationException e) {
log.error("error while evaluating query: {}", e);
throw new MarmottaException("error while evaluating query ", e);
} catch (MalformedQueryException e) {
log.error("error because malformed query: {}", e);
throw new MarmottaException("error because malformed query", e);
}
log.debug("SPARQL execution took {}ms", System.currentTimeMillis()-start);
return Boolean.TRUE;
}
});
try {
future.get(timeoutInSeconds, TimeUnit.SECONDS);
} catch (InterruptedException | TimeoutException e) {
log.info("SPARQL query execution aborted due to timeout");
future.cancel(true);
throw new TimeoutException("SPARQL query execution aborted due to timeout (" + configurationService.getIntConfiguration("sparql.timeout",60)+"s)");
} catch (ExecutionException e) {
log.info("SPARQL query execution aborted due to exception");
if(e.getCause() instanceof MarmottaException) {
throw (MarmottaException)e.getCause();
} else if(e.getCause() instanceof MalformedQueryException) {
throw (MalformedQueryException)e.getCause();
} else {
throw new MarmottaException("unknown exception while evaluating SPARQL query",e.getCause());
}
}
}
private void query(TupleQuery query, TupleQueryResultWriter writer) throws QueryEvaluationException {
try {
query.evaluate(writer);
} catch (TupleQueryResultHandlerException e) {
throw new QueryEvaluationException("error while writing query tuple result: ",e);
}
}
private void query(TupleQuery query, OutputStream output, String format) throws QueryEvaluationException {
query(query, getTupleResultWriter(format, output));
}
private void query(BooleanQuery query, BooleanQueryResultWriter writer) throws QueryEvaluationException {
try {
writer.handleBoolean(query.evaluate());
} catch (QueryResultHandlerException e) {
throw new QueryEvaluationException("error while writing query boolean result: ",e);
}
}
private void query(BooleanQuery query, OutputStream output, String format) throws QueryEvaluationException {
query(query, getBooleanResultWriter(format, output));
}
private void query(GraphQuery query, OutputStream output, String format) throws QueryEvaluationException {
query(query, output, Rio.getWriterFormatForMIMEType(format, RDFFormat.RDFXML));
}
private void query(GraphQuery query, OutputStream output, RDFFormat format) throws QueryEvaluationException {
try {
QueryResultIO.write(query.evaluate(), format, output);
} catch (IOException e) {
throw new QueryEvaluationException("error while writing query graph result: ",e);
}
catch(RDFHandlerException e) {
throw new QueryEvaluationException("error while writing query graph result: ",e);
}
catch(UnsupportedRDFormatException e) {
throw new QueryEvaluationException("Could not find requested output RDF format for results of query: ",e);
}
}
/**
* Evaluate a SPARQL query on the LMF TripleStore. Returns the results as a list of result maps, each element
* a KiWiNode.
* <p/>
* see http://www.w3.org/TR/sparql11-query/
*
* @param queryLanguage the query language to use
* @param query the SPARQL query to evaluate in SPARQL 1.1 syntax
*/
@Override
public List<Map<String, Value>> query(QueryLanguage queryLanguage, String query) throws MarmottaException {
long start = System.currentTimeMillis();
log.debug("executing {} query:\n{}", queryLanguage.getName(), query);
List<Map<String,Value>> result = new LinkedList<Map<String, Value>>();
try {
RepositoryConnection connection = sesameService.getConnection();
try {
connection.begin();
TupleQuery tupleQuery = connection.prepareTupleQuery(queryLanguage, query);
TupleQueryResult r = tupleQuery.evaluate();
try {
while (r.hasNext()) {
BindingSet s = r.next();
Map<String, Value> map = new HashMap<String, Value>();
for (Binding binding : s) {
map.put(binding.getName(), binding.getValue());
}
result.add(map);
}
} finally {
r.close();
}
//
connection.commit();
} finally {
connection.close();
}
} catch(RepositoryException ex) {
log.error("error while getting repository connection");
throw new MarmottaException("error while getting repository connection",ex);
} catch (QueryEvaluationException e) {
throw new MarmottaException("error while evaluating SPARQL query "+query,e);
} catch (MalformedQueryException e) {
throw new InvalidArgumentException("malformed SPARQL query ("+query+") for language "+queryLanguage,e);
}
log.debug("SPARQL execution took {}ms",System.currentTimeMillis()-start);
return result;
}
/**
* Execute a SPARQL update on the LMF TripleStore. Throws a KiWiException in case the update execution fails.
* <p/>
* see http://www.w3.org/TR/sparql11-update/
*
* @param queryLanguage
* @param query a string representing the update query in SPARQL Update 1.1 syntax
* @throws Exception
*/
@Override
public void update(QueryLanguage queryLanguage, String query) throws MarmottaException {
long start = System.currentTimeMillis();
log.debug("executing SPARQL update:\n{}", query);
try {
RepositoryConnection connection = sesameService.getConnection();
try {
connection.begin();
Update update = connection.prepareUpdate(queryLanguage,query,configurationService.getBaseUri());
update.execute();
connection.commit();
} catch (UpdateExecutionException e) {
connection.rollback();
throw new MarmottaException("error while executing update",e);
} catch (MalformedQueryException e) {
connection.rollback();
throw new MarmottaException("malformed query, update failed",e);
} finally {
connection.close();
}
} catch(RepositoryException ex) {
log.error("error while getting repository connection", ex);
throw new MarmottaException("error while getting repository connection",ex);
}
log.debug("SPARQL update execution took {}ms",System.currentTimeMillis()-start);
}
@Override
public boolean ask(QueryLanguage queryLanguage, String query)
throws MarmottaException {
long start = System.currentTimeMillis();
log.debug("executing SPARQL ask:\n{}", query);
boolean result = false;
try {
RepositoryConnection connection = sesameService.getConnection();
try {
connection.begin();
BooleanQuery ask = connection.prepareBooleanQuery(queryLanguage, query);
result = ask.evaluate();
connection.commit();
} catch (MalformedQueryException e) {
throw new MarmottaException("malformed query, update failed",e);
} catch (QueryEvaluationException e) {
throw new MarmottaException("error evaluating querry",e);
} finally {
connection.close();
}
} catch(RepositoryException ex) {
log.error("error while getting repository connection", ex);
throw new MarmottaException("error while getting repository connection",ex);
}
log.debug("SPARQL update execution took {}ms",System.currentTimeMillis()-start);
return result;
}
@Override
public void createServiceDescription(RDFWriter writer, String requestURL, boolean isUpdate) throws RDFHandlerException {
try {
writer.startRDF();
final ValueFactory vf = new ValueFactoryImpl();
writer.handleNamespace(SPARQL_SD.PREFIX, SPARQL_SD.NAMESPACE);
writer.handleNamespace("formats", "http://www.w3.org/ns/formats/");
writer.handleNamespace("void", "http://rdfs.org/ns/void#");
final BNode sd = vf.createBNode();
writer.handleStatement(vf.createStatement(sd, RDF.TYPE, SPARQL_SD.Service));
writer.handleStatement(vf.createStatement(sd, SPARQL_SD.endpoint, vf.createURI(requestURL)));
writer.handleStatement(vf.createStatement(sd, SPARQL_SD.supportedLanguage, isUpdate?SPARQL_SD.SPARQL11Update:SPARQL_SD.SPARQL11Query));
if (!isUpdate) {
// FIXME: really? these types?
final Set<FileFormat> formats = new HashSet<>();
formats.addAll(RDFWriterRegistry.getInstance().getKeys());
formats.addAll(TupleQueryResultFormat.values());
for (FileFormat f: formats) {
final String formatUri = w3cFormatID.get(f);
if (StringUtils.isNotBlank(formatUri)) {
writer.handleStatement(vf.createStatement(sd, SPARQL_SD.resultFormat, vf.createURI(formatUri)));
} else {
final BNode fNode = vf.createBNode();
writer.handleStatement(vf.createStatement(sd, SPARQL_SD.resultFormat, fNode));
writer.handleStatement(vf.createStatement(fNode, RDF.TYPE, vf.createURI("http://www.w3.org/ns/formats/Format")));
writer.handleStatement(vf.createStatement(fNode, vf.createURI("http://www.w3.org/ns/formats/media_type"), vf.createLiteral(f.getDefaultMIMEType())));
writer.handleStatement(vf.createStatement(fNode, vf.createURI("http://www.w3.org/ns/formats/preferred_suffix"), vf.createLiteral("."+f.getDefaultFileExtension())));
}
}
}
final BNode dataset = vf.createBNode();
writer.handleStatement(vf.createStatement(sd, SPARQL_SD.defaultDataset, dataset));
writer.handleStatement(vf.createStatement(dataset, RDF.TYPE, SPARQL_SD.Dataset));
final RepositoryConnection kiwiCon = sesameService.getConnection();
try {
kiwiCon.begin();
// FIXME: Default graph, in KiWi this is all - is it not?
final BNode defaultGraph = vf.createBNode();
writer.handleStatement(vf.createStatement(dataset, SPARQL_SD.defaultGraph, defaultGraph));
writer.handleStatement(vf.createStatement(defaultGraph, RDF.TYPE, SPARQL_SD.Graph));
// TODO: Number of triples here? This can be expensive!
writer.handleStatement(vf.createStatement(defaultGraph, vf.createURI("http://rdfs.org/ns/void#triples"), vf.createLiteral(kiwiCon.size())));
final RepositoryResult<Resource> cID = kiwiCon.getContextIDs();
try {
while (cID.hasNext()) {
final Resource c = cID.next();
if (c instanceof URI) {
// A named graph
final BNode ng = vf.createBNode();
writer.handleStatement(vf.createStatement(dataset, SPARQL_SD.namedGraph, ng));
writer.handleStatement(vf.createStatement(ng, RDF.TYPE, SPARQL_SD.NamedGraph));
writer.handleStatement(vf.createStatement(ng, SPARQL_SD.name, c));
final BNode g = vf.createBNode();
writer.handleStatement(vf.createStatement(ng, SPARQL_SD.graph, g));
writer.handleStatement(vf.createStatement(g, RDF.TYPE, SPARQL_SD.Graph));
// TODO: Number of triples here? This can be expensive!
writer.handleStatement(vf.createStatement(g, vf.createURI("http://rdfs.org/ns/void#triples"), vf.createLiteral(kiwiCon.size(c))));
}
}
} finally {
cID.close();
}
kiwiCon.commit();
} catch (final Throwable t){
kiwiCon.rollback();
throw t;
} finally {
kiwiCon.close();
}
writer.endRDF();
} catch (RepositoryException e) {
throw new RDFHandlerException("Could not build SparqlServiceDescription");
}
}
private TupleQueryResultWriter getTupleResultWriter(String format, OutputStream os) {
TupleQueryResultFormat resultFormat;
if(format == null) {
resultFormat = TupleQueryResultFormat.SPARQL;
} else {
resultFormat = QueryResultIO.getWriterFormatForMIMEType(format);
if(resultFormat == null) {
throw new InvalidArgumentException("could not produce format "+format);
}
}
TupleQueryResultWriter writer = QueryResultIO.createWriter(resultFormat, os);
if(writer.getSupportedSettings().contains(SPARQLHTMLSettings.TEMPLATING_SERVICE)) {
writer.getWriterConfig().set(SPARQLHTMLSettings.TEMPLATING_SERVICE, templatingService);
}
return writer;
}
private BooleanQueryResultWriter getBooleanResultWriter(String format, OutputStream os) {
BooleanQueryResultFormat resultFormat;
if(format == null) {
resultFormat = BooleanQueryResultFormat.SPARQL;
} else {
resultFormat = QueryResultIO.getBooleanWriterFormatForMIMEType(format);
if(resultFormat == null) {
throw new InvalidArgumentException("could not produce format "+format);
}
}
return QueryResultIO.createWriter(resultFormat, os);
}
}