Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get all of the subjects of a Jena Query?

Suppose I have some jena query object :

String query = "SELECT * WHERE{ ?s <some_uri> ?o ...etc. }";
Query q = QueryFactory.create(query, Syntax.syntaxARQ);

What would be the best way to get all of the subjects of the triples in the query? Preferably without having to do any string parsing/manipulation manually.

For example, given a query

SELECT * WHERE {
    ?s ?p ?o;
       ?p2 ?o2.
    ?s2 ?p3 ?o3.
    ?s3 ?p4 ?o4.
    <http://example.com> ?p5 ?o5.
}

I would hope to have returned some list which looks like

[?s, ?s2, ?s3, <http://example.com>]

In other words, I want the list of all subjects in a query. Even having only those subjects which were variables or those which were literals/uris would be useful, but I'd like to find a list of all of the subjects in the query.

I know there are methods to return the result variables (Query.getResultVars) and some other information (see http://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/query/Query.html), but I can't seem to find anything which will get specifically the subjects of the query (a list of all result variables would return the predicates and objects as well).

Any help appreciated.

like image 917
Nick Bartlett Avatar asked Mar 04 '13 14:03

Nick Bartlett


1 Answers

Interesting question. What you need to do is go through the query, and for each block of triples iterate through and look at the first part.

The most robust way to do this is via an element walker which will go through each part of the query. It might seem over the top in your case, but queries can contain all sorts of things, including FILTERs, OPTIONALs, and nested SELECTs. Using the walker means that you can ignore that stuff and focus on only what you want:

Query q = QueryFactory.create(query); // SPARQL 1.1

// Remember distinct subjects in this
final Set<Node> subjects = new HashSet<Node>();

// This will walk through all parts of the query
ElementWalker.walk(q.getQueryPattern(),
    // For each element...
    new ElementVisitorBase() {
        // ...when it's a block of triples...
        public void visit(ElementPathBlock el) {
            // ...go through all the triples...
            Iterator<TriplePath> triples = el.patternElts();
            while (triples.hasNext()) {
                // ...and grab the subject
                subjects.add(triples.next().getSubject());
            }
        }
    }
);
like image 184
user205512 Avatar answered Oct 06 '22 23:10

user205512