Javier Villa
Javier Villa

Reputation: 159

Jena: Property Paths when building queries programmatically

I am trying to use the API that Jena offers to build SPARQL queries programatically. To keep it simple, I'd like something like:

SELECT *
WHERE {
  ?typ rdfs:subClassOf+ myns:SomeType .
}

The problem is rdfs:subClassOf+, which uses property paths. I try to build the query like this:

    query = new Query();
    query.setQuerySelectType();
    query.addResultVar("typ");
    ElementTriplesBlock triplePattern = new ElementTriplesBlock();
    Node typ = NodeFactory.createVariable("typ");
    Node sometype = ...; // Assume OK

    triplePattern.addTriple(new Triple(typ, 
            ResourceFactory.createProperty(RDFS.subClassOf.getURI() + "+").asNode(),
            sometype));
    query.setQueryPattern(triplePattern);

If I didn't have the property path, i.e. in the SPARQL it only said rdfs:subClassOf, I could go with:

    triplePattern.addTriple(new Triple(typ, 
            RDFS.subClassOf.asNode(),
            sometype));

Which works. However I can't specify the path modifier in the URI to build the property since I get:

Caused by: com.hp.hpl.jena.shared.InvalidPropertyURIException: http://www.w3.org/2000/01/rdf-schema#subClassOf+
  at com.hp.hpl.jena.rdf.model.impl.PropertyImpl.checkLocalName(PropertyImpl.java:67)
  at com.hp.hpl.jena.rdf.model.impl.PropertyImpl.<init>(PropertyImpl.java:56)
  at com.hp.hpl.jena.rdf.model.ResourceFactory$Impl.createProperty(ResourceFactory.java:296)
  at com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty(ResourceFactory.java:144)
  ... (test class)

So the question is, how can I specify such a query in Jena through the Java API. I know I can make the query out of a string with the property path syntax, but not when building the query programmatically.

Upvotes: 3

Views: 547

Answers (1)

Javier Villa
Javier Villa

Reputation: 159

I think I found it after tinkering a bit more.

First, one has to use an ElementPathBlock if the WHERE {...} part is going to use any paths, since attempting to add a path to a ElementTripleBlock will raise an exception. Then, instead of adding a Triple, one would add a TriplePath. Code:

    ElementPathBlock triplePattern = new ElementPathBlock();
    Node typ = NodeFactory.createVariable("typ");
    Node sometype = ...; // Assume OK
    // This represents rdfs:subClassOf+
    Path pathSubClassOfPlus = PathFactory.pathOneOrMore1(
        PathFactory.pathLink(RDFS.subClassOf.asNode())
    );
    // This represents the SPARQL: ?typ rdfs:subClassOf+ sometype .
    TriplePath subClassOfPlus = new TriplePath(typ, pathSubClassOfPlus, sometype)
    triplePattern.addTriplePath(subClassOfPlus);
    // ... One can also add regular Triple instances afterwards
    query.setQueryPattern(triplePattern);

Upvotes: 4

Related Questions