package org.nextprot.api.rdf.service.impl;
import java.util.ArrayList;
import java.util.List;
import org.nextprot.api.commons.exception.ExceptionUtils;
import org.nextprot.api.commons.exception.NextProtException;
import org.nextprot.api.commons.utils.SparqlResult;
import org.nextprot.api.commons.utils.SparqlUtils;
import org.nextprot.api.rdf.service.SparqlEndpoint;
import org.nextprot.api.rdf.service.SparqlService;
import org.nextprot.api.rdf.utils.SparqlDictionary;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryParseException;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.sparql.core.Var;
import com.hp.hpl.jena.sparql.engine.binding.Binding;
import com.hp.hpl.jena.sparql.engine.http.QueryEngineHTTP;
import com.hp.hpl.jena.sparql.resultset.ResultsFormat;
@Service
public class SparqlServiceImpl implements SparqlService, InitializingBean {
private static final String ENTRY_SUFFIX_URI = "http://nextprot.org/rdf/entry/";
private String prefix = null;
@Autowired private SparqlDictionary sparqlDictionary = null;
@Autowired private SparqlEndpoint sparqlEndpoint = null;
@Override
@Cacheable("sparql")
public List<String> findEntries(String sparql, String sparqlEndpointUrl, String sparqlTitle) {
String query = SparqlUtils.buildQuery(prefix, sparql);
List<String> results = new ArrayList<String>();
QueryExecution qExec = null;
try {
qExec = QueryExecutionFactory.sparqlService(sparqlEndpointUrl, query);
} catch (QueryParseException qe) {
String msg = ExceptionUtils.fixLineNumberInErrorMessage(qe.getLocalizedMessage());
throw new NextProtException("Malformed SPARQL: " + msg);
}
ResultSet rs = qExec.execSelect();
/**
* This give an empty graph....
* Model m = rs.getResourceModel();
* Graph g = m.getGraph();
* System.err.println("The graph is" + g);
*/
Var x = Var.alloc("entry");
while (rs.hasNext()) {
Binding b = rs.nextBinding();
Node entryNode = b.get(x);
if (entryNode == null) {
qExec.close();
throw new NextProtException("Bind your protein result to a variable called ?entry. Example: \"?entry :classifiedWith cv:KW-0813.\"");
} else if (entryNode.toString().indexOf(ENTRY_SUFFIX_URI) == -1) {
qExec.close();
throw new NextProtException("Any entry found in the output, however was found: " + entryNode.toString());
}
String entry = entryNode.toString().replace(ENTRY_SUFFIX_URI, "").trim();
results.add(entry);
}
qExec.close();
return results;
}
private String buildQuery(String query) {
// If it does not start with prefix
if (!query.trim().toUpperCase().startsWith("PREFIX")) {
String resultQuery = "";
resultQuery += prefix;
// and if does not start with select
boolean selectIncluded = false;
if (!query.trim().toUpperCase().startsWith("SELECT")) {
resultQuery += "SELECT distinct ?entry {\n";
selectIncluded = true;
}
resultQuery += query;
if (selectIncluded)
resultQuery += "\n}";
return resultQuery;
} else {
String resultQuery = "";
resultQuery += prefix;
resultQuery += query;
return resultQuery;
}
}
// private static String removeComments (String query){
// TODO make a better regex not to include things like
// PREFIX : <http://nextprot.org/rdf#> --> PREFIX : <http://nextprot.org/rdf
// return query;
// return query.replaceAll("#.*(?=\\n)", "");
// }
@Override
public void afterPropertiesSet() throws Exception {
prefix = sparqlDictionary.getSparqlPrefixes();
}
@Override
public List<String> findEntriesNoCache(String queryString, String sparqlEndpoint, String queryTitle, String titleId) {
// Should not take the cache because does not go through the proxy
return this.findEntries(queryString, sparqlEndpoint, queryTitle);
}
@Override
public SparqlResult sparqlSelect(String sparql, String sparqlEndpointUrl, int timeout, String queryTitle, String testId, ResultsFormat format) {
SparqlResult result = null;
try {
QueryExecution qExec = QueryExecutionFactory.sparqlService(sparqlEndpointUrl, sparql);
qExec.setTimeout(timeout);
ResultSet rs = qExec.execSelect();
result = SparqlUtils.convertResultToFormat(rs, format);
qExec.close();
} catch (QueryParseException qe) {
String msg = ExceptionUtils.fixLineNumberInErrorMessage(qe.getLocalizedMessage());
throw new NextProtException("Malformed SPARQL: " + msg);
}
return result;
}
@Override
public QueryExecution queryExecution(String query) {
QueryEngineHTTP qExec = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(sparqlEndpoint.getUrl(), query);
qExec.addParam("timeout", sparqlEndpoint.getTimeout());
return qExec;
}
}