package won.matcher.service.common.service.sparql;
import org.apache.jena.query.*;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.sparql.core.DatasetGraph;
import org.apache.jena.sparql.expr.nodevalue.NodeValueBoolean;
import org.apache.jena.sparql.modify.UpdateProcessRemote;
import org.apache.jena.tdb.TDB;
import org.apache.jena.tdb.TDBFactory;
import org.apache.jena.update.UpdateExecutionFactory;
import org.apache.jena.update.UpdateFactory;
import org.apache.jena.update.UpdateRequest;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;
import org.apache.jena.riot.RDFFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import won.protocol.util.RdfUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
/**
* Service to access of Sparql enpoint database to save or query linked data.
*
* User: hfriedrich
* Date: 15.04.2015
*/
@Component
public class SparqlService
{
protected final Logger log = LoggerFactory.getLogger(getClass());
protected String sparqlEndpoint;
//protected DatasetAccessor accessor;
public static Dataset deserializeDataset(String serializedResource, Lang format) throws IOException {
InputStream is = new ByteArrayInputStream(serializedResource.getBytes(StandardCharsets.UTF_8));
Dataset ds = RdfUtils.toDataset(is, new RDFFormat(format));
is.close();
return ds;
}
@Autowired
public SparqlService(@Value("${uri.sparql.endpoint}") String sparqlEndpoint) {
this.sparqlEndpoint = sparqlEndpoint;
//accessor = DatasetAccessorFactory.createHTTP(sparqlEndpoint);
}
public String getSparqlEndpoint() {
return sparqlEndpoint;
}
/**
* Update named graph by first deleting it and afterwards inserting the triples of the new model.
*
* @param graph named graph to be updated
* @param model model that holds triples to set
*/
public String createUpdateNamedGraphQuery(String graph, Model model) {
StringWriter sw = new StringWriter();
RDFDataMgr.write(sw, model, Lang.NTRIPLES);
String query = "\nCLEAR GRAPH <" + graph + ">;\n" + "\nINSERT DATA { GRAPH <" + graph + "> { " + sw + "}};\n";
return query;
}
/**
* Update a dataset of names graphs first deleting them and afterwards inserting the triples of the new models.
*
* @param ds
*/
public void updateNamedGraphsOfDataset(Dataset ds) {
String query = "";
Iterator<String> graphNames = ds.listNames();
while (graphNames.hasNext()) {
log.debug("Save dataset");
String graphName = graphNames.next();
Model model = ds.getNamedModel(graphName);
query += createUpdateNamedGraphQuery(graphName, model);
// Update can also be done with accessor - use put/add?
// accessor.add(graphName, model);
}
if (query != "") {
executeUpdateQuery(query);
}
}
public Model retrieveModel(String graphName) {
String queryTemplate = "CONSTRUCT { ?s ?p ?o } WHERE { GRAPH <%s> { ?s ?p ?o } . }";
String queryString = String.format(queryTemplate, graphName);
Query query = QueryFactory.create(queryString);
QueryExecution qexec = QueryExecutionFactory.sparqlService(sparqlEndpoint, query);
Model model = qexec.execConstruct();
return model;
}
public Dataset retrieveDataset(String graphName) {
DatasetGraph dsg = TDBFactory.createDatasetGraph();
dsg.getContext().set(TDB.symUnionDefaultGraph, new NodeValueBoolean(true));
Dataset ds = DatasetFactory.create(dsg);
Model model = retrieveModel(graphName);
ds.addNamedModel(graphName, model);
return ds;
}
public Dataset retrieveNeedDataset(String uri) {
String queryString = "prefix won: <http://purl.org/webofneeds/model#> select distinct ?g where { " +
"GRAPH ?g { <" + uri + "> a won:Need. ?a ?b ?c. } }";
Query query = QueryFactory.create(queryString);
QueryExecution qexec = QueryExecutionFactory.sparqlService(sparqlEndpoint, query);
ResultSet results = qexec.execSelect();
Dataset ds = DatasetFactory.createGeneral();
while (results.hasNext()) {
QuerySolution qs = results.next();
String graphUri = qs.getResource("g").getURI();
Model model = retrieveModel(graphUri);
ds.addNamedModel(graphUri, model);
}
return ds;
}
/**
* Execute a SPARQL Update query.
*
* @param updateQuery
*/
public void executeUpdateQuery(String updateQuery) {
log.debug("Update SPARQL Endpoint: {}", sparqlEndpoint);
log.debug("Execute query: {}", updateQuery);
UpdateRequest query = UpdateFactory.create(updateQuery);
UpdateProcessRemote riStore = (UpdateProcessRemote)
UpdateExecutionFactory.createRemote(query, sparqlEndpoint);
riStore.execute();
}
}