11

Is any easy way to parse sparql query in variables for java, like Fyzz in python? How can Jena or sesame APIs been used?

Paul Collingwood
  • 9,053
  • 3
  • 23
  • 36
Eleftherios K.
  • 239
  • 1
  • 3
  • 10

2 Answers2

9

You can parse and manipulate SPARQL in java using Apache Jena's ARQ pretty simply, at either the syntax or algebra level. QueryFactory.create(queryString) will provide a java representation of the query. Then poke around:

Query query = QueryFactory.create(queryString);
query.isSelectType() && query.isQueryResultStar(); // of the form SELECT *?
query.getDatasetDescription(); // FROM / FROM NAMED bits
query.getQueryPattern(); // The meat of the query, the WHERE bit
...etc etc..
Op op = Algebra.compile(query); // Get the algebra for the query

(see the Query java documentation)

Try starting with the tutorial 'Manipulating SPARQL using ARQ'. That will give you a feel for how queries are represented, and how to pull things out from them (visitors are especially useful). Although initially the syntax level is most familiar, for many tasks the algebra works better since it corresponds to what a query actually does.

user205512
  • 8,798
  • 29
  • 28
  • i start my main with String sparql = "SELECT ?a ?b ?c WHERE { ?a ?b . ?a ?c . }"; Query query = QueryFactory.create(sparql); but i get the message Exception in thread "main" java.lang.NoClassDefFoundError: com/hp/hpl/jena/shared/PrefixMapping$IllegalPrefixException at com.hp.hpl.jena.query.QueryFactory.create(QueryFactory.java:68) at com.hp.hpl.jena.query.QueryFactory.create(QueryFactory.java:40) at com.hp.hpl.jena.query.QueryFactory.create(QueryFactory.java:28) at testsparql.main(testsparql.java:13) – Eleftherios K. Jan 24 '13 at 13:00
  • You need jena-arq and jena-core libs on your classpath. I suspect you're missing the latter. – user205512 Jan 24 '13 at 13:10
  • Oh, and jena-iri iirc. (Use a dependency manager, if possible) – user205512 Jan 24 '13 at 13:22
  • i use eclipse... i used these external jars but i still get the mistake ava.lang.NoClassDefFoundError: org/slf4j/LoggerFactory at com.hp.hpl.jena.query.ARQ.(ARQ.java:53) at com.hp.hpl.jena.query.Query.(Query.java:63) at com.hp.hpl.jena.query.QueryFactory.create(QueryFactory.java:78) at com.hp.hpl.jena.query.QueryFactory.create(QueryFactory.java:52) at com.hp.hpl.jena.query.QueryFactory.create(QueryFactory.java:40) at testsparql.main(testsparql.java:14) Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory – Eleftherios K. Jan 24 '13 at 13:32
  • sigh, and you'll need slf4j-api and and slf4j implementation, probably slf4j-log4j12 – user205512 Jan 24 '13 at 13:35
  • i am new in java... must i import import org.slf4j.spi.* ? thank you for your replies!!! – Eleftherios K. Jan 24 '13 at 13:48
  • Ah, ok. No, you just need it on you classpath. You only need to import classes you use, such as Query and QueryFactory. – user205512 Jan 24 '13 at 14:06
  • 2
    I strongly advice to spend some time learning how to setup Eclipse projects properly and the notion of Java CLASSPATH. My advice is no to manage dependencies manually (since it is very easy to make mistakes). There are plenty of good examples around to learn from and get you started quickly. – castagna Jan 25 '13 at 09:56
  • is there a maven dependency for the same – Gaurav Rawat Jun 16 '15 at 15:12
  • Yes, you need [jena-arq](http://search.maven.org/#search|ga|1|a%3A%22jena-arq%22) – user205512 Jun 17 '15 at 09:13
  • yup using the same now parses fine is there a way to get elements and visit operations .basically need the same as I want to transform sparql into sql – Gaurav Rawat Jun 18 '15 at 17:37
  • Visitors are there: see the mentioned tutorial. For your particular task you might find [Transform](https://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/sparql/algebra/Transform.html) (which builds on that infrastructure) useful. Start with SPARQL ops, and produce SQL ops. – user205512 Jun 22 '15 at 14:18
5

Here's how you can parse and manipulate a SPARQL query using Sesame:

To parse:

ParsedQuery pq = QueryParserUtil.parseQuery(QueryLanguage.SPARQL, queryString);

The output of this is a ParsedQuery, which is an algebraic object representation of the query. If you wish to specifically get the parse tree itself, that is also possible:

ASTQueryContainer parseTree = SyntaxTreeBuilder.parseQuery(queryString);

You can then directly manipulate this abstract syntax tree by implementing a custom SyntaxTreeBuilderVisitor (tip: extend ASTVisitorBase so you only have to override the methods where you actually want to do something).

If we go back to the algebraic model, you can execute the ParsedQuery on a Sesame Sail Repository:

if (pq instanceof ParsedTupleQuery) {
        SailTupleQuery query = new SailTupleQuery(pq, repositoryConnection);
        TupleQueryResult result = query.evaluate();
} else if (pq instanceof ParsedGraphQuery) {
        // etc for other query types
}

To manipulate the ParsedQuery before executing it, use a QueryModelVisitor implementation, e.g. your own custom query manipulator:

QueryModelVisitor myVisitor = new MyCustomQueryModelVisitor();
pq.getTupleExpr().visit(myVisitor);

With such a custom query model visitor you have complete control over the query, to optimize it or indeed to rewrite into a different syntax.

Whether to do this manipulation at the level of the abstract syntax tree (AST) or at the level of the query model is a matter of taste: the query model gives you more flexbility in terms of query planning/optimization and partial rewrites (for later execution on a Sesame store), while if your goal is to completely rewrite the query for another purpose (e.g. executing it on a non-Sesame store), manipulating the syntax tree directly might be easier.

As an aside, the above way to parse and execute a query is a roundabout way of doing things. If you do not need to manipulate the parsed query before executing it, you can simply prepare and execute a query on a repository like so:

String queryString = "SELECT ...";
RepositoryConnection conn = repo.getConnection();
try {
   TupleQuery tq = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
   TupleQueryResult result = tq.evaluate();
}
finally {
   conn.close();
}
Jeen Broekstra
  • 21,642
  • 4
  • 51
  • 73