I'm using RDF4J server and workbench version 2.2.2. I'm using a SPIN-capable repository in RDF4J, and I'm reading an RDF file I've created in TobBraid Composer Free Edition (TBC FE) containing many spin:construct
rules. TBD FE is set to include the SPARQL source code for my constructors via the sp:text
property. I've observed that, when the sp:text
triple is present making the SPARQL source code available to RDF4J, RDF4J appears to use the SPARQL source instead of using the RDF tokenized representation of the same query. My primary and secondary questions are:
- How can I direct RDF4J to use the RDF representation of a SPIN constructor when both the
sp:text
and the RDF representation are present in the imported RDF file? - If RDF4J uses the
sp:text
representation of a SPIN constructor, how can it be directed to use the prefix definitions present at the head of the imported RDF file? I have 69 constructors so far and counting. Although I can embed prefix definitions in each constructor, it seems wasteful to do so.
When I deprive RDF4J of the sp:text
SPARQL source code representation, the constructors run as expected using prefixes defined at the head of the imported RDF file. I can deprive RDF4J of the source code by executing a query to delete to the source code before I instantiate the class for which I have defined a constructor. I've used this SPARQL update query to accomplish that end:
PREFIX sp: <http://spinrdf.org/sp#>
DELETE {?s sp:text ?o .} WHERE {?s sp:text ?o .}
I'd like to keep the SPARQL source code around for display purposes in a GUI I'm building that communicates with the RDF4J server via SPARQL queries. My awkward interim fix is to substitute another custom data property for the sp:text
property using the SPARQL update query used in step 5 below. This property substitution successfully prevents RDF4J from finding the SPARQL source code for the SPIN constructors. RDF4J then interprets the tokenized RDF representation of the rule instead. Is there a cleaner way to force RDF4J to execute SPIN constructors from the RDF instead of from the SPARQL source code? I'm thinking there must be some way to signal RDF4J to interpret the RDF representation instead of the SPARQL source code, but I don't know how.
And now the gory details to make this situation reproducible...
- Create a SPIN-capable repository in RDF4J using RDF4J workbench. Mine is named TakeRDF4J4SPIN (Repositories → New Repository)
- Clear the repository using RDF4J workbench (Modify → Clear)
- Load pub7.rdf using RDF4J workbench... (Modify → Add w/ use base URI as context identifier unchecked)
Note that this RDF file defines all relevant prefixes at the head of the file:
<?xml version="1.0"?>
<rdf:RDF
xmlns:fn="http://www.w3.org/2005/xpath-functions#"
xmlns:soo="http://www.disa.mil/dso/a2i/ontologies/PBSM/Sharing/SpectrumOperationsOntology#"
xmlns:spolicy="http://www.disa.mil/dso/a2i/ontologies/PBSM/Sharing/spolicy#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:spin="http://spinrdf.org/spin#"
xmlns:sp="http://spinrdf.org/sp#"
xmlns:smf="http://topbraid.org/sparqlmotionfunctions#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:arg="http://spinrdf.org/arg#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:pub7="http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/Pub7#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:spl="http://spinrdf.org/spl#"
xml:base="http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/Pub7">
Also note that the SPIN constructor attached to the class pub7:Pub7TestClass
is:
CONSTRUCT {
?this spin:hasConstraintViolation _:b0 .
_:b0 a spin:ConstraintViolation ;
rdfs:label "Test message." ;
spin:violationRoot ?this ;
spin:violationLevel spin:Error ;
spolicy:sPActionRecordHasTimestamp ?timestamp .
}
WHERE {
BIND(now() AS ?timestamp) .
}
- Attempt to create an instance of
pub7:Pub7TestClass
...
I use this SPARQL update query in RDF4J workbench's Modify → SPARQL Update to create the instance...
PREFIX inst: <http://www.disa.mil/dso/a2i/ontologies/PBSM/Sharing/Instantiations#>
PREFIX pub7: <http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/Pub7#>
INSERT DATA {
inst:aPub7TestClassInstance_test1 a pub7:Pub7TestClass .
}
Which should result in an prefix undefined error reported in RDF4J workbench due to attempting to execute the above constructor based on the sp:text
SPARQL source code representation:
org.eclipse.rdf4j.query.UpdateExecutionException: org.eclipse.rdf4j.repository.RepositoryException: org.eclipse.rdf4j.sail.SailException: org.eclipse.rdf4j.query.MalformedQueryException: org.eclipse.rdf4j.query.parser.sparql.ast.VisitorException: QName 'spin:hasConstraintViolation' uses an undefined prefix
- Now hide the SPIN constructors'
sp:text
from RDF4J using the following SPARQL update query:
.
PREFIX sp: <http://spinrdf.org/sp#>
PREFIX soo: <http://www.disa.mil/dso/a2i/ontologies/PBSM/Sharing/SpectrumOperationsOntology#>
DELETE {
?originalPolicyURI sp:systemProperty ?policySourceCodeString .
?originalPolicyURI sp:text ?policySourceCodeString .
}
INSERT {
?originalPolicyURI soo:policySourceCode ?policySourceCodeString .
}
WHERE {
?originalPolicyURI sp:text ?policySourceCodeString .
}
Now re-run the SPARQL update query shown in step 4 to instantiate the test class. The update query should run without errors this time.
Now use RDF4J Workbench's Explore → Explore function to look at the instantiation/individual we just created,
inst:aPub7TestClassInstance_test1
. One should see that the instantiation has a constraint violation notice via thespin:hasConstratintViolation
property, providing evidence that the test constructor did indeed run this time absent thesp:text
representation, forced to use the RDF tokenized representation of the SPIN constructor.
I have a partial, inelegant work-around to address my secondary question about including prefixes in the spin rules. As an initialization step, I run the following SPARQL update query that adds needed prefixes to each of the
sp:text
strings. Of course, this work-around is limited since the query embeds the prefix mappings I'm using. If other prefixes were required, then the query below would need to be edited to embed the new query definitions.Here's the SPARQL Update query I'm using as an initialization step after my class/rule/property definition ontologies have been loaded into RDF4J but before I load my instantiations ontology is loaded. (Timing is critical since the instantiations ontology begins invoking SPIN constructors.)
It is possible that the query above could include a prefix definition based on a false positive if the prefix definition happened to be contained in an embedded string or comment. For example, the literal
"Greg’s solo: five measures"^^xsd:string
would cause the above query to include the definition of theolo:
prefix, perhaps needlessly. However, inclusion of non-required prefixes had no major impact on performance and no impact on correctness. One could do better by using regular expression in place of the simpleCONTAINS
matches in the query above.