package org.aksw.jena_sparql_api.web.servlets;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.MediaType;
import org.aksw.jena_sparql_api.concepts.Concept;
import org.aksw.jena_sparql_api.concepts.Path;
import org.aksw.jena_sparql_api.core.QueryExecutionFactory;
import org.aksw.jena_sparql_api.core.SparqlService;
import org.aksw.jena_sparql_api.core.SparqlServiceFactory;
import org.aksw.jena_sparql_api.model.QueryExecutionFactoryModel;
import org.aksw.jena_sparql_api.sparql_path.core.algorithm.ConceptPathFinder;
import org.aksw.jena_sparql_api.utils.SparqlFormatterUtils;
import org.aksw.jena_sparql_api.web.utils.AuthenticatorUtils;
import org.aksw.jena_sparql_api.web.utils.ThreadUtils;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.sparql.core.DatasetDescription;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.gson.Gson;
@Service
@javax.ws.rs.Path("/path-finding")
public class PathFindingApi {
//@Resource(name="jassa.sparqlServiceFactory")
public PathFindingApi() {
}
@Autowired
private SparqlServiceFactory sparqlServiceFactory;
@Autowired
private HttpServletRequest req;
@GET
@Produces(MediaType.APPLICATION_JSON)
public void findPathsPost(
@Suspended final AsyncResponse asyncResponse,
@QueryParam("service-uri") String serviceUri,
@QueryParam("default-graph-uri") List<String> defaultGraphUris,
@QueryParam("named-graph-uri") List<String> namedGraphUris,
@QueryParam("source-element") String sourceElement,
@QueryParam("source-var") String sourceVar,
@QueryParam("target-element") String targetElement,
@QueryParam("target-var") String targetVar,
@QueryParam("js-service-uri") String joinSummaryServiceUri,
@QueryParam("js-graph-uri") List<String> joinSummaryGraphUris,
@QueryParam("query") String queryString,
@QueryParam("n-paths") Integer nPaths,
@QueryParam("max-hops") Integer maxHops
) throws ClassNotFoundException, SQLException {
findPaths(asyncResponse, serviceUri, defaultGraphUris, namedGraphUris, sourceElement, sourceVar, targetElement, targetVar, joinSummaryServiceUri, joinSummaryGraphUris, queryString, nPaths, maxHops);
}
@POST
@Produces(MediaType.APPLICATION_JSON)
public void findPathsGet(
@Suspended final AsyncResponse asyncResponse,
@FormParam("service-uri") String serviceUri,
@FormParam("default-graph-uri") List<String> defaultGraphUris,
@FormParam("named-graph-uri") List<String> namedGraphUris,
@FormParam("source-element") String sourceElement,
@FormParam("source-var") String sourceVar,
@FormParam("target-element") String targetElement,
@FormParam("target-var") String targetVar,
@FormParam("js-service-uri") String joinSummaryServiceUri,
@FormParam("js-graph-uri") List<String> joinSummaryGraphUris,
@FormParam("query") String queryString,
@FormParam("n-paths") Integer nPaths,
@FormParam("max-hops") Integer maxHops
) throws ClassNotFoundException, SQLException {
findPaths(asyncResponse, serviceUri, defaultGraphUris, namedGraphUris, sourceElement, sourceVar, targetElement, targetVar, joinSummaryServiceUri, joinSummaryGraphUris, queryString, nPaths, maxHops);
}
public void findPaths(
final AsyncResponse response,
final String serviceUri,
final List<String> defaultGraphUris,
final List<String> namedGraphUris,
final String sourceElement,
final String sourceVar,
final String targetElement,
final String targetVar,
final String joinSummaryServiceUri,
final List<String> joinSummaryGraphUris,
final String queryString,
final Integer nPaths,
final Integer maxHops
) throws ClassNotFoundException, SQLException {
// Must parse the authenticator here (outside of the async thread)
UsernamePasswordCredentials credentials = AuthenticatorUtils.parseCredentials(req);
HttpClient httpClient = AuthenticatorUtils.prepareHttpClientBuilder(credentials).build();
ThreadUtils.start(response, new Runnable() {
@Override
public void run() {
int _nPaths = nPaths != null? nPaths : 3;
int _maxHops = maxHops != null ? maxHops : 3;
DatasetDescription datasetDescription = new DatasetDescription(defaultGraphUris, namedGraphUris);
Concept sourceConcept = Concept.create(sourceElement, sourceVar);
Concept targetConcept = Concept.create(targetElement, targetVar);
SparqlService sparqlService = sparqlServiceFactory.createSparqlService(serviceUri, datasetDescription, httpClient);
QueryExecutionFactory qef = sparqlService.getQueryExecutionFactory();
Model joinSummaryModel;
List<String> jss = joinSummaryGraphUris != null ? joinSummaryGraphUris : Collections.<String>emptyList();
DatasetDescription jsDs = new DatasetDescription(jss, Collections.<String>emptyList());
if(joinSummaryServiceUri != null && !joinSummaryServiceUri.isEmpty()) {
// TODO Add support for authenticating at the join summary service
SparqlService jsSparqlService = sparqlServiceFactory.createSparqlService(joinSummaryServiceUri, jsDs, null);
QueryExecutionFactory jsQef = jsSparqlService.getQueryExecutionFactory();
joinSummaryModel = ConceptPathFinder.createJoinSummary(jsQef);
} else {
joinSummaryModel = ConceptPathFinder.createDefaultJoinSummaryModel(qef);
}
List<Path> paths = ConceptPathFinder.findPaths(qef, sourceConcept, targetConcept, _nPaths, _maxHops, joinSummaryModel);
String result;
// if there is a queryString, we will use sparql mode, otherwise, we will just return the json
if(queryString != null && !queryString.isEmpty()) {
Model model = ConceptPathFinder.createModel(paths);
QueryExecutionFactoryModel pathSparqlService = new QueryExecutionFactoryModel(model);
QueryExecution qe = pathSparqlService.createQueryExecution(queryString);
ResultSet rs = qe.execSelect();
result = SparqlFormatterUtils._formatJson(rs);
// Writer writer = new JsonWriter();
// writer.wr
}
else {
List<String> tmp = new ArrayList<String>();
for(Path path : paths) {
tmp.add(path.toPathString());
}
Gson gson = new Gson();
result = gson.toJson(tmp);
}
//return result;
response.resume(result);
}
});
}
/**
* Input: A JSon object with the fields:
* {
* service: { serviceIri: '', defaultGraphIris: [] }
* sourceConcept: { elementStr: '', varName: '' }
* targetConcept:
* }
*
*
* @param serviceDesc A json object describing the service.
* @param startConcept
* @param destConcept
* @return
* @throws SQLException
* @throws ClassNotFoundException
*/
// @GET
// @Produces(MediaType.APPLICATION_JSON)
// public String findPaths(@QueryParam("query") String json) throws ClassNotFoundException, SQLException {
// Gson gson = new Gson();
// PathDesc pathDesc = gson.fromJson(json, PathDesc.class);
//
// ConceptDesc sourceDesc = pathDesc.getSourceConcept();
// Concept sourceConcept = Concept.create(sourceDesc.getElementStr(), sourceDesc.getVarName());
//
// ConceptDesc targetDesc = pathDesc.getTargetConcept();
// Concept targetConcept = Concept.create(targetDesc.getElementStr(), targetDesc.getVarName());
//
// ServiceDesc serviceDesc = pathDesc.getService();
// QueryExecutionFactory service = sparqlServiceFactory.createSparqlService(serviceDesc.getServiceIri(), serviceDesc.getDefaultGraphIris());
//
// List<Path> paths = ConceptPathFinder.findPaths(service, sourceConcept, targetConcept);
//
// List<String> tmp = new ArrayList<String>();
// for(Path path : paths) {
// tmp.add(path.toPathString());
// }
//
// String result = gson.toJson(tmp);
// return result;
// }
}