aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFederico Igne <federico.igne@cs.ox.ac.uk>2020-08-06 12:04:38 +0100
committerFederico Igne <federico.igne@cs.ox.ac.uk>2020-08-06 12:04:38 +0100
commit3408515a868ca65ab907e21160f75c858ead8d46 (patch)
tree8dcc1e2ec9a43aeb68dca6a9246415ec6569fa3e /src
parenta9e44e1b67d373faa05dd957c124eae343ff0cfa (diff)
downloadRSAComb-3408515a868ca65ab907e21160f75c858ead8d46.tar.gz
RSAComb-3408515a868ca65ab907e21160f75c858ead8d46.zip
Refactor code into different files
This has been done to better accommodate the code to detect all unsafe roles in an ontology.
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/rsacomb/Main.scala84
-rw-r--r--src/main/scala/rsacomb/RSA.scala17
-rw-r--r--src/main/scala/rsacomb/RSAAxiom.scala86
-rw-r--r--src/main/scala/rsacomb/RSAComb.scala167
-rw-r--r--src/main/scala/rsacomb/RSAOntology.scala148
5 files changed, 335 insertions, 167 deletions
diff --git a/src/main/scala/rsacomb/Main.scala b/src/main/scala/rsacomb/Main.scala
new file mode 100644
index 0000000..9cd6680
--- /dev/null
+++ b/src/main/scala/rsacomb/Main.scala
@@ -0,0 +1,84 @@
1package rsacomb
2
3/* Java imports */
4import java.io.File
5
6/* Local imports */
7import rsacomb.RSA._
8
9object RSAComb {
10
11 val help: String = """
12 rsacomb - combined approach for CQ answering for RSA ontologies.
13
14 USAGE
15 rsacomb <path/to/ontology.owl> <path/to/query.sparql>
16
17 where
18 the ontology is expected to be an OWL file and the (single)
19 query a SPARQL query file.
20 """
21
22 def main(args: Array[String]): Unit = {
23
24 /* Simple arguments handling
25 *
26 * TODO: use something better later on
27 */
28
29 if (args.length < 2) {
30 println(help)
31 return ()
32 }
33
34 val ontoPath = new File(args(0))
35 val queryPath = new File(args(1))
36
37 if (!ontoPath.isFile || !queryPath.isFile) {
38 println("The provided arguments are not regular files.\n\n")
39 println(help)
40 return ()
41 }
42
43 /* Create RSA object from generic OWLOntology
44 *
45 * TODO: It might be required to check if the ontology in input is
46 * Horn-ALCHOIQ. At the moment we are assuming this is always the
47 * case.
48 */
49
50 val ontology = RSA.loadOntology(ontoPath)
51 ontology.isRSA
52
53 /* Build canonical model */
54 //val tboxCanon = rsa.canonicalModel()
55
56 /* Load query */
57 //val query = ...
58
59 /* Compute the filtering program from the given query */
60 //val tboxFilter = rsa.filteringProgram(query)
61
62 /* ... */
63
64 /* DEBUG ONLY */
65 println("Ok!")
66 }
67}
68
69/* Notes:
70 *
71 * To establish a connection with a local RDFox instance, do the
72 * following:
73 *
74 * ```
75 * val serverConnection : ServerConnection = ConnectionFactory.newServerConnection("rdfox:local", "", "")
76 * serverConnection.createDataStore("test","seq",new HashMap())
77 * val dataStoreConnection : DataStoreConnection = serverConnection.newDataStoreConnection("test")
78 * dataStoreConnection.importData(
79 * UpdateType.ADDITION,
80 * Prefixes.s_emptyPrefixes,
81 * new File("./path/to/file")
82 * )
83 * ```
84 */
diff --git a/src/main/scala/rsacomb/RSA.scala b/src/main/scala/rsacomb/RSA.scala
new file mode 100644
index 0000000..229255c
--- /dev/null
+++ b/src/main/scala/rsacomb/RSA.scala
@@ -0,0 +1,17 @@
1package rsacomb
2
3/* Java imports */
4import java.io.File
5
6import org.semanticweb.owlapi.apibinding.OWLManager
7import org.semanticweb.owlapi.model.OWLOntology
8
9object RSA extends RSAOntology {
10
11 // TODO: move this somewhere else... maybe an OntoUtils class or something.
12 def loadOntology(onto: File ): OWLOntology = {
13 val manager = OWLManager.createOWLOntologyManager()
14 manager.loadOntologyFromOntologyDocument(onto)
15 }
16
17} // object RSA
diff --git a/src/main/scala/rsacomb/RSAAxiom.scala b/src/main/scala/rsacomb/RSAAxiom.scala
new file mode 100644
index 0000000..032b7f9
--- /dev/null
+++ b/src/main/scala/rsacomb/RSAAxiom.scala
@@ -0,0 +1,86 @@
1package rsacomb
2
3/* Java imports */
4// import java.io.File
5// import java.util.stream.{Collectors,Stream}
6
7// import org.semanticweb.owlapi.apibinding.OWLManager
8// import org.semanticweb.owlapi.model.{OWLOntologyManager,OWLOntology}
9// import org.semanticweb.owlapi.model.{OWLAxiom,OWLObjectPropertyExpression}
10import org.semanticweb.owlapi.model.{OWLAxiom,OWLSubClassOfAxiom, OWLEquivalentClassesAxiom}
11import org.semanticweb.owlapi.model.OWLAxiomVisitorEx
12// import org.semanticweb.owlapi.model.parameters.Imports
13// import org.semanticweb.owlapi.reasoner.OWLReasoner
14// import org.semanticweb.owlapi.reasoner.structural.StructuralReasonerFactory
15
16// import tech.oxfordsemantic.jrdfox.logic.Variable
17
18/* Scala imports */
19// import scala.collection.JavaConverters._
20
21/* Local imports */
22// import rsacomb.RSAAxiom
23
24/* Debug only */
25// import org.semanticweb.owlapi.dlsyntax.renderer.DLSyntaxObjectRenderer
26
27// import java.util.HashMap
28// import java.util.stream.{Stream,Collectors}
29
30// import org.semanticweb.owlapi.model.{AxiomType, ClassExpressionType, OWLObjectSomeValuesFrom}
31// import org.semanticweb.owlapi.model.OWLClassExpression
32// import org.semanticweb.owlapi.model.IRI
33// import org.semanticweb.owlapi.reasoner.{OWLReasonerFactory, OWLReasoner}
34// import uk.ac.manchester.cs.owl.owlapi.OWLObjectPropertyImpl
35
36// import tech.oxfordsemantic.jrdfox.Prefixes
37// import tech.oxfordsemantic.jrdfox.client.{ConnectionFactory, ServerConnection, DataStoreConnection}
38// import tech.oxfordsemantic.jrdfox.client.UpdateType
39// import tech.oxfordsemantic.jrdfox.logic.{Rule, Atom, Literal, Term, Variable}
40// import tech.oxfordsemantic.jrdfox.logic.{BuiltinFunctionCall, TupleTableName}
41// import tech.oxfordsemantic.jrdfox.logic.{LogicFormat}
42
43
44// import rsacomb.SkolemStrategy
45//import org.semanticweb.owlapi.model.{OWLAxiom,OWLObjectPropertyExpression}
46
47trait RSAAxiom {
48
49 sealed trait RSAAxiomType
50 object RSAAxiomType {
51 case object T3 extends RSAAxiomType
52 case object T4 extends RSAAxiomType
53 case object T5 extends RSAAxiomType
54 }
55
56 implicit class RSAAxiom(axiom: OWLAxiom) {
57
58 private class RSAAxiomTypeDetector(t: RSAAxiomType)
59 extends OWLAxiomVisitorEx[Boolean]
60 {
61
62 override
63 def visit(axiom: OWLSubClassOfAxiom): Boolean = {
64 true
65 }
66
67 override
68 def visit(axiom: OWLEquivalentClassesAxiom): Boolean = {
69 true
70 }
71
72 def doDefault(axiom : OWLAxiom): Boolean = false
73
74 }
75
76 private def isOfType(t: RSAAxiomType): Boolean = {
77 val visitor = new RSAAxiomTypeDetector(t)
78 axiom.accept(visitor)
79 }
80
81 def isT3: Boolean = isOfType(RSAAxiomType.T3)
82 def isT4: Boolean = isOfType(RSAAxiomType.T4)
83 def isT5: Boolean = isOfType(RSAAxiomType.T5)
84 }
85
86}
diff --git a/src/main/scala/rsacomb/RSAComb.scala b/src/main/scala/rsacomb/RSAComb.scala
deleted file mode 100644
index 62414e9..0000000
--- a/src/main/scala/rsacomb/RSAComb.scala
+++ /dev/null
@@ -1,167 +0,0 @@
1package rsacomb
2
3import java.io.File
4import java.util.HashMap
5import java.util.stream.{Stream,Collectors}
6
7import org.semanticweb.owlapi.apibinding.OWLManager
8import org.semanticweb.owlapi.model.{AxiomType, ClassExpressionType, OWLObjectSomeValuesFrom}
9import org.semanticweb.owlapi.model.{OWLAxiom, OWLSubClassOfAxiom, OWLEquivalentClassesAxiom}
10import org.semanticweb.owlapi.model.OWLClassExpression
11import org.semanticweb.owlapi.model.OWLOntology
12import org.semanticweb.owlapi.model.OWLOntologyManager
13import org.semanticweb.owlapi.model.IRI
14import org.semanticweb.owlapi.model.parameters.Imports
15import uk.ac.manchester.cs.owl.owlapi.OWLObjectPropertyImpl
16
17import tech.oxfordsemantic.jrdfox.Prefixes
18import tech.oxfordsemantic.jrdfox.client.{ConnectionFactory, ServerConnection, DataStoreConnection}
19import tech.oxfordsemantic.jrdfox.client.UpdateType
20import tech.oxfordsemantic.jrdfox.logic.{Rule, Atom, Literal, Term, Variable}
21import tech.oxfordsemantic.jrdfox.logic.{BuiltinFunctionCall, TupleTableName}
22import tech.oxfordsemantic.jrdfox.logic.{LogicFormat}
23
24import scala.collection.JavaConverters._
25
26import rsacomb.SkolemStrategy
27import org.semanticweb.owlapi.dlsyntax.renderer.DLSyntaxObjectRenderer
28
29class RSA(ontology : OWLOntology) {
30
31 /* Alternative constructor(s) */
32 def this(file : File) = this(RSA.loadOntology(file))
33
34 def getOntology : OWLOntology = ontology
35
36} // class RSA
37
38object RSA {
39
40 def loadOntology( onto : File ) : OWLOntology = {
41 /* Retrieve ontology manager */
42 val manager : OWLOntologyManager = OWLManager.createOWLOntologyManager()
43 /* Retrieve ontology */
44 manager.loadOntologyFromOntologyDocument(onto)
45 }
46
47 def isRSA( onto : OWLOntology ) : Boolean = {
48 /* TODO: Steps for RSA check
49 * 1) convert ontology axioms into LP rules
50 * 2) call RDFox on the onto and compute materialization
51 * 3) build graph from E(x,y) facts
52 * 4) check if the graph is tree-like
53 * ideally this annotates the graph with info about the reasons
54 * why the ontology might not be RSA. This could help a second
55 * step of approximation of an Horn-ALCHOIQ to RSA
56 */
57
58 val renderer = new DLSyntaxObjectRenderer()
59
60 // Here we need to compute the unsafe roles. This is hardcoded for now.
61 val unsafe = List(
62 new OWLObjectPropertyImpl(IRI.create("http://example.com/rsa_example.owl#S")).getInverseProperty()
63 )
64
65 /* Print TBox axioms */
66 println("TBox/RBox:")
67 for {
68 axiom <- onto.tboxAxioms(Imports.EXCLUDED).collect(Collectors.toList()).asScala
69 } yield println(renderer.render(axiom))
70 for {
71 axiom <- onto.rboxAxioms(Imports.EXCLUDED).collect(Collectors.toList()).asScala
72 } yield println(renderer.render(axiom))
73
74 /* Ontology axiom convertion into LP rules */
75 println("Logic rules:")
76 for {
77 axiom <- onto.tboxAxioms(Imports.EXCLUDED).collect(Collectors.toList()).asScala
78 visitor = new RDFoxAxiomConverter(Variable.create("x"), SkolemStrategy.ConstantRSA(axiom.toString), unsafe)
79 rule <- axiom.accept(visitor)
80 } yield println(rule)
81 for {
82 axiom <- onto.rboxAxioms(Imports.EXCLUDED).collect(Collectors.toList()).asScala
83 visitor = new RDFoxAxiomConverter(Variable.create("x"), SkolemStrategy.ConstantRSA(axiom.toString), unsafe)
84 rule <- axiom.accept(visitor)
85 } yield println(rule)
86
87 /* Return true for now... */
88 true
89 }
90
91} // object RSA
92
93object RSAComb {
94
95 val help : String = """
96 rsacomb - combined approach for CQ answering for RSA ontologies.
97
98 USAGE
99 rsacomb <path/to/ontology.owl> <path/to/query.sparql>
100
101 where
102 the ontology is expected to be an OWL file and the (single)
103 query a SPARQL query file.
104 """
105
106 def main( args : Array[String] ) : Unit = {
107
108 /* Simple arguments handling
109 *
110 * TODO: use something better later on
111 */
112
113 if (args.length < 2) {
114 println(help)
115 return ()
116 }
117
118 val ontologyPath = new File(args(0))
119 val queryPath = new File(args(1))
120
121 if (!ontologyPath.isFile || !queryPath.isFile) {
122 println("The provided arguments are not regular files.\n\n")
123 println(help)
124 return ()
125 }
126
127 /* Create RSA object from generic OWLOntology
128 *
129 * TODO: It might be required to check if the ontology in input is
130 * Horn-ALCHOIQ. At the moment we are assuming this is always the
131 * case.
132 */
133 val rsa = new RSA(ontologyPath)
134 RSA.isRSA(rsa.getOntology)
135
136 /* Build canonical model */
137 //val tboxCanon = rsa.canonicalModel()
138
139 /* Load query */
140 //val query = ...
141
142 /* Compute the filtering program from the given query */
143 //val tboxFilter = rsa.filteringProgram(query)
144
145 /* ... */
146
147 /* DEBUG ONLY */
148 println("Ok!")
149 }
150}
151
152/* Notes:
153 *
154 * To establish a connection with a local RDFox instance, do the
155 * following:
156 *
157 * ```
158 * val serverConnection : ServerConnection = ConnectionFactory.newServerConnection("rdfox:local", "", "")
159 * serverConnection.createDataStore("test","seq",new HashMap())
160 * val dataStoreConnection : DataStoreConnection = serverConnection.newDataStoreConnection("test")
161 * dataStoreConnection.importData(
162 * UpdateType.ADDITION,
163 * Prefixes.s_emptyPrefixes,
164 * new File("./path/to/file")
165 * )
166 * ```
167 */
diff --git a/src/main/scala/rsacomb/RSAOntology.scala b/src/main/scala/rsacomb/RSAOntology.scala
new file mode 100644
index 0000000..7fc8781
--- /dev/null
+++ b/src/main/scala/rsacomb/RSAOntology.scala
@@ -0,0 +1,148 @@
1package rsacomb
2
3/* Java imports */
4// import java.io.File
5import java.util.stream.{Collectors,Stream}
6
7import org.semanticweb.owlapi.model.OWLOntology
8import org.semanticweb.owlapi.model.OWLObjectPropertyExpression
9// import org.semanticweb.owlapi.model.OWLAxiomVisitorEx
10import org.semanticweb.owlapi.model.parameters.Imports
11// import org.semanticweb.owlapi.reasoner.OWLReasoner
12import org.semanticweb.owlapi.reasoner.structural.StructuralReasonerFactory
13
14import tech.oxfordsemantic.jrdfox.logic.Variable
15
16/* Scala imports */
17import scala.collection.JavaConverters._
18
19/* Local imports */
20// import rsacomb.RSAAxiom
21
22/* Debug only */
23import org.semanticweb.owlapi.dlsyntax.renderer.DLSyntaxObjectRenderer
24
25// import java.util.HashMap
26// import java.util.stream.{Stream,Collectors}
27
28// import org.semanticweb.owlapi.model.{AxiomType, ClassExpressionType, OWLObjectSomeValuesFrom}
29// import org.semanticweb.owlapi.model.{OWLSubClassOfAxiom, OWLEquivalentClassesAxiom}
30// import org.semanticweb.owlapi.model.OWLClassExpression
31// import org.semanticweb.owlapi.model.IRI
32// import org.semanticweb.owlapi.reasoner.{OWLReasonerFactory, OWLReasoner}
33// import uk.ac.manchester.cs.owl.owlapi.OWLObjectPropertyImpl
34
35// import tech.oxfordsemantic.jrdfox.Prefixes
36// import tech.oxfordsemantic.jrdfox.client.{ConnectionFactory, ServerConnection, DataStoreConnection}
37// import tech.oxfordsemantic.jrdfox.client.UpdateType
38// import tech.oxfordsemantic.jrdfox.logic.{Rule, Atom, Literal, Term, Variable}
39// import tech.oxfordsemantic.jrdfox.logic.{BuiltinFunctionCall, TupleTableName}
40// import tech.oxfordsemantic.jrdfox.logic.{LogicFormat}
41// import rsacomb.SkolemStrategy
42
43trait RSAOntology {
44
45 implicit class RSAOntology(ontology: OWLOntology) extends RSAAxiom {
46
47 def isRSA: Boolean = {
48
49 /* TODO: Steps for RSA check
50 * 1) convert ontology axioms into LP rules
51 * 2) call RDFox on the onto and compute materialization
52 * 3) build graph from E(x,y) facts
53 * 4) check if the graph is tree-like
54 * ideally this annotates the graph with info about the reasons
55 * why the ontology might not be RSA. This could help a second
56 * step of approximation of an Horn-ALCHOIQ to RSA
57 */
58
59 val tbox =
60 Stream.concat(ontology.tboxAxioms(Imports.INCLUDED), ontology.rboxAxioms(Imports.INCLUDED))
61 .collect(Collectors.toList()).asScala
62 val unsafe = ontology.getUnsafeRoles
63
64 /* DEBUG: print rules in DL syntax */
65 val renderer = new DLSyntaxObjectRenderer()
66 println("\nDL rules:")
67 tbox.foreach(x => println(renderer.render(x)))
68
69 /* Ontology convertion into LP rules */
70 println("\nLP rules:")
71 for {
72 axiom <- tbox
73 visitor = new RDFoxAxiomConverter(Variable.create("x"), SkolemStrategy.ConstantRSA(axiom.toString), unsafe)
74 rule <- axiom.accept(visitor)
75 } yield println(rule)
76
77 /* DEBUG */
78 true
79 }
80
81 def getUnsafeRoles: List[OWLObjectPropertyExpression] = {
82
83 val factory = new StructuralReasonerFactory()
84 val reasoner = factory.createReasoner(ontology)
85 val tbox = ontology.tboxAxioms(Imports.INCLUDED).collect(Collectors.toList()).asScala
86 val rbox = ontology.rboxAxioms(Imports.INCLUDED).collect(Collectors.toList()).asScala
87
88 /* DEBUG: print rules in DL syntax */
89 val renderer = new DLSyntaxObjectRenderer()
90 println("\nT5 axioms:")
91 for {
92 axiom <- tbox
93 if axiom.isT5
94 } yield println(renderer.render(axiom))
95
96 // def isT3(axiom : OWLAxiom) : Boolean = {
97 // println(axiom)
98 // axiom.getAxiomType match {
99 // case AxiomType.SUBCLASS_OF =>
100 // val axiom1 = axiom.asInstanceOf[OWLSubClassOfAxiom]
101 // axiom1.getSubClass().getClassExpressionType() == ClassExpressionType.OBJECT_SOME_VALUES_FROM &&
102 // axiom1.getSuperClass().getClassExpressionType() == ClassExpressionType.OWL_CLASS
103 // case AxiomType.EQUIVALENT_CLASSES => false // TODO
104 // }
105 // }
106
107 // def isT4(axiom : OWLAxiom) : Boolean = {
108 // axiom.getAxiomType match {
109 // case AxiomType.SUBCLASS_OF =>
110 // val axiom1 = axiom.asInstanceOf[OWLSubClassOfAxiom]
111 // axiom1.getSubClass().getClassExpressionType() == ClassExpressionType.OWL_CLASS &&
112 // axiom1.getSuperClass().getClassExpressionType() == ClassExpressionType.OBJECT_MAX_CARDINALITY
113 // case AxiomType.EQUIVALENT_CLASSES => false // TODO
114 // }
115 // }
116
117 // def isT5(axiom : OWLAxiom) : Boolean = {
118 // axiom.getAxiomType match {
119 // case AxiomType.SUBCLASS_OF => {
120 // val axiom1 = axiom.asInstanceOf[OWLSubClassOfAxiom]
121 // axiom1.getSubClass().getClassExpressionType() == ClassExpressionType.OWL_CLASS &&
122 // axiom1.getSuperClass().getClassExpressionType() == ClassExpressionType.OBJECT_SOME_VALUES_FROM
123 // }
124 // case AxiomType.EQUIVALENT_CLASSES => false // TODO
125 // }
126 // }
127
128
129 // println("T3")
130 // for {
131 // axiom <- ontology.tboxAxioms(Imports.INCLUDED)
132 // //role <- axiom.objectPropertiesInSignature()
133 // } yield println(axiom)
134
135 // println("T4")
136 // for {
137 // axiom <- ontology.tboxAxioms(Imports.INCLUDED).filter(isT4)
138 // //role <- axiom.objectPropertiesInSignature()
139 // } yield println(axiom)
140
141
142 /* DEBUG */
143 List()
144 }
145
146 } // implicit class RSAOntology
147
148} // trait RSAOntology \ No newline at end of file