I'm looking at implementing a property function that matches when its subject and object are the same blank node. This seemed like a trivial case for subclassing the assign property function that's included with Jena. Here's a relatively minimal example that creates such a property function and uses it in a SPARQL query (also available as a Gist, https://gist.github.com/tayloj/349dd97014121a6c710c). I can see that the property function is getting called based on the query output and on the logger output. However, if I change the property usage to be a property path, e.g., just by adding a * to it, i.e., changing
" ?s <java:CBDSPARQLExample$sameBlank> ?t .\n" + to " ?s <java:CBDSPARQLExample$sameBlank>* ?t .\n" + I get no log output whatsoever, which indicates that the property function isn't getting called, and of course that means I get rather different results, too. Are property functions supposed to be invoked in property paths? Thanks in advance, //JT import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; import com.hp.hpl.jena.sparql.engine.ExecutionContext; import com.hp.hpl.jena.sparql.engine.QueryIterator; import com.hp.hpl.jena.sparql.engine.binding.Binding; import com.hp.hpl.jena.sparql.pfunction.library.assign; import com.hp.hpl.jena.sparql.util.IterLib; public class CBDSPARQLExample { private final static Logger LOGGER = LoggerFactory.getLogger( CBDSPARQLExample.class ); public static class sameBlank extends assign { @Override public QueryIterator execEvaluated( Binding binding, Node subject, Node predicate, Node object, ExecutionContext execCxt) { LOGGER.info( "called with {} {} {}", new Object[] { subject, predicate , object } ); if ( subject.isBlank() || object.isBlank() ) { return super.execEvaluated(binding, subject, predicate, object, execCxt); } else { return IterLib.noResults(execCxt); } } } private final static String MODEL_CONTENT = "" + "@prefix : <urn:ex:>\n" + "\n" + ":A :p :B ;\n" + " :q [ :r :C, :D ; :s [ :t :U ] ] .\n" + ":C :p :E .\n" + ":D :q :F .\n"; private final static String CBD_QUERY = "" + "prefix : <urn:ex:>\n" + "prefix fns: <http://example.org/fns#>" + "\n" + "construct { ?t ?p ?o }\n" + "where {\n" + " ?s ?p ?o .\n" + " ?s <java:CBDSPARQLExample$sameBlank> ?t .\n" + "}\n" + ""; public static void main(String[] args) throws IOException { final Model model = ModelFactory.createDefaultModel(); try ( final InputStream in = new ByteArrayInputStream( MODEL_CONTENT.getBytes() )) { model.read( in, null, "TTL" ); } QueryExecution exec = QueryExecutionFactory.create( CBD_QUERY, model ); final Model cbd = exec.execConstruct(); cbd.write( System.out, "TTL" ); } } -- Joshua Taylor, http://www.cs.rpi.edu/~tayloj/