I'm using TopBraid Free Edition to create OWL ontologies with SPIN rules. I'm loading the ontology and SPIN rules into Sesame OpenRDF Workbench:
Application Name OpenRDF Workbench
Version 4.1.2
Runtime Information
Operating System Windows 8.1 6.3 (amd64)
Java Runtime Oracle Corporation Java HotSpot(TM) 64-Bit Server VM (1.8.0_91)
Process User Greg
Memory
Used 646 MB
Maximum 3463 MB
I've created a simple test ontology. It has one class with one SPIN rule and one datatype property.
CONSTRUCT {
?this BugReproduction:hasTimeStamp ?timeStamp .
}
WHERE {
BIND (now() AS ?timeStamp) .
}
The SPIN rule adds an xsd:dateTime
timestamp to the test instance of my test class. Here's the RDF for the entire test ontology including my class, datatype property, and rule (short):
<?xml version="1.0"?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:sp="http://spinrdf.org/sp#"
xmlns:BugReproduction="http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproduction#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:spin="http://spinrdf.org/spin#"
xmlns:spl="http://spinrdf.org/spl#"
xmlns:arg="http://spinrdf.org/arg#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xml:base="http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproduction">
<owl:Ontology rdf:about="">
<owl:imports rdf:resource="http://spinrdf.org/spl"/>
<owl:versionInfo rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
>Created with TopBraid Composer</owl:versionInfo>
</owl:Ontology>
<owl:Class rdf:ID="TimeStampBug">
<rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
<spin:rule>
<sp:Construct>
<sp:templates rdf:parseType="Collection">
<rdf:Description>
<sp:object rdf:parseType="Resource">
<sp:varName rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
>timeStamp</sp:varName>
</sp:object>
<sp:predicate>
<owl:DatatypeProperty rdf:ID="hasTimeStamp"/>
</sp:predicate>
<sp:subject rdf:resource="http://spinrdf.org/spin#_this"/>
</rdf:Description>
</sp:templates>
<sp:where rdf:parseType="Collection">
<sp:Bind>
<sp:expression>
<sp:now/>
</sp:expression>
<sp:variable rdf:parseType="Resource">
<sp:varName rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
>timeStamp</sp:varName>
</sp:variable>
</sp:Bind>
</sp:where>
</sp:Construct>
</spin:rule>
</owl:Class>
<owl:DatatypeProperty rdf:about="#hasTimeStamp">
<rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#dateTime"/>
</owl:DatatypeProperty>
</rdf:RDF>
<!-- Created with TopBraid -->
So, clear my SPIN repository in Sesame and use the workbench's Modify/Add command (with the "use base URI as context identifier" box unchecked which is important to avoid a bug). Then I use a SPARQL Update query to create a test instance of my class:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX sxxicc: <http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/SXXIComplianceCheck#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX sp: <http://spinrdf.org/sp#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX smf: <http://topbraid.org/sparqlmotionfunctions#>
PREFIX fn: <http://www.w3.org/2005/xpath-functions#>
PREFIX spl: <http://spinrdf.org/spl#>
PREFIX spin: <http://spinrdf.org/spin#>
PREFIX arg: <http://spinrdf.org/arg#>
PREFIX SXXIComplianceCheckIndividuals: <http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/SXXIComplianceCheckIndividuals#>
PREFIX sxxicci: <http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/SXXIComplianceCheckIndividuals#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX bugs: <http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproduction#>
PREFIX bugsi: <http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproductionInstantiations#>
INSERT DATA {
bugsi:aTimeStampBug_test1 a bugs:TimeStampBug .
}
I then explore the resulting bugsi:aTimeStampBug_test1 individual, to find the SPIN:rule has run several times and produced several timestamps. The number of timestamps varies from test to test. Here's one example result:
Subject
Predicate
Object
Context
<http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproductionInstantiations#aTimeStampBug_test1>
BugReproduction:hasTimeStamp
2016-07-11T20:56:58.571-05:00
<http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproductionInstantiations#aTimeStampBug_test1>
BugReproduction:hasTimeStamp
2016-07-11T20:56:58.592-05:00
<http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproductionInstantiations#aTimeStampBug_test1>
BugReproduction:hasTimeStamp
2016-07-11T20:56:58.594-05:00
<http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproductionInstantiations#aTimeStampBug_test1>
BugReproduction:hasTimeStamp
2016-07-11T20:56:58.595-05:00
<http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproductionInstantiations#aTimeStampBug_test1>
BugReproduction:hasTimeStamp
2016-07-11T20:56:58.596-05:00
<http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproductionInstantiations#aTimeStampBug_test1>
BugReproduction:hasTimeStamp
2016-07-11T20:56:58.597-05:00
<http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproductionInstantiations#aTimeStampBug_test1>
BugReproduction:hasTimeStamp
2016-07-11T20:56:58.598-05:00
<http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproductionInstantiations#aTimeStampBug_test1>
BugReproduction:hasTimeStamp
2016-07-11T20:56:58.599-05:00
<http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproductionInstantiations#aTimeStampBug_test1>
BugReproduction:hasTimeStamp
2016-07-11T20:56:58.600-05:00
<http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproductionInstantiations#aTimeStampBug_test1>
BugReproduction:hasTimeStamp
2016-07-11T20:56:58.601-05:00
<http://www.disa.mil/dso/a2i/ontologies/PBSM/Interface/BugReproductionInstantiations#aTimeStampBug_test1>
BugReproduction:hasTimeStamp
2016-07-11T20:56:58.602-05:00
So, my SPIN:rule has run several times for one instantiation of the class. How many times should a SPIN:rule run for an instantiation of a class? I thought it would only run once, but it appears that I'm wrong.
A
SPIN:rule
runs on an instance of a class whenever that instance of a class changes. The example I posted sets up an infinite loop of changes generated by my rule generating another rule run generating another change (new time stamp), etc. until some obscure limit is reached. The limit is probably related to the overall state of Sesame (e.g. resource or timeout driven), so I get a variable number of time stamps. A simple solution is to use aSPIN:constructor
instead which only runs at instantiation (when the class is asserted), not whenever the instantiation changes.